This commit is contained in:
2026-08-02 18:57:40 +02:00
parent 5e5ab8681a
commit 6fa59321c0
5759 changed files with 712133 additions and 66 deletions
@@ -0,0 +1,171 @@
########################################################################
# File name: __init__.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
"""
:mod:`~aioxmpp.misc` -- Miscellaneous XSOs
##########################################
This subpackage bundles XSO definitions for several XEPs. They do not get their
own subpackage because they often only define one or two XSOs without any logic
involved. The XSOs are often intended for re-use by other protocols.
Out of Band Data (:xep:`66`)
============================
.. autoclass:: OOBExtension
.. attribute:: aioxmpp.Message.xep0066_oob
Delayed Delivery (:xep:`203`)
=============================
.. autoclass:: Delay()
.. attribute:: aioxmpp.Message.xep0203_delay
A :class:`Delay` instance which indicates that the message has been
delivered with delay.
Stanza Forwarding (:xep:`297`)
==============================
.. autoclass:: Forwarded()
Last Message Correction (:xep:`308`)
====================================
.. autoclass:: Replace()
.. attribute:: aioxmpp.Message.xep308_replace
A :class:`Replace` instance which indicates that the message is supposed
to replcae another message.
Chat Markers (:xep:`333`)
=========================
.. autoclass:: ReceivedMarker
.. autoclass:: DisplayedMarker
.. autoclass:: AcknowledgedMarker
.. attribute:: aioxmpp.Message.xep0333_marker
JSON Containers (:xep:`335`)
============================
:xep:`335` defines a standard way to transport JSON data in XMPP. The
:class:`JSONContainer` is an XSO class which represents the ``<json/>`` element
specified in :xep:`335`.
:mod:`aioxmpp` also provides an :class:`~aioxmpp.xso.AbstractElementType`
called :class:`JSONContainerType` which can be used to extract JSON data from
an element using the :class:`JSONContainer` format.
.. autoclass:: JSONContainer
.. autoclass:: JSONContainerType
Unique and Stable Stanza IDs (:xep:`359`)
=========================================
:xep:`359` defines a way to attach additional IDs to a stanza, allowing
entities on the path from the sender to the recipient to signal under which ID
they know a specific stanza. This is most notably used by MAM (:xep:`313`).
.. autoclass:: StanzaID(*[, id_][, by])
.. autoclass:: OriginID()
.. attribute:: aioxmpp.Message.xep0359_stanza_ids
This is a mapping which associates the `by` value of a stanza ID with the
list of IDs (as strings or :data:`None` if the attribute was not set)
assigned by that entity. Normally, there should only ever be a single ID
assigned, but misbehaving parties on the path could inject IDs for other
entities.
To allow code handling the ID selection deterministically in such cases,
all IDs are exposed.
.. attribute:: aioxmpp.Message.xep0359_origin_id
The :class:`OriginID` object, if any.
Pre-Authenticated Roster Subcription (:xep:`379`)
=================================================
.. autoclass:: Preauth
.. attribute:: aioxmpp.Presence.xep0379_preauth
The pre-auth element associate with a subscription request.
Current Jabber OpenPGP Usage (:xep:`27`)
========================================
.. autoclass:: OpenPGPEncrypted
.. autoclass:: OpenPGPSigned
.. attribute:: aioxmpp.Message.xep0027_encrypted
Instance of :class:`OpenPGPEncrypted`, if present.
.. note::
:xep:`27` does not specify the signing of messages.
.. attribute:: aioxmpp.Presence.xep0027_signed
Instance of :class:`OpenPGPSigned`, if present.
"""
from .delay import Delay # NOQA: F401
from .lmc import Replace # NOQA: F401
from .forwarding import Forwarded # NOQA: F401
from .oob import OOBExtension # NOQA: F401
from .markers import ( # NOQA: F401
ReceivedMarker,
DisplayedMarker,
AcknowledgedMarker,
)
from .json import JSONContainer, JSONContainerType # NOQA: F401
from .pars import Preauth # NOQA: F401
from .openpgp_legacy import (
OpenPGPEncrypted,
OpenPGPSigned,
)
from .stanzaid import ( # NOQA: F401
StanzaID,
OriginID,
)
@@ -0,0 +1,74 @@
########################################################################
# File name: delay.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso as xso
from aioxmpp.utils import namespaces
from ..stanza import Message
namespaces.xep0203_delay = "urn:xmpp:delay"
class Delay(xso.XSO):
"""
A marker indicating delayed delivery of a stanza.
.. attribute:: from_
The address as :class:`aioxmpp.JID` of the entity where the stanza was
delayed. May be :data:`None`.
.. attribute:: stamp
The timestamp (as :class:`datetime.datetime`) at which the stanza was
originally sent or intended to be sent.
.. attribute:: reason
The reason for which the stanza was delayed or :data:`None`.
.. warning::
Please take the security considerations of :xep:`203` into account.
"""
TAG = namespaces.xep0203_delay, "delay"
from_ = xso.Attr(
"from",
type_=xso.JID(),
default=None,
)
stamp = xso.Attr(
"stamp",
type_=xso.DateTime(),
)
reason = xso.Text(
default=None
)
Message.xep0203_delay = xso.ChildList([Delay])
@@ -0,0 +1,61 @@
########################################################################
# File name: forwarding.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso as xso
from ..stanza import IQ, Message, Presence
from .delay import Delay
from aioxmpp.utils import namespaces
namespaces.xep0297_forward = "urn:xmpp:forward:0"
class Forwarded(xso.XSO):
"""
Wrap a stanza for forwarding.
.. attribute:: delay
If not :data:`None`, this is a :class:`aioxmpp.misc.Delay` XSO which
indicates the timestamp at which the wrapped stanza was originally sent.
.. attribute:: stanza
The forwarded stanza.
.. warning::
Please take the security considerations of :xep:`297` and the protocol
using this XSO into account.
"""
TAG = namespaces.xep0297_forward, "forwarded"
delay = xso.Child([Delay])
stanza = xso.Child(
[
Message,
IQ,
Presence,
]
)
@@ -0,0 +1,81 @@
########################################################################
# File name: json.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso as xso
import aioxmpp.pubsub.xso
from aioxmpp.utils import namespaces
namespaces.xep0335_json = "urn:xmpp:json:0"
@aioxmpp.pubsub.xso.as_payload_class
class JSONContainer(xso.XSO):
"""
XSO which represents the JSON container specified in :xep:`335`.
This is a full XSO and not an attribute descriptor. It is registered as
pubsub payload by default.
"""
TAG = (namespaces.xep0335_json, "json")
json_data = xso.Text(
type_=xso.JSON(),
)
def __init__(self, json_data=None):
super().__init__()
self.json_data = json_data
class JSONContainerType(xso.AbstractElementType):
"""
XSO element type to unwrap JSON container payloads specified in :xep:`335`.
This type is designed to be used with the ChildValue* descriptors provided
in :mod:`aioxmpp.xso`, for example with :class:`aioxmpp.xso.ChildValue` or
:class:`aioxmpp.xso.ChildValueList`.
.. code:: python
class HTTPRESTMessage(aioxmpp.xso.XSO):
TAG = ("https://neverdothis.example", "http-rest")
method = aioxmpp.xso.Attr("method")
payload = aioxmpp.xso.ChildValue(
type_=aioxmpp.misc.JSONContainerType
)
"""
@classmethod
def get_xso_types(cls):
return [JSONContainer]
@classmethod
def unpack(cls, v):
return v.json_data
@classmethod
def pack(cls, v):
return JSONContainer(v)
@@ -0,0 +1,48 @@
########################################################################
# File name: lmc.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso as xso
from aioxmpp.utils import namespaces
from ..stanza import Message
namespaces.xep0308_replace = "urn:xmpp:message-correct:0"
class Replace(xso.XSO):
"""
A marker indicating that the stanza is the correction of another one
.. attribute:: id_
The identifier of the stanza to correct.
"""
TAG = namespaces.xep0308_replace, "replace"
id_ = xso.Attr(
"id",
)
Message.xep0308_replace = xso.Child([Replace])
@@ -0,0 +1,57 @@
########################################################################
# File name: markers.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso
from ..stanza import Message
from aioxmpp.utils import namespaces
namespaces.xep0333_markers = "urn:xmpp:chat-markers:0"
class Marker(aioxmpp.xso.XSO):
id_ = aioxmpp.xso.Attr(
"id"
)
class ReceivedMarker(Marker):
TAG = (namespaces.xep0333_markers, "received")
class DisplayedMarker(Marker):
TAG = (namespaces.xep0333_markers, "displayed")
class AcknowledgedMarker(Marker):
TAG = (namespaces.xep0333_markers, "acknowledged")
Message.xep0333_marker = aioxmpp.xso.Child([
ReceivedMarker,
DisplayedMarker,
AcknowledgedMarker,
])
Message.xep0333_markable = aioxmpp.xso.ChildFlag(
(namespaces.xep0333_markers, "markable"),
)
@@ -0,0 +1,39 @@
########################################################################
# File name: oob.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso as xso
from ..stanza import Message
from aioxmpp.utils import namespaces
namespaces.xep0066_oob_x = "jabber:x:oob"
class OOBExtension(xso.XSO):
TAG = namespaces.xep0066_oob_x, "x"
url = xso.ChildText(
(namespaces.xep0066_oob_x, "url")
)
Message.xep0066_oob = xso.Child([OOBExtension])
@@ -0,0 +1,87 @@
########################################################################
# File name: openpgp_legacy.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.stanza
import aioxmpp.xso
from aioxmpp.utils import namespaces
namespaces.xep0027_encrypted = "jabber:x:encrypted"
namespaces.xep0027_signed = "jabber:x:signed"
class OpenPGPEncrypted(aioxmpp.xso.XSO):
"""
Wrapper around an ASCII-armored OpenPGP encrypted blob.
.. warning::
Please see the security considerations of :xep:`27` before making use
of this protocol. Consider implementation of :xep:`373` instead.
See :xep:`27` for details.
.. attribute:: payload
The character data of the wrapper element.
.. note::
While the wire format *is* base64, since the base64 output is
intended to be passed verbatim to OpenPGP, the payload is declared
as normal string and aioxmpp will *not* de-base64 it for you (and
vice versa).
"""
TAG = namespaces.xep0027_encrypted, "x"
payload = aioxmpp.xso.Text()
class OpenPGPSigned(aioxmpp.xso.XSO):
"""
Wrapper around an ASCII-armored OpenPGP signed blob.
.. warning::
Please see the security considerations of :xep:`27` before making use
of this protocol. Consider implementation of :xep:`373` instead.
See :xep:`27` for details.
.. attribute:: payload
The character data of the wrapper element.
.. note::
While the wire format *is* base64, since the base64 output is
intended to be passed verbatim to OpenPGP, the payload is declared
as normal string and aioxmpp will *not* de-base64 it for you (and
vice versa).
"""
TAG = namespaces.xep0027_signed, "x"
payload = aioxmpp.xso.Text()
aioxmpp.stanza.Message.xep0027_encrypted = aioxmpp.xso.Child([OpenPGPEncrypted])
aioxmpp.stanza.Message.xep0027_signed = aioxmpp.xso.Child([OpenPGPSigned])
@@ -0,0 +1,48 @@
########################################################################
# File name: pars.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso as xso
from aioxmpp.utils import namespaces
from ..stanza import Presence
namespaces.xep0379_pars = "urn:xmpp:pars:0"
class Preauth(xso.XSO):
"""
The preauth element for :xep:`Pre-Authenticated Roster Subcription <379>`.
.. attribute:: token
The pre-auth token associated with this subscription request.
"""
TAG = namespaces.xep0379_pars, "preauth"
token = xso.Attr(
"token",
type_=xso.String(),
)
Presence.xep0379_preauth = xso.Child([Preauth])
@@ -0,0 +1,88 @@
########################################################################
# File name: delay.py
# This file is part of: aioxmpp
#
# LICENSE
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program. If not, see
# <http://www.gnu.org/licenses/>.
#
########################################################################
import aioxmpp.xso as xso
from aioxmpp.utils import namespaces
from ..stanza import Message
namespaces.xep0359_stanza_ids = "urn:xmpp:sid:0"
class StanzaID(xso.XSO):
"""
Represent a :xep:`359` Stanza ID.
:param id_: The stanza ID to set
:param by: The entity which has set the stanza ID
:type by: :class:`aioxmpp.JID`
.. attribute:: id_
The assigned stanza ID.
.. attribute:: by
The entity who has assigned the stanza ID.
.. warning::
Stanza IDs may be spoofed. Please take the security considerations of
:xep:`359` and the protocols using it into account.
"""
TAG = (namespaces.xep0359_stanza_ids, "stanza-id")
id_ = xso.Attr("id", default=None)
by = xso.Attr("by", type_=xso.JID(), default=None)
def __init__(self, *, id_=None, by=None, **kwargs):
super().__init__(**kwargs)
self.id_ = id_
self.by = by
class OriginID(xso.XSO):
"""
Represent a :xep:`359` Origin ID.
:param id_: The origin ID to set
.. attribute:: id_
The assigned origin ID.
.. warning::
Origin IDs may be spoofed. Please take the security considerations of
:xep:`359` and the protocols using it into account.
"""
TAG = (namespaces.xep0359_stanza_ids, "origin-id")
id_ = xso.Attr("id", default=None)
def __init__(self, id_=None):
super().__init__()
self.id_ = id_
Message.xep0359_stanza_ids = xso.ChildList([StanzaID])
Message.xep0359_origin_id = xso.Child([OriginID])