quickblox 2.17.9-logger → 2.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +1 -2
  3. package/package.json +2 -1
  4. package/quickblox.js +111 -7055
  5. package/quickblox.min.js +1 -1
  6. package/src/modules/chat/qbChat.js +17 -27
  7. package/src/modules/webrtc/qbWebRTCSignalingProcessor.js +1 -2
  8. package/src/modules/webrtc/qbWebRTCSignalingProvider.js +1 -2
  9. package/src/qbConfig.js +2 -2
  10. package/src/qbStrophe.js +49 -59
  11. package/{src/libs/strophe → strophejs-1.4.0/dist}/strophe.common.js +14 -14
  12. package/{src/libs/strophe → strophejs-1.4.0/dist}/strophe.esm.js +14 -14
  13. package/{src/libs/strophe → strophejs-1.4.0/dist}/strophe.umd.js +17 -17
  14. package/strophejs-1.4.0/dist/strophe.umd.min.js +1 -0
  15. package/src/libs/strophe/strophe.umd.min.js +0 -1
  16. package/strophejs-1.4.0/.eslintrc.json +0 -264
  17. package/strophejs-1.4.0/.gitattributes +0 -1
  18. package/strophejs-1.4.0/CHANGELOG.md +0 -250
  19. package/strophejs-1.4.0/LICENSE.txt +0 -19
  20. package/strophejs-1.4.0/Makefile +0 -92
  21. package/strophejs-1.4.0/README.md +0 -45
  22. package/strophejs-1.4.0/RELEASE_CHECKLIST.md +0 -16
  23. package/strophejs-1.4.0/contrib/discojs/README.txt +0 -42
  24. package/strophejs-1.4.0/contrib/discojs/css/disco.css +0 -16
  25. package/strophejs-1.4.0/contrib/discojs/index.html +0 -47
  26. package/strophejs-1.4.0/contrib/discojs/punjab.tac +0 -18
  27. package/strophejs-1.4.0/contrib/discojs/scripts/basic.js +0 -102
  28. package/strophejs-1.4.0/contrib/discojs/scripts/disco.js +0 -60
  29. package/strophejs-1.4.0/docs.css +0 -797
  30. package/strophejs-1.4.0/examples/amd.html +0 -21
  31. package/strophejs-1.4.0/examples/attach/README +0 -37
  32. package/strophejs-1.4.0/examples/attach/__init__.py +0 -0
  33. package/strophejs-1.4.0/examples/attach/attacher/__init__.py +0 -0
  34. package/strophejs-1.4.0/examples/attach/attacher/views.py +0 -18
  35. package/strophejs-1.4.0/examples/attach/boshclient.py +0 -158
  36. package/strophejs-1.4.0/examples/attach/manage.py +0 -11
  37. package/strophejs-1.4.0/examples/attach/settings.py +0 -85
  38. package/strophejs-1.4.0/examples/attach/templates/attacher/index.html +0 -88
  39. package/strophejs-1.4.0/examples/attach/urls.py +0 -19
  40. package/strophejs-1.4.0/examples/basic.html +0 -23
  41. package/strophejs-1.4.0/examples/basic.js +0 -73
  42. package/strophejs-1.4.0/examples/echobot.html +0 -25
  43. package/strophejs-1.4.0/examples/echobot.js +0 -79
  44. package/strophejs-1.4.0/examples/main.js +0 -59
  45. package/strophejs-1.4.0/examples/prebind.html +0 -39
  46. package/strophejs-1.4.0/examples/prebind.js +0 -103
  47. package/strophejs-1.4.0/examples/restore.html +0 -24
  48. package/strophejs-1.4.0/examples/restore.js +0 -71
  49. package/strophejs-1.4.0/package-lock.json +0 -8634
  50. package/strophejs-1.4.0/package.json +0 -84
  51. package/strophejs-1.4.0/rollup.config.js +0 -76
  52. package/strophejs-1.4.0/src/bosh.js +0 -916
  53. package/strophejs-1.4.0/src/core.js +0 -3535
  54. package/strophejs-1.4.0/src/md5.js +0 -204
  55. package/strophejs-1.4.0/src/sha1.js +0 -172
  56. package/strophejs-1.4.0/src/shared-connection-worker.js +0 -114
  57. package/strophejs-1.4.0/src/shims.js +0 -123
  58. package/strophejs-1.4.0/src/strophe.js +0 -14
  59. package/strophejs-1.4.0/src/utils.js +0 -63
  60. package/strophejs-1.4.0/src/websocket.js +0 -561
  61. package/strophejs-1.4.0/src/worker-websocket.js +0 -152
  62. package/strophejs-1.4.0/tests/index.html +0 -21
  63. package/strophejs-1.4.0/tests/main.js +0 -49
  64. package/strophejs-1.4.0/tests/tests.js +0 -929
  65. package/strophejs-1.6.1/.eslintrc.json +0 -264
  66. package/strophejs-1.6.1/.gitattributes +0 -1
  67. package/strophejs-1.6.1/.nvmrc +0 -1
  68. package/strophejs-1.6.1/CHANGELOG.md +0 -288
  69. package/strophejs-1.6.1/LICENSE.txt +0 -19
  70. package/strophejs-1.6.1/Makefile +0 -92
  71. package/strophejs-1.6.1/README.md +0 -46
  72. package/strophejs-1.6.1/RELEASE_CHECKLIST.md +0 -18
  73. package/strophejs-1.6.1/babel.config.json +0 -10
  74. package/strophejs-1.6.1/contrib/discojs/README.txt +0 -42
  75. package/strophejs-1.6.1/contrib/discojs/css/disco.css +0 -16
  76. package/strophejs-1.6.1/contrib/discojs/index.html +0 -47
  77. package/strophejs-1.6.1/contrib/discojs/punjab.tac +0 -18
  78. package/strophejs-1.6.1/contrib/discojs/scripts/basic.js +0 -102
  79. package/strophejs-1.6.1/contrib/discojs/scripts/disco.js +0 -60
  80. package/strophejs-1.6.1/docs.css +0 -797
  81. package/strophejs-1.6.1/examples/amd.html +0 -21
  82. package/strophejs-1.6.1/examples/attach/README +0 -37
  83. package/strophejs-1.6.1/examples/attach/__init__.py +0 -0
  84. package/strophejs-1.6.1/examples/attach/attacher/__init__.py +0 -0
  85. package/strophejs-1.6.1/examples/attach/attacher/views.py +0 -18
  86. package/strophejs-1.6.1/examples/attach/boshclient.py +0 -158
  87. package/strophejs-1.6.1/examples/attach/manage.py +0 -11
  88. package/strophejs-1.6.1/examples/attach/settings.py +0 -85
  89. package/strophejs-1.6.1/examples/attach/templates/attacher/index.html +0 -88
  90. package/strophejs-1.6.1/examples/attach/urls.py +0 -19
  91. package/strophejs-1.6.1/examples/basic.html +0 -23
  92. package/strophejs-1.6.1/examples/basic.js +0 -73
  93. package/strophejs-1.6.1/examples/echobot.html +0 -25
  94. package/strophejs-1.6.1/examples/echobot.js +0 -79
  95. package/strophejs-1.6.1/examples/main.js +0 -59
  96. package/strophejs-1.6.1/examples/prebind.html +0 -39
  97. package/strophejs-1.6.1/examples/prebind.js +0 -103
  98. package/strophejs-1.6.1/examples/restore.html +0 -24
  99. package/strophejs-1.6.1/examples/restore.js +0 -71
  100. package/strophejs-1.6.1/package-lock.json +0 -18461
  101. package/strophejs-1.6.1/package.json +0 -87
  102. package/strophejs-1.6.1/rollup.config.js +0 -70
  103. package/strophejs-1.6.1/src/bosh.js +0 -916
  104. package/strophejs-1.6.1/src/builder.js +0 -239
  105. package/strophejs-1.6.1/src/constants.js +0 -155
  106. package/strophejs-1.6.1/src/core.js +0 -2377
  107. package/strophejs-1.6.1/src/sasl-anon.js +0 -17
  108. package/strophejs-1.6.1/src/sasl-external.js +0 -27
  109. package/strophejs-1.6.1/src/sasl-oauthbearer.js +0 -30
  110. package/strophejs-1.6.1/src/sasl-plain.js +0 -32
  111. package/strophejs-1.6.1/src/sasl-sha1.js +0 -24
  112. package/strophejs-1.6.1/src/sasl-sha256.js +0 -24
  113. package/strophejs-1.6.1/src/sasl-sha384.js +0 -24
  114. package/strophejs-1.6.1/src/sasl-sha512.js +0 -24
  115. package/strophejs-1.6.1/src/sasl-xoauth2.js +0 -27
  116. package/strophejs-1.6.1/src/sasl.js +0 -143
  117. package/strophejs-1.6.1/src/scram.js +0 -182
  118. package/strophejs-1.6.1/src/shared-connection-worker.js +0 -114
  119. package/strophejs-1.6.1/src/shims.js +0 -122
  120. package/strophejs-1.6.1/src/strophe.js +0 -15
  121. package/strophejs-1.6.1/src/utils.js +0 -626
  122. package/strophejs-1.6.1/src/websocket.js +0 -556
  123. package/strophejs-1.6.1/src/worker-websocket.js +0 -149
  124. package/strophejs-1.6.1/tests.js +0 -993
@@ -1,2377 +0,0 @@
1
- /*
2
- This program is distributed under the terms of the MIT license.
3
- Please see the LICENSE file for details.
4
-
5
- Copyright 2006-2018, OGG, LLC
6
- */
7
- /*global sessionStorage, setTimeout, clearTimeout */
8
-
9
- import SASLAnonymous from './sasl-anon.js';
10
- import SASLExternal from './sasl-external.js';
11
- import SASLMechanism from './sasl.js';
12
- import SASLOAuthBearer from './sasl-oauthbearer.js';
13
- import SASLPlain from './sasl-plain.js';
14
- import SASLSHA1 from './sasl-sha1.js';
15
- import SASLSHA256 from './sasl-sha256.js';
16
- import SASLSHA384 from './sasl-sha384.js';
17
- import SASLSHA512 from './sasl-sha512.js';
18
- import SASLXOAuth2 from './sasl-xoauth2.js';
19
- import Builder from './builder.js';
20
- import * as utils from './utils';
21
- import { ElementType, ErrorCondition, LogLevel, NS, Status, XHTML } from './constants.js';
22
- import { atob, btoa } from 'abab'
23
-
24
-
25
- /** Function: $build
26
- * Create a Strophe.Builder.
27
- * This is an alias for 'new Strophe.Builder(name, attrs)'.
28
- *
29
- * Parameters:
30
- * (String) name - The root element name.
31
- * (Object) attrs - The attributes for the root element in object notation.
32
- *
33
- * Returns:
34
- * A new Strophe.Builder object.
35
- */
36
- export function $build(name, attrs) {
37
- return new Strophe.Builder(name, attrs);
38
- }
39
-
40
- /** Function: $msg
41
- * Create a Strophe.Builder with a <message/> element as the root.
42
- *
43
- * Parameters:
44
- * (Object) attrs - The <message/> element attributes in object notation.
45
- *
46
- * Returns:
47
- * A new Strophe.Builder object.
48
- */
49
- export function $msg(attrs) {
50
- return new Strophe.Builder("message", attrs);
51
- }
52
-
53
- /** Function: $iq
54
- * Create a Strophe.Builder with an <iq/> element as the root.
55
- *
56
- * Parameters:
57
- * (Object) attrs - The <iq/> element attributes in object notation.
58
- *
59
- * Returns:
60
- * A new Strophe.Builder object.
61
- */
62
- export function $iq(attrs) {
63
- return new Strophe.Builder("iq", attrs);
64
- }
65
-
66
- /** Function: $pres
67
- * Create a Strophe.Builder with a <presence/> element as the root.
68
- *
69
- * Parameters:
70
- * (Object) attrs - The <presence/> element attributes in object notation.
71
- *
72
- * Returns:
73
- * A new Strophe.Builder object.
74
- */
75
- export function $pres(attrs) {
76
- return new Strophe.Builder("presence", attrs);
77
- }
78
-
79
- /** Class: Strophe
80
- * An object container for all Strophe library functions.
81
- *
82
- * This class is just a container for all the objects and constants
83
- * used in the library. It is not meant to be instantiated, but to
84
- * provide a namespace for library objects, constants, and functions.
85
- */
86
- export const Strophe = {
87
- /** Constant: VERSION */
88
- VERSION: "1.6.1",
89
-
90
- Builder,
91
- NS,
92
- Status,
93
- ErrorCondition,
94
- LogLevel,
95
- ElementType,
96
- ...utils,
97
-
98
- XHTML: {
99
- ...XHTML,
100
- validTag: utils.validTag,
101
- validCSS: utils.validCSS,
102
- validAttribute: utils.validAttribute,
103
- },
104
-
105
- /** Function: addNamespace
106
- * This function is used to extend the current namespaces in
107
- * Strophe.NS. It takes a key and a value with the key being the
108
- * name of the new namespace, with its actual value.
109
- * For example:
110
- * Strophe.addNamespace('PUBSUB', "http://jabber.org/protocol/pubsub");
111
- *
112
- * Parameters:
113
- * (String) name - The name under which the namespace will be
114
- * referenced under Strophe.NS
115
- * (String) value - The actual namespace.
116
- */
117
- addNamespace (name, value) {
118
- Strophe.NS[name] = value;
119
- },
120
-
121
- /** PrivateFunction: _handleError
122
- * _Private_ function that properly logs an error to the console
123
- */
124
- _handleError (e) {
125
- if (typeof e.stack !== "undefined") {
126
- Strophe.fatal(e.stack);
127
- }
128
- if (e.sourceURL) {
129
- Strophe.fatal("error: " + this.handler + " " + e.sourceURL + ":" +
130
- e.line + " - " + e.name + ": " + e.message);
131
- } else if (e.fileName) {
132
- Strophe.fatal("error: " + this.handler + " " +
133
- e.fileName + ":" + e.lineNumber + " - " +
134
- e.name + ": " + e.message);
135
- } else {
136
- Strophe.fatal("error: " + e.message);
137
- }
138
- },
139
-
140
- /** Function: log
141
- * User overrideable logging function.
142
- *
143
- * This function is called whenever the Strophe library calls any
144
- * of the logging functions. The default implementation of this
145
- * function logs only fatal errors. If client code wishes to handle the logging
146
- * messages, it should override this with
147
- * > Strophe.log = function (level, msg) {
148
- * > (user code here)
149
- * > };
150
- *
151
- * Please note that data sent and received over the wire is logged
152
- * via Strophe.Connection.rawInput() and Strophe.Connection.rawOutput().
153
- *
154
- * The different levels and their meanings are
155
- *
156
- * DEBUG - Messages useful for debugging purposes.
157
- * INFO - Informational messages. This is mostly information like
158
- * 'disconnect was called' or 'SASL auth succeeded'.
159
- * WARN - Warnings about potential problems. This is mostly used
160
- * to report transient connection errors like request timeouts.
161
- * ERROR - Some error occurred.
162
- * FATAL - A non-recoverable fatal error occurred.
163
- *
164
- * Parameters:
165
- * (Integer) level - The log level of the log message. This will
166
- * be one of the values in Strophe.LogLevel.
167
- * (String) msg - The log message.
168
- */
169
- log (level, msg) {
170
- if (level === this.LogLevel.FATAL) {
171
- console?.error(msg);
172
- }
173
- },
174
-
175
- /** Function: debug
176
- * Log a message at the Strophe.LogLevel.DEBUG level.
177
- *
178
- * Parameters:
179
- * (String) msg - The log message.
180
- */
181
- debug (msg) {
182
- this.log(this.LogLevel.DEBUG, msg);
183
- },
184
-
185
- /** Function: info
186
- * Log a message at the Strophe.LogLevel.INFO level.
187
- *
188
- * Parameters:
189
- * (String) msg - The log message.
190
- */
191
- info (msg) {
192
- this.log(this.LogLevel.INFO, msg);
193
- },
194
-
195
- /** Function: warn
196
- * Log a message at the Strophe.LogLevel.WARN level.
197
- *
198
- * Parameters:
199
- * (String) msg - The log message.
200
- */
201
- warn (msg) {
202
- this.log(this.LogLevel.WARN, msg);
203
- },
204
-
205
- /** Function: error
206
- * Log a message at the Strophe.LogLevel.ERROR level.
207
- *
208
- * Parameters:
209
- * (String) msg - The log message.
210
- */
211
- error (msg) {
212
- this.log(this.LogLevel.ERROR, msg);
213
- },
214
-
215
- /** Function: fatal
216
- * Log a message at the Strophe.LogLevel.FATAL level.
217
- *
218
- * Parameters:
219
- * (String) msg - The log message.
220
- */
221
- fatal (msg) {
222
- this.log(this.LogLevel.FATAL, msg);
223
- },
224
-
225
- /** PrivateVariable: _requestId
226
- * _Private_ variable that keeps track of the request ids for
227
- * connections.
228
- */
229
- _requestId: 0,
230
-
231
- /** PrivateVariable: Strophe.connectionPlugins
232
- * _Private_ variable Used to store plugin names that need
233
- * initialization on Strophe.Connection construction.
234
- */
235
- _connectionPlugins: {},
236
-
237
- /** Function: addConnectionPlugin
238
- * Extends the Strophe.Connection object with the given plugin.
239
- *
240
- * Parameters:
241
- * (String) name - The name of the extension.
242
- * (Object) ptype - The plugin's prototype.
243
- */
244
- addConnectionPlugin (name, ptype) {
245
- Strophe._connectionPlugins[name] = ptype;
246
- }
247
- };
248
-
249
- /** PrivateClass: Strophe.Handler
250
- * _Private_ helper class for managing stanza handlers.
251
- *
252
- * A Strophe.Handler encapsulates a user provided callback function to be
253
- * executed when matching stanzas are received by the connection.
254
- * Handlers can be either one-off or persistant depending on their
255
- * return value. Returning true will cause a Handler to remain active, and
256
- * returning false will remove the Handler.
257
- *
258
- * Users will not use Strophe.Handler objects directly, but instead they
259
- * will use Strophe.Connection.addHandler() and
260
- * Strophe.Connection.deleteHandler().
261
- */
262
-
263
- /** PrivateConstructor: Strophe.Handler
264
- * Create and initialize a new Strophe.Handler.
265
- *
266
- * Parameters:
267
- * (Function) handler - A function to be executed when the handler is run.
268
- * (String) ns - The namespace to match.
269
- * (String) name - The element name to match.
270
- * (String) type - The element type to match.
271
- * (String) id - The element id attribute to match.
272
- * (String) from - The element from attribute to match.
273
- * (Object) options - Handler options
274
- *
275
- * Returns:
276
- * A new Strophe.Handler object.
277
- */
278
- Strophe.Handler = function (handler, ns, name, type, id, from, options) {
279
- this.handler = handler;
280
- this.ns = ns;
281
- this.name = name;
282
- this.type = type;
283
- this.id = id;
284
- this.options = options || {'matchBareFromJid': false, 'ignoreNamespaceFragment': false};
285
- // BBB: Maintain backward compatibility with old `matchBare` option
286
- if (this.options.matchBare) {
287
- Strophe.warn('The "matchBare" option is deprecated, use "matchBareFromJid" instead.');
288
- this.options.matchBareFromJid = this.options.matchBare;
289
- delete this.options.matchBare;
290
- }
291
- if (this.options.matchBareFromJid) {
292
- this.from = from ? Strophe.getBareJidFromJid(from) : null;
293
- } else {
294
- this.from = from;
295
- }
296
- // whether the handler is a user handler or a system handler
297
- this.user = true;
298
- };
299
-
300
- Strophe.Handler.prototype = {
301
- /** PrivateFunction: getNamespace
302
- * Returns the XML namespace attribute on an element.
303
- * If `ignoreNamespaceFragment` was passed in for this handler, then the
304
- * URL fragment will be stripped.
305
- *
306
- * Parameters:
307
- * (XMLElement) elem - The XML element with the namespace.
308
- *
309
- * Returns:
310
- * The namespace, with optionally the fragment stripped.
311
- */
312
- getNamespace (elem) {
313
- let elNamespace = elem.getAttribute("xmlns");
314
- if (elNamespace && this.options.ignoreNamespaceFragment) {
315
- elNamespace = elNamespace.split('#')[0];
316
- }
317
- return elNamespace;
318
- },
319
-
320
- /** PrivateFunction: namespaceMatch
321
- * Tests if a stanza matches the namespace set for this Strophe.Handler.
322
- *
323
- * Parameters:
324
- * (XMLElement) elem - The XML element to test.
325
- *
326
- * Returns:
327
- * true if the stanza matches and false otherwise.
328
- */
329
- namespaceMatch (elem) {
330
- let nsMatch = false;
331
- if (!this.ns) {
332
- return true;
333
- } else {
334
- Strophe.forEachChild(elem, null, (elem) => {
335
- if (this.getNamespace(elem) === this.ns) {
336
- nsMatch = true;
337
- }
338
- });
339
- return nsMatch || this.getNamespace(elem) === this.ns;
340
- }
341
- },
342
-
343
- /** PrivateFunction: isMatch
344
- * Tests if a stanza matches the Strophe.Handler.
345
- *
346
- * Parameters:
347
- * (XMLElement) elem - The XML element to test.
348
- *
349
- * Returns:
350
- * true if the stanza matches and false otherwise.
351
- */
352
- isMatch (elem) {
353
- let from = elem.getAttribute('from');
354
- if (this.options.matchBareFromJid) {
355
- from = Strophe.getBareJidFromJid(from);
356
- }
357
- const elem_type = elem.getAttribute("type");
358
- if (this.namespaceMatch(elem) &&
359
- (!this.name || Strophe.isTagEqual(elem, this.name)) &&
360
- (!this.type || (Array.isArray(this.type) ? this.type.indexOf(elem_type) !== -1 : elem_type === this.type)) &&
361
- (!this.id || elem.getAttribute("id") === this.id) &&
362
- (!this.from || from === this.from)) {
363
- return true;
364
- }
365
- return false;
366
- },
367
-
368
- /** PrivateFunction: run
369
- * Run the callback on a matching stanza.
370
- *
371
- * Parameters:
372
- * (XMLElement) elem - The DOM element that triggered the
373
- * Strophe.Handler.
374
- *
375
- * Returns:
376
- * A boolean indicating if the handler should remain active.
377
- */
378
- run (elem) {
379
- let result = null;
380
- try {
381
- result = this.handler(elem);
382
- } catch (e) {
383
- Strophe._handleError(e);
384
- throw e;
385
- }
386
- return result;
387
- },
388
-
389
- /** PrivateFunction: toString
390
- * Get a String representation of the Strophe.Handler object.
391
- *
392
- * Returns:
393
- * A String.
394
- */
395
- toString () {
396
- return "{Handler: " + this.handler + "(" + this.name + "," +
397
- this.id + "," + this.ns + ")}";
398
- }
399
- };
400
-
401
- /** PrivateClass: Strophe.TimedHandler
402
- * _Private_ helper class for managing timed handlers.
403
- *
404
- * A Strophe.TimedHandler encapsulates a user provided callback that
405
- * should be called after a certain period of time or at regular
406
- * intervals. The return value of the callback determines whether the
407
- * Strophe.TimedHandler will continue to fire.
408
- *
409
- * Users will not use Strophe.TimedHandler objects directly, but instead
410
- * they will use Strophe.Connection.addTimedHandler() and
411
- * Strophe.Connection.deleteTimedHandler().
412
- */
413
- Strophe.TimedHandler = class TimedHandler {
414
-
415
- /** PrivateConstructor: Strophe.TimedHandler
416
- * Create and initialize a new Strophe.TimedHandler object.
417
- *
418
- * Parameters:
419
- * (Integer) period - The number of milliseconds to wait before the
420
- * handler is called.
421
- * (Function) handler - The callback to run when the handler fires. This
422
- * function should take no arguments.
423
- *
424
- * Returns:
425
- * A new Strophe.TimedHandler object.
426
- */
427
- constructor (period, handler) {
428
- this.period = period;
429
- this.handler = handler;
430
- this.lastCalled = new Date().getTime();
431
- this.user = true;
432
- }
433
-
434
- /** PrivateFunction: run
435
- * Run the callback for the Strophe.TimedHandler.
436
- *
437
- * Returns:
438
- * true if the Strophe.TimedHandler should be called again, and false
439
- * otherwise.
440
- */
441
- run () {
442
- this.lastCalled = new Date().getTime();
443
- return this.handler();
444
- }
445
-
446
- /** PrivateFunction: reset
447
- * Reset the last called time for the Strophe.TimedHandler.
448
- */
449
- reset () {
450
- this.lastCalled = new Date().getTime();
451
- }
452
-
453
- /** PrivateFunction: toString
454
- * Get a string representation of the Strophe.TimedHandler object.
455
- *
456
- * Returns:
457
- * The string representation.
458
- */
459
- toString () {
460
- return "{TimedHandler: " + this.handler + "(" + this.period +")}";
461
- }
462
- };
463
-
464
- /** Class: Strophe.Connection
465
- * XMPP Connection manager.
466
- *
467
- * This class is the main part of Strophe. It manages a BOSH or websocket
468
- * connection to an XMPP server and dispatches events to the user callbacks
469
- * as data arrives. It supports SASL PLAIN, SASL SCRAM-SHA-1
470
- * and legacy authentication.
471
- *
472
- * After creating a Strophe.Connection object, the user will typically
473
- * call connect() with a user supplied callback to handle connection level
474
- * events like authentication failure, disconnection, or connection
475
- * complete.
476
- *
477
- * The user will also have several event handlers defined by using
478
- * addHandler() and addTimedHandler(). These will allow the user code to
479
- * respond to interesting stanzas or do something periodically with the
480
- * connection. These handlers will be active once authentication is
481
- * finished.
482
- *
483
- * To send data to the connection, use send().
484
- */
485
-
486
- /** Constructor: Strophe.Connection
487
- * Create and initialize a Strophe.Connection object.
488
- *
489
- * The transport-protocol for this connection will be chosen automatically
490
- * based on the given service parameter. URLs starting with "ws://" or
491
- * "wss://" will use WebSockets, URLs starting with "http://", "https://"
492
- * or without a protocol will use BOSH.
493
- *
494
- * To make Strophe connect to the current host you can leave out the protocol
495
- * and host part and just pass the path, e.g.
496
- *
497
- * > let conn = new Strophe.Connection("/http-bind/");
498
- *
499
- * Options common to both Websocket and BOSH:
500
- * ------------------------------------------
501
- *
502
- * cookies:
503
- *
504
- * The *cookies* option allows you to pass in cookies to be added to the
505
- * document. These cookies will then be included in the BOSH XMLHttpRequest
506
- * or in the websocket connection.
507
- *
508
- * The passed in value must be a map of cookie names and string values.
509
- *
510
- * > { "myCookie": {
511
- * > "value": "1234",
512
- * > "domain": ".example.org",
513
- * > "path": "/",
514
- * > "expires": expirationDate
515
- * > }
516
- * > }
517
- *
518
- * Note that cookies can't be set in this way for other domains (i.e. cross-domain).
519
- * Those cookies need to be set under those domains, for example they can be
520
- * set server-side by making a XHR call to that domain to ask it to set any
521
- * necessary cookies.
522
- *
523
- * mechanisms:
524
- *
525
- * The *mechanisms* option allows you to specify the SASL mechanisms that this
526
- * instance of Strophe.Connection (and therefore your XMPP client) will
527
- * support.
528
- *
529
- * The value must be an array of objects with Strophe.SASLMechanism
530
- * prototypes.
531
- *
532
- * If nothing is specified, then the following mechanisms (and their
533
- * priorities) are registered:
534
- *
535
- * SCRAM-SHA-512 - 72
536
- * SCRAM-SHA-384 - 71
537
- * SCRAM-SHA-256 - 70
538
- * SCRAM-SHA-1 - 60
539
- * PLAIN - 50
540
- * OAUTHBEARER - 40
541
- * X-OAUTH2 - 30
542
- * ANONYMOUS - 20
543
- * EXTERNAL - 10
544
- *
545
- * explicitResourceBinding:
546
- *
547
- * If `explicitResourceBinding` is set to a truthy value, then the XMPP client
548
- * needs to explicitly call `Strophe.Connection.prototype.bind` once the XMPP
549
- * server has advertised the "urn:ietf:params:xml:ns:xmpp-bind" feature.
550
- *
551
- * Making this step explicit allows client authors to first finish other
552
- * stream related tasks, such as setting up an XEP-0198 Stream Management
553
- * session, before binding the JID resource for this session.
554
- *
555
- * WebSocket options:
556
- * ------------------
557
- *
558
- * protocol:
559
- *
560
- * If you want to connect to the current host with a WebSocket connection you
561
- * can tell Strophe to use WebSockets through a "protocol" attribute in the
562
- * optional options parameter. Valid values are "ws" for WebSocket and "wss"
563
- * for Secure WebSocket.
564
- * So to connect to "wss://CURRENT_HOSTNAME/xmpp-websocket" you would call
565
- *
566
- * > let conn = new Strophe.Connection("/xmpp-websocket/", {protocol: "wss"});
567
- *
568
- * Note that relative URLs _NOT_ starting with a "/" will also include the path
569
- * of the current site.
570
- *
571
- * Also because downgrading security is not permitted by browsers, when using
572
- * relative URLs both BOSH and WebSocket connections will use their secure
573
- * variants if the current connection to the site is also secure (https).
574
- *
575
- * worker:
576
- *
577
- * Set this option to URL from where the shared worker script should be loaded.
578
- *
579
- * To run the websocket connection inside a shared worker.
580
- * This allows you to share a single websocket-based connection between
581
- * multiple Strophe.Connection instances, for example one per browser tab.
582
- *
583
- * The script to use is the one in `src/shared-connection-worker.js`.
584
- *
585
- * BOSH options:
586
- * -------------
587
- *
588
- * By adding "sync" to the options, you can control if requests will
589
- * be made synchronously or not. The default behaviour is asynchronous.
590
- * If you want to make requests synchronous, make "sync" evaluate to true.
591
- * > let conn = new Strophe.Connection("/http-bind/", {sync: true});
592
- *
593
- * You can also toggle this on an already established connection.
594
- * > conn.options.sync = true;
595
- *
596
- * The *customHeaders* option can be used to provide custom HTTP headers to be
597
- * included in the XMLHttpRequests made.
598
- *
599
- * The *keepalive* option can be used to instruct Strophe to maintain the
600
- * current BOSH session across interruptions such as webpage reloads.
601
- *
602
- * It will do this by caching the sessions tokens in sessionStorage, and when
603
- * "restore" is called it will check whether there are cached tokens with
604
- * which it can resume an existing session.
605
- *
606
- * The *withCredentials* option should receive a Boolean value and is used to
607
- * indicate wether cookies should be included in ajax requests (by default
608
- * they're not).
609
- * Set this value to true if you are connecting to a BOSH service
610
- * and for some reason need to send cookies to it.
611
- * In order for this to work cross-domain, the server must also enable
612
- * credentials by setting the Access-Control-Allow-Credentials response header
613
- * to "true". For most usecases however this setting should be false (which
614
- * is the default).
615
- * Additionally, when using Access-Control-Allow-Credentials, the
616
- * Access-Control-Allow-Origin header can't be set to the wildcard "*", but
617
- * instead must be restricted to actual domains.
618
- *
619
- * The *contentType* option can be set to change the default Content-Type
620
- * of "text/xml; charset=utf-8", which can be useful to reduce the amount of
621
- * CORS preflight requests that are sent to the server.
622
- *
623
- * Parameters:
624
- * (String) service - The BOSH or WebSocket service URL.
625
- * (Object) options - A hash of configuration options
626
- *
627
- * Returns:
628
- * A new Strophe.Connection object.
629
- */
630
-
631
- Strophe.Connection = class Connection {
632
-
633
- constructor (service, options) {
634
- // The service URL
635
- this.service = service;
636
- // Configuration options
637
- this.options = options || {};
638
-
639
- this.setProtocol();
640
-
641
- /* The connected JID. */
642
- this.jid = "";
643
- /* the JIDs domain */
644
- this.domain = null;
645
- /* stream:features */
646
- this.features = null;
647
-
648
- // SASL
649
- this._sasl_data = {};
650
- this.do_bind = false;
651
- this.do_session = false;
652
- this.mechanisms = {}
653
-
654
- // handler lists
655
- this.timedHandlers = [];
656
- this.handlers = [];
657
- this.removeTimeds = [];
658
- this.removeHandlers = [];
659
- this.addTimeds = [];
660
- this.addHandlers = [];
661
- this.protocolErrorHandlers = {
662
- 'HTTP': {},
663
- 'websocket': {}
664
- };
665
-
666
- this._idleTimeout = null;
667
- this._disconnectTimeout = null;
668
-
669
- this.authenticated = false;
670
- this.connected = false;
671
- this.disconnecting = false;
672
- this.do_authentication = true;
673
- this.paused = false;
674
- this.restored = false;
675
-
676
- this._data = [];
677
- this._uniqueId = 0;
678
-
679
- this._sasl_success_handler = null;
680
- this._sasl_failure_handler = null;
681
- this._sasl_challenge_handler = null;
682
-
683
- // Max retries before disconnecting
684
- this.maxRetries = 5;
685
-
686
- // Call onIdle callback every 1/10th of a second
687
- this._idleTimeout = setTimeout(() => this._onIdle(), 100);
688
-
689
- utils.addCookies(this.options.cookies);
690
- this.registerSASLMechanisms(this.options.mechanisms);
691
-
692
- // A client must always respond to incoming IQ "set" and "get" stanzas.
693
- // See https://datatracker.ietf.org/doc/html/rfc6120#section-8.2.3
694
- //
695
- // This is a fallback handler which gets called when no other handler
696
- // was called for a received IQ "set" or "get".
697
- this.iqFallbackHandler = new Strophe.Handler(
698
- (iq) => this.send($iq({type: 'error', id: iq.getAttribute('id')})
699
- .c('error', {'type': 'cancel'})
700
- .c('service-unavailable', {'xmlns': Strophe.NS.STANZAS})),
701
- null, 'iq', ['get', 'set']);
702
-
703
- // initialize plugins
704
- for (const k in Strophe._connectionPlugins) {
705
- if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) {
706
- const F = function () {};
707
- F.prototype = Strophe._connectionPlugins[k];
708
- this[k] = new F();
709
- this[k].init(this);
710
- }
711
- }
712
- }
713
-
714
- /** Function: setProtocol
715
- * Select protocal based on this.options or this.service
716
- */
717
- setProtocol () {
718
- const proto = this.options.protocol || "";
719
- if (this.options.worker) {
720
- this._proto = new Strophe.WorkerWebsocket(this);
721
- } else if (
722
- this.service.indexOf("ws:") === 0 ||
723
- this.service.indexOf("wss:") === 0 ||
724
- proto.indexOf("ws") === 0) {
725
- this._proto = new Strophe.Websocket(this);
726
- } else {
727
- this._proto = new Strophe.Bosh(this);
728
- }
729
- }
730
-
731
- /** Function: reset
732
- * Reset the connection.
733
- *
734
- * This function should be called after a connection is disconnected
735
- * before that connection is reused.
736
- */
737
- reset () {
738
- this._proto._reset();
739
-
740
- // SASL
741
- this.do_session = false;
742
- this.do_bind = false;
743
-
744
- // handler lists
745
- this.timedHandlers = [];
746
- this.handlers = [];
747
- this.removeTimeds = [];
748
- this.removeHandlers = [];
749
- this.addTimeds = [];
750
- this.addHandlers = [];
751
-
752
- this.authenticated = false;
753
- this.connected = false;
754
- this.disconnecting = false;
755
- this.restored = false;
756
-
757
- this._data = [];
758
- this._requests = [];
759
- this._uniqueId = 0;
760
- }
761
-
762
- /** Function: pause
763
- * Pause the request manager.
764
- *
765
- * This will prevent Strophe from sending any more requests to the
766
- * server. This is very useful for temporarily pausing
767
- * BOSH-Connections while a lot of send() calls are happening quickly.
768
- * This causes Strophe to send the data in a single request, saving
769
- * many request trips.
770
- */
771
- pause () {
772
- this.paused = true;
773
- }
774
-
775
- /** Function: resume
776
- * Resume the request manager.
777
- *
778
- * This resumes after pause() has been called.
779
- */
780
- resume () {
781
- this.paused = false;
782
- }
783
-
784
- /** Function: getUniqueId
785
- * Generate a unique ID for use in <iq/> elements.
786
- *
787
- * All <iq/> stanzas are required to have unique id attributes. This
788
- * function makes creating these easy. Each connection instance has
789
- * a counter which starts from zero, and the value of this counter
790
- * plus a colon followed by the suffix becomes the unique id. If no
791
- * suffix is supplied, the counter is used as the unique id.
792
- *
793
- * Suffixes are used to make debugging easier when reading the stream
794
- * data, and their use is recommended. The counter resets to 0 for
795
- * every new connection for the same reason. For connections to the
796
- * same server that authenticate the same way, all the ids should be
797
- * the same, which makes it easy to see changes. This is useful for
798
- * automated testing as well.
799
- *
800
- * Parameters:
801
- * (String) suffix - A optional suffix to append to the id.
802
- *
803
- * Returns:
804
- * A unique string to be used for the id attribute.
805
- */
806
- getUniqueId (suffix) { // eslint-disable-line class-methods-use-this
807
- const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
808
- const r = Math.random() * 16 | 0,
809
- v = c === 'x' ? r : r & 0x3 | 0x8;
810
- return v.toString(16);
811
- });
812
- if (typeof(suffix) === "string" || typeof(suffix) === "number") {
813
- return uuid + ":" + suffix;
814
- } else {
815
- return uuid + "";
816
- }
817
- }
818
-
819
- /** Function: addProtocolErrorHandler
820
- * Register a handler function for when a protocol (websocker or HTTP)
821
- * error occurs.
822
- *
823
- * NOTE: Currently only HTTP errors for BOSH requests are handled.
824
- * Patches that handle websocket errors would be very welcome.
825
- *
826
- * Parameters:
827
- * (String) protocol - 'HTTP' or 'websocket'
828
- * (Integer) status_code - Error status code (e.g 500, 400 or 404)
829
- * (Function) callback - Function that will fire on Http error
830
- *
831
- * Example:
832
- * function onError(err_code){
833
- * //do stuff
834
- * }
835
- *
836
- * let conn = Strophe.connect('http://example.com/http-bind');
837
- * conn.addProtocolErrorHandler('HTTP', 500, onError);
838
- * // Triggers HTTP 500 error and onError handler will be called
839
- * conn.connect('user_jid@incorrect_jabber_host', 'secret', onConnect);
840
- */
841
- addProtocolErrorHandler (protocol, status_code, callback){
842
- this.protocolErrorHandlers[protocol][status_code] = callback;
843
- }
844
-
845
- /** Function: connect
846
- * Starts the connection process.
847
- *
848
- * As the connection process proceeds, the user supplied callback will
849
- * be triggered multiple times with status updates. The callback
850
- * should take two arguments - the status code and the error condition.
851
- *
852
- * The status code will be one of the values in the Strophe.Status
853
- * constants. The error condition will be one of the conditions
854
- * defined in RFC 3920 or the condition 'strophe-parsererror'.
855
- *
856
- * The Parameters _wait_, _hold_ and _route_ are optional and only relevant
857
- * for BOSH connections. Please see XEP 124 for a more detailed explanation
858
- * of the optional parameters.
859
- *
860
- * Parameters:
861
- * (String) jid - The user's JID. This may be a bare JID,
862
- * or a full JID. If a node is not supplied, SASL OAUTHBEARER or
863
- * SASL ANONYMOUS authentication will be attempted (OAUTHBEARER will
864
- * process the provided password value as an access token).
865
- * (String or Object) pass - The user's password, or an object containing
866
- * the users SCRAM client and server keys, in a fashion described as follows:
867
- *
868
- * { name: String, representing the hash used (eg. SHA-1),
869
- * salt: String, base64 encoded salt used to derive the client key,
870
- * iter: Int, the iteration count used to derive the client key,
871
- * ck: String, the base64 encoding of the SCRAM client key
872
- * sk: String, the base64 encoding of the SCRAM server key
873
- * }
874
- *
875
- * (Function) callback - The connect callback function.
876
- * (Integer) wait - The optional HTTPBIND wait value. This is the
877
- * time the server will wait before returning an empty result for
878
- * a request. The default setting of 60 seconds is recommended.
879
- * (Integer) hold - The optional HTTPBIND hold value. This is the
880
- * number of connections the server will hold at one time. This
881
- * should almost always be set to 1 (the default).
882
- * (String) route - The optional route value.
883
- * (String) authcid - The optional alternative authentication identity
884
- * (username) if intending to impersonate another user.
885
- * When using the SASL-EXTERNAL authentication mechanism, for example
886
- * with client certificates, then the authcid value is used to
887
- * determine whether an authorization JID (authzid) should be sent to
888
- * the server. The authzid should NOT be sent to the server if the
889
- * authzid and authcid are the same. So to prevent it from being sent
890
- * (for example when the JID is already contained in the client
891
- * certificate), set authcid to that same JID. See XEP-178 for more
892
- * details.
893
- * (Integer) disconnection_timeout - The optional disconnection timeout
894
- * in milliseconds before _doDisconnect will be called.
895
- */
896
- connect (jid, pass, callback, wait, hold, route, authcid, disconnection_timeout = 3000) {
897
- this.jid = jid;
898
- /** Variable: authzid
899
- * Authorization identity.
900
- */
901
- this.authzid = Strophe.getBareJidFromJid(this.jid);
902
-
903
- /** Variable: authcid
904
- * Authentication identity (User name).
905
- */
906
- this.authcid = authcid || Strophe.getNodeFromJid(this.jid);
907
-
908
- /** Variable: pass
909
- * Authentication identity (User password).
910
- *
911
- */
912
- this.pass = pass;
913
-
914
- /** Variable: scram_keys
915
- * The SASL SCRAM client and server keys. This variable will be populated with a non-null
916
- * object of the above described form after a successful SCRAM connection
917
- *
918
- */
919
- this.scram_keys = null;
920
-
921
- this.connect_callback = callback;
922
- this.disconnecting = false;
923
- this.connected = false;
924
- this.authenticated = false;
925
- this.restored = false;
926
- this.disconnection_timeout = disconnection_timeout;
927
-
928
- // parse jid for domain
929
- this.domain = Strophe.getDomainFromJid(this.jid);
930
-
931
- this._changeConnectStatus(Strophe.Status.CONNECTING, null);
932
-
933
- this._proto._connect(wait, hold, route);
934
- }
935
-
936
- /** Function: attach
937
- * Attach to an already created and authenticated BOSH session.
938
- *
939
- * This function is provided to allow Strophe to attach to BOSH
940
- * sessions which have been created externally, perhaps by a Web
941
- * application. This is often used to support auto-login type features
942
- * without putting user credentials into the page.
943
- *
944
- * Parameters:
945
- * (String) jid - The full JID that is bound by the session.
946
- * (String) sid - The SID of the BOSH session.
947
- * (String) rid - The current RID of the BOSH session. This RID
948
- * will be used by the next request.
949
- * (Function) callback The connect callback function.
950
- * (Integer) wait - The optional HTTPBIND wait value. This is the
951
- * time the server will wait before returning an empty result for
952
- * a request. The default setting of 60 seconds is recommended.
953
- * Other settings will require tweaks to the Strophe.TIMEOUT value.
954
- * (Integer) hold - The optional HTTPBIND hold value. This is the
955
- * number of connections the server will hold at one time. This
956
- * should almost always be set to 1 (the default).
957
- * (Integer) wind - The optional HTTBIND window value. This is the
958
- * allowed range of request ids that are valid. The default is 5.
959
- */
960
- attach (jid, sid, rid, callback, wait, hold, wind) {
961
- if (this._proto._attach) {
962
- return this._proto._attach(jid, sid, rid, callback, wait, hold, wind);
963
- } else {
964
- const error = new Error('The "attach" method is not available for your connection protocol');
965
- error.name = 'StropheSessionError';
966
- throw error;
967
- }
968
- }
969
-
970
- /** Function: restore
971
- * Attempt to restore a cached BOSH session.
972
- *
973
- * This function is only useful in conjunction with providing the
974
- * "keepalive":true option when instantiating a new Strophe.Connection.
975
- *
976
- * When "keepalive" is set to true, Strophe will cache the BOSH tokens
977
- * RID (Request ID) and SID (Session ID) and then when this function is
978
- * called, it will attempt to restore the session from those cached
979
- * tokens.
980
- *
981
- * This function must therefore be called instead of connect or attach.
982
- *
983
- * For an example on how to use it, please see examples/restore.js
984
- *
985
- * Parameters:
986
- * (String) jid - The user's JID. This may be a bare JID or a full JID.
987
- * (Function) callback - The connect callback function.
988
- * (Integer) wait - The optional HTTPBIND wait value. This is the
989
- * time the server will wait before returning an empty result for
990
- * a request. The default setting of 60 seconds is recommended.
991
- * (Integer) hold - The optional HTTPBIND hold value. This is the
992
- * number of connections the server will hold at one time. This
993
- * should almost always be set to 1 (the default).
994
- * (Integer) wind - The optional HTTBIND window value. This is the
995
- * allowed range of request ids that are valid. The default is 5.
996
- */
997
- restore (jid, callback, wait, hold, wind) {
998
- if (this._sessionCachingSupported()) {
999
- this._proto._restore(jid, callback, wait, hold, wind);
1000
- } else {
1001
- const error = new Error('The "restore" method can only be used with a BOSH connection.');
1002
- error.name = 'StropheSessionError';
1003
- throw error;
1004
- }
1005
- }
1006
-
1007
- /** PrivateFunction: _sessionCachingSupported
1008
- * Checks whether sessionStorage and JSON are supported and whether we're
1009
- * using BOSH.
1010
- */
1011
- _sessionCachingSupported () {
1012
- if (this._proto instanceof Strophe.Bosh) {
1013
- if (!JSON) { return false; }
1014
- try {
1015
- sessionStorage.setItem('_strophe_', '_strophe_');
1016
- sessionStorage.removeItem('_strophe_');
1017
- } catch (e) {
1018
- return false;
1019
- }
1020
- return true;
1021
- }
1022
- return false;
1023
- }
1024
-
1025
- /** Function: xmlInput
1026
- * User overrideable function that receives XML data coming into the
1027
- * connection.
1028
- *
1029
- * The default function does nothing. User code can override this with
1030
- * > Strophe.Connection.xmlInput = function (elem) {
1031
- * > (user code)
1032
- * > };
1033
- *
1034
- * Due to limitations of current Browsers' XML-Parsers the opening and closing
1035
- * <stream> tag for WebSocket-Connoctions will be passed as selfclosing here.
1036
- *
1037
- * BOSH-Connections will have all stanzas wrapped in a <body> tag. See
1038
- * <Strophe.Bosh.strip> if you want to strip this tag.
1039
- *
1040
- * Parameters:
1041
- * (XMLElement) elem - The XML data received by the connection.
1042
- */
1043
- xmlInput (elem) { // eslint-disable-line
1044
- return;
1045
- }
1046
-
1047
- /** Function: xmlOutput
1048
- * User overrideable function that receives XML data sent to the
1049
- * connection.
1050
- *
1051
- * The default function does nothing. User code can override this with
1052
- * > Strophe.Connection.xmlOutput = function (elem) {
1053
- * > (user code)
1054
- * > };
1055
- *
1056
- * Due to limitations of current Browsers' XML-Parsers the opening and closing
1057
- * <stream> tag for WebSocket-Connoctions will be passed as selfclosing here.
1058
- *
1059
- * BOSH-Connections will have all stanzas wrapped in a <body> tag. See
1060
- * <Strophe.Bosh.strip> if you want to strip this tag.
1061
- *
1062
- * Parameters:
1063
- * (XMLElement) elem - The XMLdata sent by the connection.
1064
- */
1065
- xmlOutput (elem) { // eslint-disable-line
1066
- return;
1067
- }
1068
-
1069
- /** Function: rawInput
1070
- * User overrideable function that receives raw data coming into the
1071
- * connection.
1072
- *
1073
- * The default function does nothing. User code can override this with
1074
- * > Strophe.Connection.rawInput = function (data) {
1075
- * > (user code)
1076
- * > };
1077
- *
1078
- * Parameters:
1079
- * (String) data - The data received by the connection.
1080
- */
1081
- rawInput (data) { // eslint-disable-line
1082
- return;
1083
- }
1084
-
1085
- /** Function: rawOutput
1086
- * User overrideable function that receives raw data sent to the
1087
- * connection.
1088
- *
1089
- * The default function does nothing. User code can override this with
1090
- * > Strophe.Connection.rawOutput = function (data) {
1091
- * > (user code)
1092
- * > };
1093
- *
1094
- * Parameters:
1095
- * (String) data - The data sent by the connection.
1096
- */
1097
- rawOutput (data) { // eslint-disable-line
1098
- return;
1099
- }
1100
-
1101
- /** Function: nextValidRid
1102
- * User overrideable function that receives the new valid rid.
1103
- *
1104
- * The default function does nothing. User code can override this with
1105
- * > Strophe.Connection.nextValidRid = function (rid) {
1106
- * > (user code)
1107
- * > };
1108
- *
1109
- * Parameters:
1110
- * (Number) rid - The next valid rid
1111
- */
1112
- nextValidRid (rid) { // eslint-disable-line
1113
- return;
1114
- }
1115
-
1116
- /** Function: send
1117
- * Send a stanza.
1118
- *
1119
- * This function is called to push data onto the send queue to
1120
- * go out over the wire. Whenever a request is sent to the BOSH
1121
- * server, all pending data is sent and the queue is flushed.
1122
- *
1123
- * Parameters:
1124
- * (XMLElement |
1125
- * [XMLElement] |
1126
- * Strophe.Builder) elem - The stanza to send.
1127
- */
1128
- send (elem) {
1129
- if (elem === null) { return ; }
1130
- if (typeof(elem.sort) === "function") {
1131
- for (let i=0; i < elem.length; i++) {
1132
- this._queueData(elem[i]);
1133
- }
1134
- } else if (typeof(elem.tree) === "function") {
1135
- this._queueData(elem.tree());
1136
- } else {
1137
- this._queueData(elem);
1138
- }
1139
- this._proto._send();
1140
- }
1141
-
1142
- /** Function: flush
1143
- * Immediately send any pending outgoing data.
1144
- *
1145
- * Normally send() queues outgoing data until the next idle period
1146
- * (100ms), which optimizes network use in the common cases when
1147
- * several send()s are called in succession. flush() can be used to
1148
- * immediately send all pending data.
1149
- */
1150
- flush () {
1151
- // cancel the pending idle period and run the idle function
1152
- // immediately
1153
- clearTimeout(this._idleTimeout);
1154
- this._onIdle();
1155
- }
1156
-
1157
- /** Function: sendPresence
1158
- * Helper function to send presence stanzas. The main benefit is for
1159
- * sending presence stanzas for which you expect a responding presence
1160
- * stanza with the same id (for example when leaving a chat room).
1161
- *
1162
- * Parameters:
1163
- * (XMLElement) elem - The stanza to send.
1164
- * (Function) callback - The callback function for a successful request.
1165
- * (Function) errback - The callback function for a failed or timed
1166
- * out request. On timeout, the stanza will be null.
1167
- * (Integer) timeout - The time specified in milliseconds for a
1168
- * timeout to occur.
1169
- *
1170
- * Returns:
1171
- * The id used to send the presence.
1172
- */
1173
- sendPresence (elem, callback, errback, timeout) {
1174
- let timeoutHandler = null;
1175
- if (typeof(elem.tree) === "function") {
1176
- elem = elem.tree();
1177
- }
1178
- let id = elem.getAttribute('id');
1179
- if (!id) { // inject id if not found
1180
- id = this.getUniqueId("sendPresence");
1181
- elem.setAttribute("id", id);
1182
- }
1183
-
1184
- if (typeof callback === "function" || typeof errback === "function") {
1185
- const handler = this.addHandler(stanza => {
1186
- // remove timeout handler if there is one
1187
- if (timeoutHandler) {
1188
- this.deleteTimedHandler(timeoutHandler);
1189
- }
1190
- if (stanza.getAttribute('type') === 'error') {
1191
- if (errback) {
1192
- errback(stanza);
1193
- }
1194
- } else if (callback) {
1195
- callback(stanza);
1196
- }
1197
- }, null, 'presence', null, id);
1198
-
1199
- // if timeout specified, set up a timeout handler.
1200
- if (timeout) {
1201
- timeoutHandler = this.addTimedHandler(timeout, () => {
1202
- // get rid of normal handler
1203
- this.deleteHandler(handler);
1204
- // call errback on timeout with null stanza
1205
- if (errback) {
1206
- errback(null);
1207
- }
1208
- return false;
1209
- });
1210
- }
1211
- }
1212
- this.send(elem);
1213
- return id;
1214
- }
1215
-
1216
- /** Function: sendIQ
1217
- * Helper function to send IQ stanzas.
1218
- *
1219
- * Parameters:
1220
- * (XMLElement) elem - The stanza to send.
1221
- * (Function) callback - The callback function for a successful request.
1222
- * (Function) errback - The callback function for a failed or timed
1223
- * out request. On timeout, the stanza will be null.
1224
- * (Integer) timeout - The time specified in milliseconds for a
1225
- * timeout to occur.
1226
- *
1227
- * Returns:
1228
- * The id used to send the IQ.
1229
- */
1230
- sendIQ (elem, callback, errback, timeout) {
1231
- let timeoutHandler = null;
1232
- if (typeof(elem.tree) === "function") {
1233
- elem = elem.tree();
1234
- }
1235
- let id = elem.getAttribute('id');
1236
- if (!id) { // inject id if not found
1237
- id = this.getUniqueId("sendIQ");
1238
- elem.setAttribute("id", id);
1239
- }
1240
-
1241
- if (typeof callback === "function" || typeof errback === "function") {
1242
- const handler = this.addHandler(stanza => {
1243
- // remove timeout handler if there is one
1244
- if (timeoutHandler) {
1245
- this.deleteTimedHandler(timeoutHandler);
1246
- }
1247
- const iqtype = stanza.getAttribute('type');
1248
- if (iqtype === 'result') {
1249
- if (callback) {
1250
- callback(stanza);
1251
- }
1252
- } else if (iqtype === 'error') {
1253
- if (errback) {
1254
- errback(stanza);
1255
- }
1256
- } else {
1257
- const error = new Error(`Got bad IQ type of ${iqtype}`);
1258
- error.name = "StropheError";
1259
- throw(error);
1260
- }
1261
- }, null, 'iq', ['error', 'result'], id);
1262
-
1263
- // if timeout specified, set up a timeout handler.
1264
- if (timeout) {
1265
- timeoutHandler = this.addTimedHandler(timeout, () => {
1266
- // get rid of normal handler
1267
- this.deleteHandler(handler);
1268
- // call errback on timeout with null stanza
1269
- if (errback) {
1270
- errback(null);
1271
- }
1272
- return false;
1273
- });
1274
- }
1275
- }
1276
- this.send(elem);
1277
- return id;
1278
- }
1279
-
1280
- /** PrivateFunction: _queueData
1281
- * Queue outgoing data for later sending. Also ensures that the data
1282
- * is a DOMElement.
1283
- */
1284
- _queueData (element) {
1285
- if (element === null ||
1286
- !element.tagName ||
1287
- !element.childNodes) {
1288
- const error = new Error("Cannot queue non-DOMElement.");
1289
- error.name = "StropheError";
1290
- throw(error);
1291
- }
1292
- this._data.push(element);
1293
- }
1294
-
1295
- /** PrivateFunction: _sendRestart
1296
- * Send an xmpp:restart stanza.
1297
- */
1298
- _sendRestart () {
1299
- this._data.push("restart");
1300
- this._proto._sendRestart();
1301
- this._idleTimeout = setTimeout(() => this._onIdle(), 100);
1302
- }
1303
-
1304
- /** Function: addTimedHandler
1305
- * Add a timed handler to the connection.
1306
- *
1307
- * This function adds a timed handler. The provided handler will
1308
- * be called every period milliseconds until it returns false,
1309
- * the connection is terminated, or the handler is removed. Handlers
1310
- * that wish to continue being invoked should return true.
1311
- *
1312
- * Because of method binding it is necessary to save the result of
1313
- * this function if you wish to remove a handler with
1314
- * deleteTimedHandler().
1315
- *
1316
- * Note that user handlers are not active until authentication is
1317
- * successful.
1318
- *
1319
- * Parameters:
1320
- * (Integer) period - The period of the handler.
1321
- * (Function) handler - The callback function.
1322
- *
1323
- * Returns:
1324
- * A reference to the handler that can be used to remove it.
1325
- */
1326
- addTimedHandler (period, handler) {
1327
- const thand = new Strophe.TimedHandler(period, handler);
1328
- this.addTimeds.push(thand);
1329
- return thand;
1330
- }
1331
-
1332
- /** Function: deleteTimedHandler
1333
- * Delete a timed handler for a connection.
1334
- *
1335
- * This function removes a timed handler from the connection. The
1336
- * handRef parameter is *not* the function passed to addTimedHandler(),
1337
- * but is the reference returned from addTimedHandler().
1338
- *
1339
- * Parameters:
1340
- * (Strophe.TimedHandler) handRef - The handler reference.
1341
- */
1342
- deleteTimedHandler (handRef) {
1343
- // this must be done in the Idle loop so that we don't change
1344
- // the handlers during iteration
1345
- this.removeTimeds.push(handRef);
1346
- }
1347
-
1348
- /** Function: addHandler
1349
- * Add a stanza handler for the connection.
1350
- *
1351
- * This function adds a stanza handler to the connection. The
1352
- * handler callback will be called for any stanza that matches
1353
- * the parameters. Note that if multiple parameters are supplied,
1354
- * they must all match for the handler to be invoked.
1355
- *
1356
- * The handler will receive the stanza that triggered it as its argument.
1357
- * *The handler should return true if it is to be invoked again;
1358
- * returning false will remove the handler after it returns.*
1359
- *
1360
- * As a convenience, the ns parameters applies to the top level element
1361
- * and also any of its immediate children. This is primarily to make
1362
- * matching /iq/query elements easy.
1363
- *
1364
- * Options
1365
- * ~~~~~~~
1366
- * With the options argument, you can specify boolean flags that affect how
1367
- * matches are being done.
1368
- *
1369
- * Currently two flags exist:
1370
- *
1371
- * - matchBareFromJid:
1372
- * When set to true, the from parameter and the
1373
- * from attribute on the stanza will be matched as bare JIDs instead
1374
- * of full JIDs. To use this, pass {matchBareFromJid: true} as the
1375
- * value of options. The default value for matchBareFromJid is false.
1376
- *
1377
- * - ignoreNamespaceFragment:
1378
- * When set to true, a fragment specified on the stanza's namespace
1379
- * URL will be ignored when it's matched with the one configured for
1380
- * the handler.
1381
- *
1382
- * This means that if you register like this:
1383
- * > connection.addHandler(
1384
- * > handler,
1385
- * > 'http://jabber.org/protocol/muc',
1386
- * > null, null, null, null,
1387
- * > {'ignoreNamespaceFragment': true}
1388
- * > );
1389
- *
1390
- * Then a stanza with XML namespace of
1391
- * 'http://jabber.org/protocol/muc#user' will also be matched. If
1392
- * 'ignoreNamespaceFragment' is false, then only stanzas with
1393
- * 'http://jabber.org/protocol/muc' will be matched.
1394
- *
1395
- * Deleting the handler
1396
- * ~~~~~~~~~~~~~~~~~~~~
1397
- * The return value should be saved if you wish to remove the handler
1398
- * with deleteHandler().
1399
- *
1400
- * Parameters:
1401
- * (Function) handler - The user callback.
1402
- * (String) ns - The namespace to match.
1403
- * (String) name - The stanza name to match.
1404
- * (String|Array) type - The stanza type (or types if an array) to match.
1405
- * (String) id - The stanza id attribute to match.
1406
- * (String) from - The stanza from attribute to match.
1407
- * (String) options - The handler options
1408
- *
1409
- * Returns:
1410
- * A reference to the handler that can be used to remove it.
1411
- */
1412
- addHandler (handler, ns, name, type, id, from, options) {
1413
- const hand = new Strophe.Handler(handler, ns, name, type, id, from, options);
1414
- this.addHandlers.push(hand);
1415
- return hand;
1416
- }
1417
-
1418
- /** Function: deleteHandler
1419
- * Delete a stanza handler for a connection.
1420
- *
1421
- * This function removes a stanza handler from the connection. The
1422
- * handRef parameter is *not* the function passed to addHandler(),
1423
- * but is the reference returned from addHandler().
1424
- *
1425
- * Parameters:
1426
- * (Strophe.Handler) handRef - The handler reference.
1427
- */
1428
- deleteHandler (handRef) {
1429
- // this must be done in the Idle loop so that we don't change
1430
- // the handlers during iteration
1431
- this.removeHandlers.push(handRef);
1432
- // If a handler is being deleted while it is being added,
1433
- // prevent it from getting added
1434
- const i = this.addHandlers.indexOf(handRef);
1435
- if (i >= 0) {
1436
- this.addHandlers.splice(i, 1);
1437
- }
1438
- }
1439
-
1440
- /** Function: registerSASLMechanisms
1441
- *
1442
- * Register the SASL mechanisms which will be supported by this instance of
1443
- * Strophe.Connection (i.e. which this XMPP client will support).
1444
- *
1445
- * Parameters:
1446
- * (Array) mechanisms - Array of objects with Strophe.SASLMechanism prototypes
1447
- *
1448
- */
1449
- registerSASLMechanisms (mechanisms) {
1450
- this.mechanisms = {};
1451
- mechanisms = mechanisms || [
1452
- Strophe.SASLAnonymous,
1453
- Strophe.SASLExternal,
1454
- Strophe.SASLOAuthBearer,
1455
- Strophe.SASLXOAuth2,
1456
- Strophe.SASLPlain,
1457
- Strophe.SASLSHA1,
1458
- Strophe.SASLSHA256,
1459
- Strophe.SASLSHA384,
1460
- Strophe.SASLSHA512
1461
- ];
1462
- mechanisms.forEach(m => this.registerSASLMechanism(m));
1463
- }
1464
-
1465
- /** Function: registerSASLMechanism
1466
- *
1467
- * Register a single SASL mechanism, to be supported by this client.
1468
- *
1469
- * Parameters:
1470
- * (Object) mechanism - Object with a Strophe.SASLMechanism prototype
1471
- *
1472
- */
1473
- registerSASLMechanism (Mechanism) {
1474
- const mechanism = new Mechanism()
1475
- this.mechanisms[mechanism.mechname] = mechanism;
1476
- }
1477
-
1478
- /** Function: disconnect
1479
- * Start the graceful disconnection process.
1480
- *
1481
- * This function starts the disconnection process. This process starts
1482
- * by sending unavailable presence and sending BOSH body of type
1483
- * terminate. A timeout handler makes sure that disconnection happens
1484
- * even if the BOSH server does not respond.
1485
- * If the Connection object isn't connected, at least tries to abort all pending requests
1486
- * so the connection object won't generate successful requests (which were already opened).
1487
- *
1488
- * The user supplied connection callback will be notified of the
1489
- * progress as this process happens.
1490
- *
1491
- * Parameters:
1492
- * (String) reason - The reason the disconnect is occuring.
1493
- */
1494
- disconnect (reason) {
1495
- this._changeConnectStatus(Strophe.Status.DISCONNECTING, reason);
1496
- if (reason) {
1497
- Strophe.warn("Disconnect was called because: " + reason);
1498
- } else {
1499
- Strophe.info("Disconnect was called");
1500
- }
1501
- if (this.connected) {
1502
- let pres = false;
1503
- this.disconnecting = true;
1504
- if (this.authenticated) {
1505
- pres = $pres({
1506
- 'xmlns': Strophe.NS.CLIENT,
1507
- 'type': 'unavailable'
1508
- });
1509
- }
1510
- // setup timeout handler
1511
- this._disconnectTimeout = this._addSysTimedHandler(
1512
- this.disconnection_timeout, this._onDisconnectTimeout.bind(this));
1513
- this._proto._disconnect(pres);
1514
- } else {
1515
- Strophe.warn("Disconnect was called before Strophe connected to the server");
1516
- this._proto._abortAllRequests();
1517
- this._doDisconnect();
1518
- }
1519
- }
1520
-
1521
- /** PrivateFunction: _changeConnectStatus
1522
- * _Private_ helper function that makes sure plugins and the user's
1523
- * callback are notified of connection status changes.
1524
- *
1525
- * Parameters:
1526
- * (Integer) status - the new connection status, one of the values
1527
- * in Strophe.Status
1528
- * (String) condition - the error condition or null
1529
- * (XMLElement) elem - The triggering stanza.
1530
- */
1531
- _changeConnectStatus (status, condition, elem) {
1532
- // notify all plugins listening for status changes
1533
- for (const k in Strophe._connectionPlugins) {
1534
- if (Object.prototype.hasOwnProperty.call(Strophe._connectionPlugins, k)) {
1535
- const plugin = this[k];
1536
- if (plugin.statusChanged) {
1537
- try {
1538
- plugin.statusChanged(status, condition);
1539
- } catch (err) {
1540
- Strophe.error(`${k} plugin caused an exception changing status: ${err}`);
1541
- }
1542
- }
1543
- }
1544
- }
1545
- // notify the user's callback
1546
- if (this.connect_callback) {
1547
- try {
1548
- this.connect_callback(status, condition, elem);
1549
- } catch (e) {
1550
- Strophe._handleError(e);
1551
- Strophe.error(`User connection callback caused an exception: ${e}`);
1552
- }
1553
- }
1554
- }
1555
-
1556
- /** PrivateFunction: _doDisconnect
1557
- * _Private_ function to disconnect.
1558
- *
1559
- * This is the last piece of the disconnection logic. This resets the
1560
- * connection and alerts the user's connection callback.
1561
- */
1562
- _doDisconnect (condition) {
1563
- if (typeof this._idleTimeout === "number") {
1564
- clearTimeout(this._idleTimeout);
1565
- }
1566
-
1567
- // Cancel Disconnect Timeout
1568
- if (this._disconnectTimeout !== null) {
1569
- this.deleteTimedHandler(this._disconnectTimeout);
1570
- this._disconnectTimeout = null;
1571
- }
1572
-
1573
- Strophe.debug("_doDisconnect was called");
1574
- this._proto._doDisconnect();
1575
-
1576
- this.authenticated = false;
1577
- this.disconnecting = false;
1578
- this.restored = false;
1579
-
1580
- // delete handlers
1581
- this.handlers = [];
1582
- this.timedHandlers = [];
1583
- this.removeTimeds = [];
1584
- this.removeHandlers = [];
1585
- this.addTimeds = [];
1586
- this.addHandlers = [];
1587
-
1588
- // tell the parent we disconnected
1589
- this._changeConnectStatus(Strophe.Status.DISCONNECTED, condition);
1590
- this.connected = false;
1591
- }
1592
-
1593
- /** PrivateFunction: _dataRecv
1594
- * _Private_ handler to processes incoming data from the the connection.
1595
- *
1596
- * Except for _connect_cb handling the initial connection request,
1597
- * this function handles the incoming data for all requests. This
1598
- * function also fires stanza handlers that match each incoming
1599
- * stanza.
1600
- *
1601
- * Parameters:
1602
- * (Strophe.Request) req - The request that has data ready.
1603
- * (string) req - The stanza a raw string (optiona).
1604
- */
1605
- _dataRecv (req, raw) {
1606
-
1607
- const elem = this._proto._reqToData(req);
1608
- if (elem === null) { return; }
1609
-
1610
- if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) {
1611
- if (elem.nodeName === this._proto.strip && elem.childNodes.length) {
1612
- this.xmlInput(elem.childNodes[0]);
1613
- } else {
1614
- this.xmlInput(elem);
1615
- }
1616
- }
1617
- if (this.rawInput !== Strophe.Connection.prototype.rawInput) {
1618
- if (raw) {
1619
- this.rawInput(raw);
1620
- } else {
1621
- this.rawInput(Strophe.serialize(elem));
1622
- }
1623
- }
1624
-
1625
- // remove handlers scheduled for deletion
1626
- while (this.removeHandlers.length > 0) {
1627
- const hand = this.removeHandlers.pop();
1628
- const i = this.handlers.indexOf(hand);
1629
- if (i >= 0) {
1630
- this.handlers.splice(i, 1);
1631
- }
1632
- }
1633
-
1634
- // add handlers scheduled for addition
1635
- while (this.addHandlers.length > 0) {
1636
- this.handlers.push(this.addHandlers.pop());
1637
- }
1638
-
1639
- // handle graceful disconnect
1640
- if (this.disconnecting && this._proto._emptyQueue()) {
1641
- this._doDisconnect();
1642
- return;
1643
- }
1644
-
1645
- const type = elem.getAttribute("type");
1646
- if (type !== null && type === "terminate") {
1647
- // Don't process stanzas that come in after disconnect
1648
- if (this.disconnecting) {
1649
- return;
1650
- }
1651
- // an error occurred
1652
- let cond = elem.getAttribute("condition");
1653
- const conflict = elem.getElementsByTagName("conflict");
1654
- if (cond !== null) {
1655
- if (cond === "remote-stream-error" && conflict.length > 0) {
1656
- cond = "conflict";
1657
- }
1658
- this._changeConnectStatus(Strophe.Status.CONNFAIL, cond);
1659
- } else {
1660
- this._changeConnectStatus(
1661
- Strophe.Status.CONNFAIL,
1662
- Strophe.ErrorCondition.UNKOWN_REASON
1663
- );
1664
- }
1665
- this._doDisconnect(cond);
1666
- return;
1667
- }
1668
-
1669
- // send each incoming stanza through the handler chain
1670
- Strophe.forEachChild(elem, null, (child) => {
1671
- const matches = [];
1672
- this.handlers = this.handlers.reduce((handlers, handler) => {
1673
- try {
1674
- if (handler.isMatch(child) &&
1675
- (this.authenticated || !handler.user)) {
1676
- if (handler.run(child)) {
1677
- handlers.push(handler);
1678
- }
1679
- matches.push(handler);
1680
- } else {
1681
- handlers.push(handler);
1682
- }
1683
-
1684
- } catch (e) {
1685
- // if the handler throws an exception, we consider it as false
1686
- Strophe.warn('Removing Strophe handlers due to uncaught exception: '+e.message);
1687
- }
1688
-
1689
- return handlers;
1690
- }, []);
1691
-
1692
- // If no handler was fired for an incoming IQ with type="set",
1693
- // then we return an IQ error stanza with service-unavailable.
1694
- if (!matches.length && this.iqFallbackHandler.isMatch(child)) {
1695
- this.iqFallbackHandler.run(child);
1696
- }
1697
- });
1698
- }
1699
-
1700
- /** PrivateFunction: _connect_cb
1701
- * _Private_ handler for initial connection request.
1702
- *
1703
- * This handler is used to process the initial connection request
1704
- * response from the BOSH server. It is used to set up authentication
1705
- * handlers and start the authentication process.
1706
- *
1707
- * SASL authentication will be attempted if available, otherwise
1708
- * the code will fall back to legacy authentication.
1709
- *
1710
- * Parameters:
1711
- * (Strophe.Request) req - The current request.
1712
- * (Function) _callback - low level (xmpp) connect callback function.
1713
- * Useful for plugins with their own xmpp connect callback (when they
1714
- * want to do something special).
1715
- */
1716
- _connect_cb (req, _callback, raw) {
1717
- Strophe.debug("_connect_cb was called");
1718
- this.connected = true;
1719
-
1720
- let bodyWrap;
1721
- try {
1722
- bodyWrap = this._proto._reqToData(req);
1723
- } catch (e) {
1724
- if (e.name !== Strophe.ErrorCondition.BAD_FORMAT) { throw e; }
1725
- this._changeConnectStatus(
1726
- Strophe.Status.CONNFAIL,
1727
- Strophe.ErrorCondition.BAD_FORMAT
1728
- );
1729
- this._doDisconnect(Strophe.ErrorCondition.BAD_FORMAT);
1730
- }
1731
- if (!bodyWrap) { return; }
1732
-
1733
- if (this.xmlInput !== Strophe.Connection.prototype.xmlInput) {
1734
- if (bodyWrap.nodeName === this._proto.strip && bodyWrap.childNodes.length) {
1735
- this.xmlInput(bodyWrap.childNodes[0]);
1736
- } else {
1737
- this.xmlInput(bodyWrap);
1738
- }
1739
- }
1740
- if (this.rawInput !== Strophe.Connection.prototype.rawInput) {
1741
- if (raw) {
1742
- this.rawInput(raw);
1743
- } else {
1744
- this.rawInput(Strophe.serialize(bodyWrap));
1745
- }
1746
- }
1747
-
1748
- const conncheck = this._proto._connect_cb(bodyWrap);
1749
- if (conncheck === Strophe.Status.CONNFAIL) {
1750
- return;
1751
- }
1752
-
1753
- // Check for the stream:features tag
1754
- let hasFeatures;
1755
- if (bodyWrap.getElementsByTagNameNS) {
1756
- hasFeatures = bodyWrap.getElementsByTagNameNS(Strophe.NS.STREAM, "features").length > 0;
1757
- } else {
1758
- hasFeatures = bodyWrap.getElementsByTagName("stream:features").length > 0 ||
1759
- bodyWrap.getElementsByTagName("features").length > 0;
1760
- }
1761
- if (!hasFeatures) {
1762
- this._proto._no_auth_received(_callback);
1763
- return;
1764
- }
1765
-
1766
- const matched = Array.from(bodyWrap.getElementsByTagName("mechanism"))
1767
- .map(m => this.mechanisms[m.textContent])
1768
- .filter(m => m);
1769
-
1770
- if (matched.length === 0) {
1771
- if (bodyWrap.getElementsByTagName("auth").length === 0) {
1772
- // There are no matching SASL mechanisms and also no legacy
1773
- // auth available.
1774
- this._proto._no_auth_received(_callback);
1775
- return;
1776
- }
1777
- }
1778
- if (this.do_authentication !== false) {
1779
- this.authenticate(matched);
1780
- }
1781
- }
1782
-
1783
- /** Function: sortMechanismsByPriority
1784
- *
1785
- * Sorts an array of objects with prototype SASLMechanism according to
1786
- * their priorities.
1787
- *
1788
- * Parameters:
1789
- * (Array) mechanisms - Array of SASL mechanisms.
1790
- *
1791
- */
1792
- sortMechanismsByPriority (mechanisms) { // eslint-disable-line class-methods-use-this
1793
- // Sorting mechanisms according to priority.
1794
- for (let i=0; i < mechanisms.length - 1; ++i) {
1795
- let higher = i;
1796
- for (let j=i + 1; j < mechanisms.length; ++j) {
1797
- if (mechanisms[j].priority > mechanisms[higher].priority) {
1798
- higher = j;
1799
- }
1800
- }
1801
- if (higher !== i) {
1802
- const swap = mechanisms[i];
1803
- mechanisms[i] = mechanisms[higher];
1804
- mechanisms[higher] = swap;
1805
- }
1806
- }
1807
- return mechanisms;
1808
- }
1809
-
1810
- /** Function: authenticate
1811
- * Set up authentication
1812
- *
1813
- * Continues the initial connection request by setting up authentication
1814
- * handlers and starting the authentication process.
1815
- *
1816
- * SASL authentication will be attempted if available, otherwise
1817
- * the code will fall back to legacy authentication.
1818
- *
1819
- * Parameters:
1820
- * (Array) matched - Array of SASL mechanisms supported.
1821
- *
1822
- */
1823
- authenticate (matched) {
1824
- if (!this._attemptSASLAuth(matched)) {
1825
- this._attemptLegacyAuth();
1826
- }
1827
- }
1828
-
1829
- /** PrivateFunction: _attemptSASLAuth
1830
- *
1831
- * Iterate through an array of SASL mechanisms and attempt authentication
1832
- * with the highest priority (enabled) mechanism.
1833
- *
1834
- * Parameters:
1835
- * (Array) mechanisms - Array of SASL mechanisms.
1836
- *
1837
- * Returns:
1838
- * (Boolean) mechanism_found - true or false, depending on whether a
1839
- * valid SASL mechanism was found with which authentication could be
1840
- * started.
1841
- */
1842
- _attemptSASLAuth (mechanisms) {
1843
- mechanisms = this.sortMechanismsByPriority(mechanisms || []);
1844
- let mechanism_found = false;
1845
- for (let i=0; i < mechanisms.length; ++i) {
1846
- if (!mechanisms[i].test(this)) {
1847
- continue;
1848
- }
1849
- this._sasl_success_handler = this._addSysHandler(
1850
- this._sasl_success_cb.bind(this), null,
1851
- "success", null, null);
1852
- this._sasl_failure_handler = this._addSysHandler(
1853
- this._sasl_failure_cb.bind(this), null,
1854
- "failure", null, null);
1855
- this._sasl_challenge_handler = this._addSysHandler(
1856
- this._sasl_challenge_cb.bind(this), null,
1857
- "challenge", null, null);
1858
-
1859
- this._sasl_mechanism = mechanisms[i];
1860
- this._sasl_mechanism.onStart(this);
1861
-
1862
- const request_auth_exchange = $build("auth", {
1863
- 'xmlns': Strophe.NS.SASL,
1864
- 'mechanism': this._sasl_mechanism.mechname
1865
- });
1866
- if (this._sasl_mechanism.isClientFirst) {
1867
- const response = this._sasl_mechanism.clientChallenge(this);
1868
- request_auth_exchange.t(btoa(response));
1869
- }
1870
- this.send(request_auth_exchange.tree());
1871
- mechanism_found = true;
1872
- break;
1873
- }
1874
- return mechanism_found;
1875
- }
1876
-
1877
- /** PrivateFunction: _sasl_challenge_cb
1878
- * _Private_ handler for the SASL challenge
1879
- *
1880
- */
1881
- async _sasl_challenge_cb (elem) {
1882
- const challenge = atob(Strophe.getText(elem));
1883
- const response = await this._sasl_mechanism.onChallenge(this, challenge);
1884
- const stanza = $build('response', {'xmlns': Strophe.NS.SASL});
1885
- if (response !== "") {
1886
- stanza.t(btoa(response));
1887
- }
1888
- this.send(stanza.tree());
1889
- return true;
1890
- }
1891
-
1892
- /** PrivateFunction: _attemptLegacyAuth
1893
- *
1894
- * Attempt legacy (i.e. non-SASL) authentication.
1895
- */
1896
- _attemptLegacyAuth () {
1897
- if (Strophe.getNodeFromJid(this.jid) === null) {
1898
- // we don't have a node, which is required for non-anonymous
1899
- // client connections
1900
- this._changeConnectStatus(
1901
- Strophe.Status.CONNFAIL,
1902
- Strophe.ErrorCondition.MISSING_JID_NODE
1903
- );
1904
- this.disconnect(Strophe.ErrorCondition.MISSING_JID_NODE);
1905
- } else {
1906
- // Fall back to legacy authentication
1907
- this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);
1908
- this._addSysHandler(
1909
- this._onLegacyAuthIQResult.bind(this),
1910
- null, null, null, "_auth_1"
1911
- );
1912
- this.send($iq({
1913
- 'type': "get",
1914
- 'to': this.domain,
1915
- 'id': "_auth_1"
1916
- }).c("query", {xmlns: Strophe.NS.AUTH})
1917
- .c("username", {}).t(Strophe.getNodeFromJid(this.jid))
1918
- .tree());
1919
- }
1920
- }
1921
-
1922
- /** PrivateFunction: _onLegacyAuthIQResult
1923
- * _Private_ handler for legacy authentication.
1924
- *
1925
- * This handler is called in response to the initial <iq type='get'/>
1926
- * for legacy authentication. It builds an authentication <iq/> and
1927
- * sends it, creating a handler (calling back to _auth2_cb()) to
1928
- * handle the result
1929
- *
1930
- * Parameters:
1931
- * (XMLElement) elem - The stanza that triggered the callback.
1932
- *
1933
- * Returns:
1934
- * false to remove the handler.
1935
- */
1936
- _onLegacyAuthIQResult (elem) { // eslint-disable-line no-unused-vars
1937
- // build plaintext auth iq
1938
- const iq = $iq({type: "set", id: "_auth_2"})
1939
- .c('query', {xmlns: Strophe.NS.AUTH})
1940
- .c('username', {}).t(Strophe.getNodeFromJid(this.jid))
1941
- .up()
1942
- .c('password').t(this.pass);
1943
-
1944
- if (!Strophe.getResourceFromJid(this.jid)) {
1945
- // since the user has not supplied a resource, we pick
1946
- // a default one here. unlike other auth methods, the server
1947
- // cannot do this for us.
1948
- this.jid = Strophe.getBareJidFromJid(this.jid) + '/strophe';
1949
- }
1950
- iq.up().c('resource', {}).t(Strophe.getResourceFromJid(this.jid));
1951
-
1952
- this._addSysHandler(this._auth2_cb.bind(this), null, null, null, "_auth_2");
1953
- this.send(iq.tree());
1954
- return false;
1955
- }
1956
-
1957
- /** PrivateFunction: _sasl_success_cb
1958
- * _Private_ handler for succesful SASL authentication.
1959
- *
1960
- * Parameters:
1961
- * (XMLElement) elem - The matching stanza.
1962
- *
1963
- * Returns:
1964
- * false to remove the handler.
1965
- */
1966
- _sasl_success_cb (elem) {
1967
- if (this._sasl_data["server-signature"]) {
1968
- let serverSignature;
1969
- const success = atob(Strophe.getText(elem));
1970
- const attribMatch = /([a-z]+)=([^,]+)(,|$)/;
1971
- const matches = success.match(attribMatch);
1972
- if (matches[1] === "v") {
1973
- serverSignature = matches[2];
1974
- }
1975
- if (serverSignature !== this._sasl_data["server-signature"]) {
1976
- // remove old handlers
1977
- this.deleteHandler(this._sasl_failure_handler);
1978
- this._sasl_failure_handler = null;
1979
- if (this._sasl_challenge_handler) {
1980
- this.deleteHandler(this._sasl_challenge_handler);
1981
- this._sasl_challenge_handler = null;
1982
- }
1983
- this._sasl_data = {};
1984
- return this._sasl_failure_cb(null);
1985
- }
1986
- }
1987
- Strophe.info("SASL authentication succeeded.");
1988
-
1989
- if (this._sasl_data.keys) {
1990
- this.scram_keys = this._sasl_data.keys;
1991
- }
1992
-
1993
- if (this._sasl_mechanism) {
1994
- this._sasl_mechanism.onSuccess();
1995
- }
1996
- // remove old handlers
1997
- this.deleteHandler(this._sasl_failure_handler);
1998
- this._sasl_failure_handler = null;
1999
- if (this._sasl_challenge_handler) {
2000
- this.deleteHandler(this._sasl_challenge_handler);
2001
- this._sasl_challenge_handler = null;
2002
- }
2003
- const streamfeature_handlers = [];
2004
- const wrapper = (handlers, elem) => {
2005
- while (handlers.length) {
2006
- this.deleteHandler(handlers.pop());
2007
- }
2008
- this._onStreamFeaturesAfterSASL(elem);
2009
- return false;
2010
- };
2011
- streamfeature_handlers.push(
2012
- this._addSysHandler(elem => wrapper(streamfeature_handlers, elem),
2013
- null, "stream:features", null, null)
2014
- );
2015
-
2016
- streamfeature_handlers.push(
2017
- this._addSysHandler(elem => wrapper(streamfeature_handlers, elem),
2018
- Strophe.NS.STREAM, "features", null, null)
2019
- );
2020
-
2021
- // we must send an xmpp:restart now
2022
- this._sendRestart();
2023
- return false;
2024
- }
2025
-
2026
- /** PrivateFunction: _onStreamFeaturesAfterSASL
2027
- * Parameters:
2028
- * (XMLElement) elem - The matching stanza.
2029
- *
2030
- * Returns:
2031
- * false to remove the handler.
2032
- */
2033
- _onStreamFeaturesAfterSASL (elem) {
2034
- // save stream:features for future usage
2035
- this.features = elem;
2036
- for (let i=0; i < elem.childNodes.length; i++) {
2037
- const child = elem.childNodes[i];
2038
- if (child.nodeName === 'bind') {
2039
- this.do_bind = true;
2040
- }
2041
- if (child.nodeName === 'session') {
2042
- this.do_session = true;
2043
- }
2044
- }
2045
-
2046
- if (!this.do_bind) {
2047
- this._changeConnectStatus(Strophe.Status.AUTHFAIL, null);
2048
- return false;
2049
- } else if (!this.options.explicitResourceBinding) {
2050
- this.bind();
2051
- } else {
2052
- this._changeConnectStatus(Strophe.Status.BINDREQUIRED, null);
2053
- }
2054
- return false;
2055
- }
2056
-
2057
- /** Function: bind
2058
- *
2059
- * Sends an IQ to the XMPP server to bind a JID resource for this session.
2060
- *
2061
- * https://tools.ietf.org/html/rfc6120#section-7.5
2062
- *
2063
- * If `explicitResourceBinding` was set to a truthy value in the options
2064
- * passed to the Strophe.Connection constructor, then this function needs
2065
- * to be called explicitly by the client author.
2066
- *
2067
- * Otherwise it'll be called automatically as soon as the XMPP server
2068
- * advertises the "urn:ietf:params:xml:ns:xmpp-bind" stream feature.
2069
- */
2070
- bind () {
2071
- if (!this.do_bind) {
2072
- Strophe.log(
2073
- Strophe.LogLevel.INFO,
2074
- `Strophe.Connection.prototype.bind called but "do_bind" is false`
2075
- );
2076
- return;
2077
- }
2078
- this._addSysHandler(
2079
- this._onResourceBindResultIQ.bind(this),
2080
- null, null, null, "_bind_auth_2");
2081
-
2082
- const resource = Strophe.getResourceFromJid(this.jid);
2083
- if (resource) {
2084
- this.send($iq({type: "set", id: "_bind_auth_2"})
2085
- .c('bind', {xmlns: Strophe.NS.BIND})
2086
- .c('resource', {}).t(resource).tree());
2087
- } else {
2088
- this.send($iq({type: "set", id: "_bind_auth_2"})
2089
- .c('bind', {xmlns: Strophe.NS.BIND})
2090
- .tree());
2091
- }
2092
- }
2093
-
2094
- /** PrivateFunction: _onResourceBindIQ
2095
- * _Private_ handler for binding result and session start.
2096
- *
2097
- * Parameters:
2098
- * (XMLElement) elem - The matching stanza.
2099
- *
2100
- * Returns:
2101
- * false to remove the handler.
2102
- */
2103
- _onResourceBindResultIQ (elem) {
2104
- if (elem.getAttribute("type") === "error") {
2105
- Strophe.warn("Resource binding failed.");
2106
- const conflict = elem.getElementsByTagName("conflict");
2107
- let condition;
2108
- if (conflict.length > 0) {
2109
- condition = Strophe.ErrorCondition.CONFLICT;
2110
- }
2111
- this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition, elem);
2112
- return false;
2113
- }
2114
- // TODO - need to grab errors
2115
- const bind = elem.getElementsByTagName("bind");
2116
- if (bind.length > 0) {
2117
- const jidNode = bind[0].getElementsByTagName("jid");
2118
- if (jidNode.length > 0) {
2119
- this.authenticated = true;
2120
- this.jid = Strophe.getText(jidNode[0]);
2121
- if (this.do_session) {
2122
- this._establishSession();
2123
- } else {
2124
- this._changeConnectStatus(Strophe.Status.CONNECTED, null);
2125
- }
2126
- }
2127
- } else {
2128
- Strophe.warn("Resource binding failed.");
2129
- this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
2130
- return false;
2131
- }
2132
- }
2133
-
2134
- /** PrivateFunction: _establishSession
2135
- * Send IQ request to establish a session with the XMPP server.
2136
- *
2137
- * See https://xmpp.org/rfcs/rfc3921.html#session
2138
- *
2139
- * Note: The protocol for session establishment has been determined as
2140
- * unnecessary and removed in RFC-6121.
2141
- */
2142
- _establishSession () {
2143
- if (!this.do_session) {
2144
- throw new Error(`Strophe.Connection.prototype._establishSession `+
2145
- `called but apparently ${Strophe.NS.SESSION} wasn't advertised by the server`);
2146
- }
2147
- this._addSysHandler(
2148
- this._onSessionResultIQ.bind(this),
2149
- null, null, null, "_session_auth_2");
2150
-
2151
- this.send(
2152
- $iq({type: "set", id: "_session_auth_2"})
2153
- .c('session', {xmlns: Strophe.NS.SESSION})
2154
- .tree());
2155
- }
2156
-
2157
- /** PrivateFunction: _onSessionResultIQ
2158
- * _Private_ handler for the server's IQ response to a client's session
2159
- * request.
2160
- *
2161
- * This sets Connection.authenticated to true on success, which
2162
- * starts the processing of user handlers.
2163
- *
2164
- * See https://xmpp.org/rfcs/rfc3921.html#session
2165
- *
2166
- * Note: The protocol for session establishment has been determined as
2167
- * unnecessary and removed in RFC-6121.
2168
- *
2169
- * Parameters:
2170
- * (XMLElement) elem - The matching stanza.
2171
- *
2172
- * Returns:
2173
- * false to remove the handler.
2174
- */
2175
- _onSessionResultIQ (elem) {
2176
- if (elem.getAttribute("type") === "result") {
2177
- this.authenticated = true;
2178
- this._changeConnectStatus(Strophe.Status.CONNECTED, null);
2179
- } else if (elem.getAttribute("type") === "error") {
2180
- this.authenticated = false;
2181
- Strophe.warn("Session creation failed.");
2182
- this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
2183
- return false;
2184
- }
2185
- return false;
2186
- }
2187
-
2188
- /** PrivateFunction: _sasl_failure_cb
2189
- * _Private_ handler for SASL authentication failure.
2190
- *
2191
- * Parameters:
2192
- * (XMLElement) elem - The matching stanza.
2193
- *
2194
- * Returns:
2195
- * false to remove the handler.
2196
- */
2197
- _sasl_failure_cb (elem) {
2198
- // delete unneeded handlers
2199
- if (this._sasl_success_handler) {
2200
- this.deleteHandler(this._sasl_success_handler);
2201
- this._sasl_success_handler = null;
2202
- }
2203
- if (this._sasl_challenge_handler) {
2204
- this.deleteHandler(this._sasl_challenge_handler);
2205
- this._sasl_challenge_handler = null;
2206
- }
2207
-
2208
- if(this._sasl_mechanism)
2209
- this._sasl_mechanism.onFailure();
2210
- this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
2211
- return false;
2212
- }
2213
-
2214
- /** PrivateFunction: _auth2_cb
2215
- * _Private_ handler to finish legacy authentication.
2216
- *
2217
- * This handler is called when the result from the jabber:iq:auth
2218
- * <iq/> stanza is returned.
2219
- *
2220
- * Parameters:
2221
- * (XMLElement) elem - The stanza that triggered the callback.
2222
- *
2223
- * Returns:
2224
- * false to remove the handler.
2225
- */
2226
- _auth2_cb (elem) {
2227
- if (elem.getAttribute("type") === "result") {
2228
- this.authenticated = true;
2229
- this._changeConnectStatus(Strophe.Status.CONNECTED, null);
2230
- } else if (elem.getAttribute("type") === "error") {
2231
- this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
2232
- this.disconnect('authentication failed');
2233
- }
2234
- return false;
2235
- }
2236
-
2237
- /** PrivateFunction: _addSysTimedHandler
2238
- * _Private_ function to add a system level timed handler.
2239
- *
2240
- * This function is used to add a Strophe.TimedHandler for the
2241
- * library code. System timed handlers are allowed to run before
2242
- * authentication is complete.
2243
- *
2244
- * Parameters:
2245
- * (Integer) period - The period of the handler.
2246
- * (Function) handler - The callback function.
2247
- */
2248
- _addSysTimedHandler (period, handler) {
2249
- const thand = new Strophe.TimedHandler(period, handler);
2250
- thand.user = false;
2251
- this.addTimeds.push(thand);
2252
- return thand;
2253
- }
2254
-
2255
- /** PrivateFunction: _addSysHandler
2256
- * _Private_ function to add a system level stanza handler.
2257
- *
2258
- * This function is used to add a Strophe.Handler for the
2259
- * library code. System stanza handlers are allowed to run before
2260
- * authentication is complete.
2261
- *
2262
- * Parameters:
2263
- * (Function) handler - The callback function.
2264
- * (String) ns - The namespace to match.
2265
- * (String) name - The stanza name to match.
2266
- * (String) type - The stanza type attribute to match.
2267
- * (String) id - The stanza id attribute to match.
2268
- */
2269
- _addSysHandler (handler, ns, name, type, id) {
2270
- const hand = new Strophe.Handler(handler, ns, name, type, id);
2271
- hand.user = false;
2272
- this.addHandlers.push(hand);
2273
- return hand;
2274
- }
2275
-
2276
- /** PrivateFunction: _onDisconnectTimeout
2277
- * _Private_ timeout handler for handling non-graceful disconnection.
2278
- *
2279
- * If the graceful disconnect process does not complete within the
2280
- * time allotted, this handler finishes the disconnect anyway.
2281
- *
2282
- * Returns:
2283
- * false to remove the handler.
2284
- */
2285
- _onDisconnectTimeout () {
2286
- Strophe.debug("_onDisconnectTimeout was called");
2287
- this._changeConnectStatus(Strophe.Status.CONNTIMEOUT, null);
2288
- this._proto._onDisconnectTimeout();
2289
- // actually disconnect
2290
- this._doDisconnect();
2291
- return false;
2292
- }
2293
-
2294
- /** PrivateFunction: _onIdle
2295
- * _Private_ handler to process events during idle cycle.
2296
- *
2297
- * This handler is called every 100ms to fire timed handlers that
2298
- * are ready and keep poll requests going.
2299
- */
2300
- _onIdle () {
2301
- // add timed handlers scheduled for addition
2302
- // NOTE: we add before remove in the case a timed handler is
2303
- // added and then deleted before the next _onIdle() call.
2304
- while (this.addTimeds.length > 0) {
2305
- this.timedHandlers.push(this.addTimeds.pop());
2306
- }
2307
-
2308
- // remove timed handlers that have been scheduled for deletion
2309
- while (this.removeTimeds.length > 0) {
2310
- const thand = this.removeTimeds.pop();
2311
- const i = this.timedHandlers.indexOf(thand);
2312
- if (i >= 0) {
2313
- this.timedHandlers.splice(i, 1);
2314
- }
2315
- }
2316
-
2317
- // call ready timed handlers
2318
- const now = new Date().getTime();
2319
- const newList = [];
2320
- for (let i=0; i < this.timedHandlers.length; i++) {
2321
- const thand = this.timedHandlers[i];
2322
- if (this.authenticated || !thand.user) {
2323
- const since = thand.lastCalled + thand.period;
2324
- if (since - now <= 0) {
2325
- if (thand.run()) {
2326
- newList.push(thand);
2327
- }
2328
- } else {
2329
- newList.push(thand);
2330
- }
2331
- }
2332
- }
2333
- this.timedHandlers = newList;
2334
- clearTimeout(this._idleTimeout);
2335
- this._proto._onIdle();
2336
-
2337
- // reactivate the timer only if connected
2338
- if (this.connected) {
2339
- this._idleTimeout = setTimeout(() => this._onIdle(), 100);
2340
- }
2341
- }
2342
- };
2343
-
2344
-
2345
- Strophe.SASLMechanism = SASLMechanism;
2346
-
2347
- /** Constants: SASL mechanisms
2348
- * Available authentication mechanisms
2349
- *
2350
- * Strophe.SASLAnonymous - SASL ANONYMOUS authentication.
2351
- * Strophe.SASLPlain - SASL PLAIN authentication.
2352
- * Strophe.SASLSHA1 - SASL SCRAM-SHA-1 authentication
2353
- * Strophe.SASLSHA256 - SASL SCRAM-SHA-256 authentication
2354
- * Strophe.SASLSHA384 - SASL SCRAM-SHA-384 authentication
2355
- * Strophe.SASLSHA512 - SASL SCRAM-SHA-512 authentication
2356
- * Strophe.SASLOAuthBearer - SASL OAuth Bearer authentication
2357
- * Strophe.SASLExternal - SASL EXTERNAL authentication
2358
- * Strophe.SASLXOAuth2 - SASL X-OAuth2 authentication
2359
- */
2360
- Strophe.SASLAnonymous = SASLAnonymous;
2361
- Strophe.SASLPlain = SASLPlain;
2362
- Strophe.SASLSHA1 = SASLSHA1;
2363
- Strophe.SASLSHA256 = SASLSHA256;
2364
- Strophe.SASLSHA384 = SASLSHA384;
2365
- Strophe.SASLSHA512 = SASLSHA512;
2366
- Strophe.SASLOAuthBearer = SASLOAuthBearer;
2367
- Strophe.SASLExternal = SASLExternal;
2368
- Strophe.SASLXOAuth2 = SASLXOAuth2;
2369
-
2370
-
2371
- export default {
2372
- 'Strophe': Strophe,
2373
- '$build': $build,
2374
- '$iq': $iq,
2375
- '$msg': $msg,
2376
- '$pres': $pres,
2377
- };