diff --git a/CHANGES.md b/CHANGES.md index bd6284a77..a68679bfc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,14 +6,15 @@ configuration settings should now be accessed via `_converse.api.settings.get` and not directly on the `_converse` object. Soon we'll deprecate the latter, so prepare now. -- #515 Add support for XEP-0050 Ad-Hoc commands - #1313: Stylistic improvements to the send button +- #1481: MUC OMEMO: Error No record for device - #1490: Busy-loop when fetching registration form fails - #1535: Add option to destroy a MUC - #1715: Update chat state notification after receiving a message correction. - #1793: Send button doesn't appear in Firefox in 1:1 chats - #1820: Set focus on jid field after controlbox is loaded - #1822: Don't log error if user has no bookmarks +- #515 Add support for XEP-0050 Ad-Hoc commands - #1823: New config options [muc_roomid_policy](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy) and [muc_roomid_policy_hint](https://conversejs.org/docs/html/configuration.html#muc-roomid-policy-hint) - #1826: A user can now add himself as a contact diff --git a/src/converse-omemo.js b/src/converse-omemo.js index 1fd0eb764..7a3fcc43f 100644 --- a/src/converse-omemo.js +++ b/src/converse-omemo.js @@ -172,7 +172,17 @@ async function decryptPrekeyWhisperMessage (attrs) { } async function decryptWhisperMessage (attrs) { - const session_cipher = getSessionCipher(attrs.from, parseInt(attrs.encrypted.device_id, 10)); + const from_jid = attrs.from_muc ? attrs.from_real_jid : attrs.from; + if (!from_jid) { + Object.assign(attrs, { + 'error_text': __("Sorry, could not decrypt a received OMEMO because we don't have the JID for that user."), + 'error_type': 'Decryption', + 'is_ephemeral': false, + 'is_error': true, + 'type': 'error', + }); + } + const session_cipher = getSessionCipher(from_jid, parseInt(attrs.encrypted.device_id, 10)); const key = u.base64ToArrayBuffer(attrs.encrypted.key); try { const key_and_tag = await session_cipher.decryptWhisperMessage(key, 'binary') diff --git a/src/headless/converse-muc.js b/src/headless/converse-muc.js index 3e954e578..e85b285fd 100644 --- a/src/headless/converse-muc.js +++ b/src/headless/converse-muc.js @@ -2069,6 +2069,10 @@ converse.plugins.add('converse-muc', { } }, + /** + * Handle a presence stanza that disconnects the user from the MUC + * @param { XMLElement } stanza + */ handleDisconnection (stanza) { const is_self = stanza.querySelector("status[code='110']") !== null; const x = sizzle(`x[xmlns="${Strophe.NS.MUC_USER}"]`, stanza).pop(); @@ -2600,6 +2604,11 @@ converse.plugins.add('converse-muc', { api.trigger('membersFetched'); }, + /** + * @typedef { Object} OccupantData + * @property { String } [jid] + * @property { String } [nick] + */ /** * Try to find an existing occupant based on the passed in * data object. @@ -2609,7 +2618,7 @@ converse.plugins.add('converse-muc', { * but should have at least one or the other. * @private * @method _converse.ChatRoomOccupants#findOccupant - * @param { Object } data + * @param { OccupantData } data */ findOccupant (data) { const jid = Strophe.getBareJidFromJid(data.jid); diff --git a/src/headless/utils/stanza.js b/src/headless/utils/stanza.js index 5bed72783..413461d58 100644 --- a/src/headless/utils/stanza.js +++ b/src/headless/utils/stanza.js @@ -567,6 +567,7 @@ const st = { } const delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(); const from = stanza.getAttribute('from'); + const nick = Strophe.unescapeNode(Strophe.getResourceFromJid(from)); const marker = st.getChatMarker(stanza); const now = (new Date()).toISOString(); /** @@ -594,8 +595,9 @@ const st = { * @property { String } error_condition - The defined error condition * @property { String } error_text - The error text received from the server * @property { String } error_type - The type of error received from the server - * @property { String } from - The sender JID + * @property { String } from - The sender JID (${muc_jid}/${nick}) * @property { String } from_muc - The JID of the MUC from which this message was sent + * @property { String } from_real_jid - The real JID of the sender, if available * @property { String } fullname - The full name of the sender * @property { String } marker - The XEP-0333 Chat Marker value * @property { String } marker_id - The `id` attribute of a XEP-0333 chat marker @@ -623,9 +625,11 @@ const st = { */ let attrs = Object.assign({ from, + nick, 'body': stanza.querySelector('body')?.textContent?.trim(), 'chat_state': getChatState(stanza), 'from_muc': Strophe.getBareJidFromJid(from), + 'from_real_jid': chatbox.occupants.findOccupant({nick})?.get('jid'), 'is_archived': st.isArchived(original_stanza), 'is_carbon': isCarbon(original_stanza), 'is_delayed': !!delay, @@ -634,7 +638,6 @@ const st = { 'is_marker': !!marker, 'marker_id': marker && marker.getAttribute('id'), 'msgid': stanza.getAttribute('id') || original_stanza.getAttribute('id'), - 'nick': Strophe.unescapeNode(Strophe.getResourceFromJid(from)), 'receipt_id': getReceiptId(stanza), 'received': (new Date()).toISOString(), 'references': getReferences(stanza), @@ -654,6 +657,7 @@ const st = { getEncryptionAttributes(stanza, _converse) ); + await api.emojis.initialize(); attrs = Object.assign({ 'is_only_emojis': attrs.body ? u.isOnlyEmojis(attrs.body) : false,