annotate libervia/backend/plugins/plugin_xep_0106.py @ 4306:94e0968987cd

plugin XEP-0033: code modernisation, improve delivery, data validation: - Code has been rewritten using Pydantic models and `async` coroutines for data validation and cleaner element parsing/generation. - Delivery has been completely rewritten. It now works even if server doesn't support multicast, and send to local multicast service first. Delivering to local multicast service first is due to bad support of XEP-0033 in server (notably Prosody which has an incomplete implementation), and the current impossibility to detect if a sub-domain service handles fully multicast or only for local domains. This is a workaround to have a good balance between backward compatilibity and use of bandwith, and to make it work with the incoming email gateway implementation (the gateway will only deliver to entities of its own domain). - disco feature checking now uses `async` corountines. `host` implementation still use Deferred return values for compatibility with legacy code. rel 450
author Goffi <goffi@goffi.org>
date Thu, 26 Sep 2024 16:12:01 +0200
parents 060d695ae98e
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
1 #!/usr/bin/env python3
3137
559a625a236b fixed shebangs
Goffi <goffi@goffi.org>
parents: 3136
diff changeset
2
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
3
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # SAT plugin for Explicit Message Encryption
3479
be6d91572633 date update
Goffi <goffi@goffi.org>
parents: 3450
diff changeset
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
6
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # This program is free software: you can redistribute it and/or modify
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # (at your option) any later version.
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
11
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # This program is distributed in the hope that it will be useful,
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # GNU Affero General Public License for more details.
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
16
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
19
4071
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
20 from libervia.backend.core.i18n import _
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
21 from libervia.backend.core.constants import Const as C
4b842c1fb686 refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents: 4037
diff changeset
22 from libervia.backend.core.log import getLogger
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
23 from twisted.words.protocols.jabber import xmlstream
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
24 from zope.interface import implementer
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
25 from wokkel import disco
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
26
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
27 log = getLogger(__name__)
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
28
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
29 PLUGIN_INFO = {
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
30 C.PI_NAME: "JID Escaping",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
31 C.PI_IMPORT_NAME: "XEP-0106",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
32 C.PI_TYPE: "XEP",
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
33 C.PI_MODES: C.PLUG_MODE_BOTH,
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
34 C.PI_PROTOCOLS: ["XEP-0106"],
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
35 C.PI_DEPENDENCIES: [],
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
36 C.PI_MAIN: "XEP_0106",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
37 C.PI_HANDLER: "yes",
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
38 C.PI_DESCRIPTION: _("""(Un)escape JID to use disallowed chars in local parts"""),
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
39 }
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
40
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
41 NS_JID_ESCAPING = r"jid\20escaping"
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
42 ESCAPE_MAP = {
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
43 " ": r"\20",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
44 '"': r"\22",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
45 "&": r"\26",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
46 "'": r"\27",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
47 "/": r"\2f",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
48 ":": r"\3a",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
49 "<": r"\3c",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
50 ">": r"\3e",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
51 "@": r"\40",
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
52 "\\": r"\5c",
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
53 }
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
54
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
55
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
56 class XEP_0106(object):
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
57
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
58 def __init__(self, host):
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
59 self.reverse_map = {v: k for k, v in ESCAPE_MAP.items()}
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
60
4037
524856bd7b19 massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
61 def get_handler(self, client):
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
62 return XEP_0106_handler()
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
63
4298
060d695ae98e plugin XEP-0106, tools (common/email): type hints.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
64 def escape(self, text) -> str:
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
65 """Escape text
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
66
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
67 @param text(unicode): text to escape
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
68 @return (unicode): escaped text
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
69 @raise ValueError: text can't be escaped
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
70 """
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
71 if not text or text[0] == " " or text[-1] == " ":
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
72 raise ValueError("text must not be empty, or start or end with a whitespace")
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
73 escaped = []
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
74 for c in text:
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
75 if c in ESCAPE_MAP:
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
76 escaped.append(ESCAPE_MAP[c])
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
77 else:
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
78 escaped.append(c)
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
79 return "".join(escaped)
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
80
4298
060d695ae98e plugin XEP-0106, tools (common/email): type hints.
Goffi <goffi@goffi.org>
parents: 4270
diff changeset
81 def unescape(self, escaped) -> str:
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
82 """Unescape text
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
83
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
84 @param escaped(unicode): text to unescape
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
85 @return (unicode): unescaped text
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
86 @raise ValueError: text can't be unescaped
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
87 """
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
88 if not escaped or escaped.startswith(r"\27") or escaped.endswith(r"\27"):
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
89 raise ValueError(
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
90 "escaped value must not be empty, or start or end with a "
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
91 f"whitespace: rejected value is {escaped!r}"
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
92 )
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
93 unescaped = []
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
94 idx = 0
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
95 while idx < len(escaped):
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
96 char_seq = escaped[idx : idx + 3]
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
97 if char_seq in self.reverse_map:
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
98 unescaped.append(self.reverse_map[char_seq])
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
99 idx += 3
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
100 else:
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
101 unescaped.append(escaped[idx])
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
102 idx += 1
4270
0d7bb4df2343 Reformatted code base using black.
Goffi <goffi@goffi.org>
parents: 4071
diff changeset
103 return "".join(unescaped)
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
104
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
105
3028
ab2696e34d29 Python 3 port:
Goffi <goffi@goffi.org>
parents: 2922
diff changeset
106 @implementer(disco.IDisco)
2922
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
107 class XEP_0106_handler(xmlstream.XMPPHandler):
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
108
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
109 def getDiscoInfo(self, requestor, target, nodeIdentifier=""):
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
110 return [disco.DiscoFeature(NS_JID_ESCAPING)]
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
111
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
112 def getDiscoItems(self, requestor, target, nodeIdentifier=""):
28c969432557 plugin XEP-0106: jid escaping implementation
Goffi <goffi@goffi.org>
parents:
diff changeset
113 return []