dom/wappush/src/gonk/WbxmlPduHelper.jsm

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/wappush/src/gonk/WbxmlPduHelper.jsm	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,504 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
    1.11 +
    1.12 +let WSP = {};
    1.13 +Cu.import("resource://gre/modules/WspPduHelper.jsm", WSP);
    1.14 +
    1.15 +/**
    1.16 + * Token flags
    1.17 + *
    1.18 + * @see WAP-192-WBXML-20010725-A, clause 5.8.2
    1.19 + */
    1.20 +const TAG_TOKEN_ATTR_MASK     = 0x80;
    1.21 +const TAG_TOKEN_CONTENT_MASK  = 0x40;
    1.22 +const TAG_TOKEN_VALUE_MASK    = 0x3F;
    1.23 +
    1.24 +/**
    1.25 + * Global tokens
    1.26 + *
    1.27 + * @see WAP-192-WBXML-20010725-A, clause 7.1
    1.28 + */
    1.29 +const CODE_PAGE_SWITCH_TOKEN  = 0x00;
    1.30 +const TAG_END_TOKEN           = 0x01;
    1.31 +const INLINE_STRING_TOKEN     = 0x03;
    1.32 +const STRING_TABLE_TOKEN      = 0x83;
    1.33 +const OPAQUE_TOKEN            = 0xC3;
    1.34 +
    1.35 +// Set to true to enable debug message on all WBXML decoders.
    1.36 +this.DEBUG_ALL = false;
    1.37 +
    1.38 +// Enable debug message for WBXML decoder core.
    1.39 +this.DEBUG = DEBUG_ALL | false;
    1.40 +
    1.41 +/**
    1.42 + * Handle WBXML code page switch.
    1.43 + *
    1.44 + * @param data
    1.45 + *        A wrapped object containing raw PDU data.
    1.46 + * @param decodeInfo
    1.47 + *        Internal information for decode process.
    1.48 + *
    1.49 + * @see WAP-192-WBXML-20010725-A, clause 5.8.4.7.2 and 5.8.1
    1.50 + */
    1.51 +this.WbxmlCodePageSwitch = {
    1.52 +  decode: function decode_wbxml_code_page_switch(data, decodeInfo) {
    1.53 +    let codePage = WSP.Octet.decode(data);
    1.54 +
    1.55 +    if (decodeInfo.currentState === "tag") {
    1.56 +      decodeInfo.currentTokenList.tag = decodeInfo.tokenList.tag[codePage];
    1.57 +
    1.58 +      if (!decodeInfo.currentTokenList.tag) {
    1.59 +        throw new Error("Invalid tag code page: " + codePage + ".");
    1.60 +      }
    1.61 +
    1.62 +      return "";
    1.63 +    }
    1.64 +
    1.65 +    if (decodeInfo.currentState === "attr") {
    1.66 +      decodeInfo.currentTokenList.attr = decodeInfo.tokenList.attr[codePage];
    1.67 +      decodeInfo.currentTokenList.value = decodeInfo.tokenList.value[codePage];
    1.68 +
    1.69 +      if (!decodeInfo.currentTokenList.attr ||
    1.70 +          !decodeInfo.currentTokenList.value) {
    1.71 +        throw new Error("Invalid attr code page: " + codePage + ".");
    1.72 +      }
    1.73 +
    1.74 +      return "";
    1.75 +    }
    1.76 +
    1.77 +    throw new Error("Invalid decoder state: " + decodeInfo.currentState + ".");
    1.78 +  },
    1.79 +};
    1.80 +
    1.81 +/**
    1.82 + * Parse end WBXML encoded message.
    1.83 + *
    1.84 + * @param data
    1.85 + *        A wrapped object containing raw PDU data.
    1.86 + * @param decodeInfo
    1.87 + *        Internal information for decode process.
    1.88 + *
    1.89 + * @see WAP-192-WBXML-20010725-A, clause 5.8.4.7.1
    1.90 + *
    1.91 + */
    1.92 +this.WbxmlEnd = {
    1.93 +  decode: function decode_wbxml_end(data, decodeInfo) {
    1.94 +    let tagInfo = decodeInfo.tagStack.pop();
    1.95 +    return "</" + tagInfo.name + ">";
    1.96 +  },
    1.97 +};
    1.98 +
    1.99 +/**
   1.100 + * Escape XML reserved characters &, <, >, " and ' which may appear in the
   1.101 + * WBXML-encoded strings in their original form.
   1.102 + *
   1.103 + * @param str
   1.104 + *        A string with potentially unescaped characters
   1.105 + *
   1.106 + * @return A string with the &, <, >, " and ' characters turned into XML
   1.107 + *         character entitites
   1.108 + *
   1.109 + * @see WAP-192-WBXML-20010725-A, clause 6.1
   1.110 + */
   1.111 +this.escapeReservedCharacters = function escape_reserved_characters(str) {
   1.112 +  let dst = "";
   1.113 +
   1.114 +  for (var i = 0; i < str.length; i++) {
   1.115 +    switch (str[i]) {
   1.116 +      case '&' : dst += "&amp;" ; break;
   1.117 +      case '<' : dst += "&lt;"  ; break;
   1.118 +      case '>' : dst += "&gt;"  ; break;
   1.119 +      case '"' : dst += "&quot;"; break;
   1.120 +      case '\'': dst += "&apos;"; break;
   1.121 +      default  : dst += str[i];
   1.122 +    }
   1.123 +  }
   1.124 +
   1.125 +  return dst;
   1.126 +}
   1.127 +
   1.128 +/**
   1.129 + * Handle string table in WBXML message.
   1.130 + *
   1.131 + * @see WAP-192-WBXML-20010725-A, clause 5.7
   1.132 + */
   1.133 +this.readStringTable = function decode_wbxml_read_string_table(start, stringTable, charset) {
   1.134 +  let end = start;
   1.135 +
   1.136 +  // Find end of string
   1.137 +  let stringTableLength = stringTable.length;
   1.138 +  while (end < stringTableLength) {
   1.139 +    if (stringTable[end] === 0) {
   1.140 +      break;
   1.141 +    }
   1.142 +    end++;
   1.143 +  }
   1.144 +
   1.145 +  // Read string table
   1.146 +  return WSP.PduHelper.decodeStringContent(stringTable.subarray(start, end),
   1.147 +                                           charset);
   1.148 +};
   1.149 +
   1.150 +this.WbxmlStringTable = {
   1.151 +  decode: function decode_wbxml_string_table(data, decodeInfo) {
   1.152 +    let start = WSP.Octet.decode(data);
   1.153 +    let str = readStringTable(start, decodeInfo.stringTable, decodeInfo.charset);
   1.154 +
   1.155 +    return escapeReservedCharacters(str);
   1.156 +  }
   1.157 +};
   1.158 +
   1.159 +/**
   1.160 + * Parse inline string in WBXML encoded message.
   1.161 + *
   1.162 + * @param data
   1.163 + *        A wrapped object containing raw PDU data.
   1.164 + * @param decodeInfo
   1.165 + *        Internal information for decode process.
   1.166 + *
   1.167 + * @see WAP-192-WBXML-20010725-A, clause 5.8.4.1
   1.168 + *
   1.169 + */
   1.170 +this.WbxmlInlineString = {
   1.171 +  decode: function decode_wbxml_inline_string(data, decodeInfo) {
   1.172 +    let charCode = WSP.Octet.decode(data);
   1.173 +    let stringData = [];
   1.174 +    while (charCode) {
   1.175 +      stringData.push(charCode);
   1.176 +      charCode = WSP.Octet.decode(data);
   1.177 +    }
   1.178 +
   1.179 +    let str = WSP.PduHelper.decodeStringContent(stringData, decodeInfo.charset);
   1.180 +
   1.181 +    return escapeReservedCharacters(str);
   1.182 +  },
   1.183 +};
   1.184 +
   1.185 +/**
   1.186 + * Parse inline Opaque data in WBXML encoded message.
   1.187 + *
   1.188 + * @param data
   1.189 + *        A wrapped object containing raw PDU data.
   1.190 + * @param decodeInfo
   1.191 + *        Internal information for decode process.
   1.192 + *
   1.193 + * @see WAP-192-WBXML-20010725-A, clause 5.8.4.6
   1.194 + *
   1.195 + */
   1.196 +this.WbxmlOpaque = {
   1.197 +  decode: function decode_wbxml_inline_opaque(data) {
   1.198 +    // Inline OPAQUE must be decoded based on application definition,
   1.199 +    // so it's illegal to run into OPAQUE type in general decoder.
   1.200 +    throw new Error("OPQAUE decoder is not defined.");
   1.201 +  },
   1.202 +};
   1.203 +
   1.204 +this.PduHelper = {
   1.205 +
   1.206 +  /**
   1.207 +   * Parse WBXML encoded message into plain text.
   1.208 +   *
   1.209 +   * @param data
   1.210 +   *        A wrapped object containing raw PDU data.
   1.211 +   * @param decodeInfo
   1.212 +   *        Information for decoding, now requires charset and string table.
   1.213 +   * @param appToken
   1.214 +   *        Application-specific token difinition.
   1.215 +   *
   1.216 +   * @return Decoded WBXML message string.
   1.217 +   */
   1.218 +  parseWbxml: function parseWbxml_wbxml(data, decodeInfo, appToken) {
   1.219 +
   1.220 +    // Parse token definition to my structure.
   1.221 +    decodeInfo.tokenList = {
   1.222 +      tag: appToken.tagTokenList,
   1.223 +      attr: appToken.attrTokenList,
   1.224 +      value: appToken.valueTokenList
   1.225 +    };
   1.226 +    decodeInfo.tagStack = [];   // tag decode stack
   1.227 +    decodeInfo.currentTokenList = {
   1.228 +      tag: decodeInfo.tokenList.tag[0],
   1.229 +      attr: decodeInfo.tokenList.attr[0],
   1.230 +      value: decodeInfo.tokenList.value[0]
   1.231 +    };
   1.232 +    decodeInfo.currentState = "tag";  // Current decoding state, "tag" or "attr"
   1.233 +                                      // Used to read corresponding code page
   1.234 +                                      // initial state : "tag"
   1.235 +
   1.236 +    // Merge global tag tokens into single list, so we don't have
   1.237 +    // to search two lists every time.
   1.238 +    let globalTagTokenList = Object.create(WBXML_GLOBAL_TOKENS);
   1.239 +    if (appToken.globalTokenOverride) {
   1.240 +      let globalTokenOverrideList = appToken.globalTokenOverride;
   1.241 +      for (let token in globalTokenOverrideList) {
   1.242 +        globalTagTokenList[token] = globalTokenOverrideList[token];
   1.243 +      }
   1.244 +    }
   1.245 +
   1.246 +    let content = "";
   1.247 +    while (data.offset < data.array.length) {
   1.248 +      // Decode content, might be a new tag token, an end of tag token, or an
   1.249 +      // inline string.
   1.250 +
   1.251 +      // Switch to tag domain
   1.252 +      decodeInfo.currentState = "tag";
   1.253 +
   1.254 +      let tagToken = WSP.Octet.decode(data);
   1.255 +      let tagTokenValue = tagToken & TAG_TOKEN_VALUE_MASK;
   1.256 +
   1.257 +      // Try global tag first, tagToken of string table is 0x83, and will be 0x03
   1.258 +      // in tagTokenValue, which is collision with inline string.
   1.259 +      // So tagToken need to be searched before tagTokenValue.
   1.260 +      let tagInfo = globalTagTokenList[tagToken] ||
   1.261 +                    globalTagTokenList[tagTokenValue];
   1.262 +      if (tagInfo) {
   1.263 +        content += tagInfo.coder.decode(data, decodeInfo);
   1.264 +        continue;
   1.265 +      }
   1.266 +
   1.267 +      // Check if application tag token is valid
   1.268 +      tagInfo = decodeInfo.currentTokenList.tag[tagTokenValue];
   1.269 +      if (!tagInfo) {
   1.270 +        throw new Error("Unsupported WBXML token: " + tagTokenValue + ".");
   1.271 +      }
   1.272 +
   1.273 +      content += "<" + tagInfo.name;
   1.274 +
   1.275 +      if (tagToken & TAG_TOKEN_ATTR_MASK) {
   1.276 +        // Decode attributes, might be a new attribute token, a value token,
   1.277 +        // or an inline string
   1.278 +
   1.279 +        // Switch to attr/value domain
   1.280 +        decodeInfo.currentState = "attr";
   1.281 +
   1.282 +        let attrSeperator = "";
   1.283 +        while (data.offset < data.array.length) {
   1.284 +          let attrToken = WSP.Octet.decode(data);
   1.285 +          if (attrToken === TAG_END_TOKEN) {
   1.286 +            break;
   1.287 +          }
   1.288 +
   1.289 +          let attrInfo = globalTagTokenList[attrToken];
   1.290 +          if (attrInfo) {
   1.291 +            content += attrInfo.coder.decode(data, decodeInfo);
   1.292 +            continue;
   1.293 +          }
   1.294 +
   1.295 +          // Check if attribute token is valid
   1.296 +          attrInfo = decodeInfo.currentTokenList.attr[attrToken];
   1.297 +          if (attrInfo) {
   1.298 +            content += attrSeperator + " " + attrInfo.name + "=\"" + attrInfo.value;
   1.299 +            attrSeperator = "\"";
   1.300 +            continue;
   1.301 +          }
   1.302 +
   1.303 +          attrInfo = decodeInfo.currentTokenList.value[attrToken];
   1.304 +          if (attrInfo) {
   1.305 +            content += attrInfo.value;
   1.306 +            continue;
   1.307 +          }
   1.308 +
   1.309 +          throw new Error("Unsupported WBXML token: " + attrToken + ".");
   1.310 +        }
   1.311 +
   1.312 +        content += attrSeperator;
   1.313 +      }
   1.314 +
   1.315 +      if (tagToken & TAG_TOKEN_CONTENT_MASK) {
   1.316 +        content += ">";
   1.317 +        decodeInfo.tagStack.push(tagInfo);
   1.318 +        continue;
   1.319 +      }
   1.320 +
   1.321 +      content += "/>";
   1.322 +    }
   1.323 +
   1.324 +    return content;
   1.325 +  },
   1.326 +
   1.327 +  /**
   1.328 +   * @param data
   1.329 +   *        A wrapped object containing raw PDU data.
   1.330 +   * @param appToken
   1.331 +   *        contains application-specific token info, including
   1.332 +   *        {
   1.333 +   *          publicId              : Public identifier of application.
   1.334 +   *          tagToken              : Ojbect defines application tag tokens.
   1.335 +   *                                  In form of
   1.336 +   *                                  Object[TAG_NAME] = Object[TOKEN_NUMBER] =
   1.337 +   *                                  {
   1.338 +   *                                    name: "TOKEN_NAME",
   1.339 +   *                                    number: TOKEN_NUMBER
   1.340 +   *                                  }
   1.341 +   *          attrToken             : Object defines application attribute tokens.
   1.342 +   *                                  Object[ATTR_NAME] = Object[TOKEN_NUMBER] =
   1.343 +   *                                  {
   1.344 +   *                                    name: "ATTR_NAME",
   1.345 +   *                                    value: "ATTR_VALUE",
   1.346 +   *                                    number: TOKEN_NUMBER
   1.347 +   *                                  }
   1.348 +   *                                  For attribute value tokens, assign name as ""
   1.349 +   *          globalTokenOverride   : Object overrides decoding behavior of global tokens.
   1.350 +   *                                  In form of
   1.351 +   *                                  Object[GLOBAL_TOKEN_NUMBER] =
   1.352 +   *                                  {
   1.353 +   *                                    decode: function(data),
   1.354 +   *                                    encode: function(data)
   1.355 +   *                                  }
   1.356 +   *                                  decode() returns decoded text, encode() returns
   1.357 +   *                                  encoded raw data.
   1.358 +   *        }
   1.359 +   *
   1.360 +   * @return A WBXML message object or null in case of errors found.
   1.361 +   */
   1.362 +  parse: function parse_wbxml(data, appToken) {
   1.363 +    let msg = {};
   1.364 +
   1.365 +    /**
   1.366 +     * Read WBXML header.
   1.367 +     *
   1.368 +     * @see WAP-192-WBXML-20010725-A, Clause 5.3
   1.369 +     */
   1.370 +    let headerRaw = {};
   1.371 +    headerRaw.version = WSP.Octet.decode(data);
   1.372 +    headerRaw.publicId = WSP.UintVar.decode(data);
   1.373 +    if (headerRaw.publicId === 0) {
   1.374 +      headerRaw.publicIdStr = WSP.UintVar.decode(data);
   1.375 +    }
   1.376 +    headerRaw.charset = WSP.UintVar.decode(data);
   1.377 +
   1.378 +    let stringTableLen = WSP.UintVar.decode(data);
   1.379 +    msg.stringTable =
   1.380 +        WSP.Octet.decodeMultiple(data, data.offset + stringTableLen);
   1.381 +
   1.382 +    // Transform raw header into user-friendly form
   1.383 +    let entry = WSP.WSP_WELL_KNOWN_CHARSETS[headerRaw.charset];
   1.384 +    if (!entry) {
   1.385 +      throw new Error("Charset is not supported.");
   1.386 +    }
   1.387 +    msg.charset = entry.name;
   1.388 +
   1.389 +    if (headerRaw.publicId !== 0) {
   1.390 +      msg.publicId = WBXML_PUBLIC_ID[headerRaw.publicId];
   1.391 +    } else {
   1.392 +      msg.publicId = readStringTable(headerRaw.publicIdStr, msg.stringTable,
   1.393 +                                     WSP.WSP_WELL_KNOWN_CHARSETS[msg.charset].converter);
   1.394 +    }
   1.395 +    if (msg.publicId != appToken.publicId) {
   1.396 +      throw new Error("Public ID does not match.");
   1.397 +    }
   1.398 +
   1.399 +    msg.version = ((headerRaw.version >> 4) + 1) + "." + (headerRaw.version & 0x0F);
   1.400 +
   1.401 +    let decodeInfo = {
   1.402 +      charset: WSP.WSP_WELL_KNOWN_CHARSETS[msg.charset].converter,  // document character set
   1.403 +      stringTable: msg.stringTable                                  // document string table
   1.404 +    };
   1.405 +    msg.content = this.parseWbxml(data, decodeInfo, appToken);
   1.406 +
   1.407 +    return msg;
   1.408 +  }
   1.409 +};
   1.410 +
   1.411 +/**
   1.412 + * Global Tokens
   1.413 + *
   1.414 + * @see WAP-192-WBXML-20010725-A, clause 7.1
   1.415 + */
   1.416 +const WBXML_GLOBAL_TOKENS = (function () {
   1.417 +  let names = {};
   1.418 +  function add(number, coder) {
   1.419 +    let entry = {
   1.420 +      number: number,
   1.421 +      coder: coder,
   1.422 +    };
   1.423 +    names[number] = entry;
   1.424 +  }
   1.425 +
   1.426 +  add(CODE_PAGE_SWITCH_TOKEN, WbxmlCodePageSwitch);
   1.427 +  add(TAG_END_TOKEN,          WbxmlEnd);
   1.428 +  add(INLINE_STRING_TOKEN,    WbxmlInlineString);
   1.429 +  add(STRING_TABLE_TOKEN,     WbxmlStringTable);
   1.430 +  add(OPAQUE_TOKEN,           WbxmlOpaque);
   1.431 +
   1.432 +  return names;
   1.433 +})();
   1.434 +
   1.435 +/**
   1.436 + *  Pre-defined public IDs
   1.437 + *
   1.438 + * @see http://technical.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.aspx
   1.439 + */
   1.440 +const WBXML_PUBLIC_ID = (function () {
   1.441 +  let ids = {};
   1.442 +  function add(id, text) {
   1.443 +    ids[id] = text;
   1.444 +  }
   1.445 +
   1.446 +  // Well Known Values
   1.447 +  add(0x01,     "UNKNOWN");
   1.448 +  add(0x02,     "-//WAPFORUM//DTD WML 1.0//EN");
   1.449 +  add(0x03,     "-//WAPFORUM//DTD WTA 1.0//EN");
   1.450 +  add(0x04,     "-//WAPFORUM//DTD WML 1.1//EN");
   1.451 +  add(0x05,     "-//WAPFORUM//DTD SI 1.0//EN");
   1.452 +  add(0x06,     "-//WAPFORUM//DTD SL 1.0//EN");
   1.453 +  add(0x07,     "-//WAPFORUM//DTD CO 1.0//EN");
   1.454 +  add(0x08,     "-//WAPFORUM//DTD CHANNEL 1.1//EN");
   1.455 +  add(0x09,     "-//WAPFORUM//DTD WML 1.2//EN");
   1.456 +  add(0x0A,     "-//WAPFORUM//DTD WML 1.3//EN");
   1.457 +  add(0x0B,     "-//WAPFORUM//DTD PROV 1.0//EN");
   1.458 +  add(0x0C,     "-//WAPFORUM//DTD WTA-WML 1.2//EN");
   1.459 +  add(0x0D,     "-//WAPFORUM//DTD EMN 1.0//EN");
   1.460 +  add(0x0E,     "-//OMA//DTD DRMREL 1.0//EN");
   1.461 +  add(0x0F,     "-//WIRELESSVILLAGE//DTD CSP 1.0//EN");
   1.462 +  add(0x10,     "-//WIRELESSVILLAGE//DTD CSP 1.1//EN");
   1.463 +  add(0x11,     "-//OMA//DTD WV-CSP 1.2//EN");
   1.464 +  add(0x12,     "-//OMA//DTD IMPS-CSP 1.3//EN");
   1.465 +  add(0x13,     "-//OMA//DRM 2.1//EN");
   1.466 +  add(0x14,     "-//OMA//SRM 1.0//EN");
   1.467 +  add(0x15,     "-//OMA//DCD 1.0//EN");
   1.468 +  add(0x16,     "-//OMA//DTD DS-DataObjectEmail 1.2//EN");
   1.469 +  add(0x17,     "-//OMA//DTD DS-DataObjectFolder 1.2//EN");
   1.470 +  add(0x18,     "-//OMA//DTD DS-DataObjectFile 1.2//EN");
   1.471 +
   1.472 +  // Registered Values
   1.473 +  add(0x0FD1,   "-//SYNCML//DTD SyncML 1.0//EN");
   1.474 +  add(0x0FD2,   "-//SYNCML//DTD DevInf 1.0//EN");
   1.475 +  add(0x0FD3,   "-//SYNCML//DTD SyncML 1.1//EN");
   1.476 +  add(0x0FD4,   "-//SYNCML//DTD DevInf 1.1//EN");
   1.477 +  add(0x1100,   "-//PHONE.COM//DTD ALERT 1.0//EN");
   1.478 +  add(0x1101,   "-//PHONE.COM//DTD CACHE-OPERATION 1.0//EN");
   1.479 +  add(0x1102,   "-//PHONE.COM//DTD SIGNAL 1.0//EN");
   1.480 +  add(0x1103,   "-//PHONE.COM//DTD LIST 1.0//EN");
   1.481 +  add(0x1104,   "-//PHONE.COM//DTD LISTCMD 1.0//EN");
   1.482 +  add(0x1105,   "-//PHONE.COM//DTD CHANNEL 1.0//EN");
   1.483 +  add(0x1106,   "-//PHONE.COM//DTD MMC 1.0//EN");
   1.484 +  add(0x1107,   "-//PHONE.COM//DTD BEARER-CHOICE 1.0//EN");
   1.485 +  add(0x1108,   "-//PHONE.COM//DTD WML 1.1//EN");
   1.486 +  add(0x1109,   "-//PHONE.COM//DTD CHANNEL 1.1//EN");
   1.487 +  add(0x110A,   "-//PHONE.COM//DTD LIST 1.1//EN");
   1.488 +  add(0x110B,   "-//PHONE.COM//DTD LISTCMD 1.1//EN");
   1.489 +  add(0x110C,   "-//PHONE.COM//DTD MMC 1.1//EN");
   1.490 +  add(0x110D,   "-//PHONE.COM//DTD WML 1.3//EN");
   1.491 +  add(0x110E,   "-//PHONE.COM//DTD MMC 2.0//EN");
   1.492 +  add(0x1200,   "-//3GPP2.COM//DTD IOTA 1.0//EN");
   1.493 +  add(0x1201,   "-//SYNCML//DTD SyncML 1.2//EN");
   1.494 +  add(0x1202,   "-//SYNCML//DTD MetaInf 1.2//EN");
   1.495 +  add(0x1203,   "-//SYNCML//DTD DevInf 1.2//EN");
   1.496 +  add(0x1204,   "-//NOKIA//DTD LANDMARKS 1.0//EN");
   1.497 +  add(0x1205,   "-//SyncML//Schema SyncML 2.0//EN");
   1.498 +  add(0x1206,   "-//SyncML//Schema DevInf 2.0//EN");
   1.499 +  add(0x1207,   "-//OMA//DTD DRMREL 1.0//EN");
   1.500 +
   1.501 +  return ids;
   1.502 +})();
   1.503 +
   1.504 +this.EXPORTED_SYMBOLS = [
   1.505 +  // Parser
   1.506 +  "PduHelper",
   1.507 +];

mercurial