1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/wappush/src/gonk/SiPduHelper.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,217 @@ 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 +let WBXML = {}; 1.15 +Cu.import("resource://gre/modules/WbxmlPduHelper.jsm", WBXML); 1.16 + 1.17 +// set to true to see debug messages 1.18 +let DEBUG = WBXML.DEBUG_ALL | false; 1.19 + 1.20 +/** 1.21 + * Public identifier for SI 1.22 + * 1.23 + * @see http://technical.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.aspx 1.24 + */ 1.25 +const PUBLIC_IDENTIFIER_SI = "-//WAPFORUM//DTD SI 1.0//EN"; 1.26 + 1.27 +/** 1.28 + * Parse inline date encoded in OPAQUE format. 1.29 + * 1.30 + * @param data 1.31 + * A wrapped object containing raw PDU data. 1.32 + * @param msg 1.33 + * Target object for decoding. 1.34 + * 1.35 + * @see WAP-167-SERVICEIND-20010731-A, clause 8.2.2 1.36 + * 1.37 + */ 1.38 +this.OpaqueAsDate = { 1.39 + decode: function decode_opaque_as_date(data) { 1.40 + let size = WSP.UintVar.decode(data); 1.41 + let dateBuf = [0, 0, 0, 0, 0, 0, 0]; 1.42 + 1.43 + // Maximum length for date is 7 bytes. 1.44 + if (size > dateBuf.length) 1.45 + size = dateBuf.length 1.46 + 1.47 + // Read date date, non-specified parts remain 0. 1.48 + for (let i = 0; i < size; i++) { 1.49 + dateBuf[i] = WSP.Octet.decode(data); 1.50 + } 1.51 + 1.52 + // Decode and return result in "YYYY-MM-DDThh:mm:ssZ" form 1.53 + let year = ((dateBuf[0] >> 4) & 0x0F) * 1000 + (dateBuf[0] & 0x0F) * 100 + 1.54 + ((dateBuf[1] >> 4) & 0x0F) * 10 + (dateBuf[1] & 0x0F); 1.55 + let month = ((dateBuf[2] >> 4) & 0x0F) * 10 + (dateBuf[2] & 0x0F); 1.56 + let date = ((dateBuf[3] >> 4) & 0x0F) * 10 + (dateBuf[3] & 0x0F); 1.57 + let hour = ((dateBuf[4] >> 4) & 0x0F) * 10 + (dateBuf[4] & 0x0F); 1.58 + let minute = ((dateBuf[5] >> 4) & 0x0F) * 10 + (dateBuf[5] & 0x0F); 1.59 + let second = ((dateBuf[6] >> 4) & 0x0F) * 10 + (dateBuf[6] & 0x0F); 1.60 + let dateValue = new Date(Date.UTC(year, month - 1, date, hour, minute, second)); 1.61 + 1.62 + return dateValue.toISOString().replace(".000", ""); 1.63 + }, 1.64 +}; 1.65 + 1.66 +this.PduHelper = { 1.67 + 1.68 + /** 1.69 + * @param data 1.70 + * A wrapped object containing raw PDU data. 1.71 + * @param contentType 1.72 + * Content type of incoming SI message, should be "text/vnd.wap.si" or 1.73 + * "application/vnd.wap.sic". 1.74 + * 1.75 + * @return A message object containing attribute content and contentType. 1.76 + * |content| will contain string of decoded SI message if successfully 1.77 + * decoded, or raw data if failed. 1.78 + * |contentType| will be string representing corresponding type of 1.79 + * content. 1.80 + */ 1.81 + parse: function parse_si(data, contentType) { 1.82 + // We only need content and contentType 1.83 + let msg = { 1.84 + contentType: contentType 1.85 + }; 1.86 + 1.87 + /** 1.88 + * Message is compressed by WBXML, decode into string. 1.89 + * 1.90 + * @see WAP-192-WBXML-20010725-A 1.91 + */ 1.92 + if (contentType === "application/vnd.wap.sic") { 1.93 + let globalTokenOverride = {}; 1.94 + globalTokenOverride[0xC3] = { 1.95 + number: 0xC3, 1.96 + coder: OpaqueAsDate 1.97 + }; 1.98 + 1.99 + let appToken = { 1.100 + publicId: PUBLIC_IDENTIFIER_SI, 1.101 + tagTokenList: SI_TAG_FIELDS, 1.102 + attrTokenList: SI_ATTRIBUTE_FIELDS, 1.103 + valueTokenList: SI_VALUE_FIELDS, 1.104 + globalTokenOverride: globalTokenOverride 1.105 + } 1.106 + 1.107 + try { 1.108 + let parseResult = WBXML.PduHelper.parse(data, appToken); 1.109 + msg.content = parseResult.content; 1.110 + msg.contentType = "text/vnd.wap.si"; 1.111 + } catch (e) { 1.112 + // Provide raw data if we failed to parse. 1.113 + msg.content = data.array; 1.114 + } 1.115 + return msg; 1.116 + } 1.117 + 1.118 + /** 1.119 + * Message is plain text, transform raw to string. 1.120 + */ 1.121 + try { 1.122 + let stringData = WSP.Octet.decodeMultiple(data, data.array.length); 1.123 + msg.content = WSP.PduHelper.decodeStringContent(stringData, "UTF-8"); 1.124 + } catch (e) { 1.125 + // Provide raw data if we failed to parse. 1.126 + msg.content = data.array; 1.127 + } 1.128 + return msg; 1.129 + 1.130 + } 1.131 +}; 1.132 + 1.133 +/** 1.134 + * Tag tokens 1.135 + * 1.136 + * @see WAP-167-SERVICEIND-20010731-A, clause 8.3.1 1.137 + */ 1.138 +const SI_TAG_FIELDS = (function () { 1.139 + let names = {}; 1.140 + function add(name, codepage, number) { 1.141 + let entry = { 1.142 + name: name, 1.143 + number: number, 1.144 + }; 1.145 + if (!names[codepage]) { 1.146 + names[codepage] = {}; 1.147 + } 1.148 + names[codepage][number] = entry; 1.149 + } 1.150 + 1.151 + add("si", 0, 0x05); 1.152 + add("indication", 0, 0x06); 1.153 + add("info", 0, 0x07); 1.154 + add("item", 0, 0x08); 1.155 + 1.156 + return names; 1.157 +})(); 1.158 + 1.159 +/** 1.160 + * Attribute Tokens 1.161 + * 1.162 + * @see WAP-167-SERVICEIND-20010731-A, clause 8.3.2 1.163 + */ 1.164 +const SI_ATTRIBUTE_FIELDS = (function () { 1.165 + let names = {}; 1.166 + function add(name, value, codepage, number) { 1.167 + let entry = { 1.168 + name: name, 1.169 + value: value, 1.170 + number: number, 1.171 + }; 1.172 + if (!names[codepage]) { 1.173 + names[codepage] = {}; 1.174 + } 1.175 + names[codepage][number] = entry; 1.176 + } 1.177 + 1.178 + add("action", "signal-none", 0, 0x05); 1.179 + add("action", "signal-low", 0, 0x06); 1.180 + add("action", "signal-medium", 0, 0x07); 1.181 + add("action", "signal-high", 0, 0x08); 1.182 + add("action", "delete", 0, 0x09); 1.183 + add("created", "", 0, 0x0A); 1.184 + add("href", "", 0, 0x0B); 1.185 + add("href", "http://", 0, 0x0C); 1.186 + add("href", "http://www.", 0, 0x0D); 1.187 + add("href", "https://", 0, 0x0E); 1.188 + add("href", "https://www.", 0, 0x0F); 1.189 + add("si-expires", "", 0, 0x10); 1.190 + add("si-id", "", 0, 0x11); 1.191 + add("class", "", 0, 0x12); 1.192 + 1.193 + return names; 1.194 +})(); 1.195 + 1.196 +const SI_VALUE_FIELDS = (function () { 1.197 + let names = {}; 1.198 + function add(value, codepage, number) { 1.199 + let entry = { 1.200 + value: value, 1.201 + number: number, 1.202 + }; 1.203 + if (!names[codepage]) { 1.204 + names[codepage] = {}; 1.205 + } 1.206 + names[codepage][number] = entry; 1.207 + } 1.208 + 1.209 + add(".com/", 0, 0x85); 1.210 + add(".edu/", 0, 0x86); 1.211 + add(".net/", 0, 0x87); 1.212 + add(".org/", 0, 0x88); 1.213 + 1.214 + return names; 1.215 +})(); 1.216 + 1.217 +this.EXPORTED_SYMBOLS = [ 1.218 + // Parser 1.219 + "PduHelper", 1.220 +];