strophe.js
Version:
Strophe.js is an XMPP library for JavaScript
1,670 lines (1,431 loc) • 205 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var abab = require('abab');
var global$1 = typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
function _typeof(obj) {
"@babel/helpers - typeof";
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}
function _iterableToArray(iter) {
if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
/*
* This module provides uniform
* Shims APIs and globals that are not present in all JS environments,
* the most common example for Strophe being browser APIs like WebSocket
* and DOM that don't exist under nodejs.
*
* Usually these will be supplied in nodejs by conditionally requiring a
* NPM module that provides a compatible implementation.
*/
/* global global */
/**
* WHATWG WebSockets API
* https://www.w3.org/TR/websockets/
*
* Interface to use the web socket protocol
*
* Used implementations:
* - supported browsers: built-in in WebSocket global
* https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Browser_compatibility
* - nodejs: use standard-compliant 'ws' module
* https://www.npmjs.com/package/ws
*/
function getWebSocketImplementation() {
var WebSocketImplementation = global$1.WebSocket;
if (typeof WebSocketImplementation === 'undefined') {
try {
WebSocketImplementation = require('ws');
} catch (err) {
throw new Error('You must install the "ws" package to use Strophe in nodejs.');
}
}
return WebSocketImplementation;
}
var WebSocket = getWebSocketImplementation();
/**
* DOMParser
* https://w3c.github.io/DOM-Parsing/#the-domparser-interface
*
* Interface to parse XML strings into Document objects
*
* Used implementations:
* - supported browsers: built-in in DOMParser global
* https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Browser_compatibility
* - nodejs: use 'xmldom' module
* https://www.npmjs.com/package/xmldom
*/
function getDOMParserImplementation() {
var DOMParserImplementation = global$1.DOMParser;
if (typeof DOMParserImplementation === 'undefined') {
try {
DOMParserImplementation = require('xmldom').DOMParser;
} catch (err) {
throw new Error('You must install the "xmldom" package to use Strophe in nodejs.');
}
}
return DOMParserImplementation;
}
var DOMParser = getDOMParserImplementation();
/**
* Gets IE xml doc object. Used by getDummyXMLDocument shim.
*
* Returns:
* A Microsoft XML DOM Object
* See Also:
* http://msdn.microsoft.com/en-us/library/ms757837%28VS.85%29.aspx
*/
function _getIEXmlDom() {
var docStrings = ["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"];
for (var d = 0; d < docStrings.length; d++) {
try {
// eslint-disable-next-line no-undef
var doc = new ActiveXObject(docStrings[d]);
return doc;
} catch (e) {// Try next one
}
}
}
/**
* Creates a dummy XML DOM document to serve as an element and text node generator.
*
* Used implementations:
* - IE < 10: avoid using createDocument() due to a memory leak, use ie-specific
* workaround
* - other supported browsers: use document's createDocument
* - nodejs: use 'xmldom'
*/
function getDummyXMLDOMDocument() {
// nodejs
if (typeof document === 'undefined') {
try {
var DOMImplementation = require('xmldom').DOMImplementation;
return new DOMImplementation().createDocument('jabber:client', 'strophe', null);
} catch (err) {
throw new Error('You must install the "xmldom" package to use Strophe in nodejs.');
}
} // IE < 10
if (document.implementation.createDocument === undefined || document.implementation.createDocument && document.documentMode && document.documentMode < 10) {
var doc = _getIEXmlDom();
doc.appendChild(doc.createElement('strophe'));
return doc;
} // All other supported browsers
return document.implementation.createDocument('jabber:client', 'strophe', null);
}
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Everything that isn't used by Strophe has been stripped here!
*/
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
var safe_add = function safe_add(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return msw << 16 | lsw & 0xFFFF;
};
/*
* Bitwise rotate a 32-bit number to the left.
*/
var bit_rol = function bit_rol(num, cnt) {
return num << cnt | num >>> 32 - cnt;
};
/*
* Convert a string to an array of little-endian words
*/
var str2binl = function str2binl(str) {
if (typeof str !== "string") {
throw new Error("str2binl was passed a non-string");
}
var bin = [];
for (var i = 0; i < str.length * 8; i += 8) {
bin[i >> 5] |= (str.charCodeAt(i / 8) & 255) << i % 32;
}
return bin;
};
/*
* Convert an array of little-endian words to a string
*/
var binl2str = function binl2str(bin) {
var str = "";
for (var i = 0; i < bin.length * 32; i += 8) {
str += String.fromCharCode(bin[i >> 5] >>> i % 32 & 255);
}
return str;
};
/*
* Convert an array of little-endian words to a hex string.
*/
var binl2hex = function binl2hex(binarray) {
var hex_tab = "0123456789abcdef";
var str = "";
for (var i = 0; i < binarray.length * 4; i++) {
str += hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 + 4 & 0xF) + hex_tab.charAt(binarray[i >> 2] >> i % 4 * 8 & 0xF);
}
return str;
};
/*
* These functions implement the four basic operations the algorithm uses.
*/
var md5_cmn = function md5_cmn(q, a, b, x, s, t) {
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
};
var md5_ff = function md5_ff(a, b, c, d, x, s, t) {
return md5_cmn(b & c | ~b & d, a, b, x, s, t);
};
var md5_gg = function md5_gg(a, b, c, d, x, s, t) {
return md5_cmn(b & d | c & ~d, a, b, x, s, t);
};
var md5_hh = function md5_hh(a, b, c, d, x, s, t) {
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
};
var md5_ii = function md5_ii(a, b, c, d, x, s, t) {
return md5_cmn(c ^ (b | ~d), a, b, x, s, t);
};
/*
* Calculate the MD5 of an array of little-endian words, and a bit length
*/
var core_md5 = function core_md5(x, len) {
/* append padding */
x[len >> 5] |= 0x80 << len % 32;
x[(len + 64 >>> 9 << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var olda, oldb, oldc, oldd;
for (var i = 0; i < x.length; i += 16) {
olda = a;
oldb = b;
oldc = c;
oldd = d;
a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return [a, b, c, d];
};
/*
* These are the functions you'll usually want to call.
* They take string arguments and return either hex or base-64 encoded
* strings.
*/
var MD5 = {
hexdigest: function hexdigest(s) {
return binl2hex(core_md5(str2binl(s), s.length * 8));
},
hash: function hash(s) {
return binl2str(core_md5(str2binl(s), s.length * 8));
}
};
/** Class: Strophe.SASLMechanism
*
* Encapsulates an SASL authentication mechanism.
*
* User code may override the priority for each mechanism or disable it completely.
* See <priority> for information about changing priority and <test> for informatian on
* how to disable a mechanism.
*
* By default, all mechanisms are enabled and the priorities are
*
* SCRAM-SHA-1 - 60
* PLAIN - 50
* OAUTHBEARER - 40
* X-OAUTH2 - 30
* ANONYMOUS - 20
* EXTERNAL - 10
*
* See: Strophe.Connection.addSupportedSASLMechanisms
*/
var SASLMechanism = /*#__PURE__*/function () {
/**
* PrivateConstructor: Strophe.SASLMechanism
* SASL auth mechanism abstraction.
*
* Parameters:
* (String) name - SASL Mechanism name.
* (Boolean) isClientFirst - If client should send response first without challenge.
* (Number) priority - Priority.
*
* Returns:
* A new Strophe.SASLMechanism object.
*/
function SASLMechanism(name, isClientFirst, priority) {
_classCallCheck(this, SASLMechanism);
/** PrivateVariable: mechname
* Mechanism name.
*/
this.mechname = name;
/** PrivateVariable: isClientFirst
* If client sends response without initial server challenge.
*/
this.isClientFirst = isClientFirst;
/** Variable: priority
* Determines which <SASLMechanism> is chosen for authentication (Higher is better).
* Users may override this to prioritize mechanisms differently.
*
* Example: (This will cause Strophe to choose the mechanism that the server sent first)
*
* > Strophe.SASLPlain.priority = Strophe.SASLSHA1.priority;
*
* See <SASL mechanisms> for a list of available mechanisms.
*
*/
this.priority = priority;
}
/**
* Function: test
* Checks if mechanism able to run.
* To disable a mechanism, make this return false;
*
* To disable plain authentication run
* > Strophe.SASLPlain.test = function() {
* > return false;
* > }
*
* See <SASL mechanisms> for a list of available mechanisms.
*
* Parameters:
* (Strophe.Connection) connection - Target Connection.
*
* Returns:
* (Boolean) If mechanism was able to run.
*/
_createClass(SASLMechanism, [{
key: "test",
value: function test() {
// eslint-disable-line class-methods-use-this
return true;
}
/** PrivateFunction: onStart
* Called before starting mechanism on some connection.
*
* Parameters:
* (Strophe.Connection) connection - Target Connection.
*/
}, {
key: "onStart",
value: function onStart(connection) {
this._connection = connection;
}
/** PrivateFunction: onChallenge
* Called by protocol implementation on incoming challenge.
*
* By deafult, if the client is expected to send data first (isClientFirst === true),
* this method is called with `challenge` as null on the first call,
* unless `clientChallenge` is overridden in the relevant subclass.
*
* Parameters:
* (Strophe.Connection) connection - Target Connection.
* (String) challenge - current challenge to handle.
*
* Returns:
* (String) Mechanism response.
*/
}, {
key: "onChallenge",
value: function onChallenge(connection, challenge) {
// eslint-disable-line
throw new Error("You should implement challenge handling!");
}
/** PrivateFunction: clientChallenge
* Called by the protocol implementation if the client is expected to send
* data first in the authentication exchange (i.e. isClientFirst === true).
*
* Parameters:
* (Strophe.Connection) connection - Target Connection.
*
* Returns:
* (String) Mechanism response.
*/
}, {
key: "clientChallenge",
value: function clientChallenge(connection) {
if (!this.isClientFirst) {
throw new Error("clientChallenge should not be called if isClientFirst is false!");
}
return this.onChallenge(connection);
}
/** PrivateFunction: onFailure
* Protocol informs mechanism implementation about SASL failure.
*/
}, {
key: "onFailure",
value: function onFailure() {
this._connection = null;
}
/** PrivateFunction: onSuccess
* Protocol informs mechanism implementation about SASL success.
*/
}, {
key: "onSuccess",
value: function onSuccess() {
this._connection = null;
}
}]);
return SASLMechanism;
}();
var SASLAnonymous = /*#__PURE__*/function (_SASLMechanism) {
_inherits(SASLAnonymous, _SASLMechanism);
var _super = _createSuper(SASLAnonymous);
/** PrivateConstructor: SASLAnonymous
* SASL ANONYMOUS authentication.
*/
function SASLAnonymous() {
var mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'ANONYMOUS';
var isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 20;
_classCallCheck(this, SASLAnonymous);
return _super.call(this, mechname, isClientFirst, priority);
}
_createClass(SASLAnonymous, [{
key: "test",
value: function test(connection) {
// eslint-disable-line class-methods-use-this
return connection.authcid === null;
}
}]);
return SASLAnonymous;
}(SASLMechanism);
var SASLExternal = /*#__PURE__*/function (_SASLMechanism) {
_inherits(SASLExternal, _SASLMechanism);
var _super = _createSuper(SASLExternal);
/** PrivateConstructor: SASLExternal
* SASL EXTERNAL authentication.
*
* The EXTERNAL mechanism allows a client to request the server to use
* credentials established by means external to the mechanism to
* authenticate the client. The external means may be, for instance,
* TLS services.
*/
function SASLExternal() {
var mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'EXTERNAL';
var isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;
_classCallCheck(this, SASLExternal);
return _super.call(this, mechname, isClientFirst, priority);
}
_createClass(SASLExternal, [{
key: "onChallenge",
value: function onChallenge(connection) {
// eslint-disable-line class-methods-use-this
/** According to XEP-178, an authzid SHOULD NOT be presented when the
* authcid contained or implied in the client certificate is the JID (i.e.
* authzid) with which the user wants to log in as.
*
* To NOT send the authzid, the user should therefore set the authcid equal
* to the JID when instantiating a new Strophe.Connection object.
*/
return connection.authcid === connection.authzid ? '' : connection.authzid;
}
}]);
return SASLExternal;
}(SASLMechanism);
var utils = {
utf16to8: function utf16to8(str) {
var i, c;
var out = "";
var len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if (c >= 0x0000 && c <= 0x007F) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | c >> 12 & 0x0F);
out += String.fromCharCode(0x80 | c >> 6 & 0x3F);
out += String.fromCharCode(0x80 | c >> 0 & 0x3F);
} else {
out += String.fromCharCode(0xC0 | c >> 6 & 0x1F);
out += String.fromCharCode(0x80 | c >> 0 & 0x3F);
}
}
return out;
},
addCookies: function addCookies(cookies) {
/* Parameters:
* (Object) cookies - either a map of cookie names
* to string values or to maps of cookie values.
*
* For example:
* { "myCookie": "1234" }
*
* or:
* { "myCookie": {
* "value": "1234",
* "domain": ".example.org",
* "path": "/",
* "expires": expirationDate
* }
* }
*
* These values get passed to Strophe.Connection via
* options.cookies
*/
cookies = cookies || {};
for (var cookieName in cookies) {
if (Object.prototype.hasOwnProperty.call(cookies, cookieName)) {
var expires = '';
var domain = '';
var path = '';
var cookieObj = cookies[cookieName];
var isObj = _typeof(cookieObj) === "object";
var cookieValue = escape(unescape(isObj ? cookieObj.value : cookieObj));
if (isObj) {
expires = cookieObj.expires ? ";expires=" + cookieObj.expires : '';
domain = cookieObj.domain ? ";domain=" + cookieObj.domain : '';
path = cookieObj.path ? ";path=" + cookieObj.path : '';
}
document.cookie = cookieName + '=' + cookieValue + expires + domain + path;
}
}
}
};
var SASLOAuthBearer = /*#__PURE__*/function (_SASLMechanism) {
_inherits(SASLOAuthBearer, _SASLMechanism);
var _super = _createSuper(SASLOAuthBearer);
/** PrivateConstructor: SASLOAuthBearer
* SASL OAuth Bearer authentication.
*/
function SASLOAuthBearer() {
var mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'OAUTHBEARER';
var isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 40;
_classCallCheck(this, SASLOAuthBearer);
return _super.call(this, mechname, isClientFirst, priority);
}
_createClass(SASLOAuthBearer, [{
key: "test",
value: function test(connection) {
// eslint-disable-line class-methods-use-this
return connection.pass !== null;
}
}, {
key: "onChallenge",
value: function onChallenge(connection) {
// eslint-disable-line class-methods-use-this
var auth_str = 'n,';
if (connection.authcid !== null) {
auth_str = auth_str + 'a=' + connection.authzid;
}
auth_str = auth_str + ',';
auth_str = auth_str + "\x01";
auth_str = auth_str + 'auth=Bearer ';
auth_str = auth_str + connection.pass;
auth_str = auth_str + "\x01";
auth_str = auth_str + "\x01";
return utils.utf16to8(auth_str);
}
}]);
return SASLOAuthBearer;
}(SASLMechanism);
var SASLPlain = /*#__PURE__*/function (_SASLMechanism) {
_inherits(SASLPlain, _SASLMechanism);
var _super = _createSuper(SASLPlain);
/** PrivateConstructor: SASLPlain
* SASL PLAIN authentication.
*/
function SASLPlain() {
var mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'PLAIN';
var isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 50;
_classCallCheck(this, SASLPlain);
return _super.call(this, mechname, isClientFirst, priority);
}
_createClass(SASLPlain, [{
key: "test",
value: function test(connection) {
// eslint-disable-line class-methods-use-this
return connection.authcid !== null;
}
}, {
key: "onChallenge",
value: function onChallenge(connection) {
// eslint-disable-line class-methods-use-this
var authcid = connection.authcid,
authzid = connection.authzid,
domain = connection.domain,
pass = connection.pass;
if (!domain) {
throw new Error("SASLPlain onChallenge: domain is not defined!");
} // Only include authzid if it differs from authcid.
// See: https://tools.ietf.org/html/rfc6120#section-6.3.8
var auth_str = authzid !== "".concat(authcid, "@").concat(domain) ? authzid : '';
auth_str = auth_str + "\0";
auth_str = auth_str + authcid;
auth_str = auth_str + "\0";
auth_str = auth_str + pass;
return utils.utf16to8(auth_str);
}
}]);
return SASLPlain;
}(SASLMechanism);
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
/* global define */
/* Some functions and variables have been stripped for use with Strophe */
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len) {
/* append padding */
x[len >> 5] |= 0x80 << 24 - len % 32;
x[(len + 64 >> 9 << 4) + 15] = len;
var w = new Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
var i, j, t, olda, oldb, oldc, oldd, olde;
for (i = 0; i < x.length; i += 16) {
olda = a;
oldb = b;
oldc = c;
oldd = d;
olde = e;
for (j = 0; j < 80; j++) {
if (j < 16) {
w[j] = x[i + j];
} else {
w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
}
t = safe_add$1(safe_add$1(rol(a, 5), sha1_ft(j, b, c, d)), safe_add$1(safe_add$1(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add$1(a, olda);
b = safe_add$1(b, oldb);
c = safe_add$1(c, oldc);
d = safe_add$1(d, oldd);
e = safe_add$1(e, olde);
}
return [a, b, c, d, e];
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d) {
if (t < 20) {
return b & c | ~b & d;
}
if (t < 40) {
return b ^ c ^ d;
}
if (t < 60) {
return b & c | b & d | c & d;
}
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t) {
return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data) {
var bkey = str2binb(key);
if (bkey.length > 16) {
bkey = core_sha1(bkey, key.length * 8);
}
var ipad = new Array(16),
opad = new Array(16);
for (var i = 0; i < 16; i++) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * 8);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add$1(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return msw << 16 | lsw & 0xFFFF;
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt) {
return num << cnt | num >>> 32 - cnt;
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str) {
var bin = [];
var mask = 255;
for (var i = 0; i < str.length * 8; i += 8) {
bin[i >> 5] |= (str.charCodeAt(i / 8) & mask) << 24 - i % 32;
}
return bin;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray) {
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
var triplet, j;
for (var i = 0; i < binarray.length * 4; i += 3) {
triplet = (binarray[i >> 2] >> 8 * (3 - i % 4) & 0xFF) << 16 | (binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4) & 0xFF) << 8 | binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4) & 0xFF;
for (j = 0; j < 4; j++) {
if (i * 8 + j * 6 > binarray.length * 32) {
str += "=";
} else {
str += tab.charAt(triplet >> 6 * (3 - j) & 0x3F);
}
}
}
return str;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin) {
var str = "";
var mask = 255;
for (var i = 0; i < bin.length * 32; i += 8) {
str += String.fromCharCode(bin[i >> 5] >>> 24 - i % 32 & mask);
}
return str;
}
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
var SHA1 = {
b64_hmac_sha1: function b64_hmac_sha1(key, data) {
return binb2b64(core_hmac_sha1(key, data));
},
b64_sha1: function b64_sha1(s) {
return binb2b64(core_sha1(str2binb(s), s.length * 8));
},
binb2str: binb2str,
core_hmac_sha1: core_hmac_sha1,
str_hmac_sha1: function str_hmac_sha1(key, data) {
return binb2str(core_hmac_sha1(key, data));
},
str_sha1: function str_sha1(s) {
return binb2str(core_sha1(str2binb(s), s.length * 8));
}
};
var SASLSHA1 = /*#__PURE__*/function (_SASLMechanism) {
_inherits(SASLSHA1, _SASLMechanism);
var _super = _createSuper(SASLSHA1);
/** PrivateConstructor: SASLSHA1
* SASL SCRAM SHA 1 authentication.
*/
function SASLSHA1() {
var mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'SCRAM-SHA-1';
var isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 60;
_classCallCheck(this, SASLSHA1);
return _super.call(this, mechname, isClientFirst, priority);
}
_createClass(SASLSHA1, [{
key: "test",
value: function test(connection) {
// eslint-disable-line class-methods-use-this
return connection.authcid !== null;
}
}, {
key: "onChallenge",
value: function onChallenge(connection, challenge) {
// eslint-disable-line class-methods-use-this
var nonce, salt, iter, Hi, U, U_old, i, k;
var responseText = "c=biws,";
var authMessage = "".concat(connection._sasl_data["client-first-message-bare"], ",").concat(challenge, ",");
var cnonce = connection._sasl_data.cnonce;
var attribMatch = /([a-z]+)=([^,]+)(,|$)/;
while (challenge.match(attribMatch)) {
var matches = challenge.match(attribMatch);
challenge = challenge.replace(matches[0], "");
switch (matches[1]) {
case "r":
nonce = matches[2];
break;
case "s":
salt = matches[2];
break;
case "i":
iter = matches[2];
break;
}
}
if (nonce.substr(0, cnonce.length) !== cnonce) {
connection._sasl_data = {};
return connection._sasl_failure_cb();
}
responseText += "r=" + nonce;
authMessage += responseText;
salt = atob(salt);
salt += "\x00\x00\x00\x01";
var pass = utils.utf16to8(connection.pass);
Hi = U_old = SHA1.core_hmac_sha1(pass, salt);
for (i = 1; i < iter; i++) {
U = SHA1.core_hmac_sha1(pass, SHA1.binb2str(U_old));
for (k = 0; k < 5; k++) {
Hi[k] ^= U[k];
}
U_old = U;
}
Hi = SHA1.binb2str(Hi);
var clientKey = SHA1.core_hmac_sha1(Hi, "Client Key");
var serverKey = SHA1.str_hmac_sha1(Hi, "Server Key");
var clientSignature = SHA1.core_hmac_sha1(SHA1.str_sha1(SHA1.binb2str(clientKey)), authMessage);
connection._sasl_data["server-signature"] = SHA1.b64_hmac_sha1(serverKey, authMessage);
for (k = 0; k < 5; k++) {
clientKey[k] ^= clientSignature[k];
}
responseText += ",p=" + btoa(SHA1.binb2str(clientKey));
return responseText;
}
}, {
key: "clientChallenge",
value: function clientChallenge(connection, test_cnonce) {
// eslint-disable-line class-methods-use-this
var cnonce = test_cnonce || MD5.hexdigest("" + Math.random() * 1234567890);
var auth_str = "n=" + utils.utf16to8(connection.authcid);
auth_str += ",r=";
auth_str += cnonce;
connection._sasl_data.cnonce = cnonce;
connection._sasl_data["client-first-message-bare"] = auth_str;
auth_str = "n,," + auth_str;
return auth_str;
}
}]);
return SASLSHA1;
}(SASLMechanism);
var SASLXOAuth2 = /*#__PURE__*/function (_SASLMechanism) {
_inherits(SASLXOAuth2, _SASLMechanism);
var _super = _createSuper(SASLXOAuth2);
/** PrivateConstructor: SASLXOAuth2
* SASL X-OAuth2 authentication.
*/
function SASLXOAuth2() {
var mechname = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'X-OAUTH2';
var isClientFirst = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var priority = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 30;
_classCallCheck(this, SASLXOAuth2);
return _super.call(this, mechname, isClientFirst, priority);
}
_createClass(SASLXOAuth2, [{
key: "test",
value: function test(connection) {
// eslint-disable-line class-methods-use-this
return connection.pass !== null;
}
}, {
key: "onChallenge",
value: function onChallenge(connection) {
// eslint-disable-line class-methods-use-this
var auth_str = "\0";
if (connection.authcid !== null) {
auth_str = auth_str + connection.authzid;
}
auth_str = auth_str + "\0";
auth_str = auth_str + connection.pass;
return utils.utf16to8(auth_str);
}
}]);
return SASLXOAuth2;
}(SASLMechanism);
/** Function: $build
* Create a Strophe.Builder.
* This is an alias for 'new Strophe.Builder(name, attrs)'.
*
* Parameters:
* (String) name - The root element name.
* (Object) attrs - The attributes for the root element in object notation.
*
* Returns:
* A new Strophe.Builder object.
*/
function $build(name, attrs) {
return new Strophe.Builder(name, attrs);
}
/** Function: $msg
* Create a Strophe.Builder with a <message/> element as the root.
*
* Parameters:
* (Object) attrs - The <message/> element attributes in object notation.
*
* Returns:
* A new Strophe.Builder object.
*/
function $msg(attrs) {
return new Strophe.Builder("message", attrs);
}
/** Function: $iq
* Create a Strophe.Builder with an <iq/> element as the root.
*
* Parameters:
* (Object) attrs - The <iq/> element attributes in object notation.
*
* Returns:
* A new Strophe.Builder object.
*/
function $iq(attrs) {
return new Strophe.Builder("iq", attrs);
}
/** Function: $pres
* Create a Strophe.Builder with a <presence/> element as the root.
*
* Parameters:
* (Object) attrs - The <presence/> element attributes in object notation.
*
* Returns:
* A new Strophe.Builder object.
*/
function $pres(attrs) {
return new Strophe.Builder("presence", attrs);
}
/** Class: Strophe
* An object container for all Strophe library functions.
*
* This class is just a container for all the objects and constants
* used in the library. It is not meant to be instantiated, but to
* provide a namespace for library objects, constants, and functions.
*/
var Strophe = {
/** Constant: VERSION */
VERSION: "1.4.2",
/** Constants: XMPP Namespace Constants
* Common namespace constants from the XMPP RFCs and XEPs.
*
* NS.HTTPBIND - HTTP BIND namespace from XEP 124.
* NS.BOSH - BOSH namespace from XEP 206.
* NS.CLIENT - Main XMPP client namespace.
* NS.AUTH - Legacy authentication namespace.
* NS.ROSTER - Roster operations namespace.
* NS.PROFILE - Profile namespace.
* NS.DISCO_INFO - Service discovery info namespace from XEP 30.
* NS.DISCO_ITEMS - Service discovery items namespace from XEP 30.
* NS.MUC - Multi-User Chat namespace from XEP 45.
* NS.SASL - XMPP SASL namespace from RFC 3920.
* NS.STREAM - XMPP Streams namespace from RFC 3920.
* NS.BIND - XMPP Binding namespace from RFC 3920 and RFC 6120.
* NS.SESSION - XMPP Session namespace from RFC 3920.
* NS.XHTML_IM - XHTML-IM namespace from XEP 71.
* NS.XHTML - XHTML body namespace from XEP 71.
*/
NS: {
HTTPBIND: "http://jabber.org/protocol/httpbind",
BOSH: "urn:xmpp:xbosh",
CLIENT: "jabber:client",
AUTH: "jabber:iq:auth",
ROSTER: "jabber:iq:roster",
PROFILE: "jabber:iq:profile",
DISCO_INFO: "http://jabber.org/protocol/disco#info",
DISCO_ITEMS: "http://jabber.org/protocol/disco#items",
MUC: "http://jabber.org/protocol/muc",
SASL: "urn:ietf:params:xml:ns:xmpp-sasl",
STREAM: "http://etherx.jabber.org/streams",
FRAMING: "urn:ietf:params:xml:ns:xmpp-framing",
BIND: "urn:ietf:params:xml:ns:xmpp-bind",
SESSION: "urn:ietf:params:xml:ns:xmpp-session",
VERSION: "jabber:iq:version",
STANZAS: "urn:ietf:params:xml:ns:xmpp-stanzas",
XHTML_IM: "http://jabber.org/protocol/xhtml-im",
XHTML: "http://www.w3.org/1999/xhtml"
},
/** Constants: XHTML_IM Namespace
* contains allowed tags, tag attributes, and css properties.
* Used in the createHtml function to filter incoming html into the allowed XHTML-IM subset.
* See http://xmpp.org/extensions/xep-0071.html#profile-summary for the list of recommended
* allowed tags and their attributes.
*/
XHTML: {
tags: ['a', 'blockquote', 'br', 'cite', 'em', 'img', 'li', 'ol', 'p', 'span', 'strong', 'ul', 'body'],
attributes: {
'a': ['href'],
'blockquote': ['style'],
'br': [],
'cite': ['style'],
'em': [],
'img': ['src', 'alt', 'style', 'height', 'width'],
'li': ['style'],
'ol': ['style'],
'p': ['style'],
'span': ['style'],
'strong': [],
'ul': ['style'],
'body': []
},
css: ['background-color', 'color', 'font-family', 'font-size', 'font-style', 'font-weight', 'margin-left', 'margin-right', 'text-align', 'text-decoration'],
/** Function: XHTML.validTag
*
* Utility method to determine whether a tag is allowed
* in the XHTML_IM namespace.
*
* XHTML tag names are case sensitive and must be lower case.
*/
validTag: function validTag(tag) {
for (var i = 0; i < Strophe.XHTML.tags.length; i++) {
if (tag === Strophe.XHTML.tags[i]) {
return true;
}
}
return false;
},
/** Function: XHTML.validAttribute
*
* Utility method to determine whether an attribute is allowed
* as recommended per XEP-0071
*
* XHTML attribute names are case sensitive and must be lower case.
*/
validAttribute: function validAttribute(tag, attribute) {
if (typeof Strophe.XHTML.attributes[tag] !== 'undefined' && Strophe.XHTML.attributes[tag].length > 0) {
for (var i = 0; i < Strophe.XHTML.attributes[tag].length; i++) {
if (attribute === Strophe.XHTML.attributes[tag][i]) {
return true;
}
}
}
return false;
},
validCSS: function validCSS(style) {
for (var i = 0; i < Strophe.XHTML.css.length; i++) {
if (style === Strophe.XHTML.css[i]) {
return true;
}
}
return false;
}
},
/** Constants: Connection Status Constants
* Connection status constants for use by the connection handler
* callback.
*
* Status.ERROR - An error has occurred
* Status.CONNECTING - The connection is currently being made
* Status.CONNFAIL - The connection attempt failed
* Status.AUTHENTICATING - The connection is authenticating
* Status.AUTHFAIL - The authentication attempt failed
* Status.CONNECTED - The connection has succeeded
* Status.DISCONNECTED - The connection has been terminated
* Status.DISCONNECTING - The connection is currently being terminated
* Status.ATTACHED - The connection has been attached
* Status.REDIRECT - The connection has been redirected
* Status.CONNTIMEOUT - The connection has timed out
*/
Status: {
ERROR: 0,
CONNECTING: 1,
CONNFAIL: 2,
AUTHENTICATING: 3,
AUTHFAIL: 4,
CONNECTED: 5,
DISCONNECTED: 6,
DISCONNECTING: 7,
ATTACHED: 8,
REDIRECT: 9,
CONNTIMEOUT: 10,
BINDREQUIRED: 11,
ATTACHFAIL: 12
},
ErrorCondition: {
BAD_FORMAT: "bad-format",
CONFLICT: "conflict",
MISSING_JID_NODE: "x-strophe-bad-non-anon-jid",
NO_AUTH_MECH: "no-auth-mech",
UNKNOWN_REASON: "unknown"
},
/** Constants: Log Level Constants
* Logging level indicators.
*
* LogLevel.DEBUG - Debug output
* LogLevel.INFO - Informational output
* LogLevel.WARN - Warnings
* LogLevel.ERROR - Errors
* LogLevel.FATAL - Fatal errors
*/
LogLevel: {
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3,
FATAL: 4
},
/** PrivateConstants: DOM Element Type Constants
* DOM element types.
*
* ElementType.NORMAL - Normal element.
* ElementType.TEXT - Text data element.
* ElementType.FRAGMENT - XHTML fragment element.
*/
ElementType: {
NORMAL: 1,
TEXT: 3,
CDATA: 4,
FRAGMENT: 11
},
/** PrivateConstants: Timeout Values
* Timeout values for error states. These values are in seconds.
* These should not be changed unless you know exactly what you are
* doing.
*
* TIMEOUT - Timeout multiplier. A waiting request will be considered
* failed after Math.floor(TIMEOUT * wait) seconds have elapsed.
* This defaults to 1.1, and with default wait, 66 seconds.
* SECONDARY_TIMEOUT - Secondary timeout multiplier. In cases where
* Strophe can detect early failure, it will consider the request
* failed if it doesn't return after
* Math.floor(SECONDARY_TIMEOUT * wait) seconds have elapsed.
* This defaults to 0.1, and with default wait, 6 seconds.
*/
TIMEOUT: 1.1,
SECONDARY_TIMEOUT: 0.1,
/** Function: addNamespace
* This function is used to extend the current namespaces in
* Strophe.NS. It takes a key and a value with the key being the
* name of the new namespace, with its actual value.
* For example:
* Strophe.addNamespace('PUBSUB', "http://jabber.org/protocol/pubsub");
*
* Parameters:
* (String) name - The name under which the namespace will be
* referenced under Strophe.NS
* (String) value - The actual namespace.
*/
addNamespace: function addNamespace(name, value) {
Strophe.NS[name] = value;
},
/** Function: forEachChild
* Map a function over some or all child elements of a given element.
*
* This is a small convenience function for mapping a function over
* some or all of the children of an element. If elemName is null, all
* children will be passed to the function, otherwise only children
* whose tag names match elemName will be passed.
*
* Parameters:
* (XMLElement) elem - The element to operate on.
* (String) elemName - The child element tag name filter.
* (Function) func - The function to apply to each child. This
* function should take a single argument, a DOM element.
*/
forEachChild: function forEachChild(elem, elemName, func) {
for (var i = 0; i < elem.childNodes.length; i++) {
var childNode = elem.childNodes[i];
if (childNode.nodeType === Strophe.ElementType.NORMAL && (!elemName || this.isTagEqual(childNode, elemName))) {
func(childNode);
}
}
},
/** Function: isTagEqual
* Compare an element's tag name with a string.
*
* This function is case sensitive.
*
* Parameters:
* (XMLElement) el - A DOM element.
* (String) name - The element name.
*
* Returns:
* true if the element's tag name matches _el_, and false
* otherwise.
*/
isTagEqual: function isTagEqual(el, name) {
return el.tagName === name;
},
/** PrivateVariable: _xmlGenerator
* _Private_ variable that caches a DOM document to
* generate elements.
*/
_xmlGenerator: null,
/** Function: xmlGenerator
* Get the DOM document to generate elements.
*
* Returns:
* The currently used DOM document.
*/
xmlGenerator: function xmlGenerator() {
if (!Strophe._xmlGenerator) {
Strophe._xmlGenerator = getDummyXMLDOMDocument();
}
return Strophe._xmlGenerator;
},
/** Function: xmlElement
* Create an XML DOM element.
*
* This function creates an XML DOM element correctly across all
* implementations. Note that these are not HTML DOM elements, which
* aren't appropriate for XMPP stanzas.
*
* Parameters:
* (String) name - The name for the element.
* (Array|Object) attrs - An optional array or object containing
* key/value pairs to use as element attributes. The object should
* be in the format {'key': 'value'} or {key: 'value'}. The array
* should have the format [['key1', 'value1'], ['key2', 'value2']].
* (String) text - The text child data for the element.
*
* Returns:
* A new XML DOM element.
*/
xmlElement: function xmlElement(name) {
if (!name) {
return null;
}
var node = Strophe.xmlGenerator().createElement(name); // FIXME: this should throw errors if args are the wrong type or
// there are more than two optional args
for (var a = 1; a < arguments.length; a++) {
var arg = arguments[a];
if (!arg) {
continue;
}
if (typeof arg === "string" || typeof arg === "number") {
node.appendChild(Strophe.xmlTextNode(arg));
} else if (_typeof(arg) === "object" && typeof arg.sort === "function") {
for (var i = 0; i < arg.length; i++) {
var attr = arg[i];
if (_typeof(attr) === "object" && typeof attr.sort === "function" && attr[1] !== undefined && attr[1] !== null) {
node.setAttribute(attr[0], attr[1]);
}
}
} else if (_typeof(arg) === "object") {
for (var k in arg) {
if (Object.prototype.hasOwnProperty.call(arg, k) && arg[k] !== undefined && arg[k] !== null) {
node.setAttribute(k, arg[k]);
}
}
}
}
return node;
},
/* Function: xmlescape
* Excapes invalid xml characters.
*
* Parameters:
* (String) text - text to escape.
*
* Returns:
* Escaped text.
*/
xmlescape: function xmlescape(text) {
text = text.replace(/\&/g, "&");
text = text.replace(/</g, "<");
text = text.replace(/>/g, ">");
text = text.replace(/'/g, "'");
text = text.replace(/"/g, """);
return text;
},
/* Function: xmlunescape
* Unexcapes invalid xml characters.
*
* Parameters:
* (String) text - text to unescape.
*
* Returns:
* Unescaped text.
*/
xmlunescape: function xmlunescape(text) {
text = text.replace(/\&/g, "&");
text = text.replace(/</g, "<");
text = text.replace(/>/g, ">");
text = text.replace(/&