1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
#
# This file is part of nbxmpp.
#
# SPDX-License-Identifier: GPL-3.0-or-later
import logging
from nbxmpp.modules.delay import parse_delay
from nbxmpp.namespaces import Namespace
from nbxmpp.protocol import InvalidFrom
from nbxmpp.protocol import InvalidStanza
from nbxmpp.protocol import JID
from nbxmpp.protocol import Message
from nbxmpp.protocol import NodeProcessed
from nbxmpp.protocol import Protocol
from nbxmpp.structs import CarbonData
from nbxmpp.structs import MAMData
log = logging.getLogger("nbxmpp.m.misc")
def unwrap_carbon(
stanza: Protocol, own_jid: JID
) -> tuple[Message | Protocol, CarbonData | None]:
carbon = stanza.getTag("received", namespace=Namespace.CARBONS)
if carbon is None:
carbon = stanza.getTag("sent", namespace=Namespace.CARBONS)
if carbon is None:
return stanza, None
# Carbon must be from our bare jid
if stanza.getFrom() != own_jid.new_as_bare():
raise InvalidFrom("Invalid from: %s" % stanza.getAttr("from"))
forwarded = carbon.getTag("forwarded", namespace=Namespace.FORWARD)
message = Message(node=forwarded.getTag("message"))
type_ = carbon.getName()
# Fill missing to/from
to = message.getTo()
if to is None:
message.setTo(own_jid.bare)
frm = message.getFrom()
if frm is None:
message.setFrom(own_jid.bare)
if type_ == "received":
if message.getFrom().bare_match(own_jid):
# Drop 'received' Carbons from ourself, we already
# got the message with the 'sent' Carbon or via the
# message itself
raise NodeProcessed('Drop "received"-Carbon from ourself')
if message.getTag("x", namespace=Namespace.MUC_USER) is not None:
# A MUC broadcasts messages sent to us to all resources
# there is no need to process the received carbon
raise NodeProcessed('Drop MUC-PM "received"-Carbon')
return message, CarbonData(type=type_)
def unwrap_mam(
stanza: Protocol, own_jid: JID
) -> tuple[Message | Protocol, MAMData | None]:
result = stanza.getTag("result", namespace=Namespace.MAM_2)
if result is None:
result = stanza.getTag("result", namespace=Namespace.MAM_1)
if result is None:
return stanza, None
query_id = result.getAttr("queryid")
if query_id is None:
log.warning("No queryid on MAM message")
log.warning(stanza)
raise InvalidStanza
id_ = result.getAttr("id")
if id_ is None:
log.warning("No id on MAM message")
log.warning(stanza)
raise InvalidStanza
forwarded = result.getTag("forwarded", namespace=Namespace.FORWARD)
message = Message(node=forwarded.getTag("message"))
# Fill missing to/from
to = message.getTo()
if to is None:
message.setTo(own_jid.bare)
frm = message.getFrom()
if frm is None:
message.setFrom(own_jid.bare)
# Timestamp parsing
# Most servers dont set the 'from' attr, so we cant check for it
delay_timestamp = parse_delay(forwarded, epoch=True)
if delay_timestamp is None:
log.warning("No timestamp on MAM message")
log.warning(stanza)
raise InvalidStanza
return message, MAMData(
id=id_,
query_id=query_id,
archive=stanza.getFrom(),
namespace=result.getNamespace(),
timestamp=delay_timestamp,
)
def build_xhtml_body(xhtml: str, xmllang: str | None = None) -> str | None:
try:
if xmllang is not None:
body = '<body xmlns="%s" xml:lang="%s">%s</body>' % (
Namespace.XHTML,
xmllang,
xhtml,
)
else:
body = '<body xmlns="%s">%s</body>' % (Namespace.XHTML, xhtml)
except Exception as error:
log.error("Error while building xhtml node: %s", error)
return None
return body
|