From 4f8bda2df782b1cf9731987b1fcb179a338d5938 Mon Sep 17 00:00:00 2001 From: ericgaspar Date: Sat, 3 Jul 2021 16:04:46 +0200 Subject: [PATCH] upgrade 7.0.6 --- sources/dist/converse.js | 97753 ++++++++++++++++++++ sources/dist/converse.min.js | 23 +- sources/dist/webfonts/fa-brands-400-.eot | Bin 133034 -> 0 bytes sources/dist/webfonts/fa-regular-400-.eot | Bin 34390 -> 0 bytes sources/dist/webfonts/fa-solid-900-.eot | Bin 202902 -> 0 bytes sources/manifest.json | 2 +- 6 files changed, 97769 insertions(+), 9 deletions(-) create mode 100644 sources/dist/converse.js delete mode 100644 sources/dist/webfonts/fa-brands-400-.eot delete mode 100644 sources/dist/webfonts/fa-regular-400-.eot delete mode 100644 sources/dist/webfonts/fa-solid-900-.eot diff --git a/sources/dist/converse.js b/sources/dist/converse.js new file mode 100644 index 0000000..46d9b41 --- /dev/null +++ b/sources/dist/converse.js @@ -0,0 +1,97753 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // install a JSONP callback for chunk loading +/******/ function webpackJsonpCallback(data) { +/******/ var chunkIds = data[0]; +/******/ var moreModules = data[1]; +/******/ +/******/ +/******/ // add "moreModules" to the modules object, +/******/ // then flag all "chunkIds" as loaded and fire callback +/******/ var moduleId, chunkId, i = 0, resolves = []; +/******/ for(;i < chunkIds.length; i++) { +/******/ chunkId = chunkIds[i]; +/******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) { +/******/ resolves.push(installedChunks[chunkId][0]); +/******/ } +/******/ installedChunks[chunkId] = 0; +/******/ } +/******/ for(moduleId in moreModules) { +/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { +/******/ modules[moduleId] = moreModules[moduleId]; +/******/ } +/******/ } +/******/ if(parentJsonpFunction) parentJsonpFunction(data); +/******/ +/******/ while(resolves.length) { +/******/ resolves.shift()(); +/******/ } +/******/ +/******/ }; +/******/ +/******/ +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // Promise = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ 178: 0 +/******/ }; +/******/ +/******/ +/******/ +/******/ // script path function +/******/ function jsonpScriptSrc(chunkId) { +/******/ return __webpack_require__.p + "" + ({"0":"locales/dayjs/af","1":"locales/dayjs/ar","2":"locales/dayjs/ar-dz","3":"locales/dayjs/ar-kw","4":"locales/dayjs/ar-ly","5":"locales/dayjs/ar-ma","6":"locales/dayjs/ar-sa","7":"locales/dayjs/ar-tn","8":"locales/dayjs/az","9":"locales/dayjs/be","10":"locales/dayjs/bg","11":"locales/dayjs/bi","12":"locales/dayjs/bm","13":"locales/dayjs/bn","14":"locales/dayjs/bo","15":"locales/dayjs/br","16":"locales/dayjs/bs","17":"locales/dayjs/ca","18":"locales/dayjs/cs","19":"locales/dayjs/cv","20":"locales/dayjs/cy","21":"locales/dayjs/da","22":"locales/dayjs/de","23":"locales/dayjs/de-at","24":"locales/dayjs/de-ch","25":"locales/dayjs/dv","26":"locales/dayjs/el","27":"locales/dayjs/en","28":"locales/dayjs/en-SG","29":"locales/dayjs/en-au","30":"locales/dayjs/en-ca","31":"locales/dayjs/en-gb","32":"locales/dayjs/en-ie","33":"locales/dayjs/en-il","34":"locales/dayjs/en-in","35":"locales/dayjs/en-nz","36":"locales/dayjs/en-tt","37":"locales/dayjs/eo","38":"locales/dayjs/es","39":"locales/dayjs/es-do","40":"locales/dayjs/es-pr","41":"locales/dayjs/es-us","42":"locales/dayjs/et","43":"locales/dayjs/eu","44":"locales/dayjs/fa","45":"locales/dayjs/fi","46":"locales/dayjs/fo","47":"locales/dayjs/fr","48":"locales/dayjs/fr-ca","49":"locales/dayjs/fr-ch","50":"locales/dayjs/fy","51":"locales/dayjs/ga","52":"locales/dayjs/gd","53":"locales/dayjs/gl","54":"locales/dayjs/gom-latn","55":"locales/dayjs/gu","56":"locales/dayjs/he","57":"locales/dayjs/hi","58":"locales/dayjs/hr","59":"locales/dayjs/ht","60":"locales/dayjs/hu","61":"locales/dayjs/hy-am","62":"locales/dayjs/id","63":"locales/dayjs/is","64":"locales/dayjs/it","65":"locales/dayjs/it-ch","66":"locales/dayjs/ja","67":"locales/dayjs/jv","68":"locales/dayjs/ka","69":"locales/dayjs/kk","70":"locales/dayjs/km","71":"locales/dayjs/kn","72":"locales/dayjs/ko","73":"locales/dayjs/ku","74":"locales/dayjs/ky","75":"locales/dayjs/lb","76":"locales/dayjs/lo","77":"locales/dayjs/lt","78":"locales/dayjs/lv","79":"locales/dayjs/me","80":"locales/dayjs/mi","81":"locales/dayjs/mk","82":"locales/dayjs/ml","83":"locales/dayjs/mn","84":"locales/dayjs/mr","85":"locales/dayjs/ms","86":"locales/dayjs/ms-my","87":"locales/dayjs/mt","88":"locales/dayjs/my","89":"locales/dayjs/nb","90":"locales/dayjs/ne","91":"locales/dayjs/nl","92":"locales/dayjs/nl-be","93":"locales/dayjs/nn","94":"locales/dayjs/oc-lnc","95":"locales/dayjs/pa-in","96":"locales/dayjs/pl","97":"locales/dayjs/pt","98":"locales/dayjs/pt-br","99":"locales/dayjs/ro","100":"locales/dayjs/ru","101":"locales/dayjs/rw","102":"locales/dayjs/sd","103":"locales/dayjs/se","104":"locales/dayjs/si","105":"locales/dayjs/sk","106":"locales/dayjs/sl","107":"locales/dayjs/sq","108":"locales/dayjs/sr","109":"locales/dayjs/sr-cyrl","110":"locales/dayjs/ss","111":"locales/dayjs/sv","112":"locales/dayjs/sw","113":"locales/dayjs/ta","114":"locales/dayjs/te","115":"locales/dayjs/tet","116":"locales/dayjs/tg","117":"locales/dayjs/th","118":"locales/dayjs/tk","119":"locales/dayjs/tl-ph","120":"locales/dayjs/tlh","121":"locales/dayjs/tr","122":"locales/dayjs/tzl","123":"locales/dayjs/tzm","124":"locales/dayjs/tzm-latn","125":"locales/dayjs/ug-cn","126":"locales/dayjs/uk","127":"locales/dayjs/ur","128":"locales/dayjs/uz","129":"locales/dayjs/uz-latn","130":"locales/dayjs/vi","131":"locales/dayjs/x-pseudo","132":"locales/dayjs/yo","133":"locales/dayjs/zh","134":"locales/dayjs/zh-cn","135":"locales/dayjs/zh-hk","136":"locales/dayjs/zh-tw","137":"emojis","138":"icons","139":"locales/af-LC_MESSAGES-converse-po","140":"locales/ar-LC_MESSAGES-converse-po","141":"locales/bg-LC_MESSAGES-converse-po","142":"locales/ca-LC_MESSAGES-converse-po","143":"locales/cs-LC_MESSAGES-converse-po","144":"locales/da-LC_MESSAGES-converse-po","145":"locales/dayjs/index-d-ts","146":"locales/dayjs/types-d-ts","147":"locales/de-LC_MESSAGES-converse-po","148":"locales/eo-LC_MESSAGES-converse-po","149":"locales/es-LC_MESSAGES-converse-po","150":"locales/eu-LC_MESSAGES-converse-po","151":"locales/fi-LC_MESSAGES-converse-po","152":"locales/fr-LC_MESSAGES-converse-po","153":"locales/gl-LC_MESSAGES-converse-po","154":"locales/he-LC_MESSAGES-converse-po","155":"locales/hi-LC_MESSAGES-converse-po","156":"locales/hu-LC_MESSAGES-converse-po","157":"locales/id-LC_MESSAGES-converse-po","158":"locales/it-LC_MESSAGES-converse-po","159":"locales/ja-LC_MESSAGES-converse-po","160":"locales/lt-LC_MESSAGES-converse-po","161":"locales/mr-LC_MESSAGES-converse-po","162":"locales/nb-LC_MESSAGES-converse-po","163":"locales/nl-LC_MESSAGES-converse-po","164":"locales/nl_BE-LC_MESSAGES-converse-po","165":"locales/oc-LC_MESSAGES-converse-po","166":"locales/pl-LC_MESSAGES-converse-po","167":"locales/pt-LC_MESSAGES-converse-po","168":"locales/pt_BR-LC_MESSAGES-converse-po","169":"locales/ro-LC_MESSAGES-converse-po","170":"locales/ru-LC_MESSAGES-converse-po","171":"locales/sv-LC_MESSAGES-converse-po","172":"locales/th-LC_MESSAGES-converse-po","173":"locales/tr-LC_MESSAGES-converse-po","174":"locales/uk-LC_MESSAGES-converse-po","175":"locales/vi-LC_MESSAGES-converse-po","176":"locales/zh_CN-LC_MESSAGES-converse-po","177":"locales/zh_TW-LC_MESSAGES-converse-po"}[chunkId]||chunkId) + ".js" +/******/ } +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // This file contains only the entry chunk. +/******/ // The chunk loading function for additional chunks +/******/ __webpack_require__.e = function requireEnsure(chunkId) { +/******/ var promises = []; +/******/ +/******/ +/******/ // JSONP chunk loading for javascript +/******/ +/******/ var installedChunkData = installedChunks[chunkId]; +/******/ if(installedChunkData !== 0) { // 0 means "already installed". +/******/ +/******/ // a Promise means "currently loading". +/******/ if(installedChunkData) { +/******/ promises.push(installedChunkData[2]); +/******/ } else { +/******/ // setup Promise in chunk cache +/******/ var promise = new Promise(function(resolve, reject) { +/******/ installedChunkData = installedChunks[chunkId] = [resolve, reject]; +/******/ }); +/******/ promises.push(installedChunkData[2] = promise); +/******/ +/******/ // start chunk loading +/******/ var script = document.createElement('script'); +/******/ var onScriptComplete; +/******/ +/******/ script.charset = 'utf-8'; +/******/ script.timeout = 120; +/******/ if (__webpack_require__.nc) { +/******/ script.setAttribute("nonce", __webpack_require__.nc); +/******/ } +/******/ script.src = jsonpScriptSrc(chunkId); +/******/ +/******/ // create error before stack unwound to get useful stacktrace later +/******/ var error = new Error(); +/******/ onScriptComplete = function (event) { +/******/ // avoid mem leaks in IE. +/******/ script.onerror = script.onload = null; +/******/ clearTimeout(timeout); +/******/ var chunk = installedChunks[chunkId]; +/******/ if(chunk !== 0) { +/******/ if(chunk) { +/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); +/******/ var realSrc = event && event.target && event.target.src; +/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'; +/******/ error.name = 'ChunkLoadError'; +/******/ error.type = errorType; +/******/ error.request = realSrc; +/******/ chunk[1](error); +/******/ } +/******/ installedChunks[chunkId] = undefined; +/******/ } +/******/ }; +/******/ var timeout = setTimeout(function(){ +/******/ onScriptComplete({ type: 'timeout', target: script }); +/******/ }, 120000); +/******/ script.onerror = script.onload = onScriptComplete; +/******/ document.head.appendChild(script); +/******/ } +/******/ } +/******/ return Promise.all(promises); +/******/ }; +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = "/dist/"; +/******/ +/******/ // on error function for async loading +/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; }; +/******/ +/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; +/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray); +/******/ jsonpArray.push = webpackJsonpCallback; +/******/ jsonpArray = jsonpArray.slice(); +/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]); +/******/ var parentJsonpFunction = oldJsonpFunction; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 321); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; + +// EXPORTS +__webpack_require__.d(__webpack_exports__, "a", function() { return /* binding */ $build; }); +__webpack_require__.d(__webpack_exports__, "c", function() { return /* binding */ $msg; }); +__webpack_require__.d(__webpack_exports__, "b", function() { return /* binding */ $iq; }); +__webpack_require__.d(__webpack_exports__, "d", function() { return /* binding */ $pres; }); +__webpack_require__.d(__webpack_exports__, "f", function() { return /* binding */ Strophe; }); +__webpack_require__.d(__webpack_exports__, "e", function() { return /* reexport */ sha1["a" /* default */]; }); + +// UNUSED EXPORTS: MD5 + +// EXTERNAL MODULE: ./node_modules/strophe.js/src/shims.js +var shims = __webpack_require__(8); + +// CONCATENATED MODULE: ./node_modules/strophe.js/src/md5.js +/* + * 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. + */ +const safe_add = function (x, y) { + const lsw = (x & 0xFFFF) + (y & 0xFFFF); + const msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return msw << 16 | lsw & 0xFFFF; +}; +/* + * Bitwise rotate a 32-bit number to the left. + */ + + +const bit_rol = function (num, cnt) { + return num << cnt | num >>> 32 - cnt; +}; +/* + * Convert a string to an array of little-endian words + */ + + +const str2binl = function (str) { + if (typeof str !== "string") { + throw new Error("str2binl was passed a non-string"); + } + + const bin = []; + + for (let 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 + */ + + +const binl2str = function (bin) { + let str = ""; + + for (let 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. + */ + + +const binl2hex = function (binarray) { + const hex_tab = "0123456789abcdef"; + let str = ""; + + for (let 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. + */ + + +const md5_cmn = function (q, a, b, x, s, t) { + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); +}; + +const md5_ff = function (a, b, c, d, x, s, t) { + return md5_cmn(b & c | ~b & d, a, b, x, s, t); +}; + +const md5_gg = function (a, b, c, d, x, s, t) { + return md5_cmn(b & d | c & ~d, a, b, x, s, t); +}; + +const md5_hh = function (a, b, c, d, x, s, t) { + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +}; + +const md5_ii = function (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 + */ + + +const core_md5 = function (x, len) { + /* append padding */ + x[len >> 5] |= 0x80 << len % 32; + x[(len + 64 >>> 9 << 4) + 14] = len; + let a = 1732584193; + let b = -271733879; + let c = -1732584194; + let d = 271733878; + let olda, oldb, oldc, oldd; + + for (let 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. + */ + + +const MD5 = { + hexdigest: function (s) { + return binl2hex(core_md5(str2binl(s), s.length * 8)); + }, + hash: function (s) { + return binl2str(core_md5(str2binl(s), s.length * 8)); + } +}; + +// CONCATENATED MODULE: ./node_modules/strophe.js/src/sasl.js +/** Class: Strophe.SASLMechanism + * + * Encapsulates an SASL authentication mechanism. + * + * User code may override the priority for each mechanism or disable it completely. + * See for information about changing priority and 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 + */ +class SASLMechanism { + /** + * 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. + */ + constructor(name, isClientFirst, priority) { + /** PrivateVariable: mechname + * Mechanism name. + */ + this.mechname = name; + /** PrivateVariable: isClientFirst + * If client sends response without initial server challenge. + */ + + this.isClientFirst = isClientFirst; + /** Variable: priority + * Determines which 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 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 for a list of available mechanisms. + * + * Parameters: + * (Strophe.Connection) connection - Target Connection. + * + * Returns: + * (Boolean) If mechanism was able to run. + */ + + + 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. + */ + + + 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. + */ + + + 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. + */ + + + 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. + */ + + + onFailure() { + this._connection = null; + } + /** PrivateFunction: onSuccess + * Protocol informs mechanism implementation about SASL success. + */ + + + onSuccess() { + this._connection = null; + } + +} +// CONCATENATED MODULE: ./node_modules/strophe.js/src/sasl-anon.js + // Building SASL callbacks + +class sasl_anon_SASLAnonymous extends SASLMechanism { + /** PrivateConstructor: SASLAnonymous + * SASL ANONYMOUS authentication. + */ + constructor(mechname = 'ANONYMOUS', isClientFirst = false, priority = 20) { + super(mechname, isClientFirst, priority); + } + + test(connection) { + // eslint-disable-line class-methods-use-this + return connection.authcid === null; + } + +} +// CONCATENATED MODULE: ./node_modules/strophe.js/src/sasl-external.js + +class sasl_external_SASLExternal extends SASLMechanism { + /** 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. + */ + constructor(mechname = 'EXTERNAL', isClientFirst = true, priority = 10) { + super(mechname, isClientFirst, priority); + } + + 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; + } + +} +// CONCATENATED MODULE: ./node_modules/strophe.js/src/utils.js +const utils = { + utf16to8: function (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 (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 (const cookieName in cookies) { + if (Object.prototype.hasOwnProperty.call(cookies, cookieName)) { + let expires = ''; + let domain = ''; + let path = ''; + const cookieObj = cookies[cookieName]; + const isObj = typeof cookieObj === "object"; + const 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; + } + } + } +}; + +// CONCATENATED MODULE: ./node_modules/strophe.js/src/sasl-oauthbearer.js + + +class sasl_oauthbearer_SASLOAuthBearer extends SASLMechanism { + /** PrivateConstructor: SASLOAuthBearer + * SASL OAuth Bearer authentication. + */ + constructor(mechname = 'OAUTHBEARER', isClientFirst = true, priority = 40) { + super(mechname, isClientFirst, priority); + } + + test(connection) { + // eslint-disable-line class-methods-use-this + return connection.pass !== null; + } + + onChallenge(connection) { + // eslint-disable-line class-methods-use-this + let auth_str = 'n,'; + + if (connection.authcid !== null) { + auth_str = auth_str + 'a=' + connection.authzid; + } + + auth_str = auth_str + ','; + auth_str = auth_str + "\u0001"; + auth_str = auth_str + 'auth=Bearer '; + auth_str = auth_str + connection.pass; + auth_str = auth_str + "\u0001"; + auth_str = auth_str + "\u0001"; + return utils.utf16to8(auth_str); + } + +} +// CONCATENATED MODULE: ./node_modules/strophe.js/src/sasl-plain.js + + +class sasl_plain_SASLPlain extends SASLMechanism { + /** PrivateConstructor: SASLPlain + * SASL PLAIN authentication. + */ + constructor(mechname = 'PLAIN', isClientFirst = true, priority = 50) { + super(mechname, isClientFirst, priority); + } + + test(connection) { + // eslint-disable-line class-methods-use-this + return connection.authcid !== null; + } + + onChallenge(connection) { + // eslint-disable-line class-methods-use-this + const { + authcid, + authzid, + domain, + pass + } = connection; + + 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 + + + let auth_str = authzid !== `${authcid}@${domain}` ? authzid : ''; + auth_str = auth_str + "\u0000"; + auth_str = auth_str + authcid; + auth_str = auth_str + "\u0000"; + auth_str = auth_str + pass; + return utils.utf16to8(auth_str); + } + +} +// EXTERNAL MODULE: ./node_modules/strophe.js/src/sha1.js +var sha1 = __webpack_require__(6); + +// CONCATENATED MODULE: ./node_modules/strophe.js/src/sasl-sha1.js + + + + +class sasl_sha1_SASLSHA1 extends SASLMechanism { + /** PrivateConstructor: SASLSHA1 + * SASL SCRAM SHA 1 authentication. + */ + constructor(mechname = 'SCRAM-SHA-1', isClientFirst = true, priority = 60) { + super(mechname, isClientFirst, priority); + } + + test(connection) { + // eslint-disable-line class-methods-use-this + return connection.authcid !== null; + } + + onChallenge(connection, challenge) { + // eslint-disable-line class-methods-use-this + let nonce, salt, iter, Hi, U, U_old, i, k; + let responseText = "c=biws,"; + let authMessage = `${connection._sasl_data["client-first-message-bare"]},${challenge},`; + const cnonce = connection._sasl_data.cnonce; + const attribMatch = /([a-z]+)=([^,]+)(,|$)/; + + while (challenge.match(attribMatch)) { + const 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"; + const pass = utils.utf16to8(connection.pass); + Hi = U_old = sha1["a" /* default */].core_hmac_sha1(pass, salt); + + for (i = 1; i < iter; i++) { + U = sha1["a" /* default */].core_hmac_sha1(pass, sha1["a" /* default */].binb2str(U_old)); + + for (k = 0; k < 5; k++) { + Hi[k] ^= U[k]; + } + + U_old = U; + } + + Hi = sha1["a" /* default */].binb2str(Hi); + const clientKey = sha1["a" /* default */].core_hmac_sha1(Hi, "Client Key"); + const serverKey = sha1["a" /* default */].str_hmac_sha1(Hi, "Server Key"); + const clientSignature = sha1["a" /* default */].core_hmac_sha1(sha1["a" /* default */].str_sha1(sha1["a" /* default */].binb2str(clientKey)), authMessage); + connection._sasl_data["server-signature"] = sha1["a" /* default */].b64_hmac_sha1(serverKey, authMessage); + + for (k = 0; k < 5; k++) { + clientKey[k] ^= clientSignature[k]; + } + + responseText += ",p=" + btoa(sha1["a" /* default */].binb2str(clientKey)); + return responseText; + } + + clientChallenge(connection, test_cnonce) { + // eslint-disable-line class-methods-use-this + const cnonce = test_cnonce || MD5.hexdigest("" + Math.random() * 1234567890); + let 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; + } + +} +// CONCATENATED MODULE: ./node_modules/strophe.js/src/sasl-xoauth2.js + + +class sasl_xoauth2_SASLXOAuth2 extends SASLMechanism { + /** PrivateConstructor: SASLXOAuth2 + * SASL X-OAuth2 authentication. + */ + constructor(mechname = 'X-OAUTH2', isClientFirst = true, priority = 30) { + super(mechname, isClientFirst, priority); + } + + test(connection) { + // eslint-disable-line class-methods-use-this + return connection.pass !== null; + } + + onChallenge(connection) { + // eslint-disable-line class-methods-use-this + let auth_str = '\u0000'; + + if (connection.authcid !== null) { + auth_str = auth_str + connection.authzid; + } + + auth_str = auth_str + "\u0000"; + auth_str = auth_str + connection.pass; + return utils.utf16to8(auth_str); + } + +} +// EXTERNAL MODULE: ./node_modules/abab/index.js +var abab = __webpack_require__(40); + +// CONCATENATED MODULE: ./node_modules/strophe.js/src/core.js +/* + This program is distributed under the terms of the MIT license. + Please see the LICENSE file for details. + + Copyright 2006-2018, OGG, LLC +*/ + +/*global define, document, sessionStorage, setTimeout, clearTimeout, ActiveXObject, DOMParser, btoa, atob */ + + + + + + + + + + + + +/** 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 element as the root. + * + * Parameters: + * (Object) attrs - The 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 element as the root. + * + * Parameters: + * (Object) attrs - The 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 element as the root. + * + * Parameters: + * (Object) attrs - The 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. + */ + +const Strophe = { + /** Constant: VERSION */ + VERSION: "1.4.1", + + /** 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(tag) { + for (let 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(tag, attribute) { + if (typeof Strophe.XHTML.attributes[tag] !== 'undefined' && Strophe.XHTML.attributes[tag].length > 0) { + for (let i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { + if (attribute === Strophe.XHTML.attributes[tag][i]) { + return true; + } + } + } + + return false; + }, + + validCSS(style) { + for (let 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(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(elem, elemName, func) { + for (let i = 0; i < elem.childNodes.length; i++) { + const 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(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() { + if (!Strophe._xmlGenerator) { + Strophe._xmlGenerator = shims["c" /* 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(name) { + if (!name) { + return null; + } + + const 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 (let a = 1; a < arguments.length; a++) { + const 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 (let i = 0; i < arg.length; i++) { + const 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 (const 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(text) { + 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(text) { + text = text.replace(/\&/g, "&"); + text = text.replace(/</g, "<"); + text = text.replace(/>/g, ">"); + text = text.replace(/'/g, "'"); + text = text.replace(/"/g, "\""); + return text; + }, + + /** Function: xmlTextNode + * Creates an XML DOM text node. + * + * Provides a cross implementation version of document.createTextNode. + * + * Parameters: + * (String) text - The content of the text node. + * + * Returns: + * A new XML DOM text node. + */ + xmlTextNode(text) { + return Strophe.xmlGenerator().createTextNode(text); + }, + + /** Function: xmlHtmlNode + * Creates an XML DOM html node. + * + * Parameters: + * (String) html - The content of the html node. + * + * Returns: + * A new XML DOM text node. + */ + xmlHtmlNode(html) { + let node; //ensure text is escaped + + if (shims["a" /* DOMParser */]) { + const parser = new shims["a" /* DOMParser */](); + node = parser.parseFromString(html, "text/xml"); + } else { + node = new ActiveXObject("Microsoft.XMLDOM"); + node.async = "false"; + node.loadXML(html); + } + + return node; + }, + + /** Function: getText + * Get the concatenation of all text children of an element. + * + * Parameters: + * (XMLElement) elem - A DOM element. + * + * Returns: + * A String with the concatenated text of all text element children. + */ + getText(elem) { + if (!elem) { + return null; + } + + let str = ""; + + if (elem.childNodes.length === 0 && elem.nodeType === Strophe.ElementType.TEXT) { + str += elem.nodeValue; + } + + for (let i = 0; i < elem.childNodes.length; i++) { + if (elem.childNodes[i].nodeType === Strophe.ElementType.TEXT) { + str += elem.childNodes[i].nodeValue; + } + } + + return Strophe.xmlescape(str); + }, + + /** Function: copyElement + * Copy an XML DOM element. + * + * This function copies a DOM element and all its descendants and returns + * the new copy. + * + * Parameters: + * (XMLElement) elem - A DOM element. + * + * Returns: + * A new, copied DOM element tree. + */ + copyElement(elem) { + let el; + + if (elem.nodeType === Strophe.ElementType.NORMAL) { + el = Strophe.xmlElement(elem.tagName); + + for (let i = 0; i < elem.attributes.length; i++) { + el.setAttribute(elem.attributes[i].nodeName, elem.attributes[i].value); + } + + for (let i = 0; i < elem.childNodes.length; i++) { + el.appendChild(Strophe.copyElement(elem.childNodes[i])); + } + } else if (elem.nodeType === Strophe.ElementType.TEXT) { + el = Strophe.xmlGenerator().createTextNode(elem.nodeValue); + } + + return el; + }, + + /** Function: createHtml + * Copy an HTML DOM element into an XML DOM. + * + * This function copies a DOM element and all its descendants and returns + * the new copy. + * + * Parameters: + * (HTMLElement) elem - A DOM element. + * + * Returns: + * A new, copied DOM element tree. + */ + createHtml(elem) { + let el; + + if (elem.nodeType === Strophe.ElementType.NORMAL) { + const tag = elem.nodeName.toLowerCase(); // XHTML tags must be lower case. + + if (Strophe.XHTML.validTag(tag)) { + try { + el = Strophe.xmlElement(tag); + + for (let i = 0; i < Strophe.XHTML.attributes[tag].length; i++) { + const attribute = Strophe.XHTML.attributes[tag][i]; + let value = elem.getAttribute(attribute); + + if (typeof value === 'undefined' || value === null || value === '' || value === false || value === 0) { + continue; + } + + if (attribute === 'style' && typeof value === 'object' && typeof value.cssText !== 'undefined') { + value = value.cssText; // we're dealing with IE, need to get CSS out + } // filter out invalid css styles + + + if (attribute === 'style') { + const css = []; + const cssAttrs = value.split(';'); + + for (let j = 0; j < cssAttrs.length; j++) { + const attr = cssAttrs[j].split(':'); + const cssName = attr[0].replace(/^\s*/, "").replace(/\s*$/, "").toLowerCase(); + + if (Strophe.XHTML.validCSS(cssName)) { + const cssValue = attr[1].replace(/^\s*/, "").replace(/\s*$/, ""); + css.push(cssName + ': ' + cssValue); + } + } + + if (css.length > 0) { + value = css.join('; '); + el.setAttribute(attribute, value); + } + } else { + el.setAttribute(attribute, value); + } + } + + for (let i = 0; i < elem.childNodes.length; i++) { + el.appendChild(Strophe.createHtml(elem.childNodes[i])); + } + } catch (e) { + // invalid elements + el = Strophe.xmlTextNode(''); + } + } else { + el = Strophe.xmlGenerator().createDocumentFragment(); + + for (let i = 0; i < elem.childNodes.length; i++) { + el.appendChild(Strophe.createHtml(elem.childNodes[i])); + } + } + } else if (elem.nodeType === Strophe.ElementType.FRAGMENT) { + el = Strophe.xmlGenerator().createDocumentFragment(); + + for (let i = 0; i < elem.childNodes.length; i++) { + el.appendChild(Strophe.createHtml(elem.childNodes[i])); + } + } else if (elem.nodeType === Strophe.ElementType.TEXT) { + el = Strophe.xmlTextNode(elem.nodeValue); + } + + return el; + }, + + /** Function: escapeNode + * Escape the node part (also called local part) of a JID. + * + * Parameters: + * (String) node - A node (or local part). + * + * Returns: + * An escaped node (or local part). + */ + escapeNode(node) { + if (typeof node !== "string") { + return node; + } + + return node.replace(/^\s+|\s+$/g, '').replace(/\\/g, "\\5c").replace(/ /g, "\\20").replace(/\"/g, "\\22").replace(/\&/g, "\\26").replace(/\'/g, "\\27").replace(/\//g, "\\2f").replace(/:/g, "\\3a").replace(//g, "\\3e").replace(/@/g, "\\40"); + }, + + /** Function: unescapeNode + * Unescape a node part (also called local part) of a JID. + * + * Parameters: + * (String) node - A node (or local part). + * + * Returns: + * An unescaped node (or local part). + */ + unescapeNode(node) { + if (typeof node !== "string") { + return node; + } + + return node.replace(/\\20/g, " ").replace(/\\22/g, '"').replace(/\\26/g, "&").replace(/\\27/g, "'").replace(/\\2f/g, "/").replace(/\\3a/g, ":").replace(/\\3c/g, "<").replace(/\\3e/g, ">").replace(/\\40/g, "@").replace(/\\5c/g, "\\"); + }, + + /** Function: getNodeFromJid + * Get the node portion of a JID String. + * + * Parameters: + * (String) jid - A JID. + * + * Returns: + * A String containing the node. + */ + getNodeFromJid(jid) { + if (jid.indexOf("@") < 0) { + return null; + } + + return jid.split("@")[0]; + }, + + /** Function: getDomainFromJid + * Get the domain portion of a JID String. + * + * Parameters: + * (String) jid - A JID. + * + * Returns: + * A String containing the domain. + */ + getDomainFromJid(jid) { + const bare = Strophe.getBareJidFromJid(jid); + + if (bare.indexOf("@") < 0) { + return bare; + } else { + const parts = bare.split("@"); + parts.splice(0, 1); + return parts.join('@'); + } + }, + + /** Function: getResourceFromJid + * Get the resource portion of a JID String. + * + * Parameters: + * (String) jid - A JID. + * + * Returns: + * A String containing the resource. + */ + getResourceFromJid(jid) { + if (!jid) { + return null; + } + + const s = jid.split("/"); + + if (s.length < 2) { + return null; + } + + s.splice(0, 1); + return s.join('/'); + }, + + /** Function: getBareJidFromJid + * Get the bare JID from a JID String. + * + * Parameters: + * (String) jid - A JID. + * + * Returns: + * A String containing the bare JID. + */ + getBareJidFromJid(jid) { + return jid ? jid.split("/")[0] : null; + }, + + /** PrivateFunction: _handleError + * _Private_ function that properly logs an error to the console + */ + _handleError(e) { + if (typeof e.stack !== "undefined") { + Strophe.fatal(e.stack); + } + + if (e.sourceURL) { + Strophe.fatal("error: " + this.handler + " " + e.sourceURL + ":" + e.line + " - " + e.name + ": " + e.message); + } else if (e.fileName) { + Strophe.fatal("error: " + this.handler + " " + e.fileName + ":" + e.lineNumber + " - " + e.name + ": " + e.message); + } else { + Strophe.fatal("error: " + e.message); + } + }, + + /** Function: log + * User overrideable logging function. + * + * This function is called whenever the Strophe library calls any + * of the logging functions. The default implementation of this + * function logs only fatal errors. If client code wishes to handle the logging + * messages, it should override this with + * > Strophe.log = function (level, msg) { + * > (user code here) + * > }; + * + * Please note that data sent and received over the wire is logged + * via Strophe.Connection.rawInput() and Strophe.Connection.rawOutput(). + * + * The different levels and their meanings are + * + * DEBUG - Messages useful for debugging purposes. + * INFO - Informational messages. This is mostly information like + * 'disconnect was called' or 'SASL auth succeeded'. + * WARN - Warnings about potential problems. This is mostly used + * to report transient connection errors like request timeouts. + * ERROR - Some error occurred. + * FATAL - A non-recoverable fatal error occurred. + * + * Parameters: + * (Integer) level - The log level of the log message. This will + * be one of the values in Strophe.LogLevel. + * (String) msg - The log message. + */ + log(level, msg) { + if (level === this.LogLevel.FATAL) { + var _console; + + (_console = console) === null || _console === void 0 ? void 0 : _console.error(msg); + } + }, + + /** Function: debug + * Log a message at the Strophe.LogLevel.DEBUG level. + * + * Parameters: + * (String) msg - The log message. + */ + debug(msg) { + this.log(this.LogLevel.DEBUG, msg); + }, + + /** Function: info + * Log a message at the Strophe.LogLevel.INFO level. + * + * Parameters: + * (String) msg - The log message. + */ + info(msg) { + this.log(this.LogLevel.INFO, msg); + }, + + /** Function: warn + * Log a message at the Strophe.LogLevel.WARN level. + * + * Parameters: + * (String) msg - The log message. + */ + warn(msg) { + this.log(this.LogLevel.WARN, msg); + }, + + /** Function: error + * Log a message at the Strophe.LogLevel.ERROR level. + * + * Parameters: + * (String) msg - The log message. + */ + error(msg) { + this.log(this.LogLevel.ERROR, msg); + }, + + /** Function: fatal + * Log a message at the Strophe.LogLevel.FATAL level. + * + * Parameters: + * (String) msg - The log message. + */ + fatal(msg) { + this.log(this.LogLevel.FATAL, msg); + }, + + /** Function: serialize + * Render a DOM element and all descendants to a String. + * + * Parameters: + * (XMLElement) elem - A DOM element. + * + * Returns: + * The serialized element tree as a String. + */ + serialize(elem) { + if (!elem) { + return null; + } + + if (typeof elem.tree === "function") { + elem = elem.tree(); + } + + const names = [...Array(elem.attributes.length).keys()].map(i => elem.attributes[i].nodeName); + names.sort(); + let result = names.reduce((a, n) => `${a} ${n}="${Strophe.xmlescape(elem.attributes.getNamedItem(n).value)}"`, `<${elem.nodeName}`); + + if (elem.childNodes.length > 0) { + result += ">"; + + for (let i = 0; i < elem.childNodes.length; i++) { + const child = elem.childNodes[i]; + + switch (child.nodeType) { + case Strophe.ElementType.NORMAL: + // normal element, so recurse + result += Strophe.serialize(child); + break; + + case Strophe.ElementType.TEXT: + // text element to escape values + result += Strophe.xmlescape(child.nodeValue); + break; + + case Strophe.ElementType.CDATA: + // cdata section so don't escape values + result += ""; + } + } + + result += ""; + } else { + result += "/>"; + } + + return result; + }, + + /** PrivateVariable: _requestId + * _Private_ variable that keeps track of the request ids for + * connections. + */ + _requestId: 0, + + /** PrivateVariable: Strophe.connectionPlugins + * _Private_ variable Used to store plugin names that need + * initialization on Strophe.Connection construction. + */ + _connectionPlugins: {}, + + /** Function: addConnectionPlugin + * Extends the Strophe.Connection object with the given plugin. + * + * Parameters: + * (String) name - The name of the extension. + * (Object) ptype - The plugin's prototype. + */ + addConnectionPlugin(name, ptype) { + Strophe._connectionPlugins[name] = ptype; + } + +}; +/** Class: Strophe.Builder + * XML DOM builder. + * + * This object provides an interface similar to JQuery but for building + * DOM elements easily and rapidly. All the functions except for toString() + * and tree() return the object, so calls can be chained. Here's an + * example using the $iq() builder helper. + * > $iq({to: 'you', from: 'me', type: 'get', id: '1'}) + * > .c('query', {xmlns: 'strophe:example'}) + * > .c('example') + * > .toString() + * + * The above generates this XML fragment + * > + * > + * > + * > + * > + * The corresponding DOM manipulations to get a similar fragment would be + * a lot more tedious and probably involve several helper variables. + * + * Since adding children makes new operations operate on the child, up() + * is provided to traverse up the tree. To add two children, do + * > builder.c('child1', ...).up().c('child2', ...) + * The next operation on the Builder will be relative to the second child. + */ + +/** Constructor: Strophe.Builder + * Create a Strophe.Builder object. + * + * The attributes should be passed in object notation. For example + * > let b = new Builder('message', {to: 'you', from: 'me'}); + * or + * > let b = new Builder('messsage', {'xml:lang': 'en'}); + * + * Parameters: + * (String) name - The name of the root element. + * (Object) attrs - The attributes for the root element in object notation. + * + * Returns: + * A new Strophe.Builder. + */ + +Strophe.Builder = class Builder { + constructor(name, attrs) { + // Set correct namespace for jabber:client elements + if (name === "presence" || name === "message" || name === "iq") { + if (attrs && !attrs.xmlns) { + attrs.xmlns = Strophe.NS.CLIENT; + } else if (!attrs) { + attrs = { + xmlns: Strophe.NS.CLIENT + }; + } + } // Holds the tree being built. + + + this.nodeTree = Strophe.xmlElement(name, attrs); // Points to the current operation node. + + this.node = this.nodeTree; + } + /** Function: tree + * Return the DOM tree. + * + * This function returns the current DOM tree as an element object. This + * is suitable for passing to functions like Strophe.Connection.send(). + * + * Returns: + * The DOM tree as a element object. + */ + + + tree() { + return this.nodeTree; + } + /** Function: toString + * Serialize the DOM tree to a String. + * + * This function returns a string serialization of the current DOM + * tree. It is often used internally to pass data to a + * Strophe.Request object. + * + * Returns: + * The serialized DOM tree in a String. + */ + + + toString() { + return Strophe.serialize(this.nodeTree); + } + /** Function: up + * Make the current parent element the new current element. + * + * This function is often used after c() to traverse back up the tree. + * For example, to add two children to the same element + * > builder.c('child1', {}).up().c('child2', {}); + * + * Returns: + * The Stophe.Builder object. + */ + + + up() { + this.node = this.node.parentNode; + return this; + } + /** Function: root + * Make the root element the new current element. + * + * When at a deeply nested element in the tree, this function can be used + * to jump back to the root of the tree, instead of having to repeatedly + * call up(). + * + * Returns: + * The Stophe.Builder object. + */ + + + root() { + this.node = this.nodeTree; + return this; + } + /** Function: attrs + * Add or modify attributes of the current element. + * + * The attributes should be passed in object notation. This function + * does not move the current element pointer. + * + * Parameters: + * (Object) moreattrs - The attributes to add/modify in object notation. + * + * Returns: + * The Strophe.Builder object. + */ + + + attrs(moreattrs) { + for (const k in moreattrs) { + if (Object.prototype.hasOwnProperty.call(moreattrs, k)) { + if (moreattrs[k] === undefined) { + this.node.removeAttribute(k); + } else { + this.node.setAttribute(k, moreattrs[k]); + } + } + } + + return this; + } + /** Function: c + * Add a child to the current element and make it the new current + * element. + * + * This function moves the current element pointer to the child, + * unless text is provided. If you need to add another child, it + * is necessary to use up() to go back to the parent in the tree. + * + * Parameters: + * (String) name - The name of the child. + * (Object) attrs - The attributes of the child in object notation. + * (String) text - The text to add to the child. + * + * Returns: + * The Strophe.Builder object. + */ + + + c(name, attrs, text) { + const child = Strophe.xmlElement(name, attrs, text); + this.node.appendChild(child); + + if (typeof text !== "string" && typeof text !== "number") { + this.node = child; + } + + return this; + } + /** Function: cnode + * Add a child to the current element and make it the new current + * element. + * + * This function is the same as c() except that instead of using a + * name and an attributes object to create the child it uses an + * existing DOM element object. + * + * Parameters: + * (XMLElement) elem - A DOM element. + * + * Returns: + * The Strophe.Builder object. + */ + + + cnode(elem) { + let impNode; + const xmlGen = Strophe.xmlGenerator(); + + try { + impNode = xmlGen.importNode !== undefined; + } catch (e) { + impNode = false; + } + + const newElem = impNode ? xmlGen.importNode(elem, true) : Strophe.copyElement(elem); + this.node.appendChild(newElem); + this.node = newElem; + return this; + } + /** Function: t + * Add a child text element. + * + * This *does not* make the child the new current element since there + * are no children of text elements. + * + * Parameters: + * (String) text - The text data to append to the current element. + * + * Returns: + * The Strophe.Builder object. + */ + + + t(text) { + const child = Strophe.xmlTextNode(text); + this.node.appendChild(child); + return this; + } + /** Function: h + * Replace current element contents with the HTML passed in. + * + * This *does not* make the child the new current element + * + * Parameters: + * (String) html - The html to insert as contents of current element. + * + * Returns: + * The Strophe.Builder object. + */ + + + h(html) { + const fragment = Strophe.xmlGenerator().createElement('body'); // force the browser to try and fix any invalid HTML tags + + fragment.innerHTML = html; // copy cleaned html into an xml dom + + const xhtml = Strophe.createHtml(fragment); + + while (xhtml.childNodes.length > 0) { + this.node.appendChild(xhtml.childNodes[0]); + } + + return this; + } + +}; +/** PrivateClass: Strophe.Handler + * _Private_ helper class for managing stanza handlers. + * + * A Strophe.Handler encapsulates a user provided callback function to be + * executed when matching stanzas are received by the connection. + * Handlers can be either one-off or persistant depending on their + * return value. Returning true will cause a Handler to remain active, and + * returning false will remove the Handler. + * + * Users will not use Strophe.Handler objects directly, but instead they + * will use Strophe.Connection.addHandler() and + * Strophe.Connection.deleteHandler(). + */ + +/** PrivateConstructor: Strophe.Handler + * Create and initialize a new Strophe.Handler. + * + * Parameters: + * (Function) handler - A function to be executed when the handler is run. + * (String) ns - The namespace to match. + * (String) name - The element name to match. + * (String) type - The element type to match. + * (String) id - The element id attribute to match. + * (String) from - The element from attribute to match. + * (Object) options - Handler options + * + * Returns: + * A new Strophe.Handler object. + */ + +Strophe.Handler = function (handler, ns, name, type, id, from, options) { + this.handler = handler; + this.ns = ns; + this.name = name; + this.type = type; + this.id = id; + this.options = options || { + 'matchBareFromJid': false, + 'ignoreNamespaceFragment': false + }; // BBB: Maintain backward compatibility with old `matchBare` option + + if (this.options.matchBare) { + Strophe.warn('The "matchBare" option is deprecated, use "matchBareFromJid" instead.'); + this.options.matchBareFromJid = this.options.matchBare; + delete this.options.matchBare; + } + + if (this.options.matchBareFromJid) { + this.from = from ? Strophe.getBareJidFromJid(from) : null; + } else { + this.from = from; + } // whether the handler is a user handler or a system handler + + + this.user = true; +}; + +Strophe.Handler.prototype = { + /** PrivateFunction: getNamespace + * Returns the XML namespace attribute on an element. + * If `ignoreNamespaceFragment` was passed in for this handler, then the + * URL fragment will be stripped. + * + * Parameters: + * (XMLElement) elem - The XML element with the namespace. + * + * Returns: + * The namespace, with optionally the fragment stripped. + */ + getNamespace(elem) { + let elNamespace = elem.getAttribute("xmlns"); + + if (elNamespace && this.options.ignoreNamespaceFragment) { + elNamespace = elNamespace.split('#')[0]; + } + + return elNamespace; + }, + + /** PrivateFunction: namespaceMatch + * Tests if a stanza matches the namespace set for this Strophe.Handler. + * + * Parameters: + * (XMLElement) elem - The XML element to test. + * + * Returns: + * true if the stanza matches and false otherwise. + */ + namespaceMatch(elem) { + let nsMatch = false; + + if (!this.ns) { + return true; + } else { + Strophe.forEachChild(elem, null, elem => { + if (this.getNamespace(elem) === this.ns) { + nsMatch = true; + } + }); + return nsMatch || this.getNamespace(elem) === this.ns; + } + }, + + /** PrivateFunction: isMatch + * Tests if a stanza matches the Strophe.Handler. + * + * Parameters: + * (XMLElement) elem - The XML element to test. + * + * Returns: + * true if the stanza matches and false otherwise. + */ + isMatch(elem) { + let from = elem.getAttribute('from'); + + if (this.options.matchBareFromJid) { + from = Strophe.getBareJidFromJid(from); + } + + const elem_type = elem.getAttribute("type"); + + if (this.namespaceMatch(elem) && (!this.name || Strophe.isTagEqual(elem, this.name)) && (!this.type || (Array.isArray(this.type) ? this.type.indexOf(elem_type) !== -1 : elem_type === this.type)) && (!this.id || elem.getAttribute("id") === this.id) && (!this.from || from === this.from)) { + return true; + } + + return false; + }, + + /** PrivateFunction: run + * Run the callback on a matching stanza. + * + * Parameters: + * (XMLElement) elem - The DOM element that triggered the + * Strophe.Handler. + * + * Returns: + * A boolean indicating if the handler should remain active. + */ + run(elem) { + let result = null; + + try { + result = this.handler(elem); + } catch (e) { + Strophe._handleError(e); + + throw e; + } + + return result; + }, + + /** PrivateFunction: toString + * Get a String representation of the Strophe.Handler object. + * + * Returns: + * A String. + */ + toString() { + return "{Handler: " + this.handler + "(" + this.name + "," + this.id + "," + this.ns + ")}"; + } + +}; +/** PrivateClass: Strophe.TimedHandler + * _Private_ helper class for managing timed handlers. + * + * A Strophe.TimedHandler encapsulates a user provided callback that + * should be called after a certain period of time or at regular + * intervals. The return value of the callback determines whether the + * Strophe.TimedHandler will continue to fire. + * + * Users will not use Strophe.TimedHandler objects directly, but instead + * they will use Strophe.Connection.addTimedHandler() and + * Strophe.Connection.deleteTimedHandler(). + */ + +Strophe.TimedHandler = class TimedHandler { + /** PrivateConstructor: Strophe.TimedHandler + * Create and initialize a new Strophe.TimedHandler object. + * + * Parameters: + * (Integer) period - The number of milliseconds to wait before the + * handler is called. + * (Function) handler - The callback to run when the handler fires. This + * function should take no arguments. + * + * Returns: + * A new Strophe.TimedHandler object. + */ + constructor(period, handler) { + this.period = period; + this.handler = handler; + this.lastCalled = new Date().getTime(); + this.user = true; + } + /** PrivateFunction: run + * Run the callback for the Strophe.TimedHandler. + * + * Returns: + * true if the Strophe.TimedHandler should be called again, and false + * otherwise. + */ + + + run() { + this.lastCalled = new Date().getTime(); + return this.handler(); + } + /** PrivateFunction: reset + * Reset the last called time for the Strophe.TimedHandler. + */ + + + reset() { + this.lastCalled = new Date().getTime(); + } + /** PrivateFunction: toString + * Get a string representation of the Strophe.TimedHandler object. + * + * Returns: + * The string representation. + */ + + + toString() { + return "{TimedHandler: " + this.handler + "(" + this.period + ")}"; + } + +}; +/** Class: Strophe.Connection + * XMPP Connection manager. + * + * This class is the main part of Strophe. It manages a BOSH or websocket + * connection to an XMPP server and dispatches events to the user callbacks + * as data arrives. It supports SASL PLAIN, SASL SCRAM-SHA-1 + * and legacy authentication. + * + * After creating a Strophe.Connection object, the user will typically + * call connect() with a user supplied callback to handle connection level + * events like authentication failure, disconnection, or connection + * complete. + * + * The user will also have several event handlers defined by using + * addHandler() and addTimedHandler(). These will allow the user code to + * respond to interesting stanzas or do something periodically with the + * connection. These handlers will be active once authentication is + * finished. + * + * To send data to the connection, use send(). + */ + +/** Constructor: Strophe.Connection + * Create and initialize a Strophe.Connection object. + * + * The transport-protocol for this connection will be chosen automatically + * based on the given service parameter. URLs starting with "ws://" or + * "wss://" will use WebSockets, URLs starting with "http://", "https://" + * or without a protocol will use BOSH. + * + * To make Strophe connect to the current host you can leave out the protocol + * and host part and just pass the path, e.g. + * + * > let conn = new Strophe.Connection("/http-bind/"); + * + * Options common to both Websocket and BOSH: + * ------------------------------------------ + * + * cookies: + * + * The *cookies* option allows you to pass in cookies to be added to the + * document. These cookies will then be included in the BOSH XMLHttpRequest + * or in the websocket connection. + * + * The passed in value must be a map of cookie names and string values. + * + * > { "myCookie": { + * > "value": "1234", + * > "domain": ".example.org", + * > "path": "/", + * > "expires": expirationDate + * > } + * > } + * + * Note that cookies can't be set in this way for other domains (i.e. cross-domain). + * Those cookies need to be set under those domains, for example they can be + * set server-side by making a XHR call to that domain to ask it to set any + * necessary cookies. + * + * mechanisms: + * + * The *mechanisms* option allows you to specify the SASL mechanisms that this + * instance of Strophe.Connection (and therefore your XMPP client) will + * support. + * + * The value must be an array of objects with Strophe.SASLMechanism + * prototypes. + * + * If nothing is specified, then the following mechanisms (and their + * priorities) are registered: + * + * SCRAM-SHA-1 - 60 + * PLAIN - 50 + * OAUTHBEARER - 40 + * X-OAUTH2 - 30 + * ANONYMOUS - 20 + * EXTERNAL - 10 + * + * explicitResourceBinding: + * + * If `explicitResourceBinding` is set to a truthy value, then the XMPP client + * needs to explicitly call `Strophe.Connection.prototype.bind` once the XMPP + * server has advertised the "urn:ietf:params:xml:ns:xmpp-bind" feature. + * + * Making this step explicit allows client authors to first finish other + * stream related tasks, such as setting up an XEP-0198 Stream Management + * session, before binding the JID resource for this session. + * + * WebSocket options: + * ------------------ + * + * protocol: + * + * If you want to connect to the current host with a WebSocket connection you + * can tell Strophe to use WebSockets through a "protocol" attribute in the + * optional options parameter. Valid values are "ws" for WebSocket and "wss" + * for Secure WebSocket. + * So to connect to "wss://CURRENT_HOSTNAME/xmpp-websocket" you would call + * + * > let conn = new Strophe.Connection("/xmpp-websocket/", {protocol: "wss"}); + * + * Note that relative URLs _NOT_ starting with a "/" will also include the path + * of the current site. + * + * Also because downgrading security is not permitted by browsers, when using + * relative URLs both BOSH and WebSocket connections will use their secure + * variants if the current connection to the site is also secure (https). + * + * worker: + * + * Set this option to URL from where the shared worker script should be loaded. + * + * To run the websocket connection inside a shared worker. + * This allows you to share a single websocket-based connection between + * multiple Strophe.Connection instances, for example one per browser tab. + * + * The script to use is the one in `src/shared-connection-worker.js`. + * + * BOSH options: + * ------------- + * + * By adding "sync" to the options, you can control if requests will + * be made synchronously or not. The default behaviour is asynchronous. + * If you want to make requests synchronous, make "sync" evaluate to true. + * > let conn = new Strophe.Connection("/http-bind/", {sync: true}); + * + * You can also toggle this on an already established connection. + * > conn.options.sync = true; + * + * The *customHeaders* option can be used to provide custom HTTP headers to be + * included in the XMLHttpRequests made. + * + * The *keepalive* option can be used to instruct Strophe to maintain the + * current BOSH session across interruptions such as webpage reloads. + * + * It will do this by caching the sessions tokens in sessionStorage, and when + * "restore" is called it will check whether there are cached tokens with + * which it can resume an existing session. + * + * The *withCredentials* option should receive a Boolean value and is used to + * indicate wether cookies should be included in ajax requests (by default + * they're not). + * Set this value to true if you are connecting to a BOSH service + * and for some reason need to send cookies to it. + * In order for this to work cross-domain, the server must also enable + * credentials by setting the Access-Control-Allow-Credentials response header + * to "true". For most usecases however this setting should be false (which + * is the default). + * Additionally, when using Access-Control-Allow-Credentials, the + * Access-Control-Allow-Origin header can't be set to the wildcard "*", but + * instead must be restricted to actual domains. + * + * The *contentType* option can be set to change the default Content-Type + * of "text/xml; charset=utf-8", which can be useful to reduce the amount of + * CORS preflight requests that are sent to the server. + * + * Parameters: + * (String) service - The BOSH or WebSocket service URL. + * (Object) options - A hash of configuration options + * + * Returns: + * A new Strophe.Connection object. + */ + +Strophe.Connection = class Connection { + constructor(service, options) { + // The service URL + this.service = service; // Configuration options + + this.options = options || {}; + this.setProtocol(); + /* The connected JID. */ + + this.jid = ""; + /* the JIDs domain */ + + this.domain = null; + /* stream:features */ + + this.features = null; // SASL + + this._sasl_data = {}; + this.do_bind = false; + this.do_session = false; + this.mechanisms = {}; // handler lists + + this.timedHandlers = []; + this.handlers = []; + this.removeTimeds = []; + this.removeHandlers = []; + this.addTimeds = []; + this.addHandlers = []; + this.protocolErrorHandlers = { + 'HTTP': {}, + 'websocket': {} + }; + this._idleTimeout = null; + this._disconnectTimeout = null; + this.authenticated = false; + this.connected = false; + this.disconnecting = false; + this.do_authentication = true; + this.paused = false; + this.restored = false; + this._data = []; + this._uniqueId = 0; + this._sasl_success_handler = null; + this._sasl_failure_handler = null; + this._sasl_challenge_handler = null; // Max retries before disconnecting + + this.maxRetries = 5; // Call onIdle callback every 1/10th of a second + + this._idleTimeout = setTimeout(() => this._onIdle(), 100); + utils.addCookies(this.options.cookies); + this.registerSASLMechanisms(this.options.mechanisms); // initialize plugins + + for (const k in Strophe._connectionPlugins) { + if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) { + const F = function () {}; + + F.prototype = Strophe._connectionPlugins[k]; + this[k] = new F(); + this[k].init(this); + } + } + } + /** Function: setProtocol + * Select protocal based on this.options or this.service + */ + + + setProtocol() { + const proto = this.options.protocol || ""; + + if (this.options.worker) { + this._proto = new Strophe.WorkerWebsocket(this); + } else if (this.service.indexOf("ws:") === 0 || this.service.indexOf("wss:") === 0 || proto.indexOf("ws") === 0) { + this._proto = new Strophe.Websocket(this); + } else { + this._proto = new Strophe.Bosh(this); + } + } + /** Function: reset + * Reset the connection. + * + * This function should be called after a connection is disconnected + * before that connection is reused. + */ + + + reset() { + this._proto._reset(); // SASL + + + this.do_session = false; + this.do_bind = false; // handler lists + + this.timedHandlers = []; + this.handlers = []; + this.removeTimeds = []; + this.removeHandlers = []; + this.addTimeds = []; + this.addHandlers = []; + this.authenticated = false; + this.connected = false; + this.disconnecting = false; + this.restored = false; + this._data = []; + this._requests = []; + this._uniqueId = 0; + } + /** Function: pause + * Pause the request manager. + * + * This will prevent Strophe from sending any more requests to the + * server. This is very useful for temporarily pausing + * BOSH-Connections while a lot of send() calls are happening quickly. + * This causes Strophe to send the data in a single request, saving + * many request trips. + */ + + + pause() { + this.paused = true; + } + /** Function: resume + * Resume the request manager. + * + * This resumes after pause() has been called. + */ + + + resume() { + this.paused = false; + } + /** Function: getUniqueId + * Generate a unique ID for use in elements. + * + * All stanzas are required to have unique id attributes. This + * function makes creating these easy. Each connection instance has + * a counter which starts from zero, and the value of this counter + * plus a colon followed by the suffix becomes the unique id. If no + * suffix is supplied, the counter is used as the unique id. + * + * Suffixes are used to make debugging easier when reading the stream + * data, and their use is recommended. The counter resets to 0 for + * every new connection for the same reason. For connections to the + * same server that authenticate the same way, all the ids should be + * the same, which makes it easy to see changes. This is useful for + * automated testing as well. + * + * Parameters: + * (String) suffix - A optional suffix to append to the id. + * + * Returns: + * A unique string to be used for the id attribute. + */ + + + getUniqueId(suffix) { + // eslint-disable-line class-methods-use-this + const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + const r = Math.random() * 16 | 0, + v = c === 'x' ? r : r & 0x3 | 0x8; + return v.toString(16); + }); + + if (typeof suffix === "string" || typeof suffix === "number") { + return uuid + ":" + suffix; + } else { + return uuid + ""; + } + } + /** Function: addProtocolErrorHandler + * Register a handler function for when a protocol (websocker or HTTP) + * error occurs. + * + * NOTE: Currently only HTTP errors for BOSH requests are handled. + * Patches that handle websocket errors would be very welcome. + * + * Parameters: + * (String) protocol - 'HTTP' or 'websocket' + * (Integer) status_code - Error status code (e.g 500, 400 or 404) + * (Function) callback - Function that will fire on Http error + * + * Example: + * function onError(err_code){ + * //do stuff + * } + * + * let conn = Strophe.connect('http://example.com/http-bind'); + * conn.addProtocolErrorHandler('HTTP', 500, onError); + * // Triggers HTTP 500 error and onError handler will be called + * conn.connect('user_jid@incorrect_jabber_host', 'secret', onConnect); + */ + + + addProtocolErrorHandler(protocol, status_code, callback) { + this.protocolErrorHandlers[protocol][status_code] = callback; + } + /** Function: connect + * Starts the connection process. + * + * As the connection process proceeds, the user supplied callback will + * be triggered multiple times with status updates. The callback + * should take two arguments - the status code and the error condition. + * + * The status code will be one of the values in the Strophe.Status + * constants. The error condition will be one of the conditions + * defined in RFC 3920 or the condition 'strophe-parsererror'. + * + * The Parameters _wait_, _hold_ and _route_ are optional and only relevant + * for BOSH connections. Please see XEP 124 for a more detailed explanation + * of the optional parameters. + * + * Parameters: + * (String) jid - The user's JID. This may be a bare JID, + * or a full JID. If a node is not supplied, SASL OAUTHBEARER or + * SASL ANONYMOUS authentication will be attempted (OAUTHBEARER will + * process the provided password value as an access token). + * (String) pass - The user's password. + * (Function) callback - The connect callback function. + * (Integer) wait - The optional HTTPBIND wait value. This is the + * time the server will wait before returning an empty result for + * a request. The default setting of 60 seconds is recommended. + * (Integer) hold - The optional HTTPBIND hold value. This is the + * number of connections the server will hold at one time. This + * should almost always be set to 1 (the default). + * (String) route - The optional route value. + * (String) authcid - The optional alternative authentication identity + * (username) if intending to impersonate another user. + * When using the SASL-EXTERNAL authentication mechanism, for example + * with client certificates, then the authcid value is used to + * determine whether an authorization JID (authzid) should be sent to + * the server. The authzid should NOT be sent to the server if the + * authzid and authcid are the same. So to prevent it from being sent + * (for example when the JID is already contained in the client + * certificate), set authcid to that same JID. See XEP-178 for more + * details. + */ + + + connect(jid, pass, callback, wait, hold, route, authcid) { + this.jid = jid; + /** Variable: authzid + * Authorization identity. + */ + + this.authzid = Strophe.getBareJidFromJid(this.jid); + /** Variable: authcid + * Authentication identity (User name). + */ + + this.authcid = authcid || Strophe.getNodeFromJid(this.jid); + /** Variable: pass + * Authentication identity (User password). + */ + + this.pass = pass; + this.connect_callback = callback; + this.disconnecting = false; + this.connected = false; + this.authenticated = false; + this.restored = false; // parse jid for domain + + this.domain = Strophe.getDomainFromJid(this.jid); + + this._changeConnectStatus(Strophe.Status.CONNECTING, null); + + this._proto._connect(wait, hold, route); + } + /** Function: attach + * Attach to an already created and authenticated BOSH session. + * + * This function is provided to allow Strophe to attach to BOSH + * sessions which have been created externally, perhaps by a Web + * application. This is often used to support auto-login type features + * without putting user credentials into the page. + * + * Parameters: + * (String) jid - The full JID that is bound by the session. + * (String) sid - The SID of the BOSH session. + * (String) rid - The current RID of the BOSH session. This RID + * will be used by the next request. + * (Function) callback The connect callback function. + * (Integer) wait - The optional HTTPBIND wait value. This is the + * time the server will wait before returning an empty result for + * a request. The default setting of 60 seconds is recommended. + * Other settings will require tweaks to the Strophe.TIMEOUT value. + * (Integer) hold - The optional HTTPBIND hold value. This is the + * number of connections the server will hold at one time. This + * should almost always be set to 1 (the default). + * (Integer) wind - The optional HTTBIND window value. This is the + * allowed range of request ids that are valid. The default is 5. + */ + + + attach(jid, sid, rid, callback, wait, hold, wind) { + if (this._proto._attach) { + return this._proto._attach(jid, sid, rid, callback, wait, hold, wind); + } else { + const error = new Error('The "attach" method is not available for your connection protocol'); + error.name = 'StropheSessionError'; + throw error; + } + } + /** Function: restore + * Attempt to restore a cached BOSH session. + * + * This function is only useful in conjunction with providing the + * "keepalive":true option when instantiating a new Strophe.Connection. + * + * When "keepalive" is set to true, Strophe will cache the BOSH tokens + * RID (Request ID) and SID (Session ID) and then when this function is + * called, it will attempt to restore the session from those cached + * tokens. + * + * This function must therefore be called instead of connect or attach. + * + * For an example on how to use it, please see examples/restore.js + * + * Parameters: + * (String) jid - The user's JID. This may be a bare JID or a full JID. + * (Function) callback - The connect callback function. + * (Integer) wait - The optional HTTPBIND wait value. This is the + * time the server will wait before returning an empty result for + * a request. The default setting of 60 seconds is recommended. + * (Integer) hold - The optional HTTPBIND hold value. This is the + * number of connections the server will hold at one time. This + * should almost always be set to 1 (the default). + * (Integer) wind - The optional HTTBIND window value. This is the + * allowed range of request ids that are valid. The default is 5. + */ + + + restore(jid, callback, wait, hold, wind) { + if (this._sessionCachingSupported()) { + this._proto._restore(jid, callback, wait, hold, wind); + } else { + const error = new Error('The "restore" method can only be used with a BOSH connection.'); + error.name = 'StropheSessionError'; + throw error; + } + } + /** PrivateFunction: _sessionCachingSupported + * Checks whether sessionStorage and JSON are supported and whether we're + * using BOSH. + */ + + + _sessionCachingSupported() { + if (this._proto instanceof Strophe.Bosh) { + if (!JSON) { + return false; + } + + try { + sessionStorage.setItem('_strophe_', '_strophe_'); + sessionStorage.removeItem('_strophe_'); + } catch (e) { + return false; + } + + return true; + } + + return false; + } + /** Function: xmlInput + * User overrideable function that receives XML data coming into the + * connection. + * + * The default function does nothing. User code can override this with + * > Strophe.Connection.xmlInput = function (elem) { + * > (user code) + * > }; + * + * Due to limitations of current Browsers' XML-Parsers the opening and closing + * tag for WebSocket-Connoctions will be passed as selfclosing here. + * + * BOSH-Connections will have all stanzas wrapped in a tag. See + * if you want to strip this tag. + * + * Parameters: + * (XMLElement) elem - The XML data received by the connection. + */ + + + xmlInput(elem) { + // eslint-disable-line + return; + } + /** Function: xmlOutput + * User overrideable function that receives XML data sent to the + * connection. + * + * The default function does nothing. User code can override this with + * > Strophe.Connection.xmlOutput = function (elem) { + * > (user code) + * > }; + * + * Due to limitations of current Browsers' XML-Parsers the opening and closing + * tag for WebSocket-Connoctions will be passed as selfclosing here. + * + * BOSH-Connections will have all stanzas wrapped in a tag. See + * if you want to strip this tag. + * + * Parameters: + * (XMLElement) elem - The XMLdata sent by the connection. + */ + + + xmlOutput(elem) { + // eslint-disable-line + return; + } + /** Function: rawInput + * User overrideable function that receives raw data coming into the + * connection. + * + * The default function does nothing. User code can override this with + * > Strophe.Connection.rawInput = function (data) { + * > (user code) + * > }; + * + * Parameters: + * (String) data - The data received by the connection. + */ + + + rawInput(data) { + // eslint-disable-line + return; + } + /** Function: rawOutput + * User overrideable function that receives raw data sent to the + * connection. + * + * The default function does nothing. User code can override this with + * > Strophe.Connection.rawOutput = function (data) { + * > (user code) + * > }; + * + * Parameters: + * (String) data - The data sent by the connection. + */ + + + rawOutput(data) { + // eslint-disable-line + return; + } + /** Function: nextValidRid + * User overrideable function that receives the new valid rid. + * + * The default function does nothing. User code can override this with + * > Strophe.Connection.nextValidRid = function (rid) { + * > (user code) + * > }; + * + * Parameters: + * (Number) rid - The next valid rid + */ + + + nextValidRid(rid) { + // eslint-disable-line + return; + } + /** Function: send + * Send a stanza. + * + * This function is called to push data onto the send queue to + * go out over the wire. Whenever a request is sent to the BOSH + * server, all pending data is sent and the queue is flushed. + * + * Parameters: + * (XMLElement | + * [XMLElement] | + * Strophe.Builder) elem - The stanza to send. + */ + + + send(elem) { + if (elem === null) { + return; + } + + if (typeof elem.sort === "function") { + for (let i = 0; i < elem.length; i++) { + this._queueData(elem[i]); + } + } else if (typeof elem.tree === "function") { + this._queueData(elem.tree()); + } else { + this._queueData(elem); + } + + this._proto._send(); + } + /** Function: flush + * Immediately send any pending outgoing data. + * + * Normally send() queues outgoing data until the next idle period + * (100ms), which optimizes network use in the common cases when + * several send()s are called in succession. flush() can be used to + * immediately send all pending data. + */ + + + flush() { + // cancel the pending idle period and run the idle function + // immediately + clearTimeout(this._idleTimeout); + + this._onIdle(); + } + /** Function: sendPresence + * Helper function to send presence stanzas. The main benefit is for + * sending presence stanzas for which you expect a responding presence + * stanza with the same id (for example when leaving a chat room). + * + * Parameters: + * (XMLElement) elem - The stanza to send. + * (Function) callback - The callback function for a successful request. + * (Function) errback - The callback function for a failed or timed + * out request. On timeout, the stanza will be null. + * (Integer) timeout - The time specified in milliseconds for a + * timeout to occur. + * + * Returns: + * The id used to send the presence. + */ + + + sendPresence(elem, callback, errback, timeout) { + let timeoutHandler = null; + + if (typeof elem.tree === "function") { + elem = elem.tree(); + } + + let id = elem.getAttribute('id'); + + if (!id) { + // inject id if not found + id = this.getUniqueId("sendPresence"); + elem.setAttribute("id", id); + } + + if (typeof callback === "function" || typeof errback === "function") { + const handler = this.addHandler(stanza => { + // remove timeout handler if there is one + if (timeoutHandler) { + this.deleteTimedHandler(timeoutHandler); + } + + if (stanza.getAttribute('type') === 'error') { + if (errback) { + errback(stanza); + } + } else if (callback) { + callback(stanza); + } + }, null, 'presence', null, id); // if timeout specified, set up a timeout handler. + + if (timeout) { + timeoutHandler = this.addTimedHandler(timeout, () => { + // get rid of normal handler + this.deleteHandler(handler); // call errback on timeout with null stanza + + if (errback) { + errback(null); + } + + return false; + }); + } + } + + this.send(elem); + return id; + } + /** Function: sendIQ + * Helper function to send IQ stanzas. + * + * Parameters: + * (XMLElement) elem - The stanza to send. + * (Function) callback - The callback function for a successful request. + * (Function) errback - The callback function for a failed or timed + * out request. On timeout, the stanza will be null. + * (Integer) timeout - The time specified in milliseconds for a + * timeout to occur. + * + * Returns: + * The id used to send the IQ. + */ + + + sendIQ(elem, callback, errback, timeout) { + let timeoutHandler = null; + + if (typeof elem.tree === "function") { + elem = elem.tree(); + } + + let id = elem.getAttribute('id'); + + if (!id) { + // inject id if not found + id = this.getUniqueId("sendIQ"); + elem.setAttribute("id", id); + } + + if (typeof callback === "function" || typeof errback === "function") { + const handler = this.addHandler(stanza => { + // remove timeout handler if there is one + if (timeoutHandler) { + this.deleteTimedHandler(timeoutHandler); + } + + const iqtype = stanza.getAttribute('type'); + + if (iqtype === 'result') { + if (callback) { + callback(stanza); + } + } else if (iqtype === 'error') { + if (errback) { + errback(stanza); + } + } else { + const error = new Error(`Got bad IQ type of ${iqtype}`); + error.name = "StropheError"; + throw error; + } + }, null, 'iq', ['error', 'result'], id); // if timeout specified, set up a timeout handler. + + if (timeout) { + timeoutHandler = this.addTimedHandler(timeout, () => { + // get rid of normal handler + this.deleteHandler(handler); // call errback on timeout with null stanza + + if (errback) { + errback(null); + } + + return false; + }); + } + } + + this.send(elem); + return id; + } + /** PrivateFunction: _queueData + * Queue outgoing data for later sending. Also ensures that the data + * is a DOMElement. + */ + + + _queueData(element) { + if (element === null || !element.tagName || !element.childNodes) { + const error = new Error("Cannot queue non-DOMElement."); + error.name = "StropheError"; + throw error; + } + + this._data.push(element); + } + /** PrivateFunction: _sendRestart + * Send an xmpp:restart stanza. + */ + + + _sendRestart() { + this._data.push("restart"); + + this._proto._sendRestart(); + + this._idleTimeout = setTimeout(() => this._onIdle(), 100); + } + /** Function: addTimedHandler + * Add a timed handler to the connection. + * + * This function adds a timed handler. The provided handler will + * be called every period milliseconds until it returns false, + * the connection is terminated, or the handler is removed. Handlers + * that wish to continue being invoked should return true. + * + * Because of method binding it is necessary to save the result of + * this function if you wish to remove a handler with + * deleteTimedHandler(). + * + * Note that user handlers are not active until authentication is + * successful. + * + * Parameters: + * (Integer) period - The period of the handler. + * (Function) handler - The callback function. + * + * Returns: + * A reference to the handler that can be used to remove it. + */ + + + addTimedHandler(period, handler) { + const thand = new Strophe.TimedHandler(period, handler); + this.addTimeds.push(thand); + return thand; + } + /** Function: deleteTimedHandler + * Delete a timed handler for a connection. + * + * This function removes a timed handler from the connection. The + * handRef parameter is *not* the function passed to addTimedHandler(), + * but is the reference returned from addTimedHandler(). + * + * Parameters: + * (Strophe.TimedHandler) handRef - The handler reference. + */ + + + deleteTimedHandler(handRef) { + // this must be done in the Idle loop so that we don't change + // the handlers during iteration + this.removeTimeds.push(handRef); + } + /** Function: addHandler + * Add a stanza handler for the connection. + * + * This function adds a stanza handler to the connection. The + * handler callback will be called for any stanza that matches + * the parameters. Note that if multiple parameters are supplied, + * they must all match for the handler to be invoked. + * + * The handler will receive the stanza that triggered it as its argument. + * *The handler should return true if it is to be invoked again; + * returning false will remove the handler after it returns.* + * + * As a convenience, the ns parameters applies to the top level element + * and also any of its immediate children. This is primarily to make + * matching /iq/query elements easy. + * + * Options + * ~~~~~~~ + * With the options argument, you can specify boolean flags that affect how + * matches are being done. + * + * Currently two flags exist: + * + * - matchBareFromJid: + * When set to true, the from parameter and the + * from attribute on the stanza will be matched as bare JIDs instead + * of full JIDs. To use this, pass {matchBareFromJid: true} as the + * value of options. The default value for matchBareFromJid is false. + * + * - ignoreNamespaceFragment: + * When set to true, a fragment specified on the stanza's namespace + * URL will be ignored when it's matched with the one configured for + * the handler. + * + * This means that if you register like this: + * > connection.addHandler( + * > handler, + * > 'http://jabber.org/protocol/muc', + * > null, null, null, null, + * > {'ignoreNamespaceFragment': true} + * > ); + * + * Then a stanza with XML namespace of + * 'http://jabber.org/protocol/muc#user' will also be matched. If + * 'ignoreNamespaceFragment' is false, then only stanzas with + * 'http://jabber.org/protocol/muc' will be matched. + * + * Deleting the handler + * ~~~~~~~~~~~~~~~~~~~~ + * The return value should be saved if you wish to remove the handler + * with deleteHandler(). + * + * Parameters: + * (Function) handler - The user callback. + * (String) ns - The namespace to match. + * (String) name - The stanza name to match. + * (String|Array) type - The stanza type (or types if an array) to match. + * (String) id - The stanza id attribute to match. + * (String) from - The stanza from attribute to match. + * (String) options - The handler options + * + * Returns: + * A reference to the handler that can be used to remove it. + */ + + + addHandler(handler, ns, name, type, id, from, options) { + const hand = new Strophe.Handler(handler, ns, name, type, id, from, options); + this.addHandlers.push(hand); + return hand; + } + /** Function: deleteHandler + * Delete a stanza handler for a connection. + * + * This function removes a stanza handler from the connection. The + * handRef parameter is *not* the function passed to addHandler(), + * but is the reference returned from addHandler(). + * + * Parameters: + * (Strophe.Handler) handRef - The handler reference. + */ + + + deleteHandler(handRef) { + // this must be done in the Idle loop so that we don't change + // the handlers during iteration + this.removeHandlers.push(handRef); // If a handler is being deleted while it is being added, + // prevent it from getting added + + const i = this.addHandlers.indexOf(handRef); + + if (i >= 0) { + this.addHandlers.splice(i, 1); + } + } + /** Function: registerSASLMechanisms + * + * Register the SASL mechanisms which will be supported by this instance of + * Strophe.Connection (i.e. which this XMPP client will support). + * + * Parameters: + * (Array) mechanisms - Array of objects with Strophe.SASLMechanism prototypes + * + */ + + + registerSASLMechanisms(mechanisms) { + this.mechanisms = {}; + mechanisms = mechanisms || [Strophe.SASLAnonymous, Strophe.SASLExternal, Strophe.SASLOAuthBearer, Strophe.SASLXOAuth2, Strophe.SASLPlain, Strophe.SASLSHA1]; + mechanisms.forEach(m => this.registerSASLMechanism(m)); + } + /** Function: registerSASLMechanism + * + * Register a single SASL mechanism, to be supported by this client. + * + * Parameters: + * (Object) mechanism - Object with a Strophe.SASLMechanism prototype + * + */ + + + registerSASLMechanism(Mechanism) { + const mechanism = new Mechanism(); + this.mechanisms[mechanism.mechname] = mechanism; + } + /** Function: disconnect + * Start the graceful disconnection process. + * + * This function starts the disconnection process. This process starts + * by sending unavailable presence and sending BOSH body of type + * terminate. A timeout handler makes sure that disconnection happens + * even if the BOSH server does not respond. + * If the Connection object isn't connected, at least tries to abort all pending requests + * so the connection object won't generate successful requests (which were already opened). + * + * The user supplied connection callback will be notified of the + * progress as this process happens. + * + * Parameters: + * (String) reason - The reason the disconnect is occuring. + */ + + + disconnect(reason) { + this._changeConnectStatus(Strophe.Status.DISCONNECTING, reason); + + if (reason) { + Strophe.warn("Disconnect was called because: " + reason); + } else { + Strophe.info("Disconnect was called"); + } + + if (this.connected) { + let pres = false; + this.disconnecting = true; + + if (this.authenticated) { + pres = $pres({ + 'xmlns': Strophe.NS.CLIENT, + 'type': 'unavailable' + }); + } // setup timeout handler + + + this._disconnectTimeout = this._addSysTimedHandler(3000, this._onDisconnectTimeout.bind(this)); + + this._proto._disconnect(pres); + } else { + Strophe.warn("Disconnect was called before Strophe connected to the server"); + + this._proto._abortAllRequests(); + + this._doDisconnect(); + } + } + /** PrivateFunction: _changeConnectStatus + * _Private_ helper function that makes sure plugins and the user's + * callback are notified of connection status changes. + * + * Parameters: + * (Integer) status - the new connection status, one of the values + * in Strophe.Status + * (String) condition - the error condition or null + * (XMLElement) elem - The triggering stanza. + */ + + + _changeConnectStatus(status, condition, elem) { + // notify all plugins listening for status changes + for (const k in Strophe._connectionPlugins) { + if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) { + const plugin = this[k]; + + if (plugin.statusChanged) { + try { + plugin.statusChanged(status, condition); + } catch (err) { + Strophe.error(`${k} plugin caused an exception changing status: ${err}`); + } + } + } + } // notify the user's callback + + + if (this.connect_callback) { + try { + this.connect_callback(status, condition, elem); + } catch (e) { + Strophe._handleError(e); + + Strophe.error(`User connection callback caused an exception: ${e}`); + } + } + } + /** PrivateFunction: _doDisconnect + * _Private_ function to disconnect. + * + * This is the last piece of the disconnection logic. This resets the + * connection and alerts the user's connection callback. + */ + + + _doDisconnect(condition) { + if (typeof this._idleTimeout === "number") { + clearTimeout(this._idleTimeout); + } // Cancel Disconnect Timeout + + + if (this._disconnectTimeout !== null) { + this.deleteTimedHandler(this._disconnectTimeout); + this._disconnectTimeout = null; + } + + Strophe.debug("_doDisconnect was called"); + + this._proto._doDisconnect(); + + this.authenticated = false; + this.disconnecting = false; + this.restored = false; // delete handlers + + this.handlers = []; + this.timedHandlers = []; + this.removeTimeds = []; + this.removeHandlers = []; + this.addTimeds = []; + this.addHandlers = []; // tell the parent we disconnected + + this._changeConnectStatus(Strophe.Status.DISCONNECTED, condition); + + this.connected = false; + } + /** PrivateFunction: _dataRecv + * _Private_ handler to processes incoming data from the the connection. + * + * Except for _connect_cb handling the initial connection request, + * this function handles the incoming data for all requests. This + * function also fires stanza handlers that match each incoming + * stanza. + * + * Parameters: + * (Strophe.Request) req - The request that has data ready. + * (string) req - The stanza a raw string (optiona). + */ + + + _dataRecv(req, raw) { + const elem = this._proto._reqToData(req); + + if (elem === null) { + return; + } + + if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { + if (elem.nodeName === this._proto.strip && elem.childNodes.length) { + this.xmlInput(elem.childNodes[0]); + } else { + this.xmlInput(elem); + } + } + + if (this.rawInput !== Strophe.Connection.prototype.rawInput) { + if (raw) { + this.rawInput(raw); + } else { + this.rawInput(Strophe.serialize(elem)); + } + } // remove handlers scheduled for deletion + + + while (this.removeHandlers.length > 0) { + const hand = this.removeHandlers.pop(); + const i = this.handlers.indexOf(hand); + + if (i >= 0) { + this.handlers.splice(i, 1); + } + } // add handlers scheduled for addition + + + while (this.addHandlers.length > 0) { + this.handlers.push(this.addHandlers.pop()); + } // handle graceful disconnect + + + if (this.disconnecting && this._proto._emptyQueue()) { + this._doDisconnect(); + + return; + } + + const type = elem.getAttribute("type"); + + if (type !== null && type === "terminate") { + // Don't process stanzas that come in after disconnect + if (this.disconnecting) { + return; + } // an error occurred + + + let cond = elem.getAttribute("condition"); + const conflict = elem.getElementsByTagName("conflict"); + + if (cond !== null) { + if (cond === "remote-stream-error" && conflict.length > 0) { + cond = "conflict"; + } + + this._changeConnectStatus(Strophe.Status.CONNFAIL, cond); + } else { + this._changeConnectStatus(Strophe.Status.CONNFAIL, Strophe.ErrorCondition.UNKOWN_REASON); + } + + this._doDisconnect(cond); + + return; + } // send each incoming stanza through the handler chain + + + Strophe.forEachChild(elem, null, child => { + // process handlers + const newList = this.handlers; + this.handlers = []; + + for (let i = 0; i < newList.length; i++) { + const hand = newList[i]; // encapsulate 'handler.run' not to lose the whole handler list if + // one of the handlers throws an exception + + try { + if (hand.isMatch(child) && (this.authenticated || !hand.user)) { + if (hand.run(child)) { + this.handlers.push(hand); + } + } else { + this.handlers.push(hand); + } + } catch (e) { + // if the handler throws an exception, we consider it as false + Strophe.warn('Removing Strophe handlers due to uncaught exception: ' + e.message); + } + } + }); + } + /** PrivateFunction: _connect_cb + * _Private_ handler for initial connection request. + * + * This handler is used to process the initial connection request + * response from the BOSH server. It is used to set up authentication + * handlers and start the authentication process. + * + * SASL authentication will be attempted if available, otherwise + * the code will fall back to legacy authentication. + * + * Parameters: + * (Strophe.Request) req - The current request. + * (Function) _callback - low level (xmpp) connect callback function. + * Useful for plugins with their own xmpp connect callback (when they + * want to do something special). + */ + + + _connect_cb(req, _callback, raw) { + Strophe.debug("_connect_cb was called"); + this.connected = true; + let bodyWrap; + + try { + bodyWrap = this._proto._reqToData(req); + } catch (e) { + if (e.name !== Strophe.ErrorCondition.BAD_FORMAT) { + throw e; + } + + this._changeConnectStatus(Strophe.Status.CONNFAIL, Strophe.ErrorCondition.BAD_FORMAT); + + this._doDisconnect(Strophe.ErrorCondition.BAD_FORMAT); + } + + if (!bodyWrap) { + return; + } + + if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) { + if (bodyWrap.nodeName === this._proto.strip && bodyWrap.childNodes.length) { + this.xmlInput(bodyWrap.childNodes[0]); + } else { + this.xmlInput(bodyWrap); + } + } + + if (this.rawInput !== Strophe.Connection.prototype.rawInput) { + if (raw) { + this.rawInput(raw); + } else { + this.rawInput(Strophe.serialize(bodyWrap)); + } + } + + const conncheck = this._proto._connect_cb(bodyWrap); + + if (conncheck === Strophe.Status.CONNFAIL) { + return; + } // Check for the stream:features tag + + + let hasFeatures; + + if (bodyWrap.getElementsByTagNameNS) { + hasFeatures = bodyWrap.getElementsByTagNameNS(Strophe.NS.STREAM, "features").length > 0; + } else { + hasFeatures = bodyWrap.getElementsByTagName("stream:features").length > 0 || bodyWrap.getElementsByTagName("features").length > 0; + } + + if (!hasFeatures) { + this._proto._no_auth_received(_callback); + + return; + } + + const matched = Array.from(bodyWrap.getElementsByTagName("mechanism")).map(m => this.mechanisms[m.textContent]).filter(m => m); + + if (matched.length === 0) { + if (bodyWrap.getElementsByTagName("auth").length === 0) { + // There are no matching SASL mechanisms and also no legacy + // auth available. + this._proto._no_auth_received(_callback); + + return; + } + } + + if (this.do_authentication !== false) { + this.authenticate(matched); + } + } + /** Function: sortMechanismsByPriority + * + * Sorts an array of objects with prototype SASLMechanism according to + * their priorities. + * + * Parameters: + * (Array) mechanisms - Array of SASL mechanisms. + * + */ + + + sortMechanismsByPriority(mechanisms) { + // eslint-disable-line class-methods-use-this + // Sorting mechanisms according to priority. + for (let i = 0; i < mechanisms.length - 1; ++i) { + let higher = i; + + for (let j = i + 1; j < mechanisms.length; ++j) { + if (mechanisms[j].priority > mechanisms[higher].priority) { + higher = j; + } + } + + if (higher !== i) { + const swap = mechanisms[i]; + mechanisms[i] = mechanisms[higher]; + mechanisms[higher] = swap; + } + } + + return mechanisms; + } + /** Function: authenticate + * Set up authentication + * + * Continues the initial connection request by setting up authentication + * handlers and starting the authentication process. + * + * SASL authentication will be attempted if available, otherwise + * the code will fall back to legacy authentication. + * + * Parameters: + * (Array) matched - Array of SASL mechanisms supported. + * + */ + + + authenticate(matched) { + if (!this._attemptSASLAuth(matched)) { + this._attemptLegacyAuth(); + } + } + /** PrivateFunction: _attemptSASLAuth + * + * Iterate through an array of SASL mechanisms and attempt authentication + * with the highest priority (enabled) mechanism. + * + * Parameters: + * (Array) mechanisms - Array of SASL mechanisms. + * + * Returns: + * (Boolean) mechanism_found - true or false, depending on whether a + * valid SASL mechanism was found with which authentication could be + * started. + */ + + + _attemptSASLAuth(mechanisms) { + mechanisms = this.sortMechanismsByPriority(mechanisms || []); + let mechanism_found = false; + + for (let i = 0; i < mechanisms.length; ++i) { + if (!mechanisms[i].test(this)) { + continue; + } + + this._sasl_success_handler = this._addSysHandler(this._sasl_success_cb.bind(this), null, "success", null, null); + this._sasl_failure_handler = this._addSysHandler(this._sasl_failure_cb.bind(this), null, "failure", null, null); + this._sasl_challenge_handler = this._addSysHandler(this._sasl_challenge_cb.bind(this), null, "challenge", null, null); + this._sasl_mechanism = mechanisms[i]; + + this._sasl_mechanism.onStart(this); + + const request_auth_exchange = $build("auth", { + 'xmlns': Strophe.NS.SASL, + 'mechanism': this._sasl_mechanism.mechname + }); + + if (this._sasl_mechanism.isClientFirst) { + const response = this._sasl_mechanism.clientChallenge(this); + + request_auth_exchange.t(Object(abab["btoa"])(response)); + } + + this.send(request_auth_exchange.tree()); + mechanism_found = true; + break; + } + + return mechanism_found; + } + /** PrivateFunction: _sasl_challenge_cb + * _Private_ handler for the SASL challenge + * + */ + + + _sasl_challenge_cb(elem) { + const challenge = Object(abab["atob"])(Strophe.getText(elem)); + + const response = this._sasl_mechanism.onChallenge(this, challenge); + + const stanza = $build('response', { + 'xmlns': Strophe.NS.SASL + }); + + if (response !== "") { + stanza.t(Object(abab["btoa"])(response)); + } + + this.send(stanza.tree()); + return true; + } + /** PrivateFunction: _attemptLegacyAuth + * + * Attempt legacy (i.e. non-SASL) authentication. + */ + + + _attemptLegacyAuth() { + if (Strophe.getNodeFromJid(this.jid) === null) { + // we don't have a node, which is required for non-anonymous + // client connections + this._changeConnectStatus(Strophe.Status.CONNFAIL, Strophe.ErrorCondition.MISSING_JID_NODE); + + this.disconnect(Strophe.ErrorCondition.MISSING_JID_NODE); + } else { + // Fall back to legacy authentication + this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); + + this._addSysHandler(this._onLegacyAuthIQResult.bind(this), null, null, null, "_auth_1"); + + this.send($iq({ + 'type': "get", + 'to': this.domain, + 'id': "_auth_1" + }).c("query", { + xmlns: Strophe.NS.AUTH + }).c("username", {}).t(Strophe.getNodeFromJid(this.jid)).tree()); + } + } + /** PrivateFunction: _onLegacyAuthIQResult + * _Private_ handler for legacy authentication. + * + * This handler is called in response to the initial + * for legacy authentication. It builds an authentication and + * sends it, creating a handler (calling back to _auth2_cb()) to + * handle the result + * + * Parameters: + * (XMLElement) elem - The stanza that triggered the callback. + * + * Returns: + * false to remove the handler. + */ + + + _onLegacyAuthIQResult(elem) { + // eslint-disable-line no-unused-vars + // build plaintext auth iq + const iq = $iq({ + type: "set", + id: "_auth_2" + }).c('query', { + xmlns: Strophe.NS.AUTH + }).c('username', {}).t(Strophe.getNodeFromJid(this.jid)).up().c('password').t(this.pass); + + if (!Strophe.getResourceFromJid(this.jid)) { + // since the user has not supplied a resource, we pick + // a default one here. unlike other auth methods, the server + // cannot do this for us. + this.jid = Strophe.getBareJidFromJid(this.jid) + '/strophe'; + } + + iq.up().c('resource', {}).t(Strophe.getResourceFromJid(this.jid)); + + this._addSysHandler(this._auth2_cb.bind(this), null, null, null, "_auth_2"); + + this.send(iq.tree()); + return false; + } + /** PrivateFunction: _sasl_success_cb + * _Private_ handler for succesful SASL authentication. + * + * Parameters: + * (XMLElement) elem - The matching stanza. + * + * Returns: + * false to remove the handler. + */ + + + _sasl_success_cb(elem) { + if (this._sasl_data["server-signature"]) { + let serverSignature; + const success = Object(abab["atob"])(Strophe.getText(elem)); + const attribMatch = /([a-z]+)=([^,]+)(,|$)/; + const matches = success.match(attribMatch); + + if (matches[1] === "v") { + serverSignature = matches[2]; + } + + if (serverSignature !== this._sasl_data["server-signature"]) { + // remove old handlers + this.deleteHandler(this._sasl_failure_handler); + this._sasl_failure_handler = null; + + if (this._sasl_challenge_handler) { + this.deleteHandler(this._sasl_challenge_handler); + this._sasl_challenge_handler = null; + } + + this._sasl_data = {}; + return this._sasl_failure_cb(null); + } + } + + Strophe.info("SASL authentication succeeded."); + + if (this._sasl_mechanism) { + this._sasl_mechanism.onSuccess(); + } // remove old handlers + + + this.deleteHandler(this._sasl_failure_handler); + this._sasl_failure_handler = null; + + if (this._sasl_challenge_handler) { + this.deleteHandler(this._sasl_challenge_handler); + this._sasl_challenge_handler = null; + } + + const streamfeature_handlers = []; + + const wrapper = (handlers, elem) => { + while (handlers.length) { + this.deleteHandler(handlers.pop()); + } + + this._onStreamFeaturesAfterSASL(elem); + + return false; + }; + + streamfeature_handlers.push(this._addSysHandler(elem => wrapper(streamfeature_handlers, elem), null, "stream:features", null, null)); + streamfeature_handlers.push(this._addSysHandler(elem => wrapper(streamfeature_handlers, elem), Strophe.NS.STREAM, "features", null, null)); // we must send an xmpp:restart now + + this._sendRestart(); + + return false; + } + /** PrivateFunction: _onStreamFeaturesAfterSASL + * Parameters: + * (XMLElement) elem - The matching stanza. + * + * Returns: + * false to remove the handler. + */ + + + _onStreamFeaturesAfterSASL(elem) { + // save stream:features for future usage + this.features = elem; + + for (let i = 0; i < elem.childNodes.length; i++) { + const child = elem.childNodes[i]; + + if (child.nodeName === 'bind') { + this.do_bind = true; + } + + if (child.nodeName === 'session') { + this.do_session = true; + } + } + + if (!this.do_bind) { + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); + + return false; + } else if (!this.options.explicitResourceBinding) { + this.bind(); + } else { + this._changeConnectStatus(Strophe.Status.BINDREQUIRED, null); + } + + return false; + } + /** Function: bind + * + * Sends an IQ to the XMPP server to bind a JID resource for this session. + * + * https://tools.ietf.org/html/rfc6120#section-7.5 + * + * If `explicitResourceBinding` was set to a truthy value in the options + * passed to the Strophe.Connection constructor, then this function needs + * to be called explicitly by the client author. + * + * Otherwise it'll be called automatically as soon as the XMPP server + * advertises the "urn:ietf:params:xml:ns:xmpp-bind" stream feature. + */ + + + bind() { + if (!this.do_bind) { + Strophe.log(Strophe.LogLevel.INFO, `Strophe.Connection.prototype.bind called but "do_bind" is false`); + return; + } + + this._addSysHandler(this._onResourceBindResultIQ.bind(this), null, null, null, "_bind_auth_2"); + + const resource = Strophe.getResourceFromJid(this.jid); + + if (resource) { + this.send($iq({ + type: "set", + id: "_bind_auth_2" + }).c('bind', { + xmlns: Strophe.NS.BIND + }).c('resource', {}).t(resource).tree()); + } else { + this.send($iq({ + type: "set", + id: "_bind_auth_2" + }).c('bind', { + xmlns: Strophe.NS.BIND + }).tree()); + } + } + /** PrivateFunction: _onResourceBindIQ + * _Private_ handler for binding result and session start. + * + * Parameters: + * (XMLElement) elem - The matching stanza. + * + * Returns: + * false to remove the handler. + */ + + + _onResourceBindResultIQ(elem) { + if (elem.getAttribute("type") === "error") { + Strophe.warn("Resource binding failed."); + const conflict = elem.getElementsByTagName("conflict"); + let condition; + + if (conflict.length > 0) { + condition = Strophe.ErrorCondition.CONFLICT; + } + + this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition, elem); + + return false; + } // TODO - need to grab errors + + + const bind = elem.getElementsByTagName("bind"); + + if (bind.length > 0) { + const jidNode = bind[0].getElementsByTagName("jid"); + + if (jidNode.length > 0) { + this.authenticated = true; + this.jid = Strophe.getText(jidNode[0]); + + if (this.do_session) { + this._establishSession(); + } else { + this._changeConnectStatus(Strophe.Status.CONNECTED, null); + } + } + } else { + Strophe.warn("Resource binding failed."); + + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem); + + return false; + } + } + /** PrivateFunction: _establishSession + * Send IQ request to establish a session with the XMPP server. + * + * See https://xmpp.org/rfcs/rfc3921.html#session + * + * Note: The protocol for session establishment has been determined as + * unnecessary and removed in RFC-6121. + */ + + + _establishSession() { + if (!this.do_session) { + throw new Error(`Strophe.Connection.prototype._establishSession ` + `called but apparently ${Strophe.NS.SESSION} wasn't advertised by the server`); + } + + this._addSysHandler(this._onSessionResultIQ.bind(this), null, null, null, "_session_auth_2"); + + this.send($iq({ + type: "set", + id: "_session_auth_2" + }).c('session', { + xmlns: Strophe.NS.SESSION + }).tree()); + } + /** PrivateFunction: _onSessionResultIQ + * _Private_ handler for the server's IQ response to a client's session + * request. + * + * This sets Connection.authenticated to true on success, which + * starts the processing of user handlers. + * + * See https://xmpp.org/rfcs/rfc3921.html#session + * + * Note: The protocol for session establishment has been determined as + * unnecessary and removed in RFC-6121. + * + * Parameters: + * (XMLElement) elem - The matching stanza. + * + * Returns: + * false to remove the handler. + */ + + + _onSessionResultIQ(elem) { + if (elem.getAttribute("type") === "result") { + this.authenticated = true; + + this._changeConnectStatus(Strophe.Status.CONNECTED, null); + } else if (elem.getAttribute("type") === "error") { + this.authenticated = false; + Strophe.warn("Session creation failed."); + + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem); + + return false; + } + + return false; + } + /** PrivateFunction: _sasl_failure_cb + * _Private_ handler for SASL authentication failure. + * + * Parameters: + * (XMLElement) elem - The matching stanza. + * + * Returns: + * false to remove the handler. + */ + + + _sasl_failure_cb(elem) { + // delete unneeded handlers + if (this._sasl_success_handler) { + this.deleteHandler(this._sasl_success_handler); + this._sasl_success_handler = null; + } + + if (this._sasl_challenge_handler) { + this.deleteHandler(this._sasl_challenge_handler); + this._sasl_challenge_handler = null; + } + + if (this._sasl_mechanism) this._sasl_mechanism.onFailure(); + + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem); + + return false; + } + /** PrivateFunction: _auth2_cb + * _Private_ handler to finish legacy authentication. + * + * This handler is called when the result from the jabber:iq:auth + * stanza is returned. + * + * Parameters: + * (XMLElement) elem - The stanza that triggered the callback. + * + * Returns: + * false to remove the handler. + */ + + + _auth2_cb(elem) { + if (elem.getAttribute("type") === "result") { + this.authenticated = true; + + this._changeConnectStatus(Strophe.Status.CONNECTED, null); + } else if (elem.getAttribute("type") === "error") { + this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem); + + this.disconnect('authentication failed'); + } + + return false; + } + /** PrivateFunction: _addSysTimedHandler + * _Private_ function to add a system level timed handler. + * + * This function is used to add a Strophe.TimedHandler for the + * library code. System timed handlers are allowed to run before + * authentication is complete. + * + * Parameters: + * (Integer) period - The period of the handler. + * (Function) handler - The callback function. + */ + + + _addSysTimedHandler(period, handler) { + const thand = new Strophe.TimedHandler(period, handler); + thand.user = false; + this.addTimeds.push(thand); + return thand; + } + /** PrivateFunction: _addSysHandler + * _Private_ function to add a system level stanza handler. + * + * This function is used to add a Strophe.Handler for the + * library code. System stanza handlers are allowed to run before + * authentication is complete. + * + * Parameters: + * (Function) handler - The callback function. + * (String) ns - The namespace to match. + * (String) name - The stanza name to match. + * (String) type - The stanza type attribute to match. + * (String) id - The stanza id attribute to match. + */ + + + _addSysHandler(handler, ns, name, type, id) { + const hand = new Strophe.Handler(handler, ns, name, type, id); + hand.user = false; + this.addHandlers.push(hand); + return hand; + } + /** PrivateFunction: _onDisconnectTimeout + * _Private_ timeout handler for handling non-graceful disconnection. + * + * If the graceful disconnect process does not complete within the + * time allotted, this handler finishes the disconnect anyway. + * + * Returns: + * false to remove the handler. + */ + + + _onDisconnectTimeout() { + Strophe.debug("_onDisconnectTimeout was called"); + + this._changeConnectStatus(Strophe.Status.CONNTIMEOUT, null); + + this._proto._onDisconnectTimeout(); // actually disconnect + + + this._doDisconnect(); + + return false; + } + /** PrivateFunction: _onIdle + * _Private_ handler to process events during idle cycle. + * + * This handler is called every 100ms to fire timed handlers that + * are ready and keep poll requests going. + */ + + + _onIdle() { + // add timed handlers scheduled for addition + // NOTE: we add before remove in the case a timed handler is + // added and then deleted before the next _onIdle() call. + while (this.addTimeds.length > 0) { + this.timedHandlers.push(this.addTimeds.pop()); + } // remove timed handlers that have been scheduled for deletion + + + while (this.removeTimeds.length > 0) { + const thand = this.removeTimeds.pop(); + const i = this.timedHandlers.indexOf(thand); + + if (i >= 0) { + this.timedHandlers.splice(i, 1); + } + } // call ready timed handlers + + + const now = new Date().getTime(); + const newList = []; + + for (let i = 0; i < this.timedHandlers.length; i++) { + const thand = this.timedHandlers[i]; + + if (this.authenticated || !thand.user) { + const since = thand.lastCalled + thand.period; + + if (since - now <= 0) { + if (thand.run()) { + newList.push(thand); + } + } else { + newList.push(thand); + } + } + } + + this.timedHandlers = newList; + clearTimeout(this._idleTimeout); + + this._proto._onIdle(); // reactivate the timer only if connected + + + if (this.connected) { + this._idleTimeout = setTimeout(() => this._onIdle(), 100); + } + } + +}; +Strophe.SASLMechanism = SASLMechanism; +/** Constants: SASL mechanisms + * Available authentication mechanisms + * + * Strophe.SASLAnonymous - SASL ANONYMOUS authentication. + * Strophe.SASLPlain - SASL PLAIN authentication. + * Strophe.SASLSHA1 - SASL SCRAM-SHA-1 authentication + * Strophe.SASLOAuthBearer - SASL OAuth Bearer authentication + * Strophe.SASLExternal - SASL EXTERNAL authentication + * Strophe.SASLXOAuth2 - SASL X-OAuth2 authentication + */ + +Strophe.SASLAnonymous = sasl_anon_SASLAnonymous; +Strophe.SASLPlain = sasl_plain_SASLPlain; +Strophe.SASLSHA1 = sasl_sha1_SASLSHA1; +Strophe.SASLOAuthBearer = sasl_oauthbearer_SASLOAuthBearer; +Strophe.SASLExternal = sasl_external_SASLExternal; +Strophe.SASLXOAuth2 = sasl_xoauth2_SASLXOAuth2; + +/* harmony default export */ var core = __webpack_exports__["g"] = ({ + 'Strophe': Strophe, + '$build': $build, + '$iq': $iq, + '$msg': $msg, + '$pres': $pres, + 'SHA1': sha1["a" /* default */], + 'MD5': MD5, + 'b64_hmac_sha1': sha1["a" /* default */].b64_hmac_sha1, + 'b64_sha1': sha1["a" /* default */].b64_sha1, + 'str_hmac_sha1': sha1["a" /* default */].str_hmac_sha1, + 'str_sha1': sha1["a" /* default */].str_sha1 +}); + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* unused harmony export b64_sha1 */ +/* harmony import */ var _bosh__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(152); +/* harmony import */ var _websocket__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(65); +/* harmony import */ var _worker_websocket__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(491); +/* harmony import */ var _core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(0); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "e", function() { return _core__WEBPACK_IMPORTED_MODULE_3__["f"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "a", function() { return _core__WEBPACK_IMPORTED_MODULE_3__["a"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "b", function() { return _core__WEBPACK_IMPORTED_MODULE_3__["b"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "c", function() { return _core__WEBPACK_IMPORTED_MODULE_3__["c"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "d", function() { return _core__WEBPACK_IMPORTED_MODULE_3__["d"]; }); + +/*global global*/ + + + + +global.$build = _core__WEBPACK_IMPORTED_MODULE_3__[/* default */ "g"].$build; +global.$iq = _core__WEBPACK_IMPORTED_MODULE_3__[/* default */ "g"].$iq; +global.$msg = _core__WEBPACK_IMPORTED_MODULE_3__[/* default */ "g"].$msg; +global.$pres = _core__WEBPACK_IMPORTED_MODULE_3__[/* default */ "g"].$pres; +global.Strophe = _core__WEBPACK_IMPORTED_MODULE_3__[/* default */ "g"].Strophe; + +const { + b64_sha1 +} = _core__WEBPACK_IMPORTED_MODULE_3__[/* SHA1 */ "e"]; +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(18))) + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +var __WEBPACK_AMD_DEFINE_RESULT__;/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +(function (window) { + var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function (a, b) { + if (a === b) { + hasDuplicate = true; + } + + return 0; + }, + // Instance methods + hasOwn = {}.hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function (list, elem) { + var i = 0, + len = list.length; + + for (; i < len; i++) { + if (list[i] === elem) { + return i; + } + } + + return -1; + }, + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + "ismap|loop|multiple|open|readonly|required|scoped", + // Regular expressions + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", + pseudos = ":(" + identifier + ")(?:\\((" + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + // 3. anything else (capture 2) + ".*" + ")\\)|)", + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp(whitespace + "+", "g"), + rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"), + rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"), + rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"), + rdescend = new RegExp(whitespace + "|>"), + rpseudo = new RegExp(pseudos), + ridentifier = new RegExp("^" + identifier + "$"), + matchExpr = { + "ID": new RegExp("^#(" + identifier + ")"), + "CLASS": new RegExp("^\\.(" + identifier + ")"), + "TAG": new RegExp("^(" + identifier + "|[*])"), + "ATTR": new RegExp("^" + attributes), + "PSEUDO": new RegExp("^" + pseudos), + "CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i"), + "bool": new RegExp("^(?:" + booleans + ")$", "i"), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i") + }, + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + rnative = /^[^{]+\{\s*\[native \w/, + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + rsibling = /[+~]/, + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp("\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g"), + funescape = function (escape, nonHex) { + var high = "0x" + escape.slice(1) - 0x10000; + return nonHex ? // Strip the backslash prefix from a non-hex escape sequence + nonHex : // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? String.fromCharCode(high + 0x10000) : String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00); + }, + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function (ch, asCodePoint) { + if (asCodePoint) { + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if (ch === "\0") { + return "\uFFFD"; + } // Control characters and (dependent upon position) numbers get escaped as code points + + + return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " "; + } // Other potentially-special ASCII characters get backslash-escaped + + + return "\\" + ch; + }, + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function () { + setDocument(); + }, + inDisabledFieldset = addCombinator(function (elem) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, { + dir: "parentNode", + next: "legend" + }); // Optimize for push.apply( _, NodeList ) + + + try { + push.apply(arr = slice.call(preferredDoc.childNodes), preferredDoc.childNodes); // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + + arr[preferredDoc.childNodes.length].nodeType; + } catch (e) { + push = { + apply: arr.length ? // Leverage slice if possible + function (target, els) { + pushNative.apply(target, slice.call(els)); + } : // Support: IE<9 + // Otherwise append directly + function (target, els) { + var j = target.length, + i = 0; // Can't trust NodeList.length + + while (target[j++] = els[i++]) {} + + target.length = j - 1; + } + }; + } + + function Sizzle(selector, context, results, seed) { + var m, + i, + elem, + nid, + match, + groups, + newSelector, + newContext = context && context.ownerDocument, + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + results = results || []; // Return early from calls with invalid selector or context + + if (typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) { + return results; + } // Try to shortcut find operations (as opposed to filters) in HTML documents + + + if (!seed) { + setDocument(context); + context = context || document; + + if (documentIsHTML) { + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if (nodeType !== 11 && (match = rquickExpr.exec(selector))) { + // ID selector + if (m = match[1]) { + // Document context + if (nodeType === 9) { + if (elem = context.getElementById(m)) { + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if (elem.id === m) { + results.push(elem); + return results; + } + } else { + return results; + } // Element context + + } else { + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if (newContext && (elem = newContext.getElementById(m)) && contains(context, elem) && elem.id === m) { + results.push(elem); + return results; + } + } // Type selector + + } else if (match[2]) { + push.apply(results, context.getElementsByTagName(selector)); + return results; // Class selector + } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) { + push.apply(results, context.getElementsByClassName(m)); + return results; + } + } // Take advantage of querySelectorAll + + + if (support.qsa && !nonnativeSelectorCache[selector + " "] && (!rbuggyQSA || !rbuggyQSA.test(selector)) && ( // Support: IE 8 only + // Exclude object elements + nodeType !== 1 || context.nodeName.toLowerCase() !== "object")) { + newSelector = selector; + newContext = context; // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + + if (nodeType === 1 && (rdescend.test(selector) || rcombinators.test(selector))) { + // Expand context for sibling selectors + newContext = rsibling.test(selector) && testContext(context.parentNode) || context; // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + + if (newContext !== context || !support.scope) { + // Capture the context ID, setting it first if necessary + if (nid = context.getAttribute("id")) { + nid = nid.replace(rcssescape, fcssescape); + } else { + context.setAttribute("id", nid = expando); + } + } // Prefix every selector in the list + + + groups = tokenize(selector); + i = groups.length; + + while (i--) { + groups[i] = (nid ? "#" + nid : ":scope") + " " + toSelector(groups[i]); + } + + newSelector = groups.join(","); + } + + try { + push.apply(results, newContext.querySelectorAll(newSelector)); + return results; + } catch (qsaError) { + nonnativeSelectorCache(selector, true); + } finally { + if (nid === expando) { + context.removeAttribute("id"); + } + } + } + } + } // All others + + + return select(selector.replace(rtrim, "$1"), context, results, seed); + } + /** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ + + + function createCache() { + var keys = []; + + function cache(key, value) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if (keys.push(key + " ") > Expr.cacheLength) { + // Only keep the most recent entries + delete cache[keys.shift()]; + } + + return cache[key + " "] = value; + } + + return cache; + } + /** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ + + + function markFunction(fn) { + fn[expando] = true; + return fn; + } + /** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ + + + function assert(fn) { + var el = document.createElement("fieldset"); + + try { + return !!fn(el); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if (el.parentNode) { + el.parentNode.removeChild(el); + } // release memory in IE + + + el = null; + } + } + /** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ + + + function addHandle(attrs, handler) { + var arr = attrs.split("|"), + i = arr.length; + + while (i--) { + Expr.attrHandle[arr[i]] = handler; + } + } + /** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ + + + function siblingCheck(a, b) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex; // Use IE sourceIndex if available on both nodes + + if (diff) { + return diff; + } // Check if b follows a + + + if (cur) { + while (cur = cur.nextSibling) { + if (cur === b) { + return -1; + } + } + } + + return a ? 1 : -1; + } + /** + * Returns a function to use in pseudos for input types + * @param {String} type + */ + + + function createInputPseudo(type) { + return function (elem) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; + } + /** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ + + + function createButtonPseudo(type) { + return function (elem) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; + } + /** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ + + + function createDisabledPseudo(disabled) { + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function (elem) { + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ("form" in elem) { + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if (elem.parentNode && elem.disabled === false) { + // Option elements defer to a parent optgroup if present + if ("label" in elem) { + if ("label" in elem.parentNode) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + + + return elem.isDisabled === disabled || // Where there is no isDisabled, check manually + + /* jshint -W018 */ + elem.isDisabled !== !disabled && inDisabledFieldset(elem) === disabled; + } + + return elem.disabled === disabled; // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ("label" in elem) { + return elem.disabled === disabled; + } // Remaining elements are neither :enabled nor :disabled + + + return false; + }; + } + /** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ + + + function createPositionalPseudo(fn) { + return markFunction(function (argument) { + argument = +argument; + return markFunction(function (seed, matches) { + var j, + matchIndexes = fn([], seed.length, argument), + i = matchIndexes.length; // Match elements found at the specified indexes + + while (i--) { + if (seed[j = matchIndexes[i]]) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); + } + /** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ + + + function testContext(context) { + return context && typeof context.getElementsByTagName !== "undefined" && context; + } // Expose support vars for convenience + + + support = Sizzle.support = {}; + /** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ + + isXML = Sizzle.isXML = function (elem) { + var namespace = elem && elem.namespaceURI, + docElem = elem && (elem.ownerDocument || elem).documentElement; // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + + return !rhtml.test(namespace || docElem && docElem.nodeName || "HTML"); + }; + /** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ + + + setDocument = Sizzle.setDocument = function (node) { + var hasCompare, + subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + + if (doc == document || doc.nodeType !== 9 || !doc.documentElement) { + return document; + } // Update global variables + + + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML(document); // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + + if (preferredDoc != document && (subWindow = document.defaultView) && subWindow.top !== subWindow) { + // Support: IE 11, Edge + if (subWindow.addEventListener) { + subWindow.addEventListener("unload", unloadHandler, false); // Support: IE 9 - 10 only + } else if (subWindow.attachEvent) { + subWindow.attachEvent("onunload", unloadHandler); + } + } // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + + + support.scope = assert(function (el) { + docElem.appendChild(el).appendChild(document.createElement("div")); + return typeof el.querySelectorAll !== "undefined" && !el.querySelectorAll(":scope fieldset div").length; + }); + /* Attributes + ---------------------------------------------------------------------- */ + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + + support.attributes = assert(function (el) { + el.className = "i"; + return !el.getAttribute("className"); + }); + /* getElement(s)By* + ---------------------------------------------------------------------- */ + // Check if getElementsByTagName("*") returns only elements + + support.getElementsByTagName = assert(function (el) { + el.appendChild(document.createComment("")); + return !el.getElementsByTagName("*").length; + }); // Support: IE<9 + + support.getElementsByClassName = rnative.test(document.getElementsByClassName); // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + + support.getById = assert(function (el) { + docElem.appendChild(el).id = expando; + return !document.getElementsByName || !document.getElementsByName(expando).length; + }); // ID filter and find + + if (support.getById) { + Expr.filter["ID"] = function (id) { + var attrId = id.replace(runescape, funescape); + return function (elem) { + return elem.getAttribute("id") === attrId; + }; + }; + + Expr.find["ID"] = function (id, context) { + if (typeof context.getElementById !== "undefined" && documentIsHTML) { + var elem = context.getElementById(id); + return elem ? [elem] : []; + } + }; + } else { + Expr.filter["ID"] = function (id) { + var attrId = id.replace(runescape, funescape); + return function (elem) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + + + Expr.find["ID"] = function (id, context) { + if (typeof context.getElementById !== "undefined" && documentIsHTML) { + var node, + i, + elems, + elem = context.getElementById(id); + + if (elem) { + // Verify the id attribute + node = elem.getAttributeNode("id"); + + if (node && node.value === id) { + return [elem]; + } // Fall back on getElementsByName + + + elems = context.getElementsByName(id); + i = 0; + + while (elem = elems[i++]) { + node = elem.getAttributeNode("id"); + + if (node && node.value === id) { + return [elem]; + } + } + } + + return []; + } + }; + } // Tag + + + Expr.find["TAG"] = support.getElementsByTagName ? function (tag, context) { + if (typeof context.getElementsByTagName !== "undefined") { + return context.getElementsByTagName(tag); // DocumentFragment nodes don't have gEBTN + } else if (support.qsa) { + return context.querySelectorAll(tag); + } + } : function (tag, context) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName(tag); // Filter out possible comments + + if (tag === "*") { + while (elem = results[i++]) { + if (elem.nodeType === 1) { + tmp.push(elem); + } + } + + return tmp; + } + + return results; + }; // Class + + Expr.find["CLASS"] = support.getElementsByClassName && function (className, context) { + if (typeof context.getElementsByClassName !== "undefined" && documentIsHTML) { + return context.getElementsByClassName(className); + } + }; + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + // QSA and matchesSelector support + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + + + rbuggyMatches = []; // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + + rbuggyQSA = []; + + if (support.qsa = rnative.test(document.querySelectorAll)) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function (el) { + var input; // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + + docElem.appendChild(el).innerHTML = "" + ""; // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + + if (el.querySelectorAll("[msallowcapture^='']").length) { + rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")"); + } // Support: IE8 + // Boolean attributes and "value" are not treated correctly + + + if (!el.querySelectorAll("[selected]").length) { + rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")"); + } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + + + if (!el.querySelectorAll("[id~=" + expando + "-]").length) { + rbuggyQSA.push("~="); + } // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + + + input = document.createElement("input"); + input.setAttribute("name", ""); + el.appendChild(input); + + if (!el.querySelectorAll("[name='']").length) { + rbuggyQSA.push("\\[" + whitespace + "*name" + whitespace + "*=" + whitespace + "*(?:''|\"\")"); + } // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + + + if (!el.querySelectorAll(":checked").length) { + rbuggyQSA.push(":checked"); + } // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + + + if (!el.querySelectorAll("a#" + expando + "+*").length) { + rbuggyQSA.push(".#.+[+~]"); + } // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + + + el.querySelectorAll("\\\f"); + rbuggyQSA.push("[\\r\\n\\f]"); + }); + assert(function (el) { + el.innerHTML = "" + ""; // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + + var input = document.createElement("input"); + input.setAttribute("type", "hidden"); + el.appendChild(input).setAttribute("name", "D"); // Support: IE8 + // Enforce case-sensitivity of name attribute + + if (el.querySelectorAll("[name=d]").length) { + rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?="); + } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + + + if (el.querySelectorAll(":enabled").length !== 2) { + rbuggyQSA.push(":enabled", ":disabled"); + } // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + + + docElem.appendChild(el).disabled = true; + + if (el.querySelectorAll(":disabled").length !== 2) { + rbuggyQSA.push(":enabled", ":disabled"); + } // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + + + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if (support.matchesSelector = rnative.test(matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector)) { + assert(function (el) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call(el, "*"); // This should fail with an exception + // Gecko does not error, returns false instead + + matches.call(el, "[s!='']:x"); + rbuggyMatches.push("!=", pseudos); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|")); + rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|")); + /* Contains + ---------------------------------------------------------------------- */ + + hasCompare = rnative.test(docElem.compareDocumentPosition); // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + + contains = hasCompare || rnative.test(docElem.contains) ? function (a, b) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16)); + } : function (a, b) { + if (b) { + while (b = b.parentNode) { + if (b === a) { + return true; + } + } + } + + return false; + }; + /* Sorting + ---------------------------------------------------------------------- */ + // Document order sorting + + sortOrder = hasCompare ? function (a, b) { + // Flag for duplicate removal + if (a === b) { + hasDuplicate = true; + return 0; + } // Sort on method existence if only one input has compareDocumentPosition + + + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + + if (compare) { + return compare; + } // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + + + compare = (a.ownerDocument || a) == (b.ownerDocument || b) ? a.compareDocumentPosition(b) : // Otherwise we know they are disconnected + 1; // Disconnected nodes + + if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) { + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if (a == document || a.ownerDocument == preferredDoc && contains(preferredDoc, a)) { + return -1; + } // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + + + if (b == document || b.ownerDocument == preferredDoc && contains(preferredDoc, b)) { + return 1; + } // Maintain original order + + + return sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0; + } + + return compare & 4 ? -1 : 1; + } : function (a, b) { + // Exit early if the nodes are identical + if (a === b) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [a], + bp = [b]; // Parentless nodes are either documents or disconnected + + if (!aup || !bup) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + + /* eslint-disable eqeqeq */ + return a == document ? -1 : b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : bup ? 1 : sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0; // If the nodes are siblings, we can do a quick check + } else if (aup === bup) { + return siblingCheck(a, b); + } // Otherwise we need full lists of their ancestors for comparison + + + cur = a; + + while (cur = cur.parentNode) { + ap.unshift(cur); + } + + cur = b; + + while (cur = cur.parentNode) { + bp.unshift(cur); + } // Walk down the tree looking for a discrepancy + + + while (ap[i] === bp[i]) { + i++; + } + + return i ? // Do a sibling check if the nodes have a common ancestor + siblingCheck(ap[i], bp[i]) : // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + + /* eslint-disable eqeqeq */ + ap[i] == preferredDoc ? -1 : bp[i] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + return document; + }; + + Sizzle.matches = function (expr, elements) { + return Sizzle(expr, null, null, elements); + }; + + Sizzle.matchesSelector = function (elem, expr) { + setDocument(elem); + + if (support.matchesSelector && documentIsHTML && !nonnativeSelectorCache[expr + " "] && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) { + try { + var ret = matches.call(elem, expr); // IE 9's matchesSelector returns false on disconnected nodes + + if (ret || support.disconnectedMatch || // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11) { + return ret; + } + } catch (e) { + nonnativeSelectorCache(expr, true); + } + } + + return Sizzle(expr, document, null, [elem]).length > 0; + }; + + Sizzle.contains = function (context, elem) { + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ((context.ownerDocument || context) != document) { + setDocument(context); + } + + return contains(context, elem); + }; + + Sizzle.attr = function (elem, name) { + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ((elem.ownerDocument || elem) != document) { + setDocument(elem); + } + + var fn = Expr.attrHandle[name.toLowerCase()], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined; + return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null; + }; + + Sizzle.escape = function (sel) { + return (sel + "").replace(rcssescape, fcssescape); + }; + + Sizzle.error = function (msg) { + throw new Error("Syntax error, unrecognized expression: " + msg); + }; + /** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ + + + Sizzle.uniqueSort = function (results) { + var elem, + duplicates = [], + j = 0, + i = 0; // Unless we *know* we can detect duplicates, assume their presence + + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice(0); + results.sort(sortOrder); + + if (hasDuplicate) { + while (elem = results[i++]) { + if (elem === results[i]) { + j = duplicates.push(i); + } + } + + while (j--) { + results.splice(duplicates[j], 1); + } + } // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + + + sortInput = null; + return results; + }; + /** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ + + + getText = Sizzle.getText = function (elem) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if (!nodeType) { + // If no nodeType, this is expected to be an array + while (node = elem[i++]) { + // Do not traverse comment nodes + ret += getText(node); + } + } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if (typeof elem.textContent === "string") { + return elem.textContent; + } else { + // Traverse its children + for (elem = elem.firstChild; elem; elem = elem.nextSibling) { + ret += getText(elem); + } + } + } else if (nodeType === 3 || nodeType === 4) { + return elem.nodeValue; + } // Do not include comment or processing instruction nodes + + + return ret; + }; + + Expr = Sizzle.selectors = { + // Can be adjusted by the user + cacheLength: 50, + createPseudo: markFunction, + match: matchExpr, + attrHandle: {}, + find: {}, + relative: { + ">": { + dir: "parentNode", + first: true + }, + " ": { + dir: "parentNode" + }, + "+": { + dir: "previousSibling", + first: true + }, + "~": { + dir: "previousSibling" + } + }, + preFilter: { + "ATTR": function (match) { + match[1] = match[1].replace(runescape, funescape); // Move the given value to match[3] whether quoted or unquoted + + match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape); + + if (match[2] === "~=") { + match[3] = " " + match[3] + " "; + } + + return match.slice(0, 4); + }, + "CHILD": function (match) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if (match[1].slice(0, 3) === "nth") { + // nth-* requires argument + if (!match[3]) { + Sizzle.error(match[0]); + } // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + + + match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd")); + match[5] = +(match[7] + match[8] || match[3] === "odd"); // other types prohibit arguments + } else if (match[3]) { + Sizzle.error(match[0]); + } + + return match; + }, + "PSEUDO": function (match) { + var excess, + unquoted = !match[6] && match[2]; + + if (matchExpr["CHILD"].test(match[0])) { + return null; + } // Accept quoted arguments as-is + + + if (match[3]) { + match[2] = match[4] || match[5] || ""; // Strip excess characters from unquoted arguments + } else if (unquoted && rpseudo.test(unquoted) && ( // Get excess from tokenize (recursively) + excess = tokenize(unquoted, true)) && ( // advance to the next closing parenthesis + excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) { + // excess is a negative index + match[0] = match[0].slice(0, excess); + match[2] = unquoted.slice(0, excess); + } // Return only captures needed by the pseudo filter method (type and argument) + + + return match.slice(0, 3); + } + }, + filter: { + "TAG": function (nodeNameSelector) { + var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase(); + return nodeNameSelector === "*" ? function () { + return true; + } : function (elem) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + "CLASS": function (className) { + var pattern = classCache[className + " "]; + return pattern || (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) && classCache(className, function (elem) { + return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || ""); + }); + }, + "ATTR": function (name, operator, check) { + return function (elem) { + var result = Sizzle.attr(elem, name); + + if (result == null) { + return operator === "!="; + } + + if (!operator) { + return true; + } + + result += ""; + /* eslint-disable max-len */ + + return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf(check) === 0 : operator === "*=" ? check && result.indexOf(check) > -1 : operator === "$=" ? check && result.slice(-check.length) === check : operator === "~=" ? (" " + result.replace(rwhitespace, " ") + " ").indexOf(check) > -1 : operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" : false; + /* eslint-enable max-len */ + }; + }, + "CHILD": function (type, what, _argument, first, last) { + var simple = type.slice(0, 3) !== "nth", + forward = type.slice(-4) !== "last", + ofType = what === "of-type"; + return first === 1 && last === 0 ? // Shortcut for :nth-*(n) + function (elem) { + return !!elem.parentNode; + } : function (elem, _context, xml) { + var cache, + uniqueCache, + outerCache, + node, + nodeIndex, + start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if (parent) { + // :(first|last|only)-(child|of-type) + if (simple) { + while (dir) { + node = elem; + + while (node = node[dir]) { + if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) { + return false; + } + } // Reverse direction for :only-* (if we haven't yet done so) + + + start = dir = type === "only" && !start && "nextSibling"; + } + + return true; + } + + start = [forward ? parent.firstChild : parent.lastChild]; // non-xml :nth-child(...) stores cache data on `parent` + + if (forward && useCache) { + // Seek `elem` from a previously-cached index + // ...in a gzip-friendly way + node = parent; + outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + + uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}); + cache = uniqueCache[type] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = nodeIndex && cache[2]; + node = nodeIndex && parent.childNodes[nodeIndex]; + + while (node = ++nodeIndex && node && node[dir] || ( // Fallback to seeking `elem` from the start + diff = nodeIndex = 0) || start.pop()) { + // When found, cache indexes on `parent` and break + if (node.nodeType === 1 && ++diff && node === elem) { + uniqueCache[type] = [dirruns, nodeIndex, diff]; + break; + } + } + } else { + // Use previously-cached element index if available + if (useCache) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + + uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}); + cache = uniqueCache[type] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = nodeIndex; + } // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + + + if (diff === false) { + // Use the same loop as above to seek `elem` from the start + while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) { + if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) { + // Cache the index of each encountered element + if (useCache) { + outerCache = node[expando] || (node[expando] = {}); // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + + uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}); + uniqueCache[type] = [dirruns, diff]; + } + + if (node === elem) { + break; + } + } + } + } + } // Incorporate the offset, then check against cycle size + + + diff -= last; + return diff === first || diff % first === 0 && diff / first >= 0; + } + }; + }, + "PSEUDO": function (pseudo, argument) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error("unsupported pseudo: " + pseudo); // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + + if (fn[expando]) { + return fn(argument); + } // But maintain support for old signatures + + + if (fn.length > 1) { + args = [pseudo, pseudo, "", argument]; + return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function (seed, matches) { + var idx, + matched = fn(seed, argument), + i = matched.length; + + while (i--) { + idx = indexOf(seed, matched[i]); + seed[idx] = !(matches[idx] = matched[i]); + } + }) : function (elem) { + return fn(elem, 0, args); + }; + } + + return fn; + } + }, + pseudos: { + // Potentially complex pseudos + "not": markFunction(function (selector) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile(selector.replace(rtrim, "$1")); + return matcher[expando] ? markFunction(function (seed, matches, _context, xml) { + var elem, + unmatched = matcher(seed, null, xml, []), + i = seed.length; // Match elements unmatched by `matcher` + + while (i--) { + if (elem = unmatched[i]) { + seed[i] = !(matches[i] = elem); + } + } + }) : function (elem, _context, xml) { + input[0] = elem; + matcher(input, null, xml, results); // Don't keep the element (issue #299) + + input[0] = null; + return !results.pop(); + }; + }), + "has": markFunction(function (selector) { + return function (elem) { + return Sizzle(selector, elem).length > 0; + }; + }), + "contains": markFunction(function (text) { + text = text.replace(runescape, funescape); + return function (elem) { + return (elem.textContent || getText(elem)).indexOf(text) > -1; + }; + }), + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction(function (lang) { + // lang value must be a valid identifier + if (!ridentifier.test(lang || "")) { + Sizzle.error("unsupported lang: " + lang); + } + + lang = lang.replace(runescape, funescape).toLowerCase(); + return function (elem) { + var elemLang; + + do { + if (elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang")) { + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf(lang + "-") === 0; + } + } while ((elem = elem.parentNode) && elem.nodeType === 1); + + return false; + }; + }), + // Miscellaneous + "target": function (elem) { + var hash = window.location && window.location.hash; + return hash && hash.slice(1) === elem.id; + }, + "root": function (elem) { + return elem === docElem; + }, + "focus": function (elem) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + // Boolean properties + "enabled": createDisabledPseudo(false), + "disabled": createDisabledPseudo(true), + "checked": function (elem) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return nodeName === "input" && !!elem.checked || nodeName === "option" && !!elem.selected; + }, + "selected": function (elem) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if (elem.parentNode) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + // Contents + "empty": function (elem) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for (elem = elem.firstChild; elem; elem = elem.nextSibling) { + if (elem.nodeType < 6) { + return false; + } + } + + return true; + }, + "parent": function (elem) { + return !Expr.pseudos["empty"](elem); + }, + // Element/input types + "header": function (elem) { + return rheader.test(elem.nodeName); + }, + "input": function (elem) { + return rinputs.test(elem.nodeName); + }, + "button": function (elem) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + "text": function (elem) { + var attr; + return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && ( // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text"); + }, + // Position-in-collection + "first": createPositionalPseudo(function () { + return [0]; + }), + "last": createPositionalPseudo(function (_matchIndexes, length) { + return [length - 1]; + }), + "eq": createPositionalPseudo(function (_matchIndexes, length, argument) { + return [argument < 0 ? argument + length : argument]; + }), + "even": createPositionalPseudo(function (matchIndexes, length) { + var i = 0; + + for (; i < length; i += 2) { + matchIndexes.push(i); + } + + return matchIndexes; + }), + "odd": createPositionalPseudo(function (matchIndexes, length) { + var i = 1; + + for (; i < length; i += 2) { + matchIndexes.push(i); + } + + return matchIndexes; + }), + "lt": createPositionalPseudo(function (matchIndexes, length, argument) { + var i = argument < 0 ? argument + length : argument > length ? length : argument; + + for (; --i >= 0;) { + matchIndexes.push(i); + } + + return matchIndexes; + }), + "gt": createPositionalPseudo(function (matchIndexes, length, argument) { + var i = argument < 0 ? argument + length : argument; + + for (; ++i < length;) { + matchIndexes.push(i); + } + + return matchIndexes; + }) + } + }; + Expr.pseudos["nth"] = Expr.pseudos["eq"]; // Add button/input type pseudos + + for (i in { + radio: true, + checkbox: true, + file: true, + password: true, + image: true + }) { + Expr.pseudos[i] = createInputPseudo(i); + } + + for (i in { + submit: true, + reset: true + }) { + Expr.pseudos[i] = createButtonPseudo(i); + } // Easy API for creating new setFilters + + + function setFilters() {} + + setFilters.prototype = Expr.filters = Expr.pseudos; + Expr.setFilters = new setFilters(); + + tokenize = Sizzle.tokenize = function (selector, parseOnly) { + var matched, + match, + tokens, + type, + soFar, + groups, + preFilters, + cached = tokenCache[selector + " "]; + + if (cached) { + return parseOnly ? 0 : cached.slice(0); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while (soFar) { + // Comma and first run + if (!matched || (match = rcomma.exec(soFar))) { + if (match) { + // Don't consume trailing commas as valid + soFar = soFar.slice(match[0].length) || soFar; + } + + groups.push(tokens = []); + } + + matched = false; // Combinators + + if (match = rcombinators.exec(soFar)) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace(rtrim, " ") + }); + soFar = soFar.slice(matched.length); + } // Filters + + + for (type in Expr.filter) { + if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice(matched.length); + } + } + + if (!matched) { + break; + } + } // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + + + return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : // Cache the tokens + tokenCache(selector, groups).slice(0); + }; + + function toSelector(tokens) { + var i = 0, + len = tokens.length, + selector = ""; + + for (; i < len; i++) { + selector += tokens[i].value; + } + + return selector; + } + + function addCombinator(matcher, combinator, base) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + return combinator.first ? // Check against closest ancestor/preceding element + function (elem, context, xml) { + while (elem = elem[dir]) { + if (elem.nodeType === 1 || checkNonElements) { + return matcher(elem, context, xml); + } + } + + return false; + } : // Check against all ancestor/preceding elements + function (elem, context, xml) { + var oldCache, + uniqueCache, + outerCache, + newCache = [dirruns, doneName]; // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + + if (xml) { + while (elem = elem[dir]) { + if (elem.nodeType === 1 || checkNonElements) { + if (matcher(elem, context, xml)) { + return true; + } + } + } + } else { + while (elem = elem[dir]) { + if (elem.nodeType === 1 || checkNonElements) { + outerCache = elem[expando] || (elem[expando] = {}); // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + + uniqueCache = outerCache[elem.uniqueID] || (outerCache[elem.uniqueID] = {}); + + if (skip && skip === elem.nodeName.toLowerCase()) { + elem = elem[dir] || elem; + } else if ((oldCache = uniqueCache[key]) && oldCache[0] === dirruns && oldCache[1] === doneName) { + // Assign to newCache so results back-propagate to previous elements + return newCache[2] = oldCache[2]; + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[key] = newCache; // A match means we're done; a fail means we have to keep checking + + if (newCache[2] = matcher(elem, context, xml)) { + return true; + } + } + } + } + } + + return false; + }; + } + + function elementMatcher(matchers) { + return matchers.length > 1 ? function (elem, context, xml) { + var i = matchers.length; + + while (i--) { + if (!matchers[i](elem, context, xml)) { + return false; + } + } + + return true; + } : matchers[0]; + } + + function multipleContexts(selector, contexts, results) { + var i = 0, + len = contexts.length; + + for (; i < len; i++) { + Sizzle(selector, contexts[i], results); + } + + return results; + } + + function condense(unmatched, map, filter, context, xml) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for (; i < len; i++) { + if (elem = unmatched[i]) { + if (!filter || filter(elem, context, xml)) { + newUnmatched.push(elem); + + if (mapped) { + map.push(i); + } + } + } + } + + return newUnmatched; + } + + function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) { + if (postFilter && !postFilter[expando]) { + postFilter = setMatcher(postFilter); + } + + if (postFinder && !postFinder[expando]) { + postFinder = setMatcher(postFinder, postSelector); + } + + return markFunction(function (seed, results, context, xml) { + var temp, + i, + elem, + preMap = [], + postMap = [], + preexisting = results.length, + // Get initial elements from seed or context + elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, []), + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems, + matcherOut = matcher ? // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || (seed ? preFilter : preexisting || postFilter) ? // ...intermediate processing is necessary + [] : // ...otherwise use results directly + results : matcherIn; // Find primary matches + + if (matcher) { + matcher(matcherIn, matcherOut, context, xml); + } // Apply postFilter + + + if (postFilter) { + temp = condense(matcherOut, postMap); + postFilter(temp, [], context, xml); // Un-match failing elements by moving them back to matcherIn + + i = temp.length; + + while (i--) { + if (elem = temp[i]) { + matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem); + } + } + } + + if (seed) { + if (postFinder || preFilter) { + if (postFinder) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + + while (i--) { + if (elem = matcherOut[i]) { + // Restore matcherIn since elem is not yet a final match + temp.push(matcherIn[i] = elem); + } + } + + postFinder(null, matcherOut = [], temp, xml); + } // Move matched elements from seed to results to keep them synchronized + + + i = matcherOut.length; + + while (i--) { + if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf(seed, elem) : preMap[i]) > -1) { + seed[temp] = !(results[temp] = elem); + } + } + } // Add elements to results, through postFinder if defined + + } else { + matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut); + + if (postFinder) { + postFinder(null, results, matcherOut, xml); + } else { + push.apply(results, matcherOut); + } + } + }); + } + + function matcherFromTokens(tokens) { + var checkContext, + matcher, + j, + len = tokens.length, + leadingRelative = Expr.relative[tokens[0].type], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator(function (elem) { + return elem === checkContext; + }, implicitRelative, true), + matchAnyContext = addCombinator(function (elem) { + return indexOf(checkContext, elem) > -1; + }, implicitRelative, true), + matchers = [function (elem, context, xml) { + var ret = !leadingRelative && (xml || context !== outermostContext) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml)); // Avoid hanging onto element (issue #299) + + checkContext = null; + return ret; + }]; + + for (; i < len; i++) { + if (matcher = Expr.relative[tokens[i].type]) { + matchers = [addCombinator(elementMatcher(matchers), matcher)]; + } else { + matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches); // Return special upon seeing a positional matcher + + if (matcher[expando]) { + // Find the next relative operator (if any) for proper handling + j = ++i; + + for (; j < len; j++) { + if (Expr.relative[tokens[j].type]) { + break; + } + } + + return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice(0, i - 1).concat({ + value: tokens[i - 2].type === " " ? "*" : "" + })).replace(rtrim, "$1"), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens(tokens = tokens.slice(j)), j < len && toSelector(tokens)); + } + + matchers.push(matcher); + } + } + + return elementMatcher(matchers); + } + + function matcherFromGroupMatchers(elementMatchers, setMatchers) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function (seed, context, xml, results, outermost) { + var elem, + j, + matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]("*", outermost), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = dirruns += contextBackup == null ? 1 : Math.random() || 0.1, + len = elems.length; + + if (outermost) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + + + for (; i !== len && (elem = elems[i]) != null; i++) { + if (byElement && elem) { + j = 0; // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + + if (!context && elem.ownerDocument != document) { + setDocument(elem); + xml = !documentIsHTML; + } + + while (matcher = elementMatchers[j++]) { + if (matcher(elem, context || document, xml)) { + results.push(elem); + break; + } + } + + if (outermost) { + dirruns = dirrunsUnique; + } + } // Track unmatched elements for set filters + + + if (bySet) { + // They will have gone through all possible matchers + if (elem = !matcher && elem) { + matchedCount--; + } // Lengthen the array for every element, matched or not + + + if (seed) { + unmatched.push(elem); + } + } + } // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + + + matchedCount += i; // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + + if (bySet && i !== matchedCount) { + j = 0; + + while (matcher = setMatchers[j++]) { + matcher(unmatched, setMatched, context, xml); + } + + if (seed) { + // Reintegrate element matches to eliminate the need for sorting + if (matchedCount > 0) { + while (i--) { + if (!(unmatched[i] || setMatched[i])) { + setMatched[i] = pop.call(results); + } + } + } // Discard index placeholder values to get only actual matches + + + setMatched = condense(setMatched); + } // Add matches to results + + + push.apply(results, setMatched); // Seedless set matches succeeding multiple successful matchers stipulate sorting + + if (outermost && !seed && setMatched.length > 0 && matchedCount + setMatchers.length > 1) { + Sizzle.uniqueSort(results); + } + } // Override manipulation of globals by nested matchers + + + if (outermost) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? markFunction(superMatcher) : superMatcher; + } + + compile = Sizzle.compile = function (selector, match + /* Internal Use Only */ + ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[selector + " "]; + + if (!cached) { + // Generate a function of recursive functions that can be used to check each element + if (!match) { + match = tokenize(selector); + } + + i = match.length; + + while (i--) { + cached = matcherFromTokens(match[i]); + + if (cached[expando]) { + setMatchers.push(cached); + } else { + elementMatchers.push(cached); + } + } // Cache the compiled function + + + cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers)); // Save selector and tokenization + + cached.selector = selector; + } + + return cached; + }; + /** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ + + + select = Sizzle.select = function (selector, context, results, seed) { + var i, + tokens, + token, + type, + find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize(selector = compiled.selector || selector); + results = results || []; // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + + if (match.length === 1) { + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice(0); + + if (tokens.length > 2 && (token = tokens[0]).type === "ID" && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) { + context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0]; + + if (!context) { + return results; // Precompiled matchers will still verify ancestry, so step up a level + } else if (compiled) { + context = context.parentNode; + } + + selector = selector.slice(tokens.shift().value.length); + } // Fetch a seed set for right-to-left matching + + + i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length; + + while (i--) { + token = tokens[i]; // Abort if we hit a combinator + + if (Expr.relative[type = token.type]) { + break; + } + + if (find = Expr.find[type]) { + // Search, expanding context for leading sibling combinators + if (seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testContext(context.parentNode) || context)) { + // If seed is empty or no tokens remain, we can return early + tokens.splice(i, 1); + selector = seed.length && toSelector(tokens); + + if (!selector) { + push.apply(results, seed); + return results; + } + + break; + } + } + } + } // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + + + (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, !context || rsibling.test(selector) && testContext(context.parentNode) || context); + return results; + }; // One-time assignments + // Sort stability + + + support.sortStable = expando.split("").sort(sortOrder).join("") === expando; // Support: Chrome 14-35+ + // Always assume duplicates if they aren't passed to the comparison function + + support.detectDuplicates = !!hasDuplicate; // Initialize against the default document + + setDocument(); // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) + // Detached nodes confoundingly follow *each other* + + support.sortDetached = assert(function (el) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition(document.createElement("fieldset")) & 1; + }); // Support: IE<8 + // Prevent attribute/property "interpolation" + // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx + + if (!assert(function (el) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#"; + })) { + addHandle("type|href|height|width", function (elem, name, isXML) { + if (!isXML) { + return elem.getAttribute(name, name.toLowerCase() === "type" ? 1 : 2); + } + }); + } // Support: IE<9 + // Use defaultValue in place of getAttribute("value") + + + if (!support.attributes || !assert(function (el) { + el.innerHTML = ""; + el.firstChild.setAttribute("value", ""); + return el.firstChild.getAttribute("value") === ""; + })) { + addHandle("value", function (elem, _name, isXML) { + if (!isXML && elem.nodeName.toLowerCase() === "input") { + return elem.defaultValue; + } + }); + } // Support: IE<9 + // Use getAttributeNode to fetch booleans when getAttribute lies + + + if (!assert(function (el) { + return el.getAttribute("disabled") == null; + })) { + addHandle(booleans, function (elem, name, isXML) { + var val; + + if (!isXML) { + return elem[name] === true ? name.toLowerCase() : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null; + } + }); + } // EXPOSE + + + var _sizzle = window.Sizzle; + + Sizzle.noConflict = function () { + if (window.Sizzle === Sizzle) { + window.Sizzle = _sizzle; + } + + return Sizzle; + }; + + if (true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () { + return Sizzle; + }).call(exports, __webpack_require__, exports, module), + __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); // Sizzle requires that there be a global window in Common-JS like environments + } else {} // EXPOSE + +})(window); + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +!function (t, e) { + true ? module.exports = e() : undefined; +}(this, function () { + "use strict"; + + var t = "millisecond", + e = "second", + n = "minute", + r = "hour", + i = "day", + s = "week", + u = "month", + o = "quarter", + a = "year", + h = /^(\d{4})-?(\d{1,2})-?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?.?(\d{1,3})?$/, + f = /\[([^\]]+)]|Y{2,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g, + c = function (t, e, n) { + var r = String(t); + return !r || r.length >= e ? t : "" + Array(e + 1 - r.length).join(n) + t; + }, + d = { + s: c, + z: function (t) { + var e = -t.utcOffset(), + n = Math.abs(e), + r = Math.floor(n / 60), + i = n % 60; + return (e <= 0 ? "+" : "-") + c(r, 2, "0") + ":" + c(i, 2, "0"); + }, + m: function (t, e) { + var n = 12 * (e.year() - t.year()) + (e.month() - t.month()), + r = t.clone().add(n, u), + i = e - r < 0, + s = t.clone().add(n + (i ? -1 : 1), u); + return Number(-(n + (e - r) / (i ? r - s : s - r)) || 0); + }, + a: function (t) { + return t < 0 ? Math.ceil(t) || 0 : Math.floor(t); + }, + p: function (h) { + return { + M: u, + y: a, + w: s, + d: i, + D: "date", + h: r, + m: n, + s: e, + ms: t, + Q: o + }[h] || String(h || "").toLowerCase().replace(/s$/, ""); + }, + u: function (t) { + return void 0 === t; + } + }, + $ = { + name: "en", + weekdays: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), + months: "January_February_March_April_May_June_July_August_September_October_November_December".split("_") + }, + l = "en", + m = {}; + + m[l] = $; + + var y = function (t) { + return t instanceof v; + }, + M = function (t, e, n) { + var r; + if (!t) return l; + if ("string" == typeof t) m[t] && (r = t), e && (m[t] = e, r = t);else { + var i = t.name; + m[i] = t, r = i; + } + return !n && r && (l = r), r || !n && l; + }, + g = function (t, e) { + if (y(t)) return t.clone(); + var n = "object" == typeof e ? e : {}; + return n.date = t, n.args = arguments, new v(n); + }, + D = d; + + D.l = M, D.i = y, D.w = function (t, e) { + return g(t, { + locale: e.$L, + utc: e.$u, + $offset: e.$offset + }); + }; + + var v = function () { + function c(t) { + this.$L = this.$L || M(t.locale, null, !0), this.parse(t); + } + + var d = c.prototype; + return d.parse = function (t) { + this.$d = function (t) { + var e = t.date, + n = t.utc; + if (null === e) return new Date(NaN); + if (D.u(e)) return new Date(); + if (e instanceof Date) return new Date(e); + + if ("string" == typeof e && !/Z$/i.test(e)) { + var r = e.match(h); + if (r) return n ? new Date(Date.UTC(r[1], r[2] - 1, r[3] || 1, r[4] || 0, r[5] || 0, r[6] || 0, r[7] || 0)) : new Date(r[1], r[2] - 1, r[3] || 1, r[4] || 0, r[5] || 0, r[6] || 0, r[7] || 0); + } + + return new Date(e); + }(t), this.init(); + }, d.init = function () { + var t = this.$d; + this.$y = t.getFullYear(), this.$M = t.getMonth(), this.$D = t.getDate(), this.$W = t.getDay(), this.$H = t.getHours(), this.$m = t.getMinutes(), this.$s = t.getSeconds(), this.$ms = t.getMilliseconds(); + }, d.$utils = function () { + return D; + }, d.isValid = function () { + return !("Invalid Date" === this.$d.toString()); + }, d.isSame = function (t, e) { + var n = g(t); + return this.startOf(e) <= n && n <= this.endOf(e); + }, d.isAfter = function (t, e) { + return g(t) < this.startOf(e); + }, d.isBefore = function (t, e) { + return this.endOf(e) < g(t); + }, d.$g = function (t, e, n) { + return D.u(t) ? this[e] : this.set(n, t); + }, d.year = function (t) { + return this.$g(t, "$y", a); + }, d.month = function (t) { + return this.$g(t, "$M", u); + }, d.day = function (t) { + return this.$g(t, "$W", i); + }, d.date = function (t) { + return this.$g(t, "$D", "date"); + }, d.hour = function (t) { + return this.$g(t, "$H", r); + }, d.minute = function (t) { + return this.$g(t, "$m", n); + }, d.second = function (t) { + return this.$g(t, "$s", e); + }, d.millisecond = function (e) { + return this.$g(e, "$ms", t); + }, d.unix = function () { + return Math.floor(this.valueOf() / 1e3); + }, d.valueOf = function () { + return this.$d.getTime(); + }, d.startOf = function (t, o) { + var h = this, + f = !!D.u(o) || o, + c = D.p(t), + d = function (t, e) { + var n = D.w(h.$u ? Date.UTC(h.$y, e, t) : new Date(h.$y, e, t), h); + return f ? n : n.endOf(i); + }, + $ = function (t, e) { + return D.w(h.toDate()[t].apply(h.toDate("s"), (f ? [0, 0, 0, 0] : [23, 59, 59, 999]).slice(e)), h); + }, + l = this.$W, + m = this.$M, + y = this.$D, + M = "set" + (this.$u ? "UTC" : ""); + + switch (c) { + case a: + return f ? d(1, 0) : d(31, 11); + + case u: + return f ? d(1, m) : d(0, m + 1); + + case s: + var g = this.$locale().weekStart || 0, + v = (l < g ? l + 7 : l) - g; + return d(f ? y - v : y + (6 - v), m); + + case i: + case "date": + return $(M + "Hours", 0); + + case r: + return $(M + "Minutes", 1); + + case n: + return $(M + "Seconds", 2); + + case e: + return $(M + "Milliseconds", 3); + + default: + return this.clone(); + } + }, d.endOf = function (t) { + return this.startOf(t, !1); + }, d.$set = function (s, o) { + var h, + f = D.p(s), + c = "set" + (this.$u ? "UTC" : ""), + d = (h = {}, h[i] = c + "Date", h.date = c + "Date", h[u] = c + "Month", h[a] = c + "FullYear", h[r] = c + "Hours", h[n] = c + "Minutes", h[e] = c + "Seconds", h[t] = c + "Milliseconds", h)[f], + $ = f === i ? this.$D + (o - this.$W) : o; + + if (f === u || f === a) { + var l = this.clone().set("date", 1); + l.$d[d]($), l.init(), this.$d = l.set("date", Math.min(this.$D, l.daysInMonth())).$d; + } else d && this.$d[d]($); + + return this.init(), this; + }, d.set = function (t, e) { + return this.clone().$set(t, e); + }, d.get = function (t) { + return this[D.p(t)](); + }, d.add = function (t, o) { + var h, + f = this; + t = Number(t); + + var c = D.p(o), + d = function (e) { + var n = g(f); + return D.w(n.date(n.date() + Math.round(e * t)), f); + }; + + if (c === u) return this.set(u, this.$M + t); + if (c === a) return this.set(a, this.$y + t); + if (c === i) return d(1); + if (c === s) return d(7); + var $ = (h = {}, h[n] = 6e4, h[r] = 36e5, h[e] = 1e3, h)[c] || 1, + l = this.$d.getTime() + t * $; + return D.w(l, this); + }, d.subtract = function (t, e) { + return this.add(-1 * t, e); + }, d.format = function (t) { + var e = this; + if (!this.isValid()) return "Invalid Date"; + + var n = t || "YYYY-MM-DDTHH:mm:ssZ", + r = D.z(this), + i = this.$locale(), + s = this.$H, + u = this.$m, + o = this.$M, + a = i.weekdays, + h = i.months, + c = function (t, r, i, s) { + return t && (t[r] || t(e, n)) || i[r].substr(0, s); + }, + d = function (t) { + return D.s(s % 12 || 12, t, "0"); + }, + $ = i.meridiem || function (t, e, n) { + var r = t < 12 ? "AM" : "PM"; + return n ? r.toLowerCase() : r; + }, + l = { + YY: String(this.$y).slice(-2), + YYYY: this.$y, + M: o + 1, + MM: D.s(o + 1, 2, "0"), + MMM: c(i.monthsShort, o, h, 3), + MMMM: c(h, o), + D: this.$D, + DD: D.s(this.$D, 2, "0"), + d: String(this.$W), + dd: c(i.weekdaysMin, this.$W, a, 2), + ddd: c(i.weekdaysShort, this.$W, a, 3), + dddd: a[this.$W], + H: String(s), + HH: D.s(s, 2, "0"), + h: d(1), + hh: d(2), + a: $(s, u, !0), + A: $(s, u, !1), + m: String(u), + mm: D.s(u, 2, "0"), + s: String(this.$s), + ss: D.s(this.$s, 2, "0"), + SSS: D.s(this.$ms, 3, "0"), + Z: r + }; + + return n.replace(f, function (t, e) { + return e || l[t] || r.replace(":", ""); + }); + }, d.utcOffset = function () { + return 15 * -Math.round(this.$d.getTimezoneOffset() / 15); + }, d.diff = function (t, h, f) { + var c, + d = D.p(h), + $ = g(t), + l = 6e4 * ($.utcOffset() - this.utcOffset()), + m = this - $, + y = D.m(this, $); + return y = (c = {}, c[a] = y / 12, c[u] = y, c[o] = y / 3, c[s] = (m - l) / 6048e5, c[i] = (m - l) / 864e5, c[r] = m / 36e5, c[n] = m / 6e4, c[e] = m / 1e3, c)[d] || m, f ? y : D.a(y); + }, d.daysInMonth = function () { + return this.endOf(u).$D; + }, d.$locale = function () { + return m[this.$L]; + }, d.locale = function (t, e) { + if (!t) return this.$L; + var n = this.clone(), + r = M(t, e, !0); + return r && (n.$L = r), n; + }, d.clone = function () { + return D.w(this.$d, this); + }, d.toDate = function () { + return new Date(this.valueOf()); + }, d.toJSON = function () { + return this.isValid() ? this.toISOString() : null; + }, d.toISOString = function () { + return this.$d.toISOString(); + }, d.toString = function () { + return this.$d.toUTCString(); + }, c; + }(); + + return g.prototype = v.prototype, g.extend = function (t, e) { + return t(e, v, g), g; + }, g.locale = M, g.isDayjs = y, g.unix = function (t) { + return g(1e3 * t); + }, g.en = m[l], g.Ls = m, g; +}); + +/***/ }), +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(59); + +/** Detect free variable `self`. */ + +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; +/** Used as a reference to the global object. */ + +var root = _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"] || freeSelf || Function('return this')(); +/* harmony default export */ __webpack_exports__["a"] = (root); + +/***/ }), +/* 5 */, +/* 6 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SHA1; }); +/* + * 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(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(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(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 + */ + + +const SHA1 = { + b64_hmac_sha1: function (key, data) { + return binb2b64(core_hmac_sha1(key, data)); + }, + b64_sha1: function (s) { + return binb2b64(core_sha1(str2binb(s), s.length * 8)); + }, + binb2str: binb2str, + core_hmac_sha1: core_hmac_sha1, + str_hmac_sha1: function (key, data) { + return binb2str(core_hmac_sha1(key, data)); + }, + str_sha1: function (s) { + return binb2str(core_sha1(str2binb(s), s.length * 8)); + } +}; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +var escapeHtmlChar = __webpack_require__(494), + toString = __webpack_require__(135); +/** Used to match HTML entities and HTML characters. */ + + +var reUnescapedHtml = /[&<>"']/g, + reHasUnescapedHtml = RegExp(reUnescapedHtml.source); +/** + * Converts the characters "&", "<", ">", '"', and "'" in `string` to their + * corresponding HTML entities. + * + * **Note:** No other characters are escaped. To escape additional + * characters use a third-party library like [_he_](https://mths.be/he). + * + * Though the ">" character is escaped for symmetry, characters like + * ">" and "/" don't need escaping in HTML and have no special meaning + * unless they're part of a tag or unquoted attribute value. See + * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) + * (under "semi-related fun fact") for more details. + * + * When working with HTML you should always + * [quote attribute values](http://wonko.com/post/html-escaping) to reduce + * XSS vectors. + * + * @static + * @since 0.1.0 + * @memberOf _ + * @category String + * @param {string} [string=''] The string to escape. + * @returns {string} Returns the escaped string. + * @example + * + * _.escape('fred, barney, & pebbles'); + * // => 'fred, barney, & pebbles' + */ + +function escape(string) { + string = toString(string); + return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; +} + +module.exports = escape; + +/***/ }), +/* 8 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return WebSocket; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DOMParser; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return getDummyXMLDOMDocument; }); +/* + * 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() { + let WebSocketImplementation = global.WebSocket; + + if (typeof WebSocketImplementation === 'undefined') { + try { + WebSocketImplementation = __webpack_require__(323); + } catch (err) { + throw new Error('You must install the "ws" package to use Strophe in nodejs.'); + } + } + + return WebSocketImplementation; +} + +const 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() { + let DOMParserImplementation = global.DOMParser; + + if (typeof DOMParserImplementation === 'undefined') { + try { + DOMParserImplementation = __webpack_require__(92).DOMParser; + } catch (err) { + throw new Error('You must install the "xmldom" package to use Strophe in nodejs.'); + } + } + + return DOMParserImplementation; +} + +const 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() { + const docStrings = ["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]; + + for (let d = 0; d < docStrings.length; d++) { + try { + // eslint-disable-next-line no-undef + const 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 { + const DOMImplementation = __webpack_require__(92).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) { + const doc = _getIEXmlDom(); + + doc.appendChild(doc.createElement('strophe')); + return doc; + } // All other supported browsers + + + return document.implementation.createDocument('jabber:client', 'strophe', null); +} +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(18))) + +/***/ }), +/* 9 */ +/***/ (function(module, exports, __webpack_require__) { + +var freeGlobal = __webpack_require__(94); +/** Detect free variable `self`. */ + + +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; +/** Used as a reference to the global object. */ + +var root = freeGlobal || freeSelf || Function('return this')(); +module.exports = root; + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self // eslint-disable-next-line no-new-func +: Function('return this')(); +if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef + +/***/ }), +/* 11 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(module) {/* harmony import */ var _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(59); + +/** Detect free variable `exports`. */ + +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; +/** Detect free variable `module`. */ + +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; +/** Detect the popular CommonJS extension `module.exports`. */ + +var moduleExports = freeModule && freeModule.exports === freeExports; +/** Detect free variable `process` from Node.js. */ + +var freeProcess = moduleExports && _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"].process; +/** Used to access faster Node.js helpers. */ + +var nodeUtil = function () { + try { + // Use `util.types` for Node.js 10+. + var types = freeModule && freeModule.require && freeModule.require('util').types; + + if (types) { + return types; + } // Legacy `process.binding('util')` for Node.js < 10. + + + return freeProcess && freeProcess.binding && freeProcess.binding('util'); + } catch (e) {} +}(); + +/* harmony default export */ __webpack_exports__["a"] = (nodeUtil); +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(66)(module))) + +/***/ }), +/* 12 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an array, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(document.body.children); + * // => false + * + * _.isArray('abc'); + * // => false + * + * _.isArray(_.noop); + * // => false + */ +var isArray = Array.isArray; +module.exports = isArray; + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +var store = __webpack_require__(142)('wks'); + +var uid = __webpack_require__(143); + +var Symbol = __webpack_require__(10).Symbol; + +var USE_SYMBOL = typeof Symbol == 'function'; + +var $exports = module.exports = function (name) { + return store[name] || (store[name] = USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); +}; + +$exports.store = store; + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +var require;var require;(function () { + function r(e, n, t) { + function o(i, f) { + if (!n[i]) { + if (!e[i]) { + var c = "function" == typeof require && require; + if (!f && c) return require(i, !0); + if (u) return u(i, !0); + var a = new Error("Cannot find module '" + i + "'"); + throw a.code = "MODULE_NOT_FOUND", a; + } + + var p = n[i] = { + exports: {} + }; + e[i][0].call(p.exports, function (r) { + var n = e[i][1][r]; + return o(n || r); + }, p, p.exports, r, e, n, t); + } + + return n[i].exports; + } + + for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]); + + return o; + } + + return r; +})()({ + 1: [function (require, module, exports) { + /** + * default settings + * + * @author Zongmin Lei + */ + var FilterCSS = require("cssfilter").FilterCSS; + + var getDefaultCSSWhiteList = require("cssfilter").getDefaultWhiteList; + + var _ = require("./util"); + + function getDefaultWhiteList() { + return { + a: ["target", "href", "title"], + abbr: ["title"], + address: [], + area: ["shape", "coords", "href", "alt"], + article: [], + aside: [], + audio: ["autoplay", "controls", "loop", "preload", "src"], + b: [], + bdi: ["dir"], + bdo: ["dir"], + big: [], + blockquote: ["cite"], + br: [], + caption: [], + center: [], + cite: [], + code: [], + col: ["align", "valign", "span", "width"], + colgroup: ["align", "valign", "span", "width"], + dd: [], + del: ["datetime"], + details: ["open"], + div: [], + dl: [], + dt: [], + em: [], + font: ["color", "size", "face"], + footer: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + header: [], + hr: [], + i: [], + img: ["src", "alt", "title", "width", "height"], + ins: ["datetime"], + li: [], + mark: [], + nav: [], + ol: [], + p: [], + pre: [], + s: [], + section: [], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + table: ["width", "border", "align", "valign"], + tbody: ["align", "valign"], + td: ["width", "rowspan", "colspan", "align", "valign"], + tfoot: ["align", "valign"], + th: ["width", "rowspan", "colspan", "align", "valign"], + thead: ["align", "valign"], + tr: ["rowspan", "align", "valign"], + tt: [], + u: [], + ul: [], + video: ["autoplay", "controls", "loop", "preload", "src", "height", "width"] + }; + } + + var defaultCSSFilter = new FilterCSS(); + /** + * default onTag function + * + * @param {String} tag + * @param {String} html + * @param {Object} options + * @return {String} + */ + + function onTag(tag, html, options) {// do nothing + } + /** + * default onIgnoreTag function + * + * @param {String} tag + * @param {String} html + * @param {Object} options + * @return {String} + */ + + + function onIgnoreTag(tag, html, options) {// do nothing + } + /** + * default onTagAttr function + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @return {String} + */ + + + function onTagAttr(tag, name, value) {// do nothing + } + /** + * default onIgnoreTagAttr function + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @return {String} + */ + + + function onIgnoreTagAttr(tag, name, value) {// do nothing + } + /** + * default escapeHtml function + * + * @param {String} html + */ + + + function escapeHtml(html) { + return html.replace(REGEXP_LT, "<").replace(REGEXP_GT, ">"); + } + /** + * default safeAttrValue function + * + * @param {String} tag + * @param {String} name + * @param {String} value + * @param {Object} cssFilter + * @return {String} + */ + + + function safeAttrValue(tag, name, value, cssFilter) { + // unescape attribute value firstly + value = friendlyAttrValue(value); + + if (name === "href" || name === "src") { + // filter `href` and `src` attribute + // only allow the value that starts with `http://` | `https://` | `mailto:` | `/` | `#` + value = _.trim(value); + if (value === "#") return "#"; + + if (!(value.substr(0, 7) === "http://" || value.substr(0, 8) === "https://" || value.substr(0, 7) === "mailto:" || value.substr(0, 4) === "tel:" || value.substr(0, 11) === "data:image/" || value.substr(0, 6) === "ftp://" || value.substr(0, 2) === "./" || value.substr(0, 3) === "../" || value[0] === "#" || value[0] === "/")) { + return ""; + } + } else if (name === "background") { + // filter `background` attribute (maybe no use) + // `javascript:` + REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) { + return ""; + } + } else if (name === "style") { + // `expression()` + REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) { + return ""; + } // `url()` + + + REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) { + REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0; + + if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) { + return ""; + } + } + + if (cssFilter !== false) { + cssFilter = cssFilter || defaultCSSFilter; + value = cssFilter.process(value); + } + } // escape `<>"` before returns + + + value = escapeAttrValue(value); + return value; + } // RegExp list + + + var REGEXP_LT = //g; + var REGEXP_QUOTE = /"/g; + var REGEXP_QUOTE_2 = /"/g; + var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/gim; + var REGEXP_ATTR_VALUE_COLON = /:?/gim; + var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/gim; + var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//gm; + var REGEXP_DEFAULT_ON_TAG_ATTR_4 = /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi; + var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/gi; + var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//gi; + var REGEXP_DEFAULT_ON_TAG_ATTR_7 = /e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi; + var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/gi; + /** + * escape doube quote + * + * @param {String} str + * @return {String} str + */ + + function escapeQuote(str) { + return str.replace(REGEXP_QUOTE, """); + } + /** + * unescape double quote + * + * @param {String} str + * @return {String} str + */ + + + function unescapeQuote(str) { + return str.replace(REGEXP_QUOTE_2, '"'); + } + /** + * escape html entities + * + * @param {String} str + * @return {String} + */ + + + function escapeHtmlEntities(str) { + return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode(str, code) { + return code[0] === "x" || code[0] === "X" ? String.fromCharCode(parseInt(code.substr(1), 16)) : String.fromCharCode(parseInt(code, 10)); + }); + } + /** + * escape html5 new danger entities + * + * @param {String} str + * @return {String} + */ + + + function escapeDangerHtml5Entities(str) { + return str.replace(REGEXP_ATTR_VALUE_COLON, ":").replace(REGEXP_ATTR_VALUE_NEWLINE, " "); + } + /** + * clear nonprintable characters + * + * @param {String} str + * @return {String} + */ + + + function clearNonPrintableCharacter(str) { + var str2 = ""; + + for (var i = 0, len = str.length; i < len; i++) { + str2 += str.charCodeAt(i) < 32 ? " " : str.charAt(i); + } + + return _.trim(str2); + } + /** + * get friendly attribute value + * + * @param {String} str + * @return {String} + */ + + + function friendlyAttrValue(str) { + str = unescapeQuote(str); + str = escapeHtmlEntities(str); + str = escapeDangerHtml5Entities(str); + str = clearNonPrintableCharacter(str); + return str; + } + /** + * unescape attribute value + * + * @param {String} str + * @return {String} + */ + + + function escapeAttrValue(str) { + str = escapeQuote(str); + str = escapeHtml(str); + return str; + } + /** + * `onIgnoreTag` function for removing all the tags that are not in whitelist + */ + + + function onIgnoreTagStripAll() { + return ""; + } + /** + * remove tag body + * specify a `tags` list, if the tag is not in the `tags` list then process by the specify function (optional) + * + * @param {array} tags + * @param {function} next + */ + + + function StripTagBody(tags, next) { + if (typeof next !== "function") { + next = function () {}; + } + + var isRemoveAllTag = !Array.isArray(tags); + + function isRemoveTag(tag) { + if (isRemoveAllTag) return true; + return _.indexOf(tags, tag) !== -1; + } + + var removeList = []; + var posStart = false; + return { + onIgnoreTag: function (tag, html, options) { + if (isRemoveTag(tag)) { + if (options.isClosing) { + var ret = "[/removed]"; + var end = options.position + ret.length; + removeList.push([posStart !== false ? posStart : options.position, end]); + posStart = false; + return ret; + } else { + if (!posStart) { + posStart = options.position; + } + + return "[removed]"; + } + } else { + return next(tag, html, options); + } + }, + remove: function (html) { + var rethtml = ""; + var lastPos = 0; + + _.forEach(removeList, function (pos) { + rethtml += html.slice(lastPos, pos[0]); + lastPos = pos[1]; + }); + + rethtml += html.slice(lastPos); + return rethtml; + } + }; + } + /** + * remove html comments + * + * @param {String} html + * @return {String} + */ + + + function stripCommentTag(html) { + return html.replace(STRIP_COMMENT_TAG_REGEXP, ""); + } + + var STRIP_COMMENT_TAG_REGEXP = //g; + /** + * remove invisible characters + * + * @param {String} html + * @return {String} + */ + + function stripBlankChar(html) { + var chars = html.split(""); + chars = chars.filter(function (char) { + var c = char.charCodeAt(0); + if (c === 127) return false; + + if (c <= 31) { + if (c === 10 || c === 13) return true; + return false; + } + + return true; + }); + return chars.join(""); + } + + exports.whiteList = getDefaultWhiteList(); + exports.getDefaultWhiteList = getDefaultWhiteList; + exports.onTag = onTag; + exports.onIgnoreTag = onIgnoreTag; + exports.onTagAttr = onTagAttr; + exports.onIgnoreTagAttr = onIgnoreTagAttr; + exports.safeAttrValue = safeAttrValue; + exports.escapeHtml = escapeHtml; + exports.escapeQuote = escapeQuote; + exports.unescapeQuote = unescapeQuote; + exports.escapeHtmlEntities = escapeHtmlEntities; + exports.escapeDangerHtml5Entities = escapeDangerHtml5Entities; + exports.clearNonPrintableCharacter = clearNonPrintableCharacter; + exports.friendlyAttrValue = friendlyAttrValue; + exports.escapeAttrValue = escapeAttrValue; + exports.onIgnoreTagStripAll = onIgnoreTagStripAll; + exports.StripTagBody = StripTagBody; + exports.stripCommentTag = stripCommentTag; + exports.stripBlankChar = stripBlankChar; + exports.cssFilter = defaultCSSFilter; + exports.getDefaultCSSWhiteList = getDefaultCSSWhiteList; + }, { + "./util": 4, + "cssfilter": 8 + }], + 2: [function (require, module, exports) { + /** + * xss + * + * @author Zongmin Lei + */ + var DEFAULT = require("./default"); + + var parser = require("./parser"); + + var FilterXSS = require("./xss"); + /** + * filter xss function + * + * @param {String} html + * @param {Object} options { whiteList, onTag, onTagAttr, onIgnoreTag, onIgnoreTagAttr, safeAttrValue, escapeHtml } + * @return {String} + */ + + + function filterXSS(html, options) { + var xss = new FilterXSS(options); + return xss.process(html); + } + + exports = module.exports = filterXSS; + exports.filterXSS = filterXSS; + exports.FilterXSS = FilterXSS; + + for (var i in DEFAULT) exports[i] = DEFAULT[i]; + + for (var i in parser) exports[i] = parser[i]; // using `xss` on the browser, output `filterXSS` to the globals + + + if (typeof window !== "undefined") { + window.filterXSS = module.exports; + } // using `xss` on the WebWorker, output `filterXSS` to the globals + + + function isWorkerEnv() { + return typeof self !== 'undefined' && typeof DedicatedWorkerGlobalScope !== 'undefined' && self instanceof DedicatedWorkerGlobalScope; + } + + if (isWorkerEnv()) { + self.filterXSS = module.exports; + } + }, { + "./default": 1, + "./parser": 3, + "./xss": 5 + }], + 3: [function (require, module, exports) { + /** + * Simple HTML Parser + * + * @author Zongmin Lei + */ + var _ = require("./util"); + /** + * get tag name + * + * @param {String} html e.g. '' + * @return {String} + */ + + + function getTagName(html) { + var i = _.spaceIndex(html); + + if (i === -1) { + var tagName = html.slice(1, -1); + } else { + var tagName = html.slice(1, i + 1); + } + + tagName = _.trim(tagName).toLowerCase(); + if (tagName.slice(0, 1) === "/") tagName = tagName.slice(1); + if (tagName.slice(-1) === "/") tagName = tagName.slice(0, -1); + return tagName; + } + /** + * is close tag? + * + * @param {String} html 如:'' + * @return {Boolean} + */ + + + function isClosing(html) { + return html.slice(0, 2) === "") { + rethtml += escapeHtml(html.slice(lastPos, tagStart)); + currentHtml = html.slice(tagStart, currentPos + 1); + currentTagName = getTagName(currentHtml); + rethtml += onTag(tagStart, rethtml.length, currentTagName, currentHtml, isClosing(currentHtml)); + lastPos = currentPos + 1; + tagStart = false; + continue; + } + + if (c === '"' || c === "'") { + var i = 1; + var ic = html.charAt(currentPos - i); + + while (ic === " " || ic === "=") { + if (ic === "=") { + quoteStart = c; + continue chariterator; + } + + ic = html.charAt(currentPos - ++i); + } + } + } else { + if (c === quoteStart) { + quoteStart = false; + continue; + } + } + } + } + + if (lastPos < html.length) { + rethtml += escapeHtml(html.substr(lastPos)); + } + + return rethtml; + } + + var REGEXP_ILLEGAL_ATTR_NAME = /[^a-zA-Z0-9_:\.\-]/gim; + /** + * parse input attributes and returns processed attributes + * + * @param {String} html e.g. `href="#" target="_blank"` + * @param {Function} onAttr e.g. `function (name, value)` + * @return {String} + */ + + function parseAttr(html, onAttr) { + "use strict"; + + var lastPos = 0; + var retAttrs = []; + var tmpName = false; + var len = html.length; + + function addAttr(name, value) { + name = _.trim(name); + name = name.replace(REGEXP_ILLEGAL_ATTR_NAME, "").toLowerCase(); + if (name.length < 1) return; + var ret = onAttr(name, value || ""); + if (ret) retAttrs.push(ret); + } // 逐个分析字符 + + + for (var i = 0; i < len; i++) { + var c = html.charAt(i); + var v, j; + + if (tmpName === false && c === "=") { + tmpName = html.slice(lastPos, i); + lastPos = i + 1; + continue; + } + + if (tmpName !== false) { + if (i === lastPos && (c === '"' || c === "'") && html.charAt(i - 1) === "=") { + j = html.indexOf(c, i + 1); + + if (j === -1) { + break; + } else { + v = _.trim(html.slice(lastPos + 1, j)); + addAttr(tmpName, v); + tmpName = false; + i = j; + lastPos = i + 1; + continue; + } + } + } + + if (/\s|\n|\t/.test(c)) { + html = html.replace(/\s|\n|\t/g, " "); + + if (tmpName === false) { + j = findNextEqual(html, i); + + if (j === -1) { + v = _.trim(html.slice(lastPos, i)); + addAttr(v); + tmpName = false; + lastPos = i + 1; + continue; + } else { + i = j - 1; + continue; + } + } else { + j = findBeforeEqual(html, i - 1); + + if (j === -1) { + v = _.trim(html.slice(lastPos, i)); + v = stripQuoteWrap(v); + addAttr(tmpName, v); + tmpName = false; + lastPos = i + 1; + continue; + } else { + continue; + } + } + } + } + + if (lastPos < html.length) { + if (tmpName === false) { + addAttr(html.slice(lastPos)); + } else { + addAttr(tmpName, stripQuoteWrap(_.trim(html.slice(lastPos)))); + } + } + + return _.trim(retAttrs.join(" ")); + } + + function findNextEqual(str, i) { + for (; i < str.length; i++) { + var c = str[i]; + if (c === " ") continue; + if (c === "=") return i; + return -1; + } + } + + function findBeforeEqual(str, i) { + for (; i > 0; i--) { + var c = str[i]; + if (c === " ") continue; + if (c === "=") return i; + return -1; + } + } + + function isQuoteWrapString(text) { + if (text[0] === '"' && text[text.length - 1] === '"' || text[0] === "'" && text[text.length - 1] === "'") { + return true; + } else { + return false; + } + } + + function stripQuoteWrap(text) { + if (isQuoteWrapString(text)) { + return text.substr(1, text.length - 2); + } else { + return text; + } + } + + exports.parseTag = parseTag; + exports.parseAttr = parseAttr; + }, { + "./util": 4 + }], + 4: [function (require, module, exports) { + module.exports = { + indexOf: function (arr, item) { + var i, j; + + if (Array.prototype.indexOf) { + return arr.indexOf(item); + } + + for (i = 0, j = arr.length; i < j; i++) { + if (arr[i] === item) { + return i; + } + } + + return -1; + }, + forEach: function (arr, fn, scope) { + var i, j; + + if (Array.prototype.forEach) { + return arr.forEach(fn, scope); + } + + for (i = 0, j = arr.length; i < j; i++) { + fn.call(scope, arr[i], i, arr); + } + }, + trim: function (str) { + if (String.prototype.trim) { + return str.trim(); + } + + return str.replace(/(^\s*)|(\s*$)/g, ""); + }, + spaceIndex: function (str) { + var reg = /\s|\n|\t/; + var match = reg.exec(str); + return match ? match.index : -1; + } + }; + }, {}], + 5: [function (require, module, exports) { + /** + * filter xss + * + * @author Zongmin Lei + */ + var FilterCSS = require("cssfilter").FilterCSS; + + var DEFAULT = require("./default"); + + var parser = require("./parser"); + + var parseTag = parser.parseTag; + var parseAttr = parser.parseAttr; + + var _ = require("./util"); + /** + * returns `true` if the input value is `undefined` or `null` + * + * @param {Object} obj + * @return {Boolean} + */ + + + function isNull(obj) { + return obj === undefined || obj === null; + } + /** + * get attributes for a tag + * + * @param {String} html + * @return {Object} + * - {String} html + * - {Boolean} closing + */ + + + function getAttrs(html) { + var i = _.spaceIndex(html); + + if (i === -1) { + return { + html: "", + closing: html[html.length - 2] === "/" + }; + } + + html = _.trim(html.slice(i + 1, -1)); + var isClosing = html[html.length - 1] === "/"; + if (isClosing) html = _.trim(html.slice(0, -1)); + return { + html: html, + closing: isClosing + }; + } + /** + * shallow copy + * + * @param {Object} obj + * @return {Object} + */ + + + function shallowCopyObject(obj) { + var ret = {}; + + for (var i in obj) { + ret[i] = obj[i]; + } + + return ret; + } + /** + * FilterXSS class + * + * @param {Object} options + * whiteList, onTag, onTagAttr, onIgnoreTag, + * onIgnoreTagAttr, safeAttrValue, escapeHtml + * stripIgnoreTagBody, allowCommentTag, stripBlankChar + * css{whiteList, onAttr, onIgnoreAttr} `css=false` means don't use `cssfilter` + */ + + + function FilterXSS(options) { + options = shallowCopyObject(options || {}); + + if (options.stripIgnoreTag) { + if (options.onIgnoreTag) { + console.error('Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time'); + } + + options.onIgnoreTag = DEFAULT.onIgnoreTagStripAll; + } + + options.whiteList = options.whiteList || DEFAULT.whiteList; + options.onTag = options.onTag || DEFAULT.onTag; + options.onTagAttr = options.onTagAttr || DEFAULT.onTagAttr; + options.onIgnoreTag = options.onIgnoreTag || DEFAULT.onIgnoreTag; + options.onIgnoreTagAttr = options.onIgnoreTagAttr || DEFAULT.onIgnoreTagAttr; + options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue; + options.escapeHtml = options.escapeHtml || DEFAULT.escapeHtml; + this.options = options; + + if (options.css === false) { + this.cssFilter = false; + } else { + options.css = options.css || {}; + this.cssFilter = new FilterCSS(options.css); + } + } + /** + * start process and returns result + * + * @param {String} html + * @return {String} + */ + + + FilterXSS.prototype.process = function (html) { + // compatible with the input + html = html || ""; + html = html.toString(); + if (!html) return ""; + var me = this; + var options = me.options; + var whiteList = options.whiteList; + var onTag = options.onTag; + var onIgnoreTag = options.onIgnoreTag; + var onTagAttr = options.onTagAttr; + var onIgnoreTagAttr = options.onIgnoreTagAttr; + var safeAttrValue = options.safeAttrValue; + var escapeHtml = options.escapeHtml; + var cssFilter = me.cssFilter; // remove invisible characters + + if (options.stripBlankChar) { + html = DEFAULT.stripBlankChar(html); + } // remove html comments + + + if (!options.allowCommentTag) { + html = DEFAULT.stripCommentTag(html); + } // if enable stripIgnoreTagBody + + + var stripIgnoreTagBody = false; + + if (options.stripIgnoreTagBody) { + var stripIgnoreTagBody = DEFAULT.StripTagBody(options.stripIgnoreTagBody, onIgnoreTag); + onIgnoreTag = stripIgnoreTagBody.onIgnoreTag; + } + + var retHtml = parseTag(html, function (sourcePosition, position, tag, html, isClosing) { + var info = { + sourcePosition: sourcePosition, + position: position, + isClosing: isClosing, + isWhite: whiteList.hasOwnProperty(tag) + }; // call `onTag()` + + var ret = onTag(tag, html, info); + if (!isNull(ret)) return ret; + + if (info.isWhite) { + if (info.isClosing) { + return ""; + } + + var attrs = getAttrs(html); + var whiteAttrList = whiteList[tag]; + var attrsHtml = parseAttr(attrs.html, function (name, value) { + // call `onTagAttr()` + var isWhiteAttr = _.indexOf(whiteAttrList, name) !== -1; + var ret = onTagAttr(tag, name, value, isWhiteAttr); + if (!isNull(ret)) return ret; + + if (isWhiteAttr) { + // call `safeAttrValue()` + value = safeAttrValue(tag, name, value, cssFilter); + + if (value) { + return name + '="' + value + '"'; + } else { + return name; + } + } else { + // call `onIgnoreTagAttr()` + var ret = onIgnoreTagAttr(tag, name, value, isWhiteAttr); + if (!isNull(ret)) return ret; + return; + } + }); // build new tag html + + var html = "<" + tag; + if (attrsHtml) html += " " + attrsHtml; + if (attrs.closing) html += " /"; + html += ">"; + return html; + } else { + // call `onIgnoreTag()` + var ret = onIgnoreTag(tag, html, info); + if (!isNull(ret)) return ret; + return escapeHtml(html); + } + }, escapeHtml); // if enable stripIgnoreTagBody + + if (stripIgnoreTagBody) { + retHtml = stripIgnoreTagBody.remove(retHtml); + } + + return retHtml; + }; + + module.exports = FilterXSS; + }, { + "./default": 1, + "./parser": 3, + "./util": 4, + "cssfilter": 8 + }], + 6: [function (require, module, exports) { + /** + * cssfilter + * + * @author 老雷 + */ + var DEFAULT = require('./default'); + + var parseStyle = require('./parser'); + + var _ = require('./util'); + /** + * 返回值是否为空 + * + * @param {Object} obj + * @return {Boolean} + */ + + + function isNull(obj) { + return obj === undefined || obj === null; + } + /** + * 浅拷贝对象 + * + * @param {Object} obj + * @return {Object} + */ + + + function shallowCopyObject(obj) { + var ret = {}; + + for (var i in obj) { + ret[i] = obj[i]; + } + + return ret; + } + /** + * 创建CSS过滤器 + * + * @param {Object} options + * - {Object} whiteList + * - {Function} onAttr + * - {Function} onIgnoreAttr + * - {Function} safeAttrValue + */ + + + function FilterCSS(options) { + options = shallowCopyObject(options || {}); + options.whiteList = options.whiteList || DEFAULT.whiteList; + options.onAttr = options.onAttr || DEFAULT.onAttr; + options.onIgnoreAttr = options.onIgnoreAttr || DEFAULT.onIgnoreAttr; + options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue; + this.options = options; + } + + FilterCSS.prototype.process = function (css) { + // 兼容各种奇葩输入 + css = css || ''; + css = css.toString(); + if (!css) return ''; + var me = this; + var options = me.options; + var whiteList = options.whiteList; + var onAttr = options.onAttr; + var onIgnoreAttr = options.onIgnoreAttr; + var safeAttrValue = options.safeAttrValue; + var retCSS = parseStyle(css, function (sourcePosition, position, name, value, source) { + var check = whiteList[name]; + var isWhite = false; + if (check === true) isWhite = check;else if (typeof check === 'function') isWhite = check(value);else if (check instanceof RegExp) isWhite = check.test(value); + if (isWhite !== true) isWhite = false; // 如果过滤后 value 为空则直接忽略 + + value = safeAttrValue(name, value); + if (!value) return; + var opts = { + position: position, + sourcePosition: sourcePosition, + source: source, + isWhite: isWhite + }; + + if (isWhite) { + var ret = onAttr(name, value, opts); + + if (isNull(ret)) { + return name + ':' + value; + } else { + return ret; + } + } else { + var ret = onIgnoreAttr(name, value, opts); + + if (!isNull(ret)) { + return ret; + } + } + }); + return retCSS; + }; + + module.exports = FilterCSS; + }, { + "./default": 7, + "./parser": 9, + "./util": 10 + }], + 7: [function (require, module, exports) { + /** + * cssfilter + * + * @author 老雷 + */ + function getDefaultWhiteList() { + // 白名单值说明: + // true: 允许该属性 + // Function: function (val) { } 返回true表示允许该属性,其他值均表示不允许 + // RegExp: regexp.test(val) 返回true表示允许该属性,其他值均表示不允许 + // 除上面列出的值外均表示不允许 + var whiteList = {}; + whiteList['align-content'] = false; // default: auto + + whiteList['align-items'] = false; // default: auto + + whiteList['align-self'] = false; // default: auto + + whiteList['alignment-adjust'] = false; // default: auto + + whiteList['alignment-baseline'] = false; // default: baseline + + whiteList['all'] = false; // default: depending on individual properties + + whiteList['anchor-point'] = false; // default: none + + whiteList['animation'] = false; // default: depending on individual properties + + whiteList['animation-delay'] = false; // default: 0 + + whiteList['animation-direction'] = false; // default: normal + + whiteList['animation-duration'] = false; // default: 0 + + whiteList['animation-fill-mode'] = false; // default: none + + whiteList['animation-iteration-count'] = false; // default: 1 + + whiteList['animation-name'] = false; // default: none + + whiteList['animation-play-state'] = false; // default: running + + whiteList['animation-timing-function'] = false; // default: ease + + whiteList['azimuth'] = false; // default: center + + whiteList['backface-visibility'] = false; // default: visible + + whiteList['background'] = true; // default: depending on individual properties + + whiteList['background-attachment'] = true; // default: scroll + + whiteList['background-clip'] = true; // default: border-box + + whiteList['background-color'] = true; // default: transparent + + whiteList['background-image'] = true; // default: none + + whiteList['background-origin'] = true; // default: padding-box + + whiteList['background-position'] = true; // default: 0% 0% + + whiteList['background-repeat'] = true; // default: repeat + + whiteList['background-size'] = true; // default: auto + + whiteList['baseline-shift'] = false; // default: baseline + + whiteList['binding'] = false; // default: none + + whiteList['bleed'] = false; // default: 6pt + + whiteList['bookmark-label'] = false; // default: content() + + whiteList['bookmark-level'] = false; // default: none + + whiteList['bookmark-state'] = false; // default: open + + whiteList['border'] = true; // default: depending on individual properties + + whiteList['border-bottom'] = true; // default: depending on individual properties + + whiteList['border-bottom-color'] = true; // default: current color + + whiteList['border-bottom-left-radius'] = true; // default: 0 + + whiteList['border-bottom-right-radius'] = true; // default: 0 + + whiteList['border-bottom-style'] = true; // default: none + + whiteList['border-bottom-width'] = true; // default: medium + + whiteList['border-collapse'] = true; // default: separate + + whiteList['border-color'] = true; // default: depending on individual properties + + whiteList['border-image'] = true; // default: none + + whiteList['border-image-outset'] = true; // default: 0 + + whiteList['border-image-repeat'] = true; // default: stretch + + whiteList['border-image-slice'] = true; // default: 100% + + whiteList['border-image-source'] = true; // default: none + + whiteList['border-image-width'] = true; // default: 1 + + whiteList['border-left'] = true; // default: depending on individual properties + + whiteList['border-left-color'] = true; // default: current color + + whiteList['border-left-style'] = true; // default: none + + whiteList['border-left-width'] = true; // default: medium + + whiteList['border-radius'] = true; // default: 0 + + whiteList['border-right'] = true; // default: depending on individual properties + + whiteList['border-right-color'] = true; // default: current color + + whiteList['border-right-style'] = true; // default: none + + whiteList['border-right-width'] = true; // default: medium + + whiteList['border-spacing'] = true; // default: 0 + + whiteList['border-style'] = true; // default: depending on individual properties + + whiteList['border-top'] = true; // default: depending on individual properties + + whiteList['border-top-color'] = true; // default: current color + + whiteList['border-top-left-radius'] = true; // default: 0 + + whiteList['border-top-right-radius'] = true; // default: 0 + + whiteList['border-top-style'] = true; // default: none + + whiteList['border-top-width'] = true; // default: medium + + whiteList['border-width'] = true; // default: depending on individual properties + + whiteList['bottom'] = false; // default: auto + + whiteList['box-decoration-break'] = true; // default: slice + + whiteList['box-shadow'] = true; // default: none + + whiteList['box-sizing'] = true; // default: content-box + + whiteList['box-snap'] = true; // default: none + + whiteList['box-suppress'] = true; // default: show + + whiteList['break-after'] = true; // default: auto + + whiteList['break-before'] = true; // default: auto + + whiteList['break-inside'] = true; // default: auto + + whiteList['caption-side'] = false; // default: top + + whiteList['chains'] = false; // default: none + + whiteList['clear'] = true; // default: none + + whiteList['clip'] = false; // default: auto + + whiteList['clip-path'] = false; // default: none + + whiteList['clip-rule'] = false; // default: nonzero + + whiteList['color'] = true; // default: implementation dependent + + whiteList['color-interpolation-filters'] = true; // default: auto + + whiteList['column-count'] = false; // default: auto + + whiteList['column-fill'] = false; // default: balance + + whiteList['column-gap'] = false; // default: normal + + whiteList['column-rule'] = false; // default: depending on individual properties + + whiteList['column-rule-color'] = false; // default: current color + + whiteList['column-rule-style'] = false; // default: medium + + whiteList['column-rule-width'] = false; // default: medium + + whiteList['column-span'] = false; // default: none + + whiteList['column-width'] = false; // default: auto + + whiteList['columns'] = false; // default: depending on individual properties + + whiteList['contain'] = false; // default: none + + whiteList['content'] = false; // default: normal + + whiteList['counter-increment'] = false; // default: none + + whiteList['counter-reset'] = false; // default: none + + whiteList['counter-set'] = false; // default: none + + whiteList['crop'] = false; // default: auto + + whiteList['cue'] = false; // default: depending on individual properties + + whiteList['cue-after'] = false; // default: none + + whiteList['cue-before'] = false; // default: none + + whiteList['cursor'] = false; // default: auto + + whiteList['direction'] = false; // default: ltr + + whiteList['display'] = true; // default: depending on individual properties + + whiteList['display-inside'] = true; // default: auto + + whiteList['display-list'] = true; // default: none + + whiteList['display-outside'] = true; // default: inline-level + + whiteList['dominant-baseline'] = false; // default: auto + + whiteList['elevation'] = false; // default: level + + whiteList['empty-cells'] = false; // default: show + + whiteList['filter'] = false; // default: none + + whiteList['flex'] = false; // default: depending on individual properties + + whiteList['flex-basis'] = false; // default: auto + + whiteList['flex-direction'] = false; // default: row + + whiteList['flex-flow'] = false; // default: depending on individual properties + + whiteList['flex-grow'] = false; // default: 0 + + whiteList['flex-shrink'] = false; // default: 1 + + whiteList['flex-wrap'] = false; // default: nowrap + + whiteList['float'] = false; // default: none + + whiteList['float-offset'] = false; // default: 0 0 + + whiteList['flood-color'] = false; // default: black + + whiteList['flood-opacity'] = false; // default: 1 + + whiteList['flow-from'] = false; // default: none + + whiteList['flow-into'] = false; // default: none + + whiteList['font'] = true; // default: depending on individual properties + + whiteList['font-family'] = true; // default: implementation dependent + + whiteList['font-feature-settings'] = true; // default: normal + + whiteList['font-kerning'] = true; // default: auto + + whiteList['font-language-override'] = true; // default: normal + + whiteList['font-size'] = true; // default: medium + + whiteList['font-size-adjust'] = true; // default: none + + whiteList['font-stretch'] = true; // default: normal + + whiteList['font-style'] = true; // default: normal + + whiteList['font-synthesis'] = true; // default: weight style + + whiteList['font-variant'] = true; // default: normal + + whiteList['font-variant-alternates'] = true; // default: normal + + whiteList['font-variant-caps'] = true; // default: normal + + whiteList['font-variant-east-asian'] = true; // default: normal + + whiteList['font-variant-ligatures'] = true; // default: normal + + whiteList['font-variant-numeric'] = true; // default: normal + + whiteList['font-variant-position'] = true; // default: normal + + whiteList['font-weight'] = true; // default: normal + + whiteList['grid'] = false; // default: depending on individual properties + + whiteList['grid-area'] = false; // default: depending on individual properties + + whiteList['grid-auto-columns'] = false; // default: auto + + whiteList['grid-auto-flow'] = false; // default: none + + whiteList['grid-auto-rows'] = false; // default: auto + + whiteList['grid-column'] = false; // default: depending on individual properties + + whiteList['grid-column-end'] = false; // default: auto + + whiteList['grid-column-start'] = false; // default: auto + + whiteList['grid-row'] = false; // default: depending on individual properties + + whiteList['grid-row-end'] = false; // default: auto + + whiteList['grid-row-start'] = false; // default: auto + + whiteList['grid-template'] = false; // default: depending on individual properties + + whiteList['grid-template-areas'] = false; // default: none + + whiteList['grid-template-columns'] = false; // default: none + + whiteList['grid-template-rows'] = false; // default: none + + whiteList['hanging-punctuation'] = false; // default: none + + whiteList['height'] = true; // default: auto + + whiteList['hyphens'] = false; // default: manual + + whiteList['icon'] = false; // default: auto + + whiteList['image-orientation'] = false; // default: auto + + whiteList['image-resolution'] = false; // default: normal + + whiteList['ime-mode'] = false; // default: auto + + whiteList['initial-letters'] = false; // default: normal + + whiteList['inline-box-align'] = false; // default: last + + whiteList['justify-content'] = false; // default: auto + + whiteList['justify-items'] = false; // default: auto + + whiteList['justify-self'] = false; // default: auto + + whiteList['left'] = false; // default: auto + + whiteList['letter-spacing'] = true; // default: normal + + whiteList['lighting-color'] = true; // default: white + + whiteList['line-box-contain'] = false; // default: block inline replaced + + whiteList['line-break'] = false; // default: auto + + whiteList['line-grid'] = false; // default: match-parent + + whiteList['line-height'] = false; // default: normal + + whiteList['line-snap'] = false; // default: none + + whiteList['line-stacking'] = false; // default: depending on individual properties + + whiteList['line-stacking-ruby'] = false; // default: exclude-ruby + + whiteList['line-stacking-shift'] = false; // default: consider-shifts + + whiteList['line-stacking-strategy'] = false; // default: inline-line-height + + whiteList['list-style'] = true; // default: depending on individual properties + + whiteList['list-style-image'] = true; // default: none + + whiteList['list-style-position'] = true; // default: outside + + whiteList['list-style-type'] = true; // default: disc + + whiteList['margin'] = true; // default: depending on individual properties + + whiteList['margin-bottom'] = true; // default: 0 + + whiteList['margin-left'] = true; // default: 0 + + whiteList['margin-right'] = true; // default: 0 + + whiteList['margin-top'] = true; // default: 0 + + whiteList['marker-offset'] = false; // default: auto + + whiteList['marker-side'] = false; // default: list-item + + whiteList['marks'] = false; // default: none + + whiteList['mask'] = false; // default: border-box + + whiteList['mask-box'] = false; // default: see individual properties + + whiteList['mask-box-outset'] = false; // default: 0 + + whiteList['mask-box-repeat'] = false; // default: stretch + + whiteList['mask-box-slice'] = false; // default: 0 fill + + whiteList['mask-box-source'] = false; // default: none + + whiteList['mask-box-width'] = false; // default: auto + + whiteList['mask-clip'] = false; // default: border-box + + whiteList['mask-image'] = false; // default: none + + whiteList['mask-origin'] = false; // default: border-box + + whiteList['mask-position'] = false; // default: center + + whiteList['mask-repeat'] = false; // default: no-repeat + + whiteList['mask-size'] = false; // default: border-box + + whiteList['mask-source-type'] = false; // default: auto + + whiteList['mask-type'] = false; // default: luminance + + whiteList['max-height'] = true; // default: none + + whiteList['max-lines'] = false; // default: none + + whiteList['max-width'] = true; // default: none + + whiteList['min-height'] = true; // default: 0 + + whiteList['min-width'] = true; // default: 0 + + whiteList['move-to'] = false; // default: normal + + whiteList['nav-down'] = false; // default: auto + + whiteList['nav-index'] = false; // default: auto + + whiteList['nav-left'] = false; // default: auto + + whiteList['nav-right'] = false; // default: auto + + whiteList['nav-up'] = false; // default: auto + + whiteList['object-fit'] = false; // default: fill + + whiteList['object-position'] = false; // default: 50% 50% + + whiteList['opacity'] = false; // default: 1 + + whiteList['order'] = false; // default: 0 + + whiteList['orphans'] = false; // default: 2 + + whiteList['outline'] = false; // default: depending on individual properties + + whiteList['outline-color'] = false; // default: invert + + whiteList['outline-offset'] = false; // default: 0 + + whiteList['outline-style'] = false; // default: none + + whiteList['outline-width'] = false; // default: medium + + whiteList['overflow'] = false; // default: depending on individual properties + + whiteList['overflow-wrap'] = false; // default: normal + + whiteList['overflow-x'] = false; // default: visible + + whiteList['overflow-y'] = false; // default: visible + + whiteList['padding'] = true; // default: depending on individual properties + + whiteList['padding-bottom'] = true; // default: 0 + + whiteList['padding-left'] = true; // default: 0 + + whiteList['padding-right'] = true; // default: 0 + + whiteList['padding-top'] = true; // default: 0 + + whiteList['page'] = false; // default: auto + + whiteList['page-break-after'] = false; // default: auto + + whiteList['page-break-before'] = false; // default: auto + + whiteList['page-break-inside'] = false; // default: auto + + whiteList['page-policy'] = false; // default: start + + whiteList['pause'] = false; // default: implementation dependent + + whiteList['pause-after'] = false; // default: implementation dependent + + whiteList['pause-before'] = false; // default: implementation dependent + + whiteList['perspective'] = false; // default: none + + whiteList['perspective-origin'] = false; // default: 50% 50% + + whiteList['pitch'] = false; // default: medium + + whiteList['pitch-range'] = false; // default: 50 + + whiteList['play-during'] = false; // default: auto + + whiteList['position'] = false; // default: static + + whiteList['presentation-level'] = false; // default: 0 + + whiteList['quotes'] = false; // default: text + + whiteList['region-fragment'] = false; // default: auto + + whiteList['resize'] = false; // default: none + + whiteList['rest'] = false; // default: depending on individual properties + + whiteList['rest-after'] = false; // default: none + + whiteList['rest-before'] = false; // default: none + + whiteList['richness'] = false; // default: 50 + + whiteList['right'] = false; // default: auto + + whiteList['rotation'] = false; // default: 0 + + whiteList['rotation-point'] = false; // default: 50% 50% + + whiteList['ruby-align'] = false; // default: auto + + whiteList['ruby-merge'] = false; // default: separate + + whiteList['ruby-position'] = false; // default: before + + whiteList['shape-image-threshold'] = false; // default: 0.0 + + whiteList['shape-outside'] = false; // default: none + + whiteList['shape-margin'] = false; // default: 0 + + whiteList['size'] = false; // default: auto + + whiteList['speak'] = false; // default: auto + + whiteList['speak-as'] = false; // default: normal + + whiteList['speak-header'] = false; // default: once + + whiteList['speak-numeral'] = false; // default: continuous + + whiteList['speak-punctuation'] = false; // default: none + + whiteList['speech-rate'] = false; // default: medium + + whiteList['stress'] = false; // default: 50 + + whiteList['string-set'] = false; // default: none + + whiteList['tab-size'] = false; // default: 8 + + whiteList['table-layout'] = false; // default: auto + + whiteList['text-align'] = true; // default: start + + whiteList['text-align-last'] = true; // default: auto + + whiteList['text-combine-upright'] = true; // default: none + + whiteList['text-decoration'] = true; // default: none + + whiteList['text-decoration-color'] = true; // default: currentColor + + whiteList['text-decoration-line'] = true; // default: none + + whiteList['text-decoration-skip'] = true; // default: objects + + whiteList['text-decoration-style'] = true; // default: solid + + whiteList['text-emphasis'] = true; // default: depending on individual properties + + whiteList['text-emphasis-color'] = true; // default: currentColor + + whiteList['text-emphasis-position'] = true; // default: over right + + whiteList['text-emphasis-style'] = true; // default: none + + whiteList['text-height'] = true; // default: auto + + whiteList['text-indent'] = true; // default: 0 + + whiteList['text-justify'] = true; // default: auto + + whiteList['text-orientation'] = true; // default: mixed + + whiteList['text-overflow'] = true; // default: clip + + whiteList['text-shadow'] = true; // default: none + + whiteList['text-space-collapse'] = true; // default: collapse + + whiteList['text-transform'] = true; // default: none + + whiteList['text-underline-position'] = true; // default: auto + + whiteList['text-wrap'] = true; // default: normal + + whiteList['top'] = false; // default: auto + + whiteList['transform'] = false; // default: none + + whiteList['transform-origin'] = false; // default: 50% 50% 0 + + whiteList['transform-style'] = false; // default: flat + + whiteList['transition'] = false; // default: depending on individual properties + + whiteList['transition-delay'] = false; // default: 0s + + whiteList['transition-duration'] = false; // default: 0s + + whiteList['transition-property'] = false; // default: all + + whiteList['transition-timing-function'] = false; // default: ease + + whiteList['unicode-bidi'] = false; // default: normal + + whiteList['vertical-align'] = false; // default: baseline + + whiteList['visibility'] = false; // default: visible + + whiteList['voice-balance'] = false; // default: center + + whiteList['voice-duration'] = false; // default: auto + + whiteList['voice-family'] = false; // default: implementation dependent + + whiteList['voice-pitch'] = false; // default: medium + + whiteList['voice-range'] = false; // default: medium + + whiteList['voice-rate'] = false; // default: normal + + whiteList['voice-stress'] = false; // default: normal + + whiteList['voice-volume'] = false; // default: medium + + whiteList['volume'] = false; // default: medium + + whiteList['white-space'] = false; // default: normal + + whiteList['widows'] = false; // default: 2 + + whiteList['width'] = true; // default: auto + + whiteList['will-change'] = false; // default: auto + + whiteList['word-break'] = true; // default: normal + + whiteList['word-spacing'] = true; // default: normal + + whiteList['word-wrap'] = true; // default: normal + + whiteList['wrap-flow'] = false; // default: auto + + whiteList['wrap-through'] = false; // default: wrap + + whiteList['writing-mode'] = false; // default: horizontal-tb + + whiteList['z-index'] = false; // default: auto + + return whiteList; + } + /** + * 匹配到白名单上的一个属性时 + * + * @param {String} name + * @param {String} value + * @param {Object} options + * @return {String} + */ + + + function onAttr(name, value, options) {// do nothing + } + /** + * 匹配到不在白名单上的一个属性时 + * + * @param {String} name + * @param {String} value + * @param {Object} options + * @return {String} + */ + + + function onIgnoreAttr(name, value, options) {// do nothing + } + + var REGEXP_URL_JAVASCRIPT = /javascript\s*\:/img; + /** + * 过滤属性值 + * + * @param {String} name + * @param {String} value + * @return {String} + */ + + function safeAttrValue(name, value) { + if (REGEXP_URL_JAVASCRIPT.test(value)) return ''; + return value; + } + + exports.whiteList = getDefaultWhiteList(); + exports.getDefaultWhiteList = getDefaultWhiteList; + exports.onAttr = onAttr; + exports.onIgnoreAttr = onIgnoreAttr; + exports.safeAttrValue = safeAttrValue; + }, {}], + 8: [function (require, module, exports) { + /** + * cssfilter + * + * @author 老雷 + */ + var DEFAULT = require('./default'); + + var FilterCSS = require('./css'); + /** + * XSS过滤 + * + * @param {String} css 要过滤的CSS代码 + * @param {Object} options 选项:whiteList, onAttr, onIgnoreAttr + * @return {String} + */ + + + function filterCSS(html, options) { + var xss = new FilterCSS(options); + return xss.process(html); + } // 输出 + + + exports = module.exports = filterCSS; + exports.FilterCSS = FilterCSS; + + for (var i in DEFAULT) exports[i] = DEFAULT[i]; // 在浏览器端使用 + + + if (typeof window !== 'undefined') { + window.filterCSS = module.exports; + } + }, { + "./css": 6, + "./default": 7 + }], + 9: [function (require, module, exports) { + /** + * cssfilter + * + * @author 老雷 + */ + var _ = require('./util'); + /** + * 解析style + * + * @param {String} css + * @param {Function} onAttr 处理属性的函数 + * 参数格式: function (sourcePosition, position, name, value, source) + * @return {String} + */ + + + function parseStyle(css, onAttr) { + css = _.trimRight(css); + if (css[css.length - 1] !== ';') css += ';'; + var cssLength = css.length; + var isParenthesisOpen = false; + var lastPos = 0; + var i = 0; + var retCSS = ''; + + function addNewAttr() { + // 如果没有正常的闭合圆括号,则直接忽略当前属性 + if (!isParenthesisOpen) { + var source = _.trim(css.slice(lastPos, i)); + + var j = source.indexOf(':'); + + if (j !== -1) { + var name = _.trim(source.slice(0, j)); + + var value = _.trim(source.slice(j + 1)); // 必须有属性名称 + + + if (name) { + var ret = onAttr(lastPos, retCSS.length, name, value, source); + if (ret) retCSS += ret + '; '; + } + } + } + + lastPos = i + 1; + } + + for (; i < cssLength; i++) { + var c = css[i]; + + if (c === '/' && css[i + 1] === '*') { + // 备注开始 + var j = css.indexOf('*/', i + 2); // 如果没有正常的备注结束,则后面的部分全部跳过 + + if (j === -1) break; // 直接将当前位置调到备注结尾,并且初始化状态 + + i = j + 1; + lastPos = i + 1; + isParenthesisOpen = false; + } else if (c === '(') { + isParenthesisOpen = true; + } else if (c === ')') { + isParenthesisOpen = false; + } else if (c === ';') { + if (isParenthesisOpen) {// 在圆括号里面,忽略 + } else { + addNewAttr(); + } + } else if (c === '\n') { + addNewAttr(); + } + } + + return _.trim(retCSS); + } + + module.exports = parseStyle; + }, { + "./util": 10 + }], + 10: [function (require, module, exports) { + module.exports = { + indexOf: function (arr, item) { + var i, j; + + if (Array.prototype.indexOf) { + return arr.indexOf(item); + } + + for (i = 0, j = arr.length; i < j; i++) { + if (arr[i] === item) { + return i; + } + } + + return -1; + }, + forEach: function (arr, fn, scope) { + var i, j; + + if (Array.prototype.forEach) { + return arr.forEach(fn, scope); + } + + for (i = 0, j = arr.length; i < j; i++) { + fn.call(scope, arr[i], i, arr); + } + }, + trim: function (str) { + if (String.prototype.trim) { + return str.trim(); + } + + return str.replace(/(^\s*)|(\s*$)/g, ''); + }, + trimRight: function (str) { + if (String.prototype.trimRight) { + return str.trimRight(); + } + + return str.replace(/(\s*$)/g, ''); + } + }; + }, {}] +}, {}, [2]); + +/*** EXPORTS FROM exports-loader ***/ +exports["filterXSS"] = (filterXSS); +exports["filterCSS"] = (filterCSS); + +/***/ }), +/* 15 */ +/***/ (function(module, exports) { + +var core = module.exports = { + version: '2.6.12' +}; +if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef + +/***/ }), +/* 16 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + +/***/ }), +/* 17 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* WEBPACK VAR INJECTION */(function(module) {/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); +/* harmony import */ var _stubFalse_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(156); + + +/** Detect free variable `exports`. */ + +var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; +/** Detect free variable `module`. */ + +var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; +/** Detect the popular CommonJS extension `module.exports`. */ + +var moduleExports = freeModule && freeModule.exports === freeExports; +/** Built-in value references. */ + +var Buffer = moduleExports ? _root_js__WEBPACK_IMPORTED_MODULE_0__[/* default */ "a"].Buffer : undefined; +/* Built-in method references for those with the same name as other `lodash` methods. */ + +var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined; +/** + * Checks if `value` is a buffer. + * + * @static + * @memberOf _ + * @since 4.3.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. + * @example + * + * _.isBuffer(new Buffer(2)); + * // => true + * + * _.isBuffer(new Uint8Array(2)); + * // => false + */ + +var isBuffer = nativeIsBuffer || _stubFalse_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"]; +/* harmony default export */ __webpack_exports__["a"] = (isBuffer); +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(66)(module))) + +/***/ }), +/* 18 */ +/***/ (function(module, exports) { + +var g; // This works in non-strict mode + +g = function () { + return this; +}(); + +try { + // This works if eval is allowed (see CSP) + g = g || new Function("return this")(); +} catch (e) { + // This works if the window reference is available + if (typeof window === "object") g = window; +} // g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + + +module.exports = g; + +/***/ }), +/* 19 */ +/***/ (function(module, exports) { + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + +var Symbol = __webpack_require__(45), + getRawTag = __webpack_require__(333), + objectToString = __webpack_require__(334); +/** `Object#toString` result references. */ + + +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; +/** Built-in value references. */ + +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ + +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + + return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value); +} + +module.exports = baseGetTag; + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +var baseIsNative = __webpack_require__(351), + getValue = __webpack_require__(354); +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ + + +function getNative(object, key) { + var value = getValue(object, key); + return baseIsNative(value) ? value : undefined; +} + +module.exports = getNative; + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + +var isObject = __webpack_require__(37); + +module.exports = function (it) { + if (!isObject(it)) throw TypeError(it + ' is not an object!'); + return it; +}; + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(global) {var require;var require;/*! + localForage -- Offline Storage, Improved + Version 1.9.0 + https://localforage.github.io/localForage + (c) 2013-2017 Mozilla, Apache License 2.0 +*/ +(function (f) { + if (true) { + module.exports = f(); + } else { var g; } +})(function () { + var define, module, exports; + return function e(t, n, r) { + function s(o, u) { + if (!n[o]) { + if (!t[o]) { + var a = typeof require == "function" && require; + if (!u && a) return require(o, !0); + if (i) return i(o, !0); + var f = new Error("Cannot find module '" + o + "'"); + throw f.code = "MODULE_NOT_FOUND", f; + } + + var l = n[o] = { + exports: {} + }; + t[o][0].call(l.exports, function (e) { + var n = t[o][1][e]; + return s(n ? n : e); + }, l, l.exports, e, t, n, r); + } + + return n[o].exports; + } + + var i = typeof require == "function" && require; + + for (var o = 0; o < r.length; o++) s(r[o]); + + return s; + }({ + 1: [function (_dereq_, module, exports) { + (function (global) { + 'use strict'; + + var Mutation = global.MutationObserver || global.WebKitMutationObserver; + var scheduleDrain; + { + if (Mutation) { + var called = 0; + var observer = new Mutation(nextTick); + var element = global.document.createTextNode(''); + observer.observe(element, { + characterData: true + }); + + scheduleDrain = function () { + element.data = called = ++called % 2; + }; + } else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') { + var channel = new global.MessageChannel(); + channel.port1.onmessage = nextTick; + + scheduleDrain = function () { + channel.port2.postMessage(0); + }; + } else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) { + scheduleDrain = function () { + // Create a