annotate sat/plugins/plugin_xep_0447.py @ 4002:5245b675f7ad

plugin XEP-0313: don't wait for MAM to be retrieved in connection workflow: MAM retrieval can be long, and can be done after connection, message just need to be sorted when being inserted (i.e. frontends must do insort). To avoid blocking connection for too long and result in bad UX and timeout risk, one2one MAM message are not retrieved in background.
author Goffi <goffi@goffi.org>
date Fri, 10 Mar 2023 17:22:45 +0100
parents 0ff265725489
children 78b5f356900c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # Copyright (C) 2009-2022 Jérôme Poisson (goffi@goffi.org)
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
4
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
5 # This program is free software: you can redistribute it and/or modify
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # it under the terms of the GNU Affero General Public License as published by
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # the Free Software Foundation, either version 3 of the License, or
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # (at your option) any later version.
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
9
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
10 # This program is distributed in the hope that it will be useful,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # GNU Affero General Public License for more details.
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
14
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 # You should have received a copy of the GNU Affero General Public License
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
17
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
18 from collections import namedtuple
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
19 from functools import partial
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
20 import mimetypes
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
21 from pathlib import Path
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
22 from typing import Any, Callable, Dict, List, Optional, Tuple, Union
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
23
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
24 import treq
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
25 from twisted.internet import defer
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from twisted.words.xish import domish
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
27
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
28 from sat.core import exceptions
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 from sat.core.constants import Const as C
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
30 from sat.core.core_types import SatXMPPEntity
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 from sat.core.i18n import _
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 from sat.core.log import getLogger
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
33 from sat.tools import stream
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
34 from sat.tools.web import treq_client_no_ssl
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
35
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 log = getLogger(__name__)
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
37
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
38
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 PLUGIN_INFO = {
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 C.PI_NAME: "Stateless File Sharing",
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 C.PI_IMPORT_NAME: "XEP-0447",
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 C.PI_TYPE: "XEP",
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 C.PI_MODES: C.PLUG_MODE_BOTH,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 C.PI_PROTOCOLS: ["XEP-0447"],
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
45 C.PI_DEPENDENCIES: ["XEP-0103", "XEP-0334", "XEP-0446", "ATTACH", "DOWNLOAD"],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
46 C.PI_RECOMMENDATIONS: ["XEP-0363"],
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 C.PI_MAIN: "XEP_0447",
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 C.PI_HANDLER: "no",
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 C.PI_DESCRIPTION: _("""Implementation of XEP-0447 (Stateless File Sharing)"""),
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 }
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
51
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 NS_SFS = "urn:xmpp:sfs:0"
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
53 SourceHandler = namedtuple("SourceHandler", ["callback", "encrypted"])
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
54
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
55
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 class XEP_0447:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 namespace = NS_SFS
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
58
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 def __init__(self, host):
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
60 self.host = host
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 log.info(_("XEP-0447 (Stateless File Sharing) plugin initialization"))
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 host.registerNamespace("sfs", NS_SFS)
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
63 self._sources_handlers = {}
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 self._u = host.plugins["XEP-0103"]
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
65 self._hints = host.plugins["XEP-0334"]
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 self._m = host.plugins["XEP-0446"]
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
67 self._http_upload = host.plugins.get("XEP-0363")
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
68 self._attach = host.plugins["ATTACH"]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
69 self._attach.register(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
70 self.can_handle_attachment, self.attach, priority=1000
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
71 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
72 self.register_source_handler(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
73 self._u.namespace, "url-data", self._u.parse_url_data_elt
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
74 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
75 host.plugins["DOWNLOAD"].register_download_handler(self._u.namespace, self.download)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
76 host.trigger.add("messageReceived", self._message_received_trigger)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
77
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
78 def register_source_handler(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
79 self, namespace: str, element_name: str,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
80 callback: Callable[[domish.Element], Dict[str, Any]],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
81 encrypted: bool = False
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
82 ) -> None:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
83 """Register a handler for file source
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
84
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
85 @param namespace: namespace of the element supported
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
86 @param element_name: name of the element supported
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
87 @param callback: method to call to parse the element
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
88 get the matching element as argument, must return the parsed data
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
89 @param encrypted: if True, the source is encrypted (the transmitting channel
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
90 should then be end2end encrypted to avoir leaking decrypting data to servers).
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
91 """
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
92 key = (namespace, element_name)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
93 if key in self._sources_handlers:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
94 raise exceptions.ConflictError(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
95 f"There is already a resource handler for namespace {namespace!r} and "
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
96 f"name {element_name!r}"
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
97 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
98 self._sources_handlers[key] = SourceHandler(callback, encrypted)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
99
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
100 async def download(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
101 self,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
102 client: SatXMPPEntity,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
103 attachment: Dict[str, Any],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
104 source: Dict[str, Any],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
105 dest_path: Union[Path, str],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
106 extra: Optional[Dict[str, Any]] = None
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
107 ) -> Tuple[str, defer.Deferred]:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
108 # TODO: handle url-data headers
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
109 if extra is None:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
110 extra = {}
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
111 try:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
112 download_url = source["url"]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
113 except KeyError:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
114 raise ValueError(f"{source} has missing URL")
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
115
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
116 if extra.get('ignore_tls_errors', False):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
117 log.warning(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
118 "TLS certificate check disabled, this is highly insecure"
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
119 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
120 treq_client = treq_client_no_ssl
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
121 else:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
122 treq_client = treq
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
123
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
124 try:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
125 file_size = int(attachment["size"])
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
126 except (KeyError, ValueError):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
127 head_data = await treq_client.head(download_url)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
128 file_size = int(head_data.headers.getRawHeaders('content-length')[0])
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
129
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
130 file_obj = stream.SatFile(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
131 self.host,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
132 client,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
133 dest_path,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
134 mode="wb",
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
135 size = file_size,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
136 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
137
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
138 progress_id = file_obj.uid
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
139
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
140 resp = await treq_client.get(download_url, unbuffered=True)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
141 if resp.code == 200:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
142 d = treq.collect(resp, file_obj.write)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
143 d.addCallback(lambda __: file_obj.close())
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
144 else:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
145 d = defer.Deferred()
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
146 self.host.plugins["DOWNLOAD"].errback_download(file_obj, d, resp)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
147 return progress_id, d
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
148
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
149 async def can_handle_attachment(self, client, data):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
150 if self._http_upload is None:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
151 return False
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
152 try:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
153 await self._http_upload.getHTTPUploadEntity(client)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
154 except exceptions.NotFound:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
155 return False
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
156 else:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
157 return True
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
158
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
159 def get_sources_elt(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
160 self,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
161 children: Optional[List[domish.Element]] = None
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
162 ) -> domish.Element:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
163 """Generate <sources> element"""
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
164 sources_elt = domish.Element((NS_SFS, "sources"))
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
165 if children:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
166 for child in children:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
167 sources_elt.addChild(child)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
168 return sources_elt
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
169
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 def get_file_sharing_elt(
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 self,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
172 sources: List[Dict[str, Any]],
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 disposition: Optional[str] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 name: Optional[str] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
175 media_type: Optional[str] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
176 desc: Optional[str] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 size: Optional[int] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 file_hash: Optional[Tuple[str, str]] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 date: Optional[Union[float, int]] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 width: Optional[int] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 height: Optional[int] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 length: Optional[int] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 thumbnail: Optional[str] = None,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 **kwargs,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 ) -> domish.Element:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
186 """Generate the <file-sharing/> element
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
187
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 @param extra: extra metadata describing how to access the URL
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 @return: ``<sfs/>`` element
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 """
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 file_sharing_elt = domish.Element((NS_SFS, "file-sharing"))
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 if disposition is not None:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 file_sharing_elt["disposition"] = disposition
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
194 if media_type is None and name:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
195 media_type = mimetypes.guess_type(name, strict=False)[0]
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 file_sharing_elt.addChild(
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 self._m.get_file_metadata_elt(
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 name=name,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 media_type=media_type,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 desc=desc,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 size=size,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 file_hash=file_hash,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 date=date,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 width=width,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 height=height,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 length=length,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 thumbnail=thumbnail,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 )
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 )
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
210 sources_elt = self.get_sources_elt()
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
211 file_sharing_elt.addChild(sources_elt)
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 for source_data in sources:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 if "url" in source_data:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 sources_elt.addChild(
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 self._u.get_url_data_elt(**source_data)
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 )
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 else:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 raise NotImplementedError(
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 f"source data not implemented: {source_data}"
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 )
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
221
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 return file_sharing_elt
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
223
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
224 def parse_sources_elt(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
225 self,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
226 sources_elt: domish.Element
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
227 ) -> List[Dict[str, Any]]:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
228 """Parse <sources/> element
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
229
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
230 @param sources_elt: <sources/> element, or a direct parent element
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
231 @return: list of found sources data
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
232 @raise: exceptions.NotFound: Can't find <sources/> element
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
233 """
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
234 if sources_elt.name != "sources" or sources_elt.uri != NS_SFS:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
235 try:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
236 sources_elt = next(sources_elt.elements(NS_SFS, "sources"))
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
237 except StopIteration:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
238 raise exceptions.NotFound(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
239 f"<sources/> element is missing: {sources_elt.toXml()}")
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
240 sources = []
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
241 for elt in sources_elt.elements():
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
242 if not elt.uri:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
243 log.warning("ignoring source element {elt.toXml()}")
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
244 continue
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
245 key = (elt.uri, elt.name)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
246 try:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
247 source_handler = self._sources_handlers[key]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
248 except KeyError:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
249 log.warning(f"unmanaged file sharing element: {elt.toXml}")
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
250 continue
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
251 else:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
252 source_data = source_handler.callback(elt)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
253 if source_handler.encrypted:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
254 source_data[C.MESS_KEY_ENCRYPTED] = True
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
255 if "type" not in source_data:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
256 source_data["type"] = elt.uri
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
257 sources.append(source_data)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
258 return sources
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
259
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 def parse_file_sharing_elt(
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 self,
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
262 file_sharing_elt: domish.Element
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
263 ) -> Dict[str, Any]:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
264 """Parse <file-sharing/> element and return file-sharing data
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
265
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 @param file_sharing_elt: <file-sharing/> element
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 @return: file-sharing data. It a dict whose keys correspond to
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 [get_file_sharing_elt] parameters
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 """
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 if file_sharing_elt.name != "file-sharing":
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 try:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 file_sharing_elt = next(
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 file_sharing_elt.elements(NS_SFS, "file-sharing")
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 )
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 except StopIteration:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
276 raise exceptions.NotFound
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
277 try:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
278 data = self._m.parse_file_metadata_elt(file_sharing_elt)
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
279 except exceptions.NotFound:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
280 data = {}
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
281 disposition = file_sharing_elt.getAttribute("disposition")
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
282 if disposition is not None:
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
283 data["disposition"] = disposition
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
284 try:
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
285 data["sources"] = self.parse_sources_elt(file_sharing_elt)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
286 except exceptions.NotFound as e:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
287 raise ValueError(str(e))
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
288
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
289 return data
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
290
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
291 def _add_file_sharing_attachments(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
292 self,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
293 client: SatXMPPEntity,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
294 message_elt: domish.Element,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
295 data: Dict[str, Any]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
296 ) -> Dict[str, Any]:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
297 """Check <message> for a shared file, and add it as an attachment"""
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
298 # XXX: XEP-0447 doesn't support several attachments in a single message, thus only
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
299 # one attachment can be added
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
300 try:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
301 attachment = self.parse_file_sharing_elt(message_elt)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
302 except exceptions.NotFound:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
303 return data
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
304
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
305 if any(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
306 s.get(C.MESS_KEY_ENCRYPTED, False)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
307 for s in attachment["sources"]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
308 ) and client.encryption.isEncrypted(data):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
309 # we don't add the encrypted flag if the message itself is not encrypted,
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
310 # because the decryption key is part of the link, so sending it over
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
311 # unencrypted channel is like having no encryption at all.
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
312 attachment[C.MESS_KEY_ENCRYPTED] = True
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
313
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
314 attachments = data['extra'].setdefault(C.MESS_KEY_ATTACHMENTS, [])
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
315 attachments.append(attachment)
3897
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
316
4b7106eede0c plugin XEP-0447: Stateless File Sharing implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
317 return data
3922
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
318
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
319 async def attach(self, client, data):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
320 # XXX: for now, XEP-0447 only allow to send one file per <message/>, thus we need
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
321 # to send each file in a separate message
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
322 attachments = data["extra"][C.MESS_KEY_ATTACHMENTS]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
323 if not data['message'] or data['message'] == {'': ''}:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
324 extra_attachments = attachments[1:]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
325 del attachments[1:]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
326 else:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
327 # we have a message, we must send first attachment separately
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
328 extra_attachments = attachments[:]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
329 attachments.clear()
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
330 del data["extra"][C.MESS_KEY_ATTACHMENTS]
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
331
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
332 if attachments:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
333 if len(attachments) > 1:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
334 raise exceptions.InternalError(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
335 "There should not be more that one attachment at this point"
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
336 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
337 await self._attach.upload_files(client, data)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
338 self._hints.addHintElements(data["xml"], [self._hints.HINT_STORE])
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
339 for attachment in attachments:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
340 try:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
341 file_hash = (attachment["hash_algo"], attachment["hash"])
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
342 except KeyError:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
343 file_hash = None
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
344 file_sharing_elt = self.get_file_sharing_elt(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
345 [{"url": attachment["url"]}],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
346 name=attachment["name"],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
347 size=attachment["size"],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
348 file_hash=file_hash
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
349 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
350 data["xml"].addChild(file_sharing_elt)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
351
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
352 for attachment in extra_attachments:
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
353 # we send all remaining attachment in a separate message
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
354 await client.sendMessage(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
355 to_jid=data['to'],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
356 message={'': ''},
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
357 subject=data['subject'],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
358 mess_type=data['type'],
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
359 extra={C.MESS_KEY_ATTACHMENTS: [attachment]},
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
360 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
361
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
362 if ((not data['extra']
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
363 and (not data['message'] or data['message'] == {'': ''})
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
364 and not data['subject'])):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
365 # nothing left to send, we can cancel the message
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
366 raise exceptions.CancelError("Cancelled by XEP_0447 attachment handling")
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
367
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
368 def _message_received_trigger(self, client, message_elt, post_treat):
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
369 # we use a post_treat callback instead of "message_parse" trigger because we need
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
370 # to check if the "encrypted" flag is set to decide if we add the same flag to the
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
371 # attachment
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
372 post_treat.addCallback(
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
373 partial(self._add_file_sharing_attachments, client, message_elt)
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
374 )
0ff265725489 plugin XEP-0447: handle attachment and download:
Goffi <goffi@goffi.org>
parents: 3897
diff changeset
375 return True