mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
7edec4880a
- Bug 859764 - Part 5: Changes in Test Cases. r=echen (f1a5cd4fd3) - Bug 859764 - Part 6: Changes in Payment. r=ferjm, r=smaug (2b47641375) - Bug 1010756 - Helpful errors for using nsCOMPtr on non-XPCOM types; r=froydnj (6b1521c482) - leftover (e1a24351e9) - Bug 1192102 - Remove unused file embedded/android/GeckoSmsManager.java. r=blassey (ac05ae649d) - var-let (8ddb529f96) - Bug 1181466 - Fix observe function in SmsService/MmsService. r=btseng (ca93122404) - Bug 733331 - Part 2: Update enabledGsmTableTuples when MCC changes in SmsService.js and fix segmentChars in SmsSegmentHelper.jsm. r=btseng (24fa23e4be) - Bug 1173156 - Fix typo and add a Marionette test case. r=btseng (e7199eb55a) - Bug 1132774 - [B2G][SMS] Enable DEBUG Flag in SmsService if the default value of "ril.debugging.enabled" is true. r=btseng (7300d24fb7) - Bug 1169160 - [MobileConnection] Support more call barring program: all service, outgoing service and incoming service. r=hsinyi,aknow (872c2cc056) - Bug 1169225 - [MobileConnectionService] Support setting/getting call waiting on all serviceClass. r=aknow (14c546a9ca) - Bug 1110619 - Part 1: IDL Interface Changes. r=echen (beae2b4b77) - Bug 1168064 - B2G RIL: filter out cell info with unknown values. r=echen (11dfc5a7e8) - Bug 1159591 - Part 2: Move MMI logic from ril_worker to telephonyService (Call Forwarding). r=aknow (b4edb76863) - Bug 1159591 - Part 3: Move MMI logic from ril_worker to telephonyService (Icc Lock). r=aknow (3faba76808) - Bug 1138263 - Make TelephonyService.js JSHint friendly. r=hsinyi (454bd4c765) - Bug 1159591 - Part 4: Move MMI logic from ril_worker to telephonyService (IMEI). r=aknow (57f423ecdd) - Bug 1159591 - Part 5: Move MMI logic from ril_worker to telephonyService (CLIP). r=aknow (c6611dbcb8) - Bug 1159591 - Part 6: Move MMI logic from ril_worker to telephonyService (CLIR). r=aknow (8c1fc03edb) - Bug 1159591 - Part 7: Move MMI logic from ril_worker to telephonyService (Call Barring Password). r=aknow (5d8bcbf177) - Bug 1159591 - Part 8: Move MMI logic from ril_worker to telephonyService (Call Barring). r=aknow (aa0b89aea1) - Bug 1159591 - Part 9: Move MMI logic from ril_worker to telephonyService (Call Waiting). r=aknow (1d14d2b864) - Bug 1159591 - Part 10: Move MMI logic from ril_worker to telephonyService (USSD). r=aknow (c92130b5b2) - Bug 1159591 - Part 11: Move MMI consts from ril_consts to telephonyService. r=aknow (0e7b3fea9a) - Bug 1159591 - Part 12: Move radio check for MMI to a common place. r=aknow (dcdc3178ad) - Bug 1110619 - Part 2: Implementation Changes. r=echen (6d8e78d684) - Bug 1110619 - Part 3: Bluetooth Changes. r=btian (9787727be0) - Bug 1147736 - Part 1: Extend TelephonyCallInfo. r=aknow (2a426cc99f) - Bug 1147736 - Part 2: Bypass NotifyError. r=aknow (6cd6fd6867) - Bug 1147736 - Part 3: Deprecate NotifyError. r=aknow (e41c719442) - Bug 1147736 - Part 4: Deprecate NotifyError(Bluetooth). r=btian (9c8f97bb22) - Bug 1204817 - Delete the child property of a parent call only when the parent call exists. r=btseng (d35dc6b08f) - Bug 1191205 - Cancel USSD sessions only when needed. r=edgar (01a72dbacb) - Bug 1200134 - Control USSD Sessions with State-Transitions instead of Boolean. r=echen (a4e55b3d9d) - Bug 1163511 - Use defineLazyModuleGetter. r=hsinyi (8a97a4912c) - Bug 991582 - Part 2: Handle the result of RIL request in a consistent way. r=aknow (914ecc2bbb) - Bug 1164248 - Handling of session/sessionEnded for notifyUssdReceived. r=edgar (a79df75d38) - Bug 1223662 - Part 1: Check mmiServiceCode with correct constant. r=echen (abeb286050) - Bug 1174673 - Part 1: Automatically resume the held call. r=hsinyi (280543af7d) - Bug 1174673 - Part 2: Update test case. r=hsinyi (cfe19f1a52) - Bug 1185156 - Fix bug in resuming held call. r=hsinyi (b96346d319) - Bug 1162426 - Part 1: Provide TelephonyUtils. r=hsinyi (62b71e6e83) - Bug 1162426 - Part 2: Test case. r=hsniyi (13a0b3c6f5) - Bug 1171807 - Part 1: Add enums for TelephonyCall::State and TelephonyCallGroup::State (WebIDL). r=hsinyi (0b698eecc4) - Bug 1145551 - DTMF should be sent using the active SIM, the given or the default one (in that order). r=aknow (6157636493) - Bug 1171807 - Part 2: Move to enums and deprecate TelephonyCall.mCallState and TelephonyCallGroup.mCallState (DOM). r=btseng (5faef22d91) - Bug 1168515 - do not block incall MMI requests on alerting state. r=aknow (b1f85c5789) - Bug 1155072 - Part 1: Deprecate nsITelephonyListener.conferenceCallStateChanged (Telephony). r=btseng (e41d1a4bc9) - Bug 1155072 - Part 2: Deprecate nsITelephonyListener.conferenceCallStateChanged (Bluetooth). r=btian (27e69fa89b) - Bug 1166936 - JS Warning in TelephonyService.js r=aknow (3559d3ad3d) - Bug 1191237 - Part 1: Enhance |TelephonyService.js|. r=aknow (86576a6d32) - Bug 1202902 - Fix the world. (0dc256d67d) - Bug 1161438 - Part 1 - Exporting contact to SIM should also return updated contact. r=echen (505d7d7f83) - Bug 1159622 - Split test_icc_contact.js into read contact and add contact. r=echen (fec0c428df) - Bug 1122376 - Support read SIM contact dialling number exceed 20 digits. r=echen (5d0599e93c) - Bug 1161438 - Part 2 - marionette testcase. r=echen (1f0d18a479) - Bug 1114937 - Part 5: Fix Test Case to Remove Contact with Correct Contact Id. r=echen (8d746fdbd2) - Bug 1194149 - Continue importing contacts when there is no sufficient Type 2 USIM contact fields record. r=echen (e9be40dbf2) - Bug 962995 - xpcshell tests for write ICC UCS2 characters for 0x81 and 0x82 encoding. r=echen (9500afaa4d) - Bug 1161438 - Part 3 - xpcshell testcase. r=echen (01f7fb4514) - Bug 1122376 - Support write SIM contact dialling number exceed 20 digits. r=echen (91133e286d) - Bug 999300 - Part 1: Removed the Ril v5 legacy support. r=edgar (ded77fcb6f) - Bug 999300 - Part 2: Update the related testcases. r=edgar (f77a8b96cc) - Bug 1177146 - [Aries][RIL] Reply from QUERY_AVAILABLE_NETWORKS has extra strings. r=hsinyi (a6816cbbab) - Bug 1043250 - Part 1: Update ril_worker and xpcshell test. r=btseng (8b9b25b5cf) - Bug 1185406 - B2G RIL: Read 'pcscf' and expose it in nsIRilNetworkInfo. r=hsinyi (ce707ecb83) - Bug 1174998 - Part 3: Read data call's MTU from network/apn settings. r=echen (bfa08d8380) - Bug 1166320 - Make volume service safer to use off main thread. r=dhylands (b3976622ad) - Bug 1177374 - Call realpath on volume mount points so thatVolumeService::GetVolumeByPath works properly. r=achen (aea97080eb) - Bug 1195166 - AutoMounter: add ignore command to allow volumes to be ignored. r=alchen (f265d832c8) - Bug 1196724 - Refactoring of AudioManager r=alwu (e5b896b7ce) - Bug 1222564 - Save audio volume to database r=alwu (1303d01ae7) - Bug 1164049 - Fix some mode lines in embedding/. r=smaug (79ddce4871)
1711 lines
52 KiB
JavaScript
1711 lines
52 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
"use strict";
|
|
|
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
|
|
var WSP = {};
|
|
Cu.import("resource://gre/modules/WspPduHelper.jsm", WSP);
|
|
|
|
Cu.import("resource://gre/modules/mms_consts.js");
|
|
|
|
Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
|
|
|
|
var DEBUG; // set to true to see debug messages
|
|
|
|
this.MMS_VERSION = (function() {
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
|
|
try {
|
|
return Services.prefs.getIntPref("dom.mms.version");
|
|
} catch(ex) {}
|
|
|
|
return MMS_VERSION_1_3;
|
|
})();
|
|
|
|
this.translatePduErrorToStatus = function translatePduErrorToStatus(error) {
|
|
if (error == MMS_PDU_ERROR_OK) {
|
|
return MMS_PDU_STATUS_RETRIEVED;
|
|
}
|
|
|
|
if ((error >= MMS_PDU_ERROR_TRANSIENT_FAILURE)
|
|
&& (error < MMS_PDU_ERROR_PERMANENT_FAILURE)) {
|
|
return MMS_PDU_STATUS_DEFERRED;
|
|
}
|
|
|
|
return MMS_PDU_STATUS_UNRECOGNISED;
|
|
}
|
|
|
|
function defineLazyRegExp(obj, name, pattern) {
|
|
obj.__defineGetter__(name, function() {
|
|
delete obj[name];
|
|
return obj[name] = new RegExp(pattern);
|
|
});
|
|
}
|
|
|
|
function RangedValue(name, min, max) {
|
|
this.name = name;
|
|
this.min = min;
|
|
this.max = max;
|
|
}
|
|
RangedValue.prototype = {
|
|
name: null,
|
|
min: null,
|
|
max: null,
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded integer.
|
|
*
|
|
* @throws CodeError if decoded value is not in the range [this.min, this.max].
|
|
*/
|
|
decode: function(data) {
|
|
let value = WSP.Octet.decode(data);
|
|
if ((value >= this.min) && (value <= this.max)) {
|
|
return value;
|
|
}
|
|
|
|
throw new WSP.CodeError(this.name + ": invalid value " + value);
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param value
|
|
* An integer value within thr range [this.min, this.max].
|
|
*/
|
|
encode: function(data, value) {
|
|
if ((value < this.min) || (value > this.max)) {
|
|
throw new WSP.CodeError(this.name + ": invalid value " + value);
|
|
}
|
|
|
|
WSP.Octet.encode(data, value);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Internal decoding function for boolean values.
|
|
*
|
|
* Boolean-value = Yes | No
|
|
* Yes = <Octet 128>
|
|
* No = <Octet 129>
|
|
*/
|
|
this.BooleanValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return Boolean true or false.
|
|
*
|
|
* @throws CodeError if read octet equals to neither 128 nor 129.
|
|
*/
|
|
decode: function(data) {
|
|
let value = WSP.Octet.decode(data);
|
|
if ((value != 128) && (value != 129)) {
|
|
throw new WSP.CodeError("Boolean-value: invalid value " + value);
|
|
}
|
|
|
|
return value == 128;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param value
|
|
* A boolean value to be encoded.
|
|
*/
|
|
encode: function(data, value) {
|
|
WSP.Octet.encode(data, value ? 128 : 129);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* MMS Address
|
|
*
|
|
* address = email | device-address | alphanum-shortcode | num-shortcode
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A section 8
|
|
*/
|
|
this.Address = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
*
|
|
* @return An object of two string-typed attributes: address and type.
|
|
*/
|
|
decode: function(data) {
|
|
let str = EncodedStringValue.decode(data);
|
|
|
|
let result;
|
|
if (((result = str.match(this.REGEXP_DECODE_PLMN)) != null)
|
|
|| ((result = str.match(this.REGEXP_DECODE_IPV4)) != null)
|
|
|| ((result = str.match(this.REGEXP_DECODE_IPV6)) != null)
|
|
|| (((result = str.match(this.REGEXP_DECODE_CUSTOM)) != null)
|
|
&& (result[2] != "PLMN")
|
|
&& (result[2] != "IPv4")
|
|
&& (result[2] != "IPv6"))) {
|
|
return {address: result[1], type: result[2]};
|
|
}
|
|
|
|
let type;
|
|
if (str.match(this.REGEXP_NUM)) {
|
|
type = "num";
|
|
} else if (str.match(this.REGEXP_ALPHANUM)) {
|
|
type = "alphanum";
|
|
} else if (str.match(this.REGEXP_EMAIL)) {
|
|
type = "email";
|
|
} else {
|
|
throw new WSP.CodeError("Address: invalid address");
|
|
}
|
|
|
|
return {address: str, type: type};
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param value
|
|
* An object of two string-typed attributes: address and type.
|
|
*/
|
|
encode: function(data, value) {
|
|
if (!value || !value.type || !value.address) {
|
|
throw new WSP.CodeError("Address: invalid value");
|
|
}
|
|
|
|
let str;
|
|
switch (value.type) {
|
|
case "email":
|
|
if (value.address.match(this.REGEXP_EMAIL)) {
|
|
str = value.address;
|
|
}
|
|
break;
|
|
case "num":
|
|
if (value.address.match(this.REGEXP_NUM)) {
|
|
str = value.address;
|
|
}
|
|
break;
|
|
case "alphanum":
|
|
if (value.address.match(this.REGEXP_ALPHANUM)) {
|
|
str = value.address;
|
|
}
|
|
break;
|
|
case "IPv4":
|
|
if (value.address.match(this.REGEXP_ENCODE_IPV4)) {
|
|
str = value.address + "/TYPE=IPv4";
|
|
}
|
|
break;
|
|
case "IPv6":
|
|
if (value.address.match(this.REGEXP_ENCODE_IPV6)) {
|
|
str = value.address + "/TYPE=IPv6";
|
|
}
|
|
break;
|
|
case "PLMN":
|
|
if (value.address.match(this.REGEXP_ENCODE_PLMN)) {
|
|
str = value.address + "/TYPE=PLMN";
|
|
}
|
|
break;
|
|
default:
|
|
if (value.type.match(this.REGEXP_ENCODE_CUSTOM_TYPE)
|
|
&& value.address.match(this.REGEXP_ENCODE_CUSTOM_ADDR)) {
|
|
str = value.address + "/TYPE=" + value.type;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!str) {
|
|
throw new WSP.CodeError("Address: invalid value: " + JSON.stringify(value));
|
|
}
|
|
|
|
EncodedStringValue.encode(data, str);
|
|
},
|
|
|
|
/**
|
|
* @param address
|
|
* Address string which want to find the type.
|
|
*
|
|
* @return Address type.
|
|
*/
|
|
resolveType: function(address) {
|
|
if (address.match(this.REGEXP_EMAIL)) {
|
|
return "email";
|
|
}
|
|
|
|
if (address.match(this.REGEXP_ENCODE_IPV4)) {
|
|
return "IPv4";
|
|
}
|
|
|
|
if (address.match(this.REGEXP_ENCODE_IPV6)) {
|
|
return "IPv6";
|
|
}
|
|
|
|
let normalizedAddress = PhoneNumberUtils.normalize(address, false);
|
|
if (PhoneNumberUtils.isPlainPhoneNumber(normalizedAddress)) {
|
|
return "PLMN";
|
|
}
|
|
|
|
return "Others";
|
|
},
|
|
};
|
|
|
|
defineLazyRegExp(Address, "REGEXP_DECODE_PLMN", "^(\\+?[\\d.-]+)\\/TYPE=(PLMN)$");
|
|
defineLazyRegExp(Address, "REGEXP_DECODE_IPV4", "^((?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9]){0,1}[0-9])\\.){3,3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9]){0,1}[0-9]))\\/TYPE=(IPv4)$");
|
|
defineLazyRegExp(Address, "REGEXP_DECODE_IPV6", "^(" +
|
|
"(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,7}:|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|" +
|
|
"[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|" +
|
|
":(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9]){0,1}[0-9])\\.){3,3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9]){0,1}[0-9])" +
|
|
")\\/TYPE=(IPv6)$");
|
|
defineLazyRegExp(Address, "REGEXP_DECODE_CUSTOM", "^([\\w\\+\\-.%]+)\\/TYPE=(\\w+)$");
|
|
defineLazyRegExp(Address, "REGEXP_ENCODE_PLMN", "^\\+?[\\d.-]+$");
|
|
defineLazyRegExp(Address, "REGEXP_ENCODE_IPV4", "^(?:(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9]){0,1}[0-9])\\.){3,3}(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9]){0,1}[0-9])$");
|
|
defineLazyRegExp(Address, "REGEXP_ENCODE_IPV6", "^(?:" +
|
|
"(?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,7}:|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|" +
|
|
"(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|" +
|
|
"[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|" +
|
|
":(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)" +
|
|
")$");
|
|
defineLazyRegExp(Address, "REGEXP_ENCODE_CUSTOM_TYPE", "^\\w+$");
|
|
defineLazyRegExp(Address, "REGEXP_ENCODE_CUSTOM_ADDR", "^[\\w\\+\\-.%]+$");
|
|
defineLazyRegExp(Address, "REGEXP_NUM", "^[\\+*#]?\\d+$");
|
|
defineLazyRegExp(Address, "REGEXP_ALPHANUM", "^\\w+$");
|
|
// OMA-TS-MMS_ENC-V1_3-20110913-A chapter 8:
|
|
//
|
|
// E-mail should match the definition of `mailbox` as described in section
|
|
// 3.4 of RFC2822, but excluding the obsolete definitions as indicated by
|
|
// the "obs-" prefix.
|
|
//
|
|
// Here we try to match addr-spec only.
|
|
defineLazyRegExp(Address, "REGEXP_EMAIL", "(?:" +
|
|
"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|" +
|
|
"\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\"" +
|
|
")@(?:" +
|
|
"[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|" +
|
|
"\\[(?:" +
|
|
"[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f]" +
|
|
")*\\]" +
|
|
")");
|
|
|
|
/**
|
|
* Header-field = MMS-header | Application-header
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.2
|
|
*/
|
|
this.HeaderField = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param options
|
|
* Extra context for decoding.
|
|
*
|
|
* @return A decoded object containing `name` and `value` properties or null
|
|
* in case of a failed parsing. The `name` property must be a string,
|
|
* but the `value` property can be many different types depending on
|
|
* `name`.
|
|
*/
|
|
decode: function(data, options) {
|
|
return WSP.decodeAlternatives(data, options,
|
|
MmsHeader, WSP.ApplicationHeader);
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param octet
|
|
* Octet value to be encoded.
|
|
* @param options
|
|
* Extra context for encoding.
|
|
*/
|
|
encode: function(data, value, options) {
|
|
WSP.encodeAlternatives(data, value, options,
|
|
MmsHeader, WSP.ApplicationHeader);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* MMS-header = MMS-field-name MMS-value
|
|
* MMS-field-name = Short-integer
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.2
|
|
*/
|
|
this.MmsHeader = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param options
|
|
* Extra context for decoding.
|
|
*
|
|
* @return A decoded object containing `name` and `value` properties or null
|
|
* in case of a failed parsing. The `name` property must be a string,
|
|
* but the `value` property can be many different types depending on
|
|
* `name`.
|
|
*
|
|
* @throws NotWellKnownEncodingError if decoded well-known header field
|
|
* number is not registered or supported.
|
|
*/
|
|
decode: function(data, options) {
|
|
let index = WSP.ShortInteger.decode(data);
|
|
|
|
let entry = MMS_HEADER_FIELDS[index];
|
|
if (!entry) {
|
|
throw new WSP.NotWellKnownEncodingError(
|
|
"MMS-header: not well known header " + index);
|
|
}
|
|
|
|
let cur = data.offset, value;
|
|
try {
|
|
value = entry.coder.decode(data, options);
|
|
} catch (e) {
|
|
data.offset = cur;
|
|
|
|
value = WSP.skipValue(data);
|
|
debug("Skip malformed well known header: "
|
|
+ JSON.stringify({name: entry.name, value: value}));
|
|
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
name: entry.name,
|
|
value: value,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param header
|
|
* An object containing two attributes: a string-typed `name` and a
|
|
* `value` of arbitrary type.
|
|
*
|
|
* @throws CodeError if got an empty header name.
|
|
* @throws NotWellKnownEncodingError if the well-known header field number is
|
|
* not registered or supported.
|
|
*/
|
|
encode: function(data, header) {
|
|
if (!header.name) {
|
|
throw new WSP.CodeError("MMS-header: empty header name");
|
|
}
|
|
|
|
let entry = MMS_HEADER_FIELDS[header.name.toLowerCase()];
|
|
if (!entry) {
|
|
throw new WSP.NotWellKnownEncodingError(
|
|
"MMS-header: not well known header " + header.name);
|
|
}
|
|
|
|
WSP.ShortInteger.encode(data, entry.number);
|
|
entry.coder.encode(data, header.value);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Cancel-status-value = Cancel Request Successfully received |
|
|
* Cancel Request corrupted
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.7
|
|
*/
|
|
this.CancelStatusValue = new RangedValue("Cancel-status-value", 128, 129);
|
|
|
|
/**
|
|
* Content-class-value = text | image-basic| image-rich | video-basic |
|
|
* video-rich | megapixel | content-basic | content-rich
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.9
|
|
*/
|
|
this.ContentClassValue = new RangedValue("Content-class-value", 128, 135);
|
|
|
|
/**
|
|
* When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
|
|
*
|
|
* Content-location-value = Uri-value
|
|
*
|
|
* When used in the M-Mbox-Delete.conf and M-Delete.conf PDU:
|
|
*
|
|
* Content-location-Del-value = Value-length Status-count-value Content-location-value
|
|
* Status-count-value = Integer-value
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.10
|
|
*/
|
|
this.ContentLocationValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param options
|
|
* Extra context for decoding.
|
|
*
|
|
* @return A decoded object containing `uri` and conditional `statusCount`
|
|
* properties.
|
|
*/
|
|
decode: function(data, options) {
|
|
let type = WSP.ensureHeader(options, "x-mms-message-type");
|
|
|
|
let result = {};
|
|
if ((type == MMS_PDU_TYPE_MBOX_DELETE_CONF)
|
|
|| (type == MMS_PDU_TYPE_DELETE_CONF)) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
result.statusCount = WSP.IntegerValue.decode(data);
|
|
result.uri = WSP.UriValue.decode(data);
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
} else {
|
|
result.uri = WSP.UriValue.decode(data);
|
|
}
|
|
|
|
return result;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Element-Descriptor-value = Value-length Content-Reference-value *(Parameter)
|
|
* Content-Reference-value = Text-string
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.18
|
|
*/
|
|
this.ElementDescriptorValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded object containing a string property `contentReference`
|
|
* and an optinal `params` name-value map.
|
|
*/
|
|
decode: function(data) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
let result = {};
|
|
result.contentReference = WSP.TextString.decode(data);
|
|
if (data.offset < end) {
|
|
result.params = Parameter.decodeMultiple(data, end);
|
|
}
|
|
|
|
if (data.offset != end) {
|
|
// Explicitly seek to end in case of skipped parameters.
|
|
data.offset = end;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.18:
|
|
* `For well-known parameter names binary tokens MUST be used as defined in
|
|
* Table 27.` So we can't reuse that of WSP.
|
|
*
|
|
* Parameter = Parameter-name Parameter-value
|
|
* Parameter-name = Short-integer | Text-string
|
|
* Parameter-value = Constrained-encoding | Text-string
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.18
|
|
*/
|
|
this.Parameter = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded string.
|
|
*
|
|
* @throws NotWellKnownEncodingError if decoded well-known parameter number
|
|
* is not registered or supported.
|
|
*/
|
|
decodeParameterName: function(data) {
|
|
let begin = data.offset;
|
|
let number;
|
|
try {
|
|
number = WSP.ShortInteger.decode(data);
|
|
} catch (e) {
|
|
data.offset = begin;
|
|
return WSP.TextString.decode(data).toLowerCase();
|
|
}
|
|
|
|
let entry = MMS_WELL_KNOWN_PARAMS[number];
|
|
if (!entry) {
|
|
throw new WSP.NotWellKnownEncodingError(
|
|
"Parameter-name: not well known parameter " + number);
|
|
}
|
|
|
|
return entry.name;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded object containing `name` and `value` properties or null
|
|
* in case of a failed parsing. The `name` property must be a string,
|
|
* but the `value` property can be many different types depending on
|
|
* `name`.
|
|
*/
|
|
decode: function(data) {
|
|
let name = this.decodeParameterName(data);
|
|
let value = WSP.decodeAlternatives(data, null,
|
|
WSP.ConstrainedEncoding, WSP.TextString);
|
|
return {
|
|
name: name,
|
|
value: value,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param end
|
|
* Ending offset of following parameters.
|
|
*
|
|
* @return An array of decoded objects.
|
|
*/
|
|
decodeMultiple: function(data, end) {
|
|
let params, param;
|
|
|
|
while (data.offset < end) {
|
|
try {
|
|
param = this.decode(data);
|
|
} catch (e) {
|
|
break;
|
|
}
|
|
if (param) {
|
|
if (!params) {
|
|
params = {};
|
|
}
|
|
params[param.name] = param.value;
|
|
}
|
|
}
|
|
|
|
return params;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param param
|
|
* An object containing two attributes: `name` and `value`.
|
|
* @param options
|
|
* Extra context for encoding.
|
|
*/
|
|
encode: function(data, param, options) {
|
|
if (!param || !param.name) {
|
|
throw new WSP.CodeError("Parameter-name: empty param name");
|
|
}
|
|
|
|
let entry = MMS_WELL_KNOWN_PARAMS[param.name.toLowerCase()];
|
|
if (entry) {
|
|
WSP.ShortInteger.encode(data, entry.number);
|
|
} else {
|
|
WSP.TextString.encode(data, param.name);
|
|
}
|
|
|
|
WSP.encodeAlternatives(data, param.value, options,
|
|
WSP.ConstrainedEncoding, WSP.TextString);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* The Char-set values are registered by IANA as MIBEnum value and SHALL be
|
|
* encoded as Integer-value.
|
|
*
|
|
* Encoded-string-value = Text-string | Value-length Char-set Text-string
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.19
|
|
* @see OMA-TS-MMS_CONF-V1_3-20110913-A clause 10.2.1
|
|
*/
|
|
this.EncodedStringValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return Decoded string.
|
|
*
|
|
* @throws CodeError if the raw octets cannot be converted.
|
|
* @throws NotWellKnownEncodingError if decoded well-known charset number is
|
|
* not registered or supported.
|
|
*/
|
|
decodeCharsetEncodedString: function(data) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
let charset = WSP.IntegerValue.decode(data);
|
|
let entry = WSP.WSP_WELL_KNOWN_CHARSETS[charset];
|
|
if (!entry) {
|
|
throw new WSP.NotWellKnownEncodingError(
|
|
"Charset-encoded-string: not well known charset " + charset);
|
|
}
|
|
|
|
let str;
|
|
if (entry.converter) {
|
|
// Read a possible string quote(<Octet 127>).
|
|
let begin = data.offset;
|
|
if (WSP.Octet.decode(data) != 127) {
|
|
data.offset = begin;
|
|
}
|
|
|
|
let raw = WSP.Octet.decodeMultiple(data, end - 1);
|
|
// Read NUL character.
|
|
WSP.Octet.decodeEqualTo(data, 0);
|
|
|
|
if (!raw) {
|
|
str = "";
|
|
} else {
|
|
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
|
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
|
conv.charset = entry.converter;
|
|
try {
|
|
str = conv.convertFromByteArray(raw, raw.length);
|
|
} catch (e) {
|
|
throw new WSP.CodeError("Charset-encoded-string: " + e.message);
|
|
}
|
|
}
|
|
} else {
|
|
str = WSP.TextString.decode(data);
|
|
}
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
|
|
return str;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return Decoded string.
|
|
*/
|
|
decode: function(data) {
|
|
let begin = data.offset;
|
|
try {
|
|
return WSP.TextString.decode(data);
|
|
} catch (e) {
|
|
data.offset = begin;
|
|
return this.decodeCharsetEncodedString(data);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Always encode target string with UTF-8 encoding.
|
|
*
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param str
|
|
* A string.
|
|
*/
|
|
encodeCharsetEncodedString: function(data, str) {
|
|
let conv = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
|
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
|
// `When the text string cannot be represented as us-ascii, the character
|
|
// set SHALL be encoded as utf-8(IANA MIBenum 106) which has unique byte
|
|
// ordering.` ~ OMA-TS-MMS_CONF-V1_3-20110913-A clause 10.2.1
|
|
conv.charset = "UTF-8";
|
|
|
|
let raw;
|
|
try {
|
|
raw = conv.convertToByteArray(str);
|
|
} catch (e) {
|
|
throw new WSP.CodeError("Charset-encoded-string: " + e.message);
|
|
}
|
|
|
|
let length = raw.length + 2; // Charset number and NUL character
|
|
// Prepend <Octet 127> if necessary.
|
|
if (raw[0] >= 128) {
|
|
++length;
|
|
}
|
|
|
|
WSP.ValueLength.encode(data, length);
|
|
|
|
let entry = WSP.WSP_WELL_KNOWN_CHARSETS["utf-8"];
|
|
WSP.IntegerValue.encode(data, entry.number);
|
|
|
|
if (raw[0] >= 128) {
|
|
WSP.Octet.encode(data, 127);
|
|
}
|
|
WSP.Octet.encodeMultiple(data, raw);
|
|
WSP.Octet.encode(data, 0);
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param str
|
|
* A string.
|
|
*/
|
|
encode: function(data, str) {
|
|
let begin = data.offset;
|
|
try {
|
|
// Quoted from OMA-TS-MMS-CONF-V1_3-20110913-A:
|
|
// Some of the MMS headers have been defined as "Encoded-string-value".
|
|
// The character set IANA MIBEnum value in these headers SHALL be
|
|
// encoded as Integer-value ([WAPWSP] section 8.4.2.3). The character
|
|
// set us-ascii (IANA MIBenum 3) SHALL always be accepted. If the
|
|
// character set is not specified (simple Text-string encoding) the
|
|
// character set SHALL be identified as us-ascii (lower half of ISO
|
|
// 8859-1 [ISO8859-1]). When the text string cannot be represented as
|
|
// us-ascii, the character set SHALL be encoded as utf-8 (IANA MIBenum
|
|
// 106) which has unique byte ordering.
|
|
WSP.TextString.encode(data, str, true);
|
|
} catch (e) {
|
|
data.offset = begin;
|
|
this.encodeCharsetEncodedString(data, str);
|
|
}
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Expiry-value = Value-length (Absolute-token Date-value | Relative-token Delta-seconds-value)
|
|
* Absolute-token = <Octet 128>
|
|
* Relative-token = <Octet 129>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.20
|
|
*/
|
|
this.ExpiryValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A Date object for absolute expiry or an integer for relative one.
|
|
*
|
|
* @throws CodeError if decoded token equals to neither 128 nor 129.
|
|
*/
|
|
decode: function(data) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
let token = WSP.Octet.decode(data);
|
|
if ((token != 128) && (token != 129)) {
|
|
throw new WSP.CodeError("Expiry-value: invalid token " + token);
|
|
}
|
|
|
|
let result;
|
|
if (token == 128) {
|
|
result = WSP.DateValue.decode(data);
|
|
} else {
|
|
result = WSP.DeltaSecondsValue.decode(data);
|
|
}
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param value
|
|
* A Date object for absolute expiry or an integer for relative one.
|
|
*/
|
|
encode: function(data, value) {
|
|
let isDate, begin = data.offset;
|
|
if (value instanceof Date) {
|
|
isDate = true;
|
|
WSP.DateValue.encode(data, value);
|
|
} else if (typeof value == "number") {
|
|
isDate = false;
|
|
WSP.DeltaSecondsValue.encode(data, value);
|
|
} else {
|
|
throw new CodeError("Expiry-value: invalid value type");
|
|
}
|
|
|
|
// Calculate how much octets will be written and seek back.
|
|
// TODO: use memmove, see bug 730873
|
|
let len = data.offset - begin;
|
|
data.offset = begin;
|
|
|
|
WSP.ValueLength.encode(data, len + 1);
|
|
if (isDate) {
|
|
WSP.Octet.encode(data, 128);
|
|
WSP.DateValue.encode(data, value);
|
|
} else {
|
|
WSP.Octet.encode(data, 129);
|
|
WSP.DeltaSecondsValue.encode(data, value);
|
|
}
|
|
},
|
|
};
|
|
|
|
/**
|
|
* From-value = Value-length (Address-present-token Address | Insert-address-token)
|
|
* Address-present-token = <Octet 128>
|
|
* Insert-address-token = <Octet 129>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.21
|
|
*/
|
|
this.FromValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded Address-value or null for MMS Proxy-Relay Insert-Address
|
|
* mode.
|
|
*
|
|
* @throws CodeError if decoded token equals to neither 128 nor 129.
|
|
*/
|
|
decode: function(data) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
let token = WSP.Octet.decode(data);
|
|
if ((token != 128) && (token != 129)) {
|
|
throw new WSP.CodeError("From-value: invalid token " + token);
|
|
}
|
|
|
|
let result = null;
|
|
if (token == 128) {
|
|
result = Address.decode(data);
|
|
}
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param value
|
|
* A Address-value or null for MMS Proxy-Relay Insert-Address mode.
|
|
*/
|
|
encode: function(data, value) {
|
|
if (!value) {
|
|
WSP.ValueLength.encode(data, 1);
|
|
WSP.Octet.encode(data, 129);
|
|
return;
|
|
}
|
|
|
|
// Calculate how much octets will be written and seek back.
|
|
// TODO: use memmove, see bug 730873
|
|
let begin = data.offset;
|
|
Address.encode(data, value);
|
|
let len = data.offset - begin;
|
|
data.offset = begin;
|
|
|
|
WSP.ValueLength.encode(data, len + 1);
|
|
WSP.Octet.encode(data, 128);
|
|
Address.encode(data, value);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Previously-sent-by-value = Value-length Forwarded-count-value Address
|
|
* Forwarded-count-value = Integer-value
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.23
|
|
*/
|
|
this.PreviouslySentByValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return Decoded object containing an integer `forwardedCount` and an
|
|
* string-typed `originator` attributes.
|
|
*/
|
|
decode: function(data) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
let result = {};
|
|
result.forwardedCount = WSP.IntegerValue.decode(data);
|
|
result.originator = Address.decode(data);
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Previously-sent-date-value = Value-length Forwarded-count-value Date-value
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.23
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.24
|
|
*/
|
|
this.PreviouslySentDateValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return Decoded object containing an integer `forwardedCount` and an
|
|
* Date-typed `timestamp` attributes.
|
|
*/
|
|
decode: function(data) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
let result = {};
|
|
result.forwardedCount = WSP.IntegerValue.decode(data);
|
|
result.timestamp = WSP.DateValue.decode(data);
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Message-class-value = Class-identifier | Token-text
|
|
* Class-identifier = Personal | Advertisement | Informational | Auto
|
|
* Personal = <Octet 128>
|
|
* Advertisement = <Octet 129>
|
|
* Informational = <Octet 130>
|
|
* Auto = <Octet 131>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.27
|
|
*/
|
|
this.MessageClassValue = {
|
|
WELL_KNOWN_CLASSES: ["personal", "advertisement", "informational", "auto"],
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded string.
|
|
*
|
|
* @throws CodeError if decoded value is not in the range 128..131.
|
|
*/
|
|
decodeClassIdentifier: function(data) {
|
|
let value = WSP.Octet.decode(data);
|
|
if ((value >= 128) && (value < (128 + this.WELL_KNOWN_CLASSES.length))) {
|
|
return this.WELL_KNOWN_CLASSES[value - 128];
|
|
}
|
|
|
|
throw new WSP.CodeError("Class-identifier: invalid id " + value);
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded string.
|
|
*/
|
|
decode: function(data) {
|
|
let begin = data.offset;
|
|
try {
|
|
return this.decodeClassIdentifier(data);
|
|
} catch (e) {
|
|
data.offset = begin;
|
|
return WSP.TokenText.decode(data);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param klass
|
|
*/
|
|
encode: function(data, klass) {
|
|
let index = this.WELL_KNOWN_CLASSES.indexOf(klass.toLowerCase());
|
|
if (index >= 0) {
|
|
WSP.Octet.encode(data, index + 128);
|
|
} else {
|
|
WSP.TokenText.encode(data, klass);
|
|
}
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Message-type-value = <Octet 128..151>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.30
|
|
*/
|
|
this.MessageTypeValue = new RangedValue("Message-type-value", 128, 151);
|
|
|
|
/**
|
|
* MM-flags-value = Value-length ( Add-token | Remove-token | Filter-token ) Encoded-string-value
|
|
* Add-token = <Octet 128>
|
|
* Remove-token = <Octet 129>
|
|
* Filter-token = <Octet 130>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.32
|
|
*/
|
|
this.MmFlagsValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return Decoded object containing an integer `type` and an string-typed
|
|
* `text` attributes.
|
|
*
|
|
* @throws CodeError if decoded value is not in the range 128..130.
|
|
*/
|
|
decode: function(data) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
let result = {};
|
|
result.type = WSP.Octet.decode(data);
|
|
if ((result.type < 128) || (result.type > 130)) {
|
|
throw new WSP.CodeError("MM-flags-value: invalid type " + result.type);
|
|
}
|
|
result.text = EncodedStringValue.decode(data);
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param value
|
|
* An object containing an integer `type` and an string-typed
|
|
* `text` attributes.
|
|
*/
|
|
encode: function(data, value) {
|
|
if ((value.type < 128) || (value.type > 130)) {
|
|
throw new WSP.CodeError("MM-flags-value: invalid type " + value.type);
|
|
}
|
|
|
|
// Calculate how much octets will be written and seek back.
|
|
// TODO: use memmove, see bug 730873
|
|
let begin = data.offset;
|
|
EncodedStringValue.encode(data, value.text);
|
|
let len = data.offset - begin;
|
|
data.offset = begin;
|
|
|
|
WSP.ValueLength.encode(data, len + 1);
|
|
WSP.Octet.encode(data, value.type);
|
|
EncodedStringValue.encode(data, value.text);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* MM-state-value = Draft | Sent | New | Retrieved | Forwarded
|
|
* Draft = <Octet 128>
|
|
* Sent = <Octet 129>
|
|
* New = <Octet 130>
|
|
* Retrieved = <Octet 131>
|
|
* Forwarded = <Octet 132>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.33
|
|
*/
|
|
this.MmStateValue = new RangedValue("MM-state-value", 128, 132);
|
|
|
|
/**
|
|
* Priority-value = Low | Normal | High
|
|
* Low = <Octet 128>
|
|
* Normal = <Octet 129>
|
|
* High = <Octet 130>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.35
|
|
*/
|
|
this.PriorityValue = new RangedValue("Priority-value", 128, 130);
|
|
|
|
/**
|
|
* Read-status-value = Read | Deleted without being read
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.38
|
|
*/
|
|
this.ReadStatusValue = new RangedValue("Read-status-value", 128, 129);
|
|
|
|
/**
|
|
* Recommended-Retrieval-Mode-value = Manual
|
|
* Manual = <Octet 128>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.39
|
|
*/
|
|
this.RecommendedRetrievalModeValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded integer.
|
|
*/
|
|
decode: function(data) {
|
|
return WSP.Octet.decodeEqualTo(data, 128);
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Reply-charging-value = Requested | Requested text only | Accepted |
|
|
* Accepted text only
|
|
* Requested = <Octet 128>
|
|
* Requested text only = <Octet 129>
|
|
* Accepted = <Octet 130>
|
|
* Accepted text only = <Octet 131>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.43
|
|
*/
|
|
this.ReplyChargingValue = new RangedValue("Reply-charging-value", 128, 131);
|
|
|
|
/**
|
|
* When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
|
|
*
|
|
* Response-text-value = Encoded-string-value
|
|
*
|
|
* When used in the M-Mbox-Delete.conf and M-Delete.conf PDUs:
|
|
*
|
|
* Response-text-Del-value = Value-length Status-count-value Response-text-value
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.49
|
|
*/
|
|
this.ResponseText = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param options
|
|
* Extra context for decoding.
|
|
*
|
|
* @return An object containing a string-typed `text` attribute and a
|
|
* integer-typed `statusCount` one.
|
|
*/
|
|
decode: function(data, options) {
|
|
let type = WSP.ensureHeader(options, "x-mms-message-type");
|
|
|
|
let result = {};
|
|
if ((type == MMS_PDU_TYPE_MBOX_DELETE_CONF)
|
|
|| (type == MMS_PDU_TYPE_DELETE_CONF)) {
|
|
let length = WSP.ValueLength.decode(data);
|
|
let end = data.offset + length;
|
|
|
|
result.statusCount = WSP.IntegerValue.decode(data);
|
|
result.text = EncodedStringValue.decode(data);
|
|
|
|
if (data.offset != end) {
|
|
data.offset = end;
|
|
}
|
|
} else {
|
|
result.text = EncodedStringValue.decode(data);
|
|
}
|
|
|
|
return result;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Retrieve-status-value = Ok | Error-transient-failure |
|
|
* Error-transient-message-not-found |
|
|
* Error-transient-network-problem |
|
|
* Error-permanent-failure |
|
|
* Error-permanent-service-denied |
|
|
* Error-permanent-message-not-found |
|
|
* Error-permanent-content-unsupported
|
|
* Ok = <Octet 128>
|
|
* Error-transient-failure = <Octet 192>
|
|
* Error-transient-message-not-found = <Octet 193>
|
|
* Error-transient-network-problem = <Octet 194>
|
|
* Error-permanent-failure = <Octet 224>
|
|
* Error-permanent-service-denied = <Octet 225>
|
|
* Error-permanent-message-not-found = <Octet 226>
|
|
* Error-permanent-content-unsupported = <Octet 227>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.50
|
|
*/
|
|
this.RetrieveStatusValue = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
*
|
|
* @return A decoded integer.
|
|
*/
|
|
decode: function(data) {
|
|
let value = WSP.Octet.decode(data);
|
|
if (value == MMS_PDU_ERROR_OK) {
|
|
return value;
|
|
}
|
|
|
|
if ((value >= MMS_PDU_ERROR_TRANSIENT_FAILURE) && (value < 256)) {
|
|
return value;
|
|
}
|
|
|
|
// Any other values SHALL NOT be used. They are reserved for future use.
|
|
// An MMS Client that receives such a reserved value MUST react the same
|
|
// as it does to the value 224 (Error-permanent-failure).
|
|
return MMS_PDU_ERROR_PERMANENT_FAILURE;
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Sender-visibility-value = Hide | Show
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.52
|
|
*/
|
|
this.SenderVisibilityValue = new RangedValue("Sender-visibility-value", 128, 129);
|
|
|
|
/**
|
|
* Status-value = Expired | Retrieved | Rejected | Deferred | Unrecognised |
|
|
* Indeterminate | Forwarded | Unreachable
|
|
* Expired = <Octet 128>
|
|
* Retrieved = <Octet 129>
|
|
* Rejected = <Octet 130>
|
|
* Deferred = <Octet 131>
|
|
* Unrecognised = <Octet 132>
|
|
* Indeterminate = <Octet 133>
|
|
* Forwarded = <Octet 134>
|
|
* Unreachable = <Octet 135>
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.3.54
|
|
*/
|
|
this.StatusValue = new RangedValue("Status-value", 128, 135);
|
|
|
|
this.PduHelper = {
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param headers
|
|
* An optional object to store parsed header fields. Created
|
|
* automatically if undefined.
|
|
*
|
|
* @return A boolean value indicating whether it's followed by message body.
|
|
*/
|
|
parseHeaders: function(data, headers) {
|
|
if (!headers) {
|
|
headers = {};
|
|
}
|
|
|
|
let header;
|
|
while (data.offset < data.array.length) {
|
|
// There is no `header length` information in MMS PDU. If we just got
|
|
// something wrong in parsing header fields, we might not be able to
|
|
// determine the correct header-content boundary.
|
|
header = HeaderField.decode(data, headers);
|
|
|
|
if (header) {
|
|
let orig = headers[header.name];
|
|
if (Array.isArray(orig)) {
|
|
headers[header.name].push(header.value);
|
|
} else if (orig) {
|
|
headers[header.name] = [orig, header.value];
|
|
} else {
|
|
headers[header.name] = header.value;
|
|
}
|
|
if (header.name == "content-type") {
|
|
// `... if the PDU contains a message body the Content Type MUST be
|
|
// the last header field, followed by message body.` See
|
|
// OMA-TS-MMS_ENC-V1_3-20110913-A section 7.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return headers;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param msg
|
|
* A message object to store decoded multipart or octet array content.
|
|
*/
|
|
parseContent: function(data, msg) {
|
|
let contentType = msg.headers["content-type"].media;
|
|
if ((contentType == "application/vnd.wap.multipart.related")
|
|
|| (contentType == "application/vnd.wap.multipart.mixed")) {
|
|
msg.parts = WSP.PduHelper.parseMultiPart(data);
|
|
return;
|
|
}
|
|
|
|
if (data.offset >= data.array.length) {
|
|
return;
|
|
}
|
|
|
|
msg.content = WSP.Octet.decodeMultiple(data, data.array.length);
|
|
if (false) {
|
|
for (let begin = 0; begin < msg.content.length; begin += 20) {
|
|
debug("content: " + JSON.stringify(msg.content.subarray(begin, begin + 20)));
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Check existences of all mandatory fields of a MMS message. Also sets `type`
|
|
* for convenient access.
|
|
*
|
|
* @param msg
|
|
* A MMS message object.
|
|
*
|
|
* @return The corresponding entry in MMS_PDU_TYPES;
|
|
*
|
|
* @throws FatalCodeError if the PDU type is not supported yet.
|
|
*/
|
|
checkMandatoryFields: function(msg) {
|
|
let type = WSP.ensureHeader(msg.headers, "x-mms-message-type");
|
|
let entry = MMS_PDU_TYPES[type];
|
|
if (!entry) {
|
|
throw new WSP.FatalCodeError(
|
|
"checkMandatoryFields: unsupported message type " + type);
|
|
}
|
|
|
|
entry.mandatoryFields.forEach(function(name) {
|
|
WSP.ensureHeader(msg.headers, name);
|
|
});
|
|
|
|
// Setup convenient alias that referenced frequently.
|
|
msg.type = type;
|
|
|
|
return entry;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object containing raw PDU data.
|
|
* @param msg [optional]
|
|
* Optional target object for decoding.
|
|
*
|
|
* @return A MMS message object or null in case of errors found.
|
|
*/
|
|
parse: function(data, msg) {
|
|
if (!msg) {
|
|
msg = {};
|
|
}
|
|
|
|
try {
|
|
msg.headers = this.parseHeaders(data, msg.headers);
|
|
|
|
// Validity checks
|
|
let typeinfo = this.checkMandatoryFields(msg);
|
|
if (typeinfo.hasContent) {
|
|
this.parseContent(data, msg);
|
|
}
|
|
} catch (e) {
|
|
debug("Failed to parse MMS message, error message: " + e.message);
|
|
return null;
|
|
}
|
|
|
|
return msg;
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param headers
|
|
* A dictionary object containing multiple name/value mapping.
|
|
* @param name
|
|
* Name of the header field to be encoded.
|
|
*/
|
|
encodeHeader: function(data, headers, name) {
|
|
let value = headers[name];
|
|
if (Array.isArray(value)) {
|
|
for (let i = 0; i < value.length; i++) {
|
|
HeaderField.encode(data, {name: name, value: value[i]}, headers);
|
|
}
|
|
} else {
|
|
HeaderField.encode(data, {name: name, value: value}, headers);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @param data
|
|
* A wrapped object to store encoded raw data.
|
|
* @param headers
|
|
* A dictionary object containing multiple name/value mapping.
|
|
*/
|
|
encodeHeaderIfExists: function(data, headers, name) {
|
|
// Header value could be zero or null.
|
|
if (headers[name] !== undefined) {
|
|
this.encodeHeader(data, headers, name);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @param data [optional]
|
|
* A wrapped object to store encoded raw data. Created if undefined.
|
|
* @param headers
|
|
* A dictionary object containing multiple name/value mapping.
|
|
*
|
|
* @return the passed data parameter or a created one.
|
|
*/
|
|
encodeHeaders: function(data, headers) {
|
|
if (!data) {
|
|
data = {array: [], offset: 0};
|
|
}
|
|
|
|
// `In the encoding of the header fields, the order of the fields is not
|
|
// significant, except that X-Mms-Message-Type, X-Mms-Transaction-ID (when
|
|
// present) and X-Mms-MMS-Version MUST be at the beginning of the message
|
|
// headers, in that order, and if the PDU contains a message body the
|
|
// Content Type MUST be the last header field, followed by message body.`
|
|
// ~ OMA-TS-MMS_ENC-V1_3-20110913-A section 7
|
|
this.encodeHeader(data, headers, "x-mms-message-type");
|
|
this.encodeHeaderIfExists(data, headers, "x-mms-transaction-id");
|
|
this.encodeHeaderIfExists(data, headers, "x-mms-mms-version");
|
|
|
|
for (let key in headers) {
|
|
if ((key == "x-mms-message-type")
|
|
|| (key == "x-mms-transaction-id")
|
|
|| (key == "x-mms-mms-version")
|
|
|| (key == "content-type")) {
|
|
continue;
|
|
}
|
|
this.encodeHeader(data, headers, key);
|
|
}
|
|
|
|
this.encodeHeaderIfExists(data, headers, "content-type");
|
|
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* @param multiStream
|
|
* An exsiting nsIMultiplexInputStream.
|
|
* @param msg
|
|
* A MMS message object.
|
|
*
|
|
* @return An instance of nsIMultiplexInputStream or null in case of errors.
|
|
*/
|
|
compose: function(multiStream, msg) {
|
|
if (!multiStream) {
|
|
multiStream = Cc["@mozilla.org/io/multiplex-input-stream;1"]
|
|
.createInstance(Ci.nsIMultiplexInputStream);
|
|
}
|
|
|
|
try {
|
|
// Validity checks
|
|
let typeinfo = this.checkMandatoryFields(msg);
|
|
|
|
let data = this.encodeHeaders(null, msg.headers);
|
|
debug("Composed PDU Header: " + JSON.stringify(data.array));
|
|
WSP.PduHelper.appendArrayToMultiStream(multiStream, data.array, data.offset);
|
|
|
|
if (msg.content) {
|
|
WSP.PduHelper.appendArrayToMultiStream(multiStream, msg.content, msg.content.length);
|
|
} else if (msg.parts) {
|
|
WSP.PduHelper.composeMultiPart(multiStream, msg.parts);
|
|
} else if (typeinfo.hasContent) {
|
|
throw new WSP.CodeError("Missing message content");
|
|
}
|
|
|
|
return multiStream;
|
|
} catch (e) {
|
|
debug("Failed to compose MMS message, error message: " + e.message);
|
|
return null;
|
|
}
|
|
},
|
|
};
|
|
|
|
const MMS_PDU_TYPES = (function() {
|
|
let pdus = {};
|
|
function add(number, hasContent, mandatoryFields) {
|
|
pdus[number] = {
|
|
number: number,
|
|
hasContent: hasContent,
|
|
mandatoryFields: mandatoryFields,
|
|
};
|
|
}
|
|
|
|
add(MMS_PDU_TYPE_SEND_REQ, true, ["x-mms-message-type",
|
|
"x-mms-transaction-id",
|
|
"x-mms-mms-version",
|
|
"from",
|
|
"content-type"]);
|
|
add(MMS_PDU_TYPE_SEND_CONF, false, ["x-mms-message-type",
|
|
"x-mms-transaction-id",
|
|
"x-mms-mms-version",
|
|
"x-mms-response-status"]);
|
|
add(MMS_PDU_TYPE_NOTIFICATION_IND, false, ["x-mms-message-type",
|
|
"x-mms-transaction-id",
|
|
"x-mms-mms-version",
|
|
"x-mms-message-class",
|
|
"x-mms-message-size",
|
|
"x-mms-expiry",
|
|
"x-mms-content-location"]);
|
|
add(MMS_PDU_TYPE_RETRIEVE_CONF, true, ["x-mms-message-type",
|
|
"x-mms-mms-version",
|
|
"date",
|
|
"content-type"]);
|
|
add(MMS_PDU_TYPE_NOTIFYRESP_IND, false, ["x-mms-message-type",
|
|
"x-mms-transaction-id",
|
|
"x-mms-mms-version",
|
|
"x-mms-status"]);
|
|
add(MMS_PDU_TYPE_DELIVERY_IND, false, ["x-mms-message-type",
|
|
"x-mms-mms-version",
|
|
"message-id",
|
|
"to",
|
|
"date",
|
|
"x-mms-status"]);
|
|
add(MMS_PDU_TYPE_ACKNOWLEDGE_IND, false, ["x-mms-message-type",
|
|
"x-mms-transaction-id",
|
|
"x-mms-mms-version"]);
|
|
add(MMS_PDU_TYPE_READ_REC_IND, false, ["x-mms-message-type",
|
|
"message-id",
|
|
"x-mms-mms-version",
|
|
"to",
|
|
"from",
|
|
"x-mms-read-status"]);
|
|
add(MMS_PDU_TYPE_READ_ORIG_IND, false, ["x-mms-message-type",
|
|
"x-mms-mms-version",
|
|
"message-id",
|
|
"to",
|
|
"from",
|
|
"date",
|
|
"x-mms-read-status"]);
|
|
|
|
return pdus;
|
|
})();
|
|
|
|
/**
|
|
* Header field names and assigned numbers.
|
|
*
|
|
* @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.4
|
|
*/
|
|
const MMS_HEADER_FIELDS = (function() {
|
|
let names = {};
|
|
function add(name, number, coder) {
|
|
let entry = {
|
|
name: name,
|
|
number: number,
|
|
coder: coder,
|
|
};
|
|
names[name] = names[number] = entry;
|
|
}
|
|
|
|
add("bcc", 0x01, Address);
|
|
add("cc", 0x02, Address);
|
|
add("x-mms-content-location", 0x03, ContentLocationValue);
|
|
add("content-type", 0x04, WSP.ContentTypeValue);
|
|
add("date", 0x05, WSP.DateValue);
|
|
add("x-mms-delivery-report", 0x06, BooleanValue);
|
|
add("x-mms-delivery-time", 0x07, ExpiryValue);
|
|
add("x-mms-expiry", 0x08, ExpiryValue);
|
|
add("from", 0x09, FromValue);
|
|
add("x-mms-message-class", 0x0A, MessageClassValue);
|
|
add("message-id", 0x0B, WSP.TextString);
|
|
add("x-mms-message-type", 0x0C, MessageTypeValue);
|
|
add("x-mms-mms-version", 0x0D, WSP.ShortInteger);
|
|
add("x-mms-message-size", 0x0E, WSP.LongInteger);
|
|
add("x-mms-priority", 0x0F, PriorityValue);
|
|
add("x-mms-read-report", 0x10, BooleanValue);
|
|
add("x-mms-report-allowed", 0x11, BooleanValue);
|
|
add("x-mms-response-status", 0x12, RetrieveStatusValue);
|
|
add("x-mms-response-text", 0x13, ResponseText);
|
|
add("x-mms-sender-visibility", 0x14, SenderVisibilityValue);
|
|
add("x-mms-status", 0x15, StatusValue);
|
|
add("subject", 0x16, EncodedStringValue);
|
|
add("to", 0x17, Address);
|
|
add("x-mms-transaction-id", 0x18, WSP.TextString);
|
|
add("x-mms-retrieve-status", 0x19, RetrieveStatusValue);
|
|
add("x-mms-retrieve-text", 0x1A, EncodedStringValue);
|
|
add("x-mms-read-status", 0x1B, ReadStatusValue);
|
|
add("x-mms-reply-charging", 0x1C, ReplyChargingValue);
|
|
add("x-mms-reply-charging-deadline", 0x1D, ExpiryValue);
|
|
add("x-mms-reply-charging-id", 0x1E, WSP.TextString);
|
|
add("x-mms-reply-charging-size", 0x1F, WSP.LongInteger);
|
|
add("x-mms-previously-sent-by", 0x20, PreviouslySentByValue);
|
|
add("x-mms-previously-sent-date", 0x21, PreviouslySentDateValue);
|
|
add("x-mms-store", 0x22, BooleanValue);
|
|
add("x-mms-mm-state", 0x23, MmStateValue);
|
|
add("x-mms-mm-flags", 0x24, MmFlagsValue);
|
|
add("x-mms-store-status", 0x25, RetrieveStatusValue);
|
|
add("x-mms-store-status-text", 0x26, EncodedStringValue);
|
|
add("x-mms-stored", 0x27, BooleanValue);
|
|
//add("x-mms-attributes", 0x28);
|
|
add("x-mms-totals", 0x29, BooleanValue);
|
|
//add("x-mms-mbox-totals", 0x2A);
|
|
add("x-mms-quotas", 0x2B, BooleanValue);
|
|
//add("x-mms-mbox-quotas", 0x2C);
|
|
add("x-mms-message-count", 0x2D, WSP.IntegerValue);
|
|
//add("content", 0x2E);
|
|
add("x-mms-start", 0x2F, WSP.IntegerValue);
|
|
//add("additional-headers", 0x30);
|
|
add("x-mms-distribution-indicator", 0x31, BooleanValue);
|
|
add("x-mms-element-descriptor", 0x32, ElementDescriptorValue);
|
|
add("x-mms-limit", 0x33, WSP.IntegerValue);
|
|
add("x-mms-recommended-retrieval-mode", 0x34, RecommendedRetrievalModeValue);
|
|
add("x-mms-recommended-retrieval-mode-text", 0x35, EncodedStringValue);
|
|
//add("x-mms-status-text", 0x36);
|
|
add("x-mms-applic-id", 0x37, WSP.TextString);
|
|
add("x-mms-reply-applic-id", 0x38, WSP.TextString);
|
|
add("x-mms-aux-applic-id", 0x39, WSP.TextString);
|
|
add("x-mms-content-class", 0x3A, ContentClassValue);
|
|
add("x-mms-drm-content", 0x3B, BooleanValue);
|
|
add("x-mms-adaptation-allowed", 0x3C, BooleanValue);
|
|
add("x-mms-replace-id", 0x3D, WSP.TextString);
|
|
add("x-mms-cancel-id", 0x3E, WSP.TextString);
|
|
add("x-mms-cancel-status", 0x3F, CancelStatusValue);
|
|
|
|
return names;
|
|
})();
|
|
|
|
// @see OMA-TS-MMS_ENC-V1_3-20110913-A Table 27: Parameter Name Assignments
|
|
const MMS_WELL_KNOWN_PARAMS = (function() {
|
|
let params = {};
|
|
|
|
function add(name, number, coder) {
|
|
let entry = {
|
|
name: name,
|
|
number: number,
|
|
coder: coder,
|
|
};
|
|
params[name] = params[number] = entry;
|
|
}
|
|
|
|
// Encoding Version: 1.2
|
|
add("type", 0x02, WSP.TypeValue);
|
|
|
|
return params;
|
|
})();
|
|
|
|
var debug;
|
|
if (DEBUG) {
|
|
debug = function(s) {
|
|
dump("-$- MmsPduHelper: " + s + "\n");
|
|
};
|
|
} else {
|
|
debug = function(s) {};
|
|
}
|
|
|
|
this.EXPORTED_SYMBOLS = ALL_CONST_SYMBOLS.concat([
|
|
// Constant values
|
|
"MMS_VERSION",
|
|
|
|
// Utility functions
|
|
"translatePduErrorToStatus",
|
|
|
|
// Decoders
|
|
"BooleanValue",
|
|
"Address",
|
|
"HeaderField",
|
|
"MmsHeader",
|
|
"CancelStatusValue",
|
|
"ContentClassValue",
|
|
"ContentLocationValue",
|
|
"ElementDescriptorValue",
|
|
"Parameter",
|
|
"EncodedStringValue",
|
|
"ExpiryValue",
|
|
"FromValue",
|
|
"PreviouslySentByValue",
|
|
"PreviouslySentDateValue",
|
|
"MessageClassValue",
|
|
"MessageTypeValue",
|
|
"MmFlagsValue",
|
|
"MmStateValue",
|
|
"PriorityValue",
|
|
"ReadStatusValue",
|
|
"RecommendedRetrievalModeValue",
|
|
"ReplyChargingValue",
|
|
"ResponseText",
|
|
"RetrieveStatusValue",
|
|
"SenderVisibilityValue",
|
|
"StatusValue",
|
|
|
|
// Parser
|
|
"PduHelper",
|
|
]);
|
|
|