(stanza)
| 38 | * @returns {Promise<import('../../shared/types.ts').MessageAttributes|StanzaParseError>} |
| 39 | */ |
| 40 | export async function parseMessage(stanza) { |
| 41 | throwErrorIfInvalidForward(stanza); |
| 42 | |
| 43 | let to_jid = stanza.getAttribute('to'); |
| 44 | const to_resource = Strophe.getResourceFromJid(to_jid); |
| 45 | const resource = _converse.session.get('resource'); |
| 46 | if (api.settings.get('filter_by_resource') && to_resource && to_resource !== resource) { |
| 47 | return new StanzaParseError(stanza, `Ignoring incoming message intended for a different resource: ${to_jid}`); |
| 48 | } |
| 49 | |
| 50 | const bare_jid = _converse.session.get('bare_jid'); |
| 51 | const original_stanza = stanza; |
| 52 | let from_jid = stanza.getAttribute('from') || bare_jid; |
| 53 | if (isCarbon(stanza)) { |
| 54 | if (from_jid === bare_jid) { |
| 55 | const selector = `[xmlns="${Strophe.NS.CARBONS}"] > forwarded[xmlns="${Strophe.NS.FORWARD}"] > message`; |
| 56 | stanza = sizzle(selector, stanza).pop(); |
| 57 | to_jid = stanza.getAttribute('to'); |
| 58 | from_jid = stanza.getAttribute('from'); |
| 59 | } else { |
| 60 | // Prevent message forging via carbons: https://xmpp.org/extensions/xep-0280.html#security |
| 61 | rejectMessage(stanza, 'Rejecting carbon from invalid JID'); |
| 62 | return new StanzaParseError(stanza, `Rejecting carbon from invalid JID ${to_jid}`); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | const is_archived = isArchived(stanza); |
| 67 | if (is_archived) { |
| 68 | if (from_jid === bare_jid) { |
| 69 | const selector = `[xmlns="${Strophe.NS.MAM}"] > forwarded[xmlns="${Strophe.NS.FORWARD}"] > message`; |
| 70 | stanza = sizzle(selector, stanza).pop(); |
| 71 | to_jid = stanza.getAttribute('to'); |
| 72 | from_jid = stanza.getAttribute('from'); |
| 73 | } else { |
| 74 | return new StanzaParseError( |
| 75 | stanza, |
| 76 | `Invalid Stanza: alleged MAM message from ${stanza.getAttribute('from')}`, |
| 77 | ); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | const from_bare_jid = Strophe.getBareJidFromJid(from_jid); |
| 82 | const is_me = from_bare_jid === bare_jid; |
| 83 | if (is_me && to_jid === null) { |
| 84 | return new StanzaParseError( |
| 85 | stanza, |
| 86 | `Don't know how to handle message stanza without 'to' attribute. ${stanza.outerHTML}`, |
| 87 | ); |
| 88 | } |
| 89 | |
| 90 | const is_headline = isHeadline(stanza); |
| 91 | const is_server_message = isServerMessage(stanza); |
| 92 | let contact, contact_jid; |
| 93 | if (!is_headline && !is_server_message) { |
| 94 | contact_jid = is_me ? Strophe.getBareJidFromJid(to_jid) : from_bare_jid; |
| 95 | contact = await api.contacts.get(contact_jid); |
| 96 | if (contact === undefined && !api.settings.get('allow_non_roster_messaging')) { |
| 97 | log.error(stanza); |
no test coverage detected