Commit ebcf7098 authored by JC Brand's avatar JC Brand

New dist files

parent 4e67b420
...@@ -10760,7 +10760,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -10760,7 +10760,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
// Converse.js // Converse.js
// https://conversejs.org // https://conversejs.org
// //
// Copyright (c) 2012-2018, the Converse.js developers // Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2) // Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) { (function (root, factory) {
define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory); define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory);
...@@ -11427,6 +11427,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -11427,6 +11427,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
_converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id); _converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
_converse.session.fetch(); _converse.session.fetch();
_converse.emit('sessionInitialized');
}; };
this.clearSession = function () { this.clearSession = function () {
...@@ -13086,15 +13088,15 @@ define("emojione", (function (global) { ...@@ -13086,15 +13088,15 @@ define("emojione", (function (global) {
initialize: function initialize() { initialize: function initialize() {
this.waitUntilFeaturesDiscovered = utils.getResolveablePromise(); this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
this.dataforms = new Backbone.Collection(); this.dataforms = new Backbone.Collection();
this.dataforms.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.dataforms-{this.get('jid')}")); this.dataforms.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.dataforms-{this.get('jid')}"));
this.features = new Backbone.Collection(); this.features = new Backbone.Collection();
this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.features-".concat(this.get('jid')))); this.features.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.features-".concat(this.get('jid'))));
this.features.on('add', this.onFeatureAdded, this); this.features.on('add', this.onFeatureAdded, this);
this.identities = new Backbone.Collection(); this.identities = new Backbone.Collection();
this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.identities-".concat(this.get('jid')))); this.identities.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.identities-".concat(this.get('jid'))));
this.fetchFeatures(); this.fetchFeatures();
this.items = new _converse.DiscoEntities(); this.items = new _converse.DiscoEntities();
this.items.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.disco-items-".concat(this.get('jid')))); this.items.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.disco-items-".concat(this.get('jid'))));
this.items.fetch(); this.items.fetch();
}, },
getIdentity: function getIdentity(category, type) { getIdentity: function getIdentity(category, type) {
...@@ -13275,13 +13277,33 @@ define("emojione", (function (global) { ...@@ -13275,13 +13277,33 @@ define("emojione", (function (global) {
return this; return this;
} }
function initStreamFeatures() {
_converse.stream_features = new Backbone.Collection();
_converse.stream_features.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.stream-features-".concat(_converse.bare_jid)));
_converse.stream_features.fetch({
success: function success(collection) {
if (collection.length === 0 && _converse.connection.features) {
_.forEach(_converse.connection.features.childNodes, function (feature) {
_converse.stream_features.create({
'name': feature.nodeName,
'xmlns': feature.getAttribute('xmlns')
});
});
}
}
});
_converse.emit('streamFeaturesAdded');
}
function initializeDisco() { function initializeDisco() {
addClientFeatures(); addClientFeatures();
_converse.connection.addHandler(onDiscoInfoRequest, Strophe.NS.DISCO_INFO, 'iq', 'get', null, null); _converse.connection.addHandler(onDiscoInfoRequest, Strophe.NS.DISCO_INFO, 'iq', 'get', null, null);
_converse.disco_entities = new _converse.DiscoEntities(); _converse.disco_entities = new _converse.DiscoEntities();
_converse.disco_entities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.disco-entities-".concat(_converse.bare_jid))); _converse.disco_entities.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.disco-entities-".concat(_converse.bare_jid)));
_converse.disco_entities.fetchEntities().then(function (collection) { _converse.disco_entities.fetchEntities().then(function (collection) {
if (collection.length === 0 || !collection.get(_converse.domain)) { if (collection.length === 0 || !collection.get(_converse.domain)) {
...@@ -13296,6 +13318,8 @@ define("emojione", (function (global) { ...@@ -13296,6 +13318,8 @@ define("emojione", (function (global) {
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
} }
_converse.api.listen.on('sessionInitialized', initStreamFeatures);
_converse.api.listen.on('reconnected', initializeDisco); _converse.api.listen.on('reconnected', initializeDisco);
_converse.api.listen.on('connected', initializeDisco); _converse.api.listen.on('connected', initializeDisco);
...@@ -13376,6 +13400,19 @@ define("emojione", (function (global) { ...@@ -13376,6 +13400,19 @@ define("emojione", (function (global) {
* @namespace * @namespace
*/ */
'disco': { 'disco': {
'stream': {
'getFeature': function getFeature(name, xmlns) {
if (_.isNil(name) || _.isNil(xmlns)) {
throw new Error("name and xmlns need to be provided when calling disco.stream.getFeature");
}
return _converse.stream_features.findWhere({
'name': name,
'xmlns': xmlns
});
}
},
/** /**
* The "own" grouping * The "own" grouping
* @namespace * @namespace
...@@ -15890,19 +15927,24 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -15890,19 +15927,24 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
this.on('change:image_hash', this.onAvatarChanged, this); this.on('change:image_hash', this.onAvatarChanged, this);
}, },
onAvatarChanged: function onAvatarChanged() { onAvatarChanged: function onAvatarChanged() {
var vcard = _converse.vcards.findWhere({ var hash = this.get('image_hash');
'jid': this.get('from') var vcards = [];
});
if (!vcard) { if (this.get('jid')) {
return; vcards.push(this.updateVCard(_converse.vcards.findWhere({
'jid': this.get('jid')
})));
} }
var hash = this.get('image_hash'); vcards.push(this.updateVCard(_converse.vcards.findWhere({
'jid': this.get('from')
})));
_.forEach(_.filter(vcards, undefined), function (vcard) {
if (hash && vcard.get('image_hash') !== hash) { if (hash && vcard.get('image_hash') !== hash) {
_converse.api.vcard.update(vcard); _converse.api.vcard.update(vcard);
} }
});
}, },
getDisplayName: function getDisplayName() { getDisplayName: function getDisplayName() {
return this.get('nick') || this.get('jid'); return this.get('nick') || this.get('jid');
...@@ -15950,6 +15992,10 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -15950,6 +15992,10 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
'jid': removed_jid 'jid': removed_jid
}); });
if (!occupant) {
return;
}
if (occupant.get('show') === 'offline') { if (occupant.get('show') === 'offline') {
occupant.destroy(); occupant.destroy();
} }
...@@ -25093,7 +25139,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -25093,7 +25139,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
// Converse.js // Converse.js
// http://conversejs.org // http://conversejs.org
// //
// Copyright (c) 2012-2018, the Converse.js developers // Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2) // Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) { (function (root, factory) {
define('converse-vcard',["converse-core", "crypto", "tpl!vcard"], factory); define('converse-vcard',["converse-core", "crypto", "tpl!vcard"], factory);
...@@ -25166,7 +25212,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -25166,7 +25212,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'), 'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'),
'url': _.get(vcard.querySelector('URL'), 'textContent'), 'url': _.get(vcard.querySelector('URL'), 'textContent'),
'role': _.get(vcard.querySelector('ROLE'), 'textContent'), 'role': _.get(vcard.querySelector('ROLE'), 'textContent'),
'email': _.get(vcard.querySelector('EMAIL USERID'), 'textContent') 'email': _.get(vcard.querySelector('EMAIL USERID'), 'textContent'),
'vcard_updated': moment().format(),
'vcard_error': undefined
}; };
} }
...@@ -25184,7 +25232,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -25184,7 +25232,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
if (errback) { if (errback) {
errback({ errback({
'stanza': iq, 'stanza': iq,
'jid': jid 'jid': jid,
'vcard_error': moment().format()
}); });
} }
} }
...@@ -25250,8 +25299,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -25250,8 +25299,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
'get': function get(model, force) { 'get': function get(model, force) {
if (_.isString(model)) { if (_.isString(model)) {
return getVCard(_converse, model); return getVCard(_converse, model);
} else if (!model.get('vcard_updated') || force) { } else if (force || !model.get('vcard_updated') || !moment(model.get('vcard_error')).isSame(new Date(), "day")) {
var jid = model.get('jid') || model.get('muc_jid'); var jid = model.get('jid');
if (!jid) { if (!jid) {
throw new Error("No JID to get vcard for!"); throw new Error("No JID to get vcard for!");
...@@ -25267,9 +25316,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -25267,9 +25316,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
_this.get(model, force).then(function (vcard) { _this.get(model, force).then(function (vcard) {
model.save(_.extend(_.pick(vcard, ['fullname', 'nickname', 'email', 'url', 'role', 'image_type', 'image', 'image_hash']), { delete vcard['stanza'];
'vcard_updated': moment().format() model.save(vcard);
}));
resolve(); resolve();
}); });
}); });
...@@ -31439,6 +31487,13 @@ return __p ...@@ -31439,6 +31487,13 @@ return __p
_converse.roster = new _converse.RosterContacts(); _converse.roster = new _converse.RosterContacts();
_converse.roster.browserStorage = new Backbone.BrowserStorage[_converse.storage]( _converse.roster.browserStorage = new Backbone.BrowserStorage[_converse.storage](
b64_sha1(`converse.contacts-${_converse.bare_jid}`)); b64_sha1(`converse.contacts-${_converse.bare_jid}`));
_converse.roster.data = new Backbone.Model();
const id = b64_sha1(`converse-roster-model-${_converse.bare_jid}`);
_converse.roster.data.id = id;
_converse.roster.data.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
_converse.roster.data.fetch();
_converse.rostergroups = new _converse.RosterGroups(); _converse.rostergroups = new _converse.RosterGroups();
_converse.rostergroups.browserStorage = new Backbone.BrowserStorage[_converse.storage]( _converse.rostergroups.browserStorage = new Backbone.BrowserStorage[_converse.storage](
b64_sha1(`converse.roster.groups${_converse.bare_jid}`)); b64_sha1(`converse.roster.groups${_converse.bare_jid}`));
...@@ -31733,10 +31788,10 @@ return __p ...@@ -31733,10 +31788,10 @@ return __p
/* Register a handler for roster IQ "set" stanzas, which update /* Register a handler for roster IQ "set" stanzas, which update
* roster contacts. * roster contacts.
*/ */
_converse.connection.addHandler( _converse.connection.addHandler((iq) => {
_converse.roster.onRosterPush.bind(_converse.roster), _converse.roster.onRosterPush(iq);
Strophe.NS.ROSTER, 'iq', "set" return true;
); }, Strophe.NS.ROSTER, 'iq', "set");
}, },
registerRosterXHandler () { registerRosterXHandler () {
...@@ -31766,12 +31821,14 @@ return __p ...@@ -31766,12 +31821,14 @@ return __p
* Returns a promise which resolves once the contacts have been * Returns a promise which resolves once the contacts have been
* fetched. * fetched.
*/ */
const that = this;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.fetch({ this.fetch({
'add': true, 'add': true,
'silent': true, 'silent': true,
success (collection) { success (collection) {
if (collection.length === 0) { if (collection.length === 0 ||
(that.rosterVersioningSupported() && !_converse.session.get('roster_fetched'))) {
_converse.send_initial_presence = true; _converse.send_initial_presence = true;
_converse.roster.fetchFromServer().then(resolve).catch(reject); _converse.roster.fetchFromServer().then(resolve).catch(reject);
} else { } else {
...@@ -31904,23 +31961,37 @@ return __p ...@@ -31904,23 +31961,37 @@ return __p
*/ */
const id = iq.getAttribute('id'); const id = iq.getAttribute('id');
const from = iq.getAttribute('from'); const from = iq.getAttribute('from');
if (from && from !== "" && Strophe.getBareJidFromJid(from) !== _converse.bare_jid) { if (from && from !== _converse.connection.jid) {
// Receiving client MUST ignore stanza unless it has no from or from = user's bare JID. // https://tools.ietf.org/html/rfc6121#page-15
// XXX: Some naughty servers apparently send from a full //
// JID so we need to explicitly compare bare jids here. // A receiving client MUST ignore the stanza unless it has no 'from'
// https://github.com/jcbrand/converse.js/issues/493 // attribute (i.e., implicitly from the bare JID of the user's
_converse.connection.send( // account) or it has a 'from' attribute whose value matches the
$iq({type: 'error', id, from: _converse.connection.jid}) // user's bare JID <user@domainpart>.
.c('error', {'type': 'cancel'}) return;
.c('service-unavailable', {'xmlns': Strophe.NS.ROSTER })
);
return true;
} }
_converse.connection.send($iq({type: 'result', id, from: _converse.connection.jid})); _converse.connection.send($iq({type: 'result', id, from: _converse.connection.jid}));
const items = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"] item`, iq);
_.each(items, this.updateContact.bind(this)); const query = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"]`, iq).pop();
this.data.save('version', query.getAttribute('ver'));
const items = sizzle(`item`, query);
if (items.length > 1) {
_converse.log(iq, Strophe.LogLevel.ERROR);
throw new Error('Roster push query may not contain more than one "item" element.');
}
if (items.length === 0) {
_converse.log(iq, Strophe.LogLevel.WARN);
_converse.log('Received a roster push stanza without an "item" element.', Strophe.LogLevel.WARN);
return;
}
this.updateContact(items.pop());
_converse.emit('rosterPush', iq); _converse.emit('rosterPush', iq);
return true; return;
},
rosterVersioningSupported () {
return _converse.api.disco.stream.getFeature('ver', 'urn:xmpp:features:rosterver') && this.data.get('version');
}, },
fetchFromServer () { fetchFromServer () {
...@@ -31930,7 +32001,9 @@ return __p ...@@ -31930,7 +32001,9 @@ return __p
'type': 'get', 'type': 'get',
'id': _converse.connection.getUniqueId('roster') 'id': _converse.connection.getUniqueId('roster')
}).c('query', {xmlns: Strophe.NS.ROSTER}); }).c('query', {xmlns: Strophe.NS.ROSTER});
if (this.rosterVersioningSupported()) {
iq.attrs({'ver': this.data.get('version')});
}
const callback = _.flow(this.onReceivedFromServer.bind(this), resolve); const callback = _.flow(this.onReceivedFromServer.bind(this), resolve);
const errback = function (iq) { const errback = function (iq) {
const errmsg = "Error while trying to fetch roster from the server"; const errmsg = "Error while trying to fetch roster from the server";
...@@ -31945,8 +32018,13 @@ return __p ...@@ -31945,8 +32018,13 @@ return __p
/* An IQ stanza containing the roster has been received from /* An IQ stanza containing the roster has been received from
* the XMPP server. * the XMPP server.
*/ */
const items = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"] item`, iq); const query = sizzle(`query[xmlns="${Strophe.NS.ROSTER}"]`, iq).pop();
_.each(items, this.updateContact.bind(this)); if (query) {
const items = sizzle(`item`, query);
_.each(items, (item) => this.updateContact(item));
this.data.save('version', query.getAttribute('ver'));
_converse.session.save('roster_fetched', true);
}
_converse.emit('roster', iq); _converse.emit('roster', iq);
}, },
...@@ -32610,6 +32610,8 @@ if (!root.atob) { ...@@ -32610,6 +32610,8 @@ if (!root.atob) {
define('strophe-sha1', [],function () { define('strophe-sha1', [],function () {
return factory(); return factory();
}); });
} else if (typeof exports === 'object') {
module.exports = factory();
} else { } else {
// Browser globals // Browser globals
root.SHA1 = factory(); root.SHA1 = factory();
...@@ -32804,6 +32806,8 @@ return { ...@@ -32804,6 +32806,8 @@ return {
define('strophe-md5',[], function () { define('strophe-md5',[], function () {
return factory(); return factory();
}); });
} else if (typeof exports === 'object') {
module.exports = factory();
} else { } else {
// Browser globals // Browser globals
root.MD5 = factory(); root.MD5 = factory();
...@@ -33006,6 +33010,8 @@ return { ...@@ -33006,6 +33010,8 @@ return {
define('strophe-utils',[], function () { define('strophe-utils',[], function () {
return factory(); return factory();
}); });
} else if (typeof exports === 'object') {
module.exports = factory();
} else { } else {
// Browser globals // Browser globals
root.stropheUtils = factory(); root.stropheUtils = factory();
...@@ -33094,6 +33100,12 @@ return { ...@@ -33094,6 +33100,12 @@ return {
], function () { ], function () {
return factory.apply(this, arguments); return factory.apply(this, arguments);
}); });
} else if (typeof exports === 'object') {
module.exports = factory(
require('./sha1'),
require('./md5'),
require('./utils')
);
} else { } else {
// Browser globals // Browser globals
var o = factory(root.SHA1, root.MD5, root.stropheUtils); var o = factory(root.SHA1, root.MD5, root.stropheUtils);
...@@ -33168,7 +33180,7 @@ function $pres(attrs) { return new Strophe.Builder("presence", attrs); } ...@@ -33168,7 +33180,7 @@ function $pres(attrs) { return new Strophe.Builder("presence", attrs); }
*/ */
Strophe = { Strophe = {
/** Constant: VERSION */ /** Constant: VERSION */
VERSION: "1.2.14", VERSION: "1.2.15",
/** Constants: XMPP Namespace Constants /** Constants: XMPP Namespace Constants
* Common namespace constants from the XMPP RFCs and XEPs. * Common namespace constants from the XMPP RFCs and XEPs.
...@@ -33306,6 +33318,14 @@ Strophe = { ...@@ -33306,6 +33318,14 @@ Strophe = {
CONNTIMEOUT: 10 CONNTIMEOUT: 10
}, },
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 /** Constants: Log Level Constants
* Logging level indicators. * Logging level indicators.
* *
...@@ -33882,7 +33902,7 @@ Strophe = { ...@@ -33882,7 +33902,7 @@ Strophe = {
* *
* This function is called whenever the Strophe library calls any * This function is called whenever the Strophe library calls any
* of the logging functions. The default implementation of this * of the logging functions. The default implementation of this
* function does nothing. If client code wishes to handle the logging * function logs only fatal errors. If client code wishes to handle the logging
* messages, it should override this with * messages, it should override this with
* > Strophe.log = function (level, msg) { * > Strophe.log = function (level, msg) {
* > (user code here) * > (user code here)
...@@ -33906,11 +33926,13 @@ Strophe = { ...@@ -33906,11 +33926,13 @@ Strophe = {
* be one of the values in Strophe.LogLevel. * be one of the values in Strophe.LogLevel.
* (String) msg - The log message. * (String) msg - The log message.
*/ */
/* jshint ignore:start */
log: function (level, msg) { log: function (level, msg) {
return; if (level === this.LogLevel.FATAL &&
typeof window.console === 'object' &&
typeof window.console.error === 'function') {
window.console.error(msg);
}
}, },
/* jshint ignore:end */
/** Function: debug /** Function: debug
* Log a message at the Strophe.LogLevel.DEBUG level. * Log a message at the Strophe.LogLevel.DEBUG level.
...@@ -34576,10 +34598,11 @@ Strophe.TimedHandler.prototype = { ...@@ -34576,10 +34598,11 @@ Strophe.TimedHandler.prototype = {
* If nothing is specified, then the following mechanisms (and their * If nothing is specified, then the following mechanisms (and their
* priorities) are registered: * priorities) are registered:
* *
* OAUTHBEARER - 60 * SCRAM-SHA1 - 70
* SCRAM-SHA1 - 50 * DIGEST-MD5 - 60
* DIGEST-MD5 - 40 * PLAIN - 50
* PLAIN - 30 * OAUTH-BEARER - 40
* OAUTH-2 - 30
* ANONYMOUS - 20 * ANONYMOUS - 20
* EXTERNAL - 10 * EXTERNAL - 10
* *
...@@ -35460,6 +35483,7 @@ Strophe.Connection.prototype = { ...@@ -35460,6 +35483,7 @@ Strophe.Connection.prototype = {
Strophe.SASLExternal, Strophe.SASLExternal,
Strophe.SASLMD5, Strophe.SASLMD5,
Strophe.SASLOAuthBearer, Strophe.SASLOAuthBearer,
Strophe.SASLXOAuth2,
Strophe.SASLPlain, Strophe.SASLPlain,
Strophe.SASLSHA1 Strophe.SASLSHA1
]; ];
...@@ -35526,8 +35550,9 @@ Strophe.Connection.prototype = { ...@@ -35526,8 +35550,9 @@ Strophe.Connection.prototype = {
* (Integer) status - the new connection status, one of the values * (Integer) status - the new connection status, one of the values
* in Strophe.Status * in Strophe.Status
* (String) condition - the error condition or null * (String) condition - the error condition or null
* (XMLElement) elem - The triggering stanza.
*/ */
_changeConnectStatus: function (status, condition) { _changeConnectStatus: function (status, condition, elem) {
// notify all plugins listening for status changes // notify all plugins listening for status changes
for (var k in Strophe._connectionPlugins) { for (var k in Strophe._connectionPlugins) {
if (Strophe._connectionPlugins.hasOwnProperty(k)) { if (Strophe._connectionPlugins.hasOwnProperty(k)) {
...@@ -35546,7 +35571,7 @@ Strophe.Connection.prototype = { ...@@ -35546,7 +35571,7 @@ Strophe.Connection.prototype = {
// notify the user's callback // notify the user's callback
if (this.connect_callback) { if (this.connect_callback) {
try { try {
this.connect_callback(status, condition); this.connect_callback(status, condition, elem);
} catch (e) { } catch (e) {
Strophe._handleError(e); Strophe._handleError(e);
Strophe.error( Strophe.error(
...@@ -35662,7 +35687,10 @@ Strophe.Connection.prototype = { ...@@ -35662,7 +35687,10 @@ Strophe.Connection.prototype = {
} }
this._changeConnectStatus(Strophe.Status.CONNFAIL, cond); this._changeConnectStatus(Strophe.Status.CONNFAIL, cond);
} else { } else {
this._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown"); this._changeConnectStatus(
Strophe.Status.CONNFAIL,
Strophe.ErrorCondition.UNKOWN_REASON
);
} }
this._doDisconnect(cond); this._doDisconnect(cond);
return; return;
...@@ -35702,6 +35730,26 @@ Strophe.Connection.prototype = { ...@@ -35702,6 +35730,26 @@ Strophe.Connection.prototype = {
*/ */
mechanisms: {}, mechanisms: {},
/** PrivateFunction: _no_auth_received
*
* Called on stream start/restart when no stream:features
* has been received or when no viable authentication mechanism is offered.
*
* Sends a blank poll request.
*/
_no_auth_received: function (_callback) {
var error_msg = "Server did not offer a supported authentication mechanism";
Strophe.error(error_msg);
this._changeConnectStatus(
Strophe.Status.CONNFAIL,
Strophe.ErrorCondition.NO_AUTH_MECH
);
if (_callback) {
_callback.call(this);
}
this._doDisconnect();
},
/** PrivateFunction: _connect_cb /** PrivateFunction: _connect_cb
* _Private_ handler for initial connection request. * _Private_ handler for initial connection request.
* *
...@@ -35715,7 +35763,7 @@ Strophe.Connection.prototype = { ...@@ -35715,7 +35763,7 @@ Strophe.Connection.prototype = {
* Parameters: * Parameters:
* (Strophe.Request) req - The current request. * (Strophe.Request) req - The current request.
* (Function) _callback - low level (xmpp) connect callback function. * (Function) _callback - low level (xmpp) connect callback function.
* Useful for plugins with their own xmpp connect callback (when their) * Useful for plugins with their own xmpp connect callback (when they
* want to do something special). * want to do something special).
*/ */
_connect_cb: function (req, _callback, raw) { _connect_cb: function (req, _callback, raw) {
...@@ -35727,8 +35775,11 @@ Strophe.Connection.prototype = { ...@@ -35727,8 +35775,11 @@ Strophe.Connection.prototype = {
bodyWrap = this._proto._reqToData(req); bodyWrap = this._proto._reqToData(req);
} catch (e) { } catch (e) {
if (e !== "badformat") { throw e; } if (e !== "badformat") { throw e; }
this._changeConnectStatus(Strophe.Status.CONNFAIL, 'bad-format'); this._changeConnectStatus(
this._doDisconnect('bad-format'); Strophe.Status.CONNFAIL,
Strophe.ErrorCondition.BAD_FORMAT
);
this._doDisconnect(Strophe.ErrorCondition.BAD_FORMAT);
} }
if (!bodyWrap) { return; } if (!bodyWrap) { return; }
...@@ -35761,7 +35812,7 @@ Strophe.Connection.prototype = { ...@@ -35761,7 +35812,7 @@ Strophe.Connection.prototype = {
bodyWrap.getElementsByTagName("features").length > 0; bodyWrap.getElementsByTagName("features").length > 0;
} }
if (!hasFeatures) { if (!hasFeatures) {
this._proto._no_auth_received(_callback); this._no_auth_received(_callback);
return; return;
} }
...@@ -35777,7 +35828,7 @@ Strophe.Connection.prototype = { ...@@ -35777,7 +35828,7 @@ Strophe.Connection.prototype = {
if (bodyWrap.getElementsByTagName("auth").length === 0) { if (bodyWrap.getElementsByTagName("auth").length === 0) {
// There are no matching SASL mechanisms and also no legacy // There are no matching SASL mechanisms and also no legacy
// auth available. // auth available.
this._proto._no_auth_received(_callback); this._no_auth_received(_callback);
return; return;
} }
} }
...@@ -35873,9 +35924,9 @@ Strophe.Connection.prototype = { ...@@ -35873,9 +35924,9 @@ Strophe.Connection.prototype = {
// client connections // client connections
this._changeConnectStatus( this._changeConnectStatus(
Strophe.Status.CONNFAIL, Strophe.Status.CONNFAIL,
'x-strophe-bad-non-anon-jid' Strophe.ErrorCondition.MISSING_JID_NODE
); );
this.disconnect('x-strophe-bad-non-anon-jid'); this.disconnect(Strophe.ErrorCondition.MISSING_JID_NODE);
} else { } else {
// Fall back to legacy authentication // Fall back to legacy authentication
this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null); this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);
...@@ -36093,9 +36144,9 @@ Strophe.Connection.prototype = { ...@@ -36093,9 +36144,9 @@ Strophe.Connection.prototype = {
Strophe.info("SASL binding failed."); Strophe.info("SASL binding failed.");
var conflict = elem.getElementsByTagName("conflict"), condition; var conflict = elem.getElementsByTagName("conflict"), condition;
if (conflict.length > 0) { if (conflict.length > 0) {
condition = 'conflict'; condition = Strophe.ErrorCondition.CONFLICT;
} }
this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition); this._changeConnectStatus(Strophe.Status.AUTHFAIL, condition, elem);
return false; return false;
} }
...@@ -36122,7 +36173,7 @@ Strophe.Connection.prototype = { ...@@ -36122,7 +36173,7 @@ Strophe.Connection.prototype = {
} }
} else { } else {
Strophe.info("SASL binding failed."); Strophe.info("SASL binding failed.");
this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
return false; return false;
} }
}, },
...@@ -36145,7 +36196,7 @@ Strophe.Connection.prototype = { ...@@ -36145,7 +36196,7 @@ Strophe.Connection.prototype = {
this._changeConnectStatus(Strophe.Status.CONNECTED, null); this._changeConnectStatus(Strophe.Status.CONNECTED, null);
} else if (elem.getAttribute("type") === "error") { } else if (elem.getAttribute("type") === "error") {
Strophe.info("Session creation failed."); Strophe.info("Session creation failed.");
this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
return false; return false;
} }
return false; return false;
...@@ -36174,7 +36225,7 @@ Strophe.Connection.prototype = { ...@@ -36174,7 +36225,7 @@ Strophe.Connection.prototype = {
if(this._sasl_mechanism) if(this._sasl_mechanism)
this._sasl_mechanism.onFailure(); this._sasl_mechanism.onFailure();
this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
return false; return false;
}, },
/* jshint unused:true */ /* jshint unused:true */
...@@ -36196,7 +36247,7 @@ Strophe.Connection.prototype = { ...@@ -36196,7 +36247,7 @@ Strophe.Connection.prototype = {
this.authenticated = true; this.authenticated = true;
this._changeConnectStatus(Strophe.Status.CONNECTED, null); this._changeConnectStatus(Strophe.Status.CONNECTED, null);
} else if (elem.getAttribute("type") === "error") { } else if (elem.getAttribute("type") === "error") {
this._changeConnectStatus(Strophe.Status.AUTHFAIL, null); this._changeConnectStatus(Strophe.Status.AUTHFAIL, null, elem);
this.disconnect('authentication failed'); this.disconnect('authentication failed');
} }
return false; return false;
...@@ -36453,6 +36504,7 @@ Strophe.SASLMechanism.prototype = { ...@@ -36453,6 +36504,7 @@ Strophe.SASLMechanism.prototype = {
* Strophe.SASLSHA1 - SASL SCRAM-SHA1 authentication * Strophe.SASLSHA1 - SASL SCRAM-SHA1 authentication
* Strophe.SASLOAuthBearer - SASL OAuth Bearer authentication * Strophe.SASLOAuthBearer - SASL OAuth Bearer authentication
* Strophe.SASLExternal - SASL EXTERNAL authentication * Strophe.SASLExternal - SASL EXTERNAL authentication
* Strophe.SASLXOAuth2 - SASL X-OAuth2 authentication
*/ */
// Building SASL callbacks // Building SASL callbacks
...@@ -36472,7 +36524,7 @@ Strophe.SASLAnonymous.prototype.test = function(connection) { ...@@ -36472,7 +36524,7 @@ Strophe.SASLAnonymous.prototype.test = function(connection) {
* SASL PLAIN authentication. * SASL PLAIN authentication.
*/ */
Strophe.SASLPlain = function() {}; Strophe.SASLPlain = function() {};
Strophe.SASLPlain.prototype = new Strophe.SASLMechanism("PLAIN", true, 30); Strophe.SASLPlain.prototype = new Strophe.SASLMechanism("PLAIN", true, 50);
Strophe.SASLPlain.prototype.test = function(connection) { Strophe.SASLPlain.prototype.test = function(connection) {
return connection.authcid !== null; return connection.authcid !== null;
...@@ -36492,7 +36544,7 @@ Strophe.SASLPlain.prototype.onChallenge = function(connection) { ...@@ -36492,7 +36544,7 @@ Strophe.SASLPlain.prototype.onChallenge = function(connection) {
* SASL SCRAM SHA 1 authentication. * SASL SCRAM SHA 1 authentication.
*/ */
Strophe.SASLSHA1 = function() {}; Strophe.SASLSHA1 = function() {};
Strophe.SASLSHA1.prototype = new Strophe.SASLMechanism("SCRAM-SHA-1", true, 50); Strophe.SASLSHA1.prototype = new Strophe.SASLMechanism("SCRAM-SHA-1", true, 70);
Strophe.SASLSHA1.prototype.test = function(connection) { Strophe.SASLSHA1.prototype.test = function(connection) {
return connection.authcid !== null; return connection.authcid !== null;
...@@ -36576,7 +36628,7 @@ Strophe.SASLSHA1.prototype.onChallenge = function(connection, challenge, test_cn ...@@ -36576,7 +36628,7 @@ Strophe.SASLSHA1.prototype.onChallenge = function(connection, challenge, test_cn
* SASL DIGEST MD5 authentication. * SASL DIGEST MD5 authentication.
*/ */
Strophe.SASLMD5 = function() {}; Strophe.SASLMD5 = function() {};
Strophe.SASLMD5.prototype = new Strophe.SASLMechanism("DIGEST-MD5", false, 40); Strophe.SASLMD5.prototype = new Strophe.SASLMechanism("DIGEST-MD5", false, 60);
Strophe.SASLMD5.prototype.test = function(connection) { Strophe.SASLMD5.prototype.test = function(connection) {
return connection.authcid !== null; return connection.authcid !== null;
...@@ -36659,7 +36711,7 @@ Strophe.SASLMD5.prototype.onChallenge = function(connection, challenge, test_cno ...@@ -36659,7 +36711,7 @@ Strophe.SASLMD5.prototype.onChallenge = function(connection, challenge, test_cno
* SASL OAuth Bearer authentication. * SASL OAuth Bearer authentication.
*/ */
Strophe.SASLOAuthBearer = function() {}; Strophe.SASLOAuthBearer = function() {};
Strophe.SASLOAuthBearer.prototype = new Strophe.SASLMechanism("OAUTHBEARER", true, 60); Strophe.SASLOAuthBearer.prototype = new Strophe.SASLMechanism("OAUTHBEARER", true, 40);
Strophe.SASLOAuthBearer.prototype.test = function(connection) { Strophe.SASLOAuthBearer.prototype.test = function(connection) {
return connection.pass !== null; return connection.pass !== null;
...@@ -36703,6 +36755,29 @@ Strophe.SASLExternal.prototype.onChallenge = function(connection) { ...@@ -36703,6 +36755,29 @@ Strophe.SASLExternal.prototype.onChallenge = function(connection) {
return connection.authcid === connection.authzid ? '' : connection.authzid; return connection.authcid === connection.authzid ? '' : connection.authzid;
}; };
/** PrivateConstructor: SASLXOAuth2
* SASL X-OAuth2 authentication.
*/
Strophe.SASLXOAuth2 = function () { };
Strophe.SASLXOAuth2.prototype = new Strophe.SASLMechanism("X-OAUTH2", true, 30);
Strophe.SASLXOAuth2.prototype.test = function (connection) {
return connection.pass !== null;
};
Strophe.SASLXOAuth2.prototype.onChallenge = function (connection) {
var 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);
};
return { return {
'Strophe': Strophe, 'Strophe': Strophe,
'$build': $build, '$build': $build,
...@@ -36736,6 +36811,10 @@ return { ...@@ -36736,6 +36811,10 @@ return {
core.$build core.$build
); );
}); });
} else if (typeof exports === 'object') {
var core = require('./core');
module.exports = factory(core.Strophe, core.$build);
} else { } else {
// Browser globals // Browser globals
return factory(Strophe, $build); return factory(Strophe, $build);
...@@ -36813,11 +36892,17 @@ Strophe.Request.prototype = { ...@@ -36813,11 +36892,17 @@ Strophe.Request.prototype = {
throw "parsererror"; throw "parsererror";
} }
} else if (this.xhr.responseText) { } else if (this.xhr.responseText) {
Strophe.error("invalid response received"); // In React Native, we may get responseText but no responseXML. We can try to parse it manually.
Strophe.debug("Got responseText but no responseXML; attempting to parse it with DOMParser...");
node = new DOMParser().parseFromString(this.xhr.responseText, 'application/xml').documentElement;
if (!node) {
throw new Error('Parsing produced null node');
} else if (node.querySelector('parsererror')) {
Strophe.error("invalid response received: " + node.querySelector('parsererror').textContent);
Strophe.error("responseText: " + this.xhr.responseText); Strophe.error("responseText: " + this.xhr.responseText);
throw "badformat"; throw "badformat";
} }
}
return node; return node;
}, },
...@@ -36883,6 +36968,8 @@ Strophe.Bosh = function(connection) { ...@@ -36883,6 +36968,8 @@ Strophe.Bosh = function(connection) {
this.errors = 0; this.errors = 0;
this.inactivity = null; this.inactivity = null;
this.lastResponseHeaders = null;
this._requests = []; this._requests = [];
}; };
...@@ -37190,26 +37277,6 @@ Strophe.Bosh.prototype = { ...@@ -37190,26 +37277,6 @@ Strophe.Bosh.prototype = {
} }
}, },
/** PrivateFunction: _no_auth_received
*
* Called on stream start/restart when no stream:features
* has been received and sends a blank poll request.
*/
_no_auth_received: function (_callback) {
if (_callback) {
_callback = _callback.bind(this._conn);
} else {
_callback = this._conn._connect_cb.bind(this._conn);
}
var body = this._buildBody();
this._requests.push(
new Strophe.Request(body.tree(),
this._onRequestStateChange.bind(
this, _callback.bind(this._conn)),
body.tree().getAttribute("rid")));
this._throttledRequestHandler();
},
/** PrivateFunction: _onDisconnectTimeout /** PrivateFunction: _onDisconnectTimeout
* _Private_ timeout handler for handling non-graceful disconnection. * _Private_ timeout handler for handling non-graceful disconnection.
* *
...@@ -37350,6 +37417,7 @@ Strophe.Bosh.prototype = { ...@@ -37350,6 +37417,7 @@ Strophe.Bosh.prototype = {
return; return;
} }
var reqStatus = this._getRequestStatus(req); var reqStatus = this._getRequestStatus(req);
this.lastResponseHeaders = req.xhr.getAllResponseHeaders();
if (this.disconnecting && reqStatus >= 400) { if (this.disconnecting && reqStatus >= 400) {
this._hitError(reqStatus); this._hitError(reqStatus);
this._callProtocolErrorHandlers(req); this._callProtocolErrorHandlers(req);
...@@ -37674,6 +37742,10 @@ return Strophe; ...@@ -37674,6 +37742,10 @@ return Strophe;
core.$build core.$build
); );
}); });
} else if (typeof exports === 'object') {
var core = require('./core');
module.exports = factory(core.Strophe, core.$build);
} else { } else {
// Browser globals // Browser globals
return factory(Strophe, $build); return factory(Strophe, $build);
...@@ -37948,7 +38020,7 @@ Strophe.Websocket.prototype = { ...@@ -37948,7 +38020,7 @@ Strophe.Websocket.prototype = {
this._conn.send(pres); this._conn.send(pres);
} }
var close = $build("close", { "xmlns": Strophe.NS.FRAMING }); var close = $build("close", { "xmlns": Strophe.NS.FRAMING });
this._conn.xmlOutput(close); this._conn.xmlOutput(close.tree());
var closeString = Strophe.serialize(close); var closeString = Strophe.serialize(close);
this._conn.rawOutput(closeString); this._conn.rawOutput(closeString);
try { try {
...@@ -37986,6 +38058,7 @@ Strophe.Websocket.prototype = { ...@@ -37986,6 +38058,7 @@ Strophe.Websocket.prototype = {
*/ */
_closeSocket: function () { _closeSocket: function () {
if (this.socket) { try { if (this.socket) { try {
this.socket.onerror = null;
this.socket.close(); this.socket.close();
} catch (e) {} } } catch (e) {} }
this.socket = null; this.socket = null;
...@@ -38026,24 +38099,6 @@ Strophe.Websocket.prototype = { ...@@ -38026,24 +38099,6 @@ Strophe.Websocket.prototype = {
} }
}, },
/** PrivateFunction: _no_auth_received
*
* Called on stream start/restart when no stream:features
* has been received.
*/
_no_auth_received: function (_callback) {
Strophe.error("Server did not send any auth methods");
this._conn._changeConnectStatus(
Strophe.Status.CONNFAIL,
"Server did not send any auth methods"
);
if (_callback) {
_callback = _callback.bind(this._conn);
_callback();
}
this._conn._doDisconnect();
},
/** PrivateFunction: _onDisconnectTimeout /** PrivateFunction: _onDisconnectTimeout
* _Private_ timeout handler for handling non-graceful disconnection. * _Private_ timeout handler for handling non-graceful disconnection.
* *
...@@ -38219,6 +38274,11 @@ return Strophe; ...@@ -38219,6 +38274,11 @@ return Strophe;
], function (wrapper) { ], function (wrapper) {
return wrapper; return wrapper;
}); });
} else if (typeof exports === 'object') {
var core = require('./core');
require('./bosh');
require('./websocket');
module.exports = core;
} }
})(this); })(this);
...@@ -43335,7 +43395,7 @@ return Backbone.BrowserStorage; ...@@ -43335,7 +43395,7 @@ return Backbone.BrowserStorage;
// Converse.js // Converse.js
// https://conversejs.org // https://conversejs.org
// //
// Copyright (c) 2012-2018, the Converse.js developers // Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2) // Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) { (function (root, factory) {
define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory); define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory);
...@@ -44002,6 +44062,8 @@ return Backbone.BrowserStorage; ...@@ -44002,6 +44062,8 @@ return Backbone.BrowserStorage;
_converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id); _converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
_converse.session.fetch(); _converse.session.fetch();
_converse.emit('sessionInitialized');
}; };
this.clearSession = function () { this.clearSession = function () {
...@@ -45661,15 +45723,15 @@ define("emojione", (function (global) { ...@@ -45661,15 +45723,15 @@ define("emojione", (function (global) {
initialize: function initialize() { initialize: function initialize() {
this.waitUntilFeaturesDiscovered = utils.getResolveablePromise(); this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
this.dataforms = new Backbone.Collection(); this.dataforms = new Backbone.Collection();
this.dataforms.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.dataforms-{this.get('jid')}")); this.dataforms.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.dataforms-{this.get('jid')}"));
this.features = new Backbone.Collection(); this.features = new Backbone.Collection();
this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.features-".concat(this.get('jid')))); this.features.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.features-".concat(this.get('jid'))));
this.features.on('add', this.onFeatureAdded, this); this.features.on('add', this.onFeatureAdded, this);
this.identities = new Backbone.Collection(); this.identities = new Backbone.Collection();
this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.identities-".concat(this.get('jid')))); this.identities.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.identities-".concat(this.get('jid'))));
this.fetchFeatures(); this.fetchFeatures();
this.items = new _converse.DiscoEntities(); this.items = new _converse.DiscoEntities();
this.items.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.disco-items-".concat(this.get('jid')))); this.items.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.disco-items-".concat(this.get('jid'))));
this.items.fetch(); this.items.fetch();
}, },
getIdentity: function getIdentity(category, type) { getIdentity: function getIdentity(category, type) {
...@@ -45850,13 +45912,33 @@ define("emojione", (function (global) { ...@@ -45850,13 +45912,33 @@ define("emojione", (function (global) {
return this; return this;
} }
function initStreamFeatures() {
_converse.stream_features = new Backbone.Collection();
_converse.stream_features.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.stream-features-".concat(_converse.bare_jid)));
_converse.stream_features.fetch({
success: function success(collection) {
if (collection.length === 0 && _converse.connection.features) {
_.forEach(_converse.connection.features.childNodes, function (feature) {
_converse.stream_features.create({
'name': feature.nodeName,
'xmlns': feature.getAttribute('xmlns')
});
});
}
}
});
_converse.emit('streamFeaturesAdded');
}
function initializeDisco() { function initializeDisco() {
addClientFeatures(); addClientFeatures();
_converse.connection.addHandler(onDiscoInfoRequest, Strophe.NS.DISCO_INFO, 'iq', 'get', null, null); _converse.connection.addHandler(onDiscoInfoRequest, Strophe.NS.DISCO_INFO, 'iq', 'get', null, null);
_converse.disco_entities = new _converse.DiscoEntities(); _converse.disco_entities = new _converse.DiscoEntities();
_converse.disco_entities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.disco-entities-".concat(_converse.bare_jid))); _converse.disco_entities.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.disco-entities-".concat(_converse.bare_jid)));
_converse.disco_entities.fetchEntities().then(function (collection) { _converse.disco_entities.fetchEntities().then(function (collection) {
if (collection.length === 0 || !collection.get(_converse.domain)) { if (collection.length === 0 || !collection.get(_converse.domain)) {
...@@ -45871,6 +45953,8 @@ define("emojione", (function (global) { ...@@ -45871,6 +45953,8 @@ define("emojione", (function (global) {
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
} }
_converse.api.listen.on('sessionInitialized', initStreamFeatures);
_converse.api.listen.on('reconnected', initializeDisco); _converse.api.listen.on('reconnected', initializeDisco);
_converse.api.listen.on('connected', initializeDisco); _converse.api.listen.on('connected', initializeDisco);
...@@ -45951,6 +46035,19 @@ define("emojione", (function (global) { ...@@ -45951,6 +46035,19 @@ define("emojione", (function (global) {
* @namespace * @namespace
*/ */
'disco': { 'disco': {
'stream': {
'getFeature': function getFeature(name, xmlns) {
if (_.isNil(name) || _.isNil(xmlns)) {
throw new Error("name and xmlns need to be provided when calling disco.stream.getFeature");
}
return _converse.stream_features.findWhere({
'name': name,
'xmlns': xmlns
});
}
},
/** /**
* The "own" grouping * The "own" grouping
* @namespace * @namespace
...@@ -48627,19 +48724,24 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -48627,19 +48724,24 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
this.on('change:image_hash', this.onAvatarChanged, this); this.on('change:image_hash', this.onAvatarChanged, this);
}, },
onAvatarChanged: function onAvatarChanged() { onAvatarChanged: function onAvatarChanged() {
var vcard = _converse.vcards.findWhere({ var hash = this.get('image_hash');
'jid': this.get('from') var vcards = [];
});
if (!vcard) { if (this.get('jid')) {
return; vcards.push(this.updateVCard(_converse.vcards.findWhere({
'jid': this.get('jid')
})));
} }
var hash = this.get('image_hash'); vcards.push(this.updateVCard(_converse.vcards.findWhere({
'jid': this.get('from')
})));
_.forEach(_.filter(vcards, undefined), function (vcard) {
if (hash && vcard.get('image_hash') !== hash) { if (hash && vcard.get('image_hash') !== hash) {
_converse.api.vcard.update(vcard); _converse.api.vcard.update(vcard);
} }
});
}, },
getDisplayName: function getDisplayName() { getDisplayName: function getDisplayName() {
return this.get('nick') || this.get('jid'); return this.get('nick') || this.get('jid');
...@@ -48687,6 +48789,10 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -48687,6 +48789,10 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
'jid': removed_jid 'jid': removed_jid
}); });
if (!occupant) {
return;
}
if (occupant.get('show') === 'offline') { if (occupant.get('show') === 'offline') {
occupant.destroy(); occupant.destroy();
} }
...@@ -60751,7 +60857,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -60751,7 +60857,7 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
// Converse.js // Converse.js
// http://conversejs.org // http://conversejs.org
// //
// Copyright (c) 2012-2018, the Converse.js developers // Copyright (c) 2013-2018, the Converse.js developers
// Licensed under the Mozilla Public License (MPLv2) // Licensed under the Mozilla Public License (MPLv2)
(function (root, factory) { (function (root, factory) {
define('converse-vcard',["converse-core", "crypto", "tpl!vcard"], factory); define('converse-vcard',["converse-core", "crypto", "tpl!vcard"], factory);
...@@ -60824,7 +60930,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -60824,7 +60930,9 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'), 'image_type': _.get(vcard.querySelector('PHOTO TYPE'), 'textContent'),
'url': _.get(vcard.querySelector('URL'), 'textContent'), 'url': _.get(vcard.querySelector('URL'), 'textContent'),
'role': _.get(vcard.querySelector('ROLE'), 'textContent'), 'role': _.get(vcard.querySelector('ROLE'), 'textContent'),
'email': _.get(vcard.querySelector('EMAIL USERID'), 'textContent') 'email': _.get(vcard.querySelector('EMAIL USERID'), 'textContent'),
'vcard_updated': moment().format(),
'vcard_error': undefined
}; };
} }
...@@ -60842,7 +60950,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -60842,7 +60950,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
if (errback) { if (errback) {
errback({ errback({
'stanza': iq, 'stanza': iq,
'jid': jid 'jid': jid,
'vcard_error': moment().format()
}); });
} }
} }
...@@ -60908,8 +61017,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -60908,8 +61017,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
'get': function get(model, force) { 'get': function get(model, force) {
if (_.isString(model)) { if (_.isString(model)) {
return getVCard(_converse, model); return getVCard(_converse, model);
} else if (!model.get('vcard_updated') || force) { } else if (force || !model.get('vcard_updated') || !moment(model.get('vcard_error')).isSame(new Date(), "day")) {
var jid = model.get('jid') || model.get('muc_jid'); var jid = model.get('jid');
if (!jid) { if (!jid) {
throw new Error("No JID to get vcard for!"); throw new Error("No JID to get vcard for!");
...@@ -60925,9 +61034,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat ...@@ -60925,9 +61034,8 @@ function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterat
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
_this.get(model, force).then(function (vcard) { _this.get(model, force).then(function (vcard) {
model.save(_.extend(_.pick(vcard, ['fullname', 'nickname', 'email', 'url', 'role', 'image_type', 'image', 'image_hash']), { delete vcard['stanza'];
'vcard_updated': moment().format() model.save(vcard);
}));
resolve(); resolve();
}); });
}); });
...@@ -72046,6 +72154,13 @@ return __p ...@@ -72046,6 +72154,13 @@ return __p
*/ */
_converse.roster = new _converse.RosterContacts(); _converse.roster = new _converse.RosterContacts();
_converse.roster.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.contacts-".concat(_converse.bare_jid))); _converse.roster.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.contacts-".concat(_converse.bare_jid)));
_converse.roster.data = new Backbone.Model();
var id = b64_sha1("converse-roster-model-".concat(_converse.bare_jid));
_converse.roster.data.id = id;
_converse.roster.data.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
_converse.roster.data.fetch();
_converse.rostergroups = new _converse.RosterGroups(); _converse.rostergroups = new _converse.RosterGroups();
_converse.rostergroups.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.roster.groups".concat(_converse.bare_jid))); _converse.rostergroups.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.roster.groups".concat(_converse.bare_jid)));
...@@ -72361,7 +72476,11 @@ return __p ...@@ -72361,7 +72476,11 @@ return __p
/* Register a handler for roster IQ "set" stanzas, which update /* Register a handler for roster IQ "set" stanzas, which update
* roster contacts. * roster contacts.
*/ */
_converse.connection.addHandler(_converse.roster.onRosterPush.bind(_converse.roster), Strophe.NS.ROSTER, 'iq', "set"); _converse.connection.addHandler(function (iq) {
_converse.roster.onRosterPush(iq);
return true;
}, Strophe.NS.ROSTER, 'iq', "set");
}, },
registerRosterXHandler: function registerRosterXHandler() { registerRosterXHandler: function registerRosterXHandler() {
/* Register a handler for RosterX message stanzas, which are /* Register a handler for RosterX message stanzas, which are
...@@ -72389,12 +72508,13 @@ return __p ...@@ -72389,12 +72508,13 @@ return __p
* Returns a promise which resolves once the contacts have been * Returns a promise which resolves once the contacts have been
* fetched. * fetched.
*/ */
var that = this;
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
_this2.fetch({ _this2.fetch({
'add': true, 'add': true,
'silent': true, 'silent': true,
success: function success(collection) { success: function success(collection) {
if (collection.length === 0) { if (collection.length === 0 || that.rosterVersioningSupported() && !_converse.session.get('roster_fetched')) {
_converse.send_initial_presence = true; _converse.send_initial_presence = true;
_converse.roster.fetchFromServer().then(resolve).catch(reject); _converse.roster.fetchFromServer().then(resolve).catch(reject);
...@@ -72544,22 +72664,14 @@ return __p ...@@ -72544,22 +72664,14 @@ return __p
var id = iq.getAttribute('id'); var id = iq.getAttribute('id');
var from = iq.getAttribute('from'); var from = iq.getAttribute('from');
if (from && from !== "" && Strophe.getBareJidFromJid(from) !== _converse.bare_jid) { if (from && from !== _converse.connection.jid) {
// Receiving client MUST ignore stanza unless it has no from or from = user's bare JID. // https://tools.ietf.org/html/rfc6121#page-15
// XXX: Some naughty servers apparently send from a full //
// JID so we need to explicitly compare bare jids here. // A receiving client MUST ignore the stanza unless it has no 'from'
// https://github.com/jcbrand/converse.js/issues/493 // attribute (i.e., implicitly from the bare JID of the user's
_converse.connection.send($iq({ // account) or it has a 'from' attribute whose value matches the
type: 'error', // user's bare JID <user@domainpart>.
id: id, return;
from: _converse.connection.jid
}).c('error', {
'type': 'cancel'
}).c('service-unavailable', {
'xmlns': Strophe.NS.ROSTER
}));
return true;
} }
_converse.connection.send($iq({ _converse.connection.send($iq({
...@@ -72568,13 +72680,32 @@ return __p ...@@ -72568,13 +72680,32 @@ return __p
from: _converse.connection.jid from: _converse.connection.jid
})); }));
var items = sizzle("query[xmlns=\"".concat(Strophe.NS.ROSTER, "\"] item"), iq); var query = sizzle("query[xmlns=\"".concat(Strophe.NS.ROSTER, "\"]"), iq).pop();
this.data.save('version', query.getAttribute('ver'));
var items = sizzle("item", query);
if (items.length > 1) {
_converse.log(iq, Strophe.LogLevel.ERROR);
throw new Error('Roster push query may not contain more than one "item" element.');
}
if (items.length === 0) {
_converse.log(iq, Strophe.LogLevel.WARN);
_converse.log('Received a roster push stanza without an "item" element.', Strophe.LogLevel.WARN);
return;
}
_.each(items, this.updateContact.bind(this)); this.updateContact(items.pop());
_converse.emit('rosterPush', iq); _converse.emit('rosterPush', iq);
return true; return;
},
rosterVersioningSupported: function rosterVersioningSupported() {
return _converse.api.disco.stream.getFeature('ver', 'urn:xmpp:features:rosterver') && this.data.get('version');
}, },
fetchFromServer: function fetchFromServer() { fetchFromServer: function fetchFromServer() {
var _this4 = this; var _this4 = this;
...@@ -72588,6 +72719,12 @@ return __p ...@@ -72588,6 +72719,12 @@ return __p
xmlns: Strophe.NS.ROSTER xmlns: Strophe.NS.ROSTER
}); });
if (_this4.rosterVersioningSupported()) {
iq.attrs({
'ver': _this4.data.get('version')
});
}
var callback = _.flow(_this4.onReceivedFromServer.bind(_this4), resolve); var callback = _.flow(_this4.onReceivedFromServer.bind(_this4), resolve);
var errback = function errback(iq) { var errback = function errback(iq) {
...@@ -72602,12 +72739,24 @@ return __p ...@@ -72602,12 +72739,24 @@ return __p
}); });
}, },
onReceivedFromServer: function onReceivedFromServer(iq) { onReceivedFromServer: function onReceivedFromServer(iq) {
var _this5 = this;
/* An IQ stanza containing the roster has been received from /* An IQ stanza containing the roster has been received from
* the XMPP server. * the XMPP server.
*/ */
var items = sizzle("query[xmlns=\"".concat(Strophe.NS.ROSTER, "\"] item"), iq); var query = sizzle("query[xmlns=\"".concat(Strophe.NS.ROSTER, "\"]"), iq).pop();
if (query) {
var items = sizzle("item", query);
_.each(items, function (item) {
return _this5.updateContact(item);
});
this.data.save('version', query.getAttribute('ver'));
_.each(items, this.updateContact.bind(this)); _converse.session.save('roster_fetched', true);
}
_converse.emit('roster', iq); _converse.emit('roster', iq);
}, },
...@@ -72795,7 +72944,7 @@ return __p ...@@ -72795,7 +72944,7 @@ return __p
_converse.RosterGroups = Backbone.Collection.extend({ _converse.RosterGroups = Backbone.Collection.extend({
model: _converse.RosterGroup, model: _converse.RosterGroup,
fetchRosterGroups: function fetchRosterGroups() { fetchRosterGroups: function fetchRosterGroups() {
var _this5 = this; var _this6 = this;
/* Fetches all the roster groups from sessionStorage. /* Fetches all the roster groups from sessionStorage.
* *
...@@ -72803,7 +72952,7 @@ return __p ...@@ -72803,7 +72952,7 @@ return __p
* returned. * returned.
*/ */
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
_this5.fetch({ _this6.fetch({
silent: true, silent: true,
// We need to first have all groups before // We need to first have all groups before
// we can start positioning them, so we set // we can start positioning them, so we set
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment