diff --git a/package-lock.json b/package-lock.json index 4dc5bb8b8..ba597af5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13702,28 +13702,8 @@ } }, "strophe.js": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/strophe.js/-/strophe.js-1.3.3.tgz", - "integrity": "sha512-sKPmbgQbwte+XhnUuHbCwl21LRguLdFGQs8KP6R7ki1Lw9F/yeZPECPqDLxpazoFO49nhPwb8rWvPTYGX1fhjw==" - }, - "strophejs-plugin-ping": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/strophejs-plugin-ping/-/strophejs-plugin-ping-0.0.3.tgz", - "integrity": "sha512-HS/ArEGKXfu36fihjUSfjqmqOSyppQTJUbrkfEtOBRJmnaP3LsRRe5T2S3dmCdsWHKORaJYc/OHSKfFlxHPdqw==", - "requires": { - "strophe.js": "^1.2.12" - } - }, - "strophejs-plugin-register": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/strophejs-plugin-register/-/strophejs-plugin-register-0.0.1.tgz", - "integrity": "sha1-0oXTPH1oK40co3ZHgJrCZ8CgiaM=", - "dev": true - }, - "strophejs-plugin-rsm": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/strophejs-plugin-rsm/-/strophejs-plugin-rsm-0.0.2.tgz", - "integrity": "sha512-Yn/VpxNz3Gkb790rJkwMyjlwHWCjWA9UxIl5kwGnsr7Ofo1MHztgyQ8XwQF1DGFp3Y4oiXbjZ/whG3S/cIgIew==" + "version": "github:strophe/strophejs#44da5faca8baa61c691739d63af8b1dea1d2436c", + "from": "github:strophe/strophejs#44da5faca8baa61c691739d63af8b1dea1d2436c" }, "style-loader": { "version": "0.23.1", diff --git a/package.json b/package.json index 6126345f6..55771f6b8 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "converse.js", "version": "4.2.0", "description": "Browser based XMPP chat client", - "main": "dist/converse.min.js", + "browser": "dist/converse.js", + "module": "src/converse.js", "files": [ "CHANGES.md", "LICENSE.txt", @@ -95,7 +96,6 @@ "sinon": "^2.1.0", "sizzle": "^2.3.3", "snabbdom": "0.7.2", - "strophejs-plugin-register": "0.0.1", "style-loader": "^0.23.1", "uglify-es": "^3.0.24", "urijs": "^1.19.1", diff --git a/spec/mam.js b/spec/mam.js index c62ff33dc..9ebeaae7e 100644 --- a/spec/mam.js +++ b/spec/mam.js @@ -507,7 +507,7 @@ done(); })); - it("accepts a Strophe.RSM object for the query options", + it("accepts a _converse.RSM object for the query options", mock.initConverse( null, [], {}, async function (done, _converse) { @@ -519,11 +519,11 @@ sent_stanza = iq; IQ_id = sendIQ.bind(this)(iq, callback, errback); }); - // Normally the user wouldn't manually make a Strophe.RSM object + // Normally the user wouldn't manually make a _converse.RSM object // and pass it in. However, in the callback method an RSM object is // returned which can be reused for easy paging. This test is // more for that usecase. - const rsm = new Strophe.RSM({'max': '10'}); + const rsm = new _converse.RSM({'max': '10'}); rsm['with'] = 'romeo@montague.lit'; // eslint-disable-line dot-notation rsm.start = '2010-06-07T00:00:00Z'; _converse.api.archive.query(rsm); @@ -551,7 +551,7 @@ done(); })); - it("returns an object which includes the messages and a Strophe.RSM object", + it("returns an object which includes the messages and a _converse.RSM object", mock.initConverse( null, [], {}, async function (done, _converse) { diff --git a/src/converse-chatview.js b/src/converse-chatview.js index b1ec9ef1b..30706995c 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -31,7 +31,7 @@ import tpl_user_details_modal from "templates/user_details_modal.html"; import u from "@converse/headless/utils/emoji"; import xss from "xss/dist/xss"; -const { $msg, Backbone, Promise, Strophe, _, b64_sha1, sizzle, dayjs } = converse.env; +const { $msg, Backbone, Promise, Strophe, _, sizzle, dayjs } = converse.env; converse.plugins.add('converse-chatview', { diff --git a/src/converse-rosterview.js b/src/converse-rosterview.js index f8047a823..5b08ae14e 100644 --- a/src/converse-rosterview.js +++ b/src/converse-rosterview.js @@ -9,6 +9,7 @@ import "@converse/headless/converse-roster"; import "converse-modal"; import BrowserStorage from "backbone.browserStorage"; import { OrderedListView } from "backbone.overview"; +import SHA1 from 'strophe.js/src/sha1'; import _FormData from "formdata-polyfill"; import converse from "@converse/headless/converse-core"; import tpl_add_contact_modal from "templates/add_contact_modal.html"; @@ -20,8 +21,7 @@ import tpl_roster_filter from "templates/roster_filter.html"; import tpl_roster_item from "templates/roster_item.html"; import tpl_search_contact from "templates/search_contact.html"; - -const { Backbone, Strophe, $iq, b64_sha1, sizzle, _ } = converse.env; +const { Backbone, Strophe, $iq, sizzle, _ } = converse.env; const u = converse.env.utils; @@ -897,7 +897,7 @@ converse.plugins.add('converse-rosterview', { if (view) { return view.model; } - return this.model.create({name, 'id': b64_sha1(name)}); + return this.model.create({name, 'id': SHA1.b64_sha1(name)}); }, addContactToGroup (contact, name, options) { diff --git a/src/converse.js b/src/converse.js index 325a5cf76..9608d18c1 100644 --- a/src/converse.js +++ b/src/converse.js @@ -3,12 +3,7 @@ * Any of the following components may be removed if they're not needed. */ -import "@converse/headless/converse-caps"; // XEP-0115 Entity Capabilities -import "@converse/headless/converse-mam"; // XEP-0313 Message Archive Management -import "@converse/headless/converse-ping"; // XEP-0199 XMPP Ping -import "@converse/headless/converse-pubsub"; // XEP-0060 PubSub -import "@converse/headless/converse-vcard"; // XEP-0054 VCard-temp -import "@converse/headless/converse-bookmarks"; // XEP-0048 Bookmarks +import "@converse/headless/headless"; import "converse-autocomplete"; import "converse-bookmark-views"; // Views for XEP-0048 Bookmarks import "converse-chatview"; // Renders standalone chat boxes for single user chat diff --git a/src/headless/converse-caps.js b/src/headless/converse-caps.js index d0aefbbf5..162e6b7c2 100644 --- a/src/headless/converse-caps.js +++ b/src/headless/converse-caps.js @@ -4,10 +4,10 @@ // Copyright (c) 2013-2019, the Converse.js developers // Licensed under the Mozilla Public License (MPLv2) - +import SHA1 from 'strophe.js/src/sha1'; import converse from "@converse/headless/converse-core"; -const { Strophe, $build, _, b64_sha1 } = converse.env; +const { Strophe, $build, _ } = converse.env; Strophe.addNamespace('CAPS', "http://jabber.org/protocol/caps"); @@ -32,7 +32,7 @@ function generateVerificationString (_converse) { features.sort(); S = _.reduce(features, (result, feature) => `${result}${feature}<`, S); - return b64_sha1(S); + return SHA1.b64_sha1(S); } function createCapsNode (_converse) { diff --git a/src/headless/converse-core.js b/src/headless/converse-core.js index 19e91b880..f005686e8 100644 --- a/src/headless/converse-core.js +++ b/src/headless/converse-core.js @@ -4,7 +4,10 @@ // Copyright (c) 2013-2019, the Converse.js developers // Licensed under the Mozilla Public License (MPLv2) -import { $build, $iq, $msg, $pres, SHA1, Strophe } from "strophe.js"; +import * as bosh from 'strophe.js/src/bosh'; +import * as strophe from 'strophe.js/src/core'; +import * as websocket from 'strophe.js/src/websocket'; + import Backbone from "backbone"; import BrowserStorage from "backbone.browserStorage"; import Promise from "es6-promise/dist/es6-promise.auto"; @@ -17,13 +20,16 @@ import polyfill from "./polyfill"; import sizzle from "sizzle"; import u from "@converse/headless/utils/core"; +const Strophe = strophe.default.Strophe; +const $build = strophe.default.$build; +const $iq = strophe.default.$iq; +const $msg = strophe.default.$msg; +const $pres = strophe.default.$pres; + Backbone = Backbone.noConflict(); dayjs.extend(advancedFormat); -// Strophe globals -const b64_sha1 = SHA1.b64_sha1; - // Add Strophe Namespaces Strophe.addNamespace('CARBONS', 'urn:xmpp:carbons:2'); Strophe.addNamespace('CHATSTATES', 'http://jabber.org/protocol/chatstates'); @@ -95,6 +101,7 @@ _converse.core_plugins = [ 'converse-ping', 'converse-pubsub', 'converse-roster', + 'converse-rsm', 'converse-vcard' ]; @@ -433,7 +440,7 @@ async function initSession () { _converse.session.browserStorage = new BrowserStorage.session(id); try { await new Promise((success, error) => _converse.session.fetch({success, error})); - if (_converse.jid && _converse.session.get('jid') !== _converse.jid) { + if (_converse.jid && !u.isSameBareJID(_converse.session.get('jid'), _converse.jid)) { _converse.session.clear({'silent': true}); _converse.session.save({'jid': _converse.jid, id}); } @@ -1211,6 +1218,9 @@ _converse.initialize = async function (settings, callback) { }; this.restoreBOSHSession = function (jid_is_required) { + if (!(_converse.connection._proto instanceof Strophe.Bosh)) { + return false; + } /* Tries to restore a cached BOSH session. */ const jid = _converse.session.get('jid'); if (!jid) { @@ -1940,7 +1950,6 @@ const converse = { 'Promise': Promise, 'Strophe': Strophe, '_': _, - 'b64_sha1': b64_sha1, 'dayjs': dayjs, 'sizzle': sizzle, 'utils': u diff --git a/src/headless/converse-mam.js b/src/headless/converse-mam.js index 2384f6324..01bba750e 100644 --- a/src/headless/converse-mam.js +++ b/src/headless/converse-mam.js @@ -1,28 +1,26 @@ // Converse.js (A browser based XMPP chat client) // https://conversejs.org // -// Copyright (c) 2012-2019, Jan-Carel Brand +// Copyright (c) Jan-Carel Brand // Licensed under the Mozilla Public License (MPLv2) // // XEP-0313 Message Archive Management import "./converse-disco"; -import "strophejs-plugin-rsm"; import converse from "./converse-core"; import sizzle from "sizzle"; -const { Promise, Strophe, $iq, _, dayjs } = converse.env; +const { Strophe, $iq, $build, _, dayjs } = converse.env; const u = converse.env.utils; -const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count']; // XEP-0313 Message Archive Management const MAM_ATTRIBUTES = ['with', 'start', 'end']; converse.plugins.add('converse-mam', { - dependencies: ['converse-disco', 'converse-muc'], + dependencies: ['converse-rsm', 'converse-disco', 'converse-muc'], overrides: { // Overrides mentioned here will be picked up by converse.js's @@ -240,12 +238,12 @@ converse.plugins.add('converse-mam', { * Query for archived messages. * * The options parameter can also be an instance of - * Strophe.RSM to enable easy querying between results pages. + * _converse.RSM to enable easy querying between results pages. * * @method _converse.api.archive.query - * @param {(Object|Strophe.RSM)} options Query parameters, either + * @param {(Object|_converse.RSM)} options Query parameters, either * MAM-specific or also for Result Set Management. - * Can be either an object or an instance of Strophe.RSM. + * Can be either an object or an instance of _converse.RSM. * Valid query parameters are: * * `with` * * `start` @@ -258,7 +256,7 @@ converse.plugins.add('converse-mam', { * * `count` * @throws {Error} An error is thrown if the XMPP server responds with an error. * @returns {Promise} A promise which resolves to an object which - * will have keys `messages` and `rsm` which contains a Strophe.RSM object + * will have keys `messages` and `rsm` which contains a _converse.RSM object * on which "next" or "previous" can be called before passing it in again * to this method, to get the next or previous page in the result set. * @@ -347,7 +345,7 @@ converse.plugins.add('converse-mam', { * // repeatedly make a further query to fetch the next batch of messages. * // * // To simplify this usecase for you, the callback method receives not only an array - * // with the returned archived messages, but also a special Strophe.RSM (*Result Set Management*) + * // with the returned archived messages, but also a special _converse.RSM (*Result Set Management*) * // object which contains the query parameters you passed in, as well * // as two utility methods `next`, and `previous`. * // @@ -446,10 +444,10 @@ converse.plugins.add('converse-mam', { } }); stanza.up(); - if (options instanceof Strophe.RSM) { + if (options instanceof _converse.RSM) { stanza.cnode(options.toXML()); - } else if (_.intersection(RSM_ATTRIBUTES, Object.keys(options)).length) { - stanza.cnode(new Strophe.RSM(options).toXML()); + } else if (_.intersection(_converse.RSM_ATTRIBUTES, Object.keys(options)).length) { + stanza.cnode(new _converse.RSM(options).toXML()); } } @@ -476,7 +474,7 @@ converse.plugins.add('converse-mam', { const set = iq.querySelector('set'); let rsm; if (!_.isNull(set)) { - rsm = new Strophe.RSM({'xml': set}); + rsm = new _converse.RSM({'xml': set}); Object.assign(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max']))); } return { diff --git a/src/headless/converse-ping.js b/src/headless/converse-ping.js index de649e51d..b90f77340 100644 --- a/src/headless/converse-ping.js +++ b/src/headless/converse-ping.js @@ -8,11 +8,13 @@ * as specified in XEP-0199 XMPP Ping. */ -import "strophejs-plugin-ping"; import converse from "./converse-core"; // Strophe methods for building stanzas -const { Strophe, _ } = converse.env; +const { Strophe, $iq, _ } = converse.env; + +Strophe.addNamespace('PING', "urn:xmpp:ping"); + converse.plugins.add('converse-ping', { @@ -41,7 +43,13 @@ converse.plugins.add('converse-ping', { if (_.isUndefined(success) ) { success = null; } if (_.isUndefined(error) ) { error = null; } if (_converse.connection) { - _converse.connection.ping.ping(jid, success, error, timeout); + const id = _converse.connection.getUniqueId('ping'); + const iq = $iq({ + 'type': 'get', + 'to': jid, + 'id': id + }).c('ping', {'xmlns': Strophe.NS.PING}); + _converse.connection.sendIQ(iq, success, error, timeout); return true; } return false; @@ -49,7 +57,10 @@ converse.plugins.add('converse-ping', { _converse.pong = function (ping) { _converse.lastStanzaDate = new Date(); - _converse.connection.ping.pong(ping); + const from = ping.getAttribute('from'); + const id = ping.getAttribute('id'); + const iq = $iq({type: 'result', to: from,id: id}); + _converse.connection.sendIQ(iq); return true; }; @@ -57,7 +68,7 @@ converse.plugins.add('converse-ping', { if (!_.isUndefined(_converse.connection.disco)) { _converse.api.disco.own.features.add(Strophe.NS.PING); } - _converse.connection.ping.addPingHandler(_converse.pong); + return _converse.connection.addHandler(_converse.pong, Strophe.NS.PING, "iq", "get"); }; _converse.registerPingHandler = function () { diff --git a/src/headless/converse-rsm.js b/src/headless/converse-rsm.js new file mode 100644 index 000000000..23d845226 --- /dev/null +++ b/src/headless/converse-rsm.js @@ -0,0 +1,72 @@ +// Converse.js (A browser based XMPP chat client) +// https://conversejs.org +// +// Copyright (c) Jan-Carel Brand +// Licensed under the Mozilla Public License (MPLv2) +// +// Some code taken from the Strophe RSM plugin, licensed under the MIT License +// Copyright 2006-2017 Strophe (https://github.com/strophe/strophejs) +// +// XEP-0059 Result Set Management + +import converse from "./converse-core"; + +const { Strophe, $build } = converse.env; + +Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm'); + + +converse.plugins.add('converse-rsm', { + initialize () { + const { _converse } = this; + const RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count']; + _converse.RSM_ATTRIBUTES = RSM_ATTRIBUTES; + + + class RSM { + constructor (options) { + if (typeof options.xml != 'undefined') { + this.fromXMLElement(options.xml); + } else { + for (let ii = 0; ii < RSM_ATTRIBUTES.length; ii++) { + const attrib = RSM_ATTRIBUTES[ii]; + this[attrib] = options[attrib]; + } + } + } + + toXML () { + let xml = $build('set', {xmlns: Strophe.NS.RSM}); + for (let ii = 0; ii < RSM_ATTRIBUTES.length; ii++) { + const attrib = RSM_ATTRIBUTES[ii]; + if (typeof this[attrib] != 'undefined') { + xml = xml.c(attrib).t(this[attrib].toString()).up(); + } + } + return xml.tree(); + } + + next (max) { + return new RSM({max: max, after: this.last}); + } + + previous (max) { + return new RSM({max: max, before: this.first}); + } + + fromXMLElement (xmlElement) { + for (var ii = 0; ii < RSM_ATTRIBUTES.length; ii++) { + const attrib = RSM_ATTRIBUTES[ii]; + const elem = xmlElement.getElementsByTagName(attrib)[0]; + if (typeof elem != 'undefined' && elem !== null) { + this[attrib] = Strophe.getText(elem); + if (attrib == 'first') { + this.index = elem.getAttribute('index'); + } + } + } + } + } + _converse.RSM = RSM; + } +}); diff --git a/src/headless/headless.js b/src/headless/headless.js index 8d5c5de42..c815b8545 100644 --- a/src/headless/headless.js +++ b/src/headless/headless.js @@ -2,16 +2,17 @@ * -------------------- * Any of the following components may be removed if they're not needed. */ -import "./converse-pubsub"; // XEP-0199 XMPP Ping import "./converse-bookmarks"; // XEP-0199 XMPP Ping +import "./converse-caps"; // XEP-0115 Entity Capabilities import "./converse-chatboxes"; // Backbone Collection and Models for chat boxes -import "./converse-disco"; // Service discovery plugin +import "./converse-disco"; // XEP-0030 Service discovery import "./converse-mam"; // XEP-0313 Message Archive Management import "./converse-muc"; // XEP-0045 Multi-user chat import "./converse-ping"; // XEP-0199 XMPP Ping +import "./converse-pubsub"; // XEP-0199 XMPP Ping import "./converse-roster"; // Contacts Roster +import "./converse-rsm"; // XEP-0059 Result Set management import "./converse-vcard"; // XEP-0054 VCard-temp -import "./converse-caps"; // XEP-0115 Entity Capabilities /* END: Removable components */ import converse from "./converse-core"; diff --git a/src/headless/package.json b/src/headless/package.json index b7f6557bf..8c2fa2b3d 100644 --- a/src/headless/package.json +++ b/src/headless/package.json @@ -29,9 +29,7 @@ "jed": "1.1.1", "lodash": "^4.17.11", "pluggable.js": "2.0.1", - "strophe.js": "1.3.3", - "strophejs-plugin-ping": "0.0.3", - "strophejs-plugin-rsm": "0.0.2", + "strophe.js": "strophe/strophejs#44da5faca8baa61c691739d63af8b1dea1d2436c", "twemoji": "^11.0.1", "urijs": "^1.19.1" }