annotate sat/plugins/plugin_xep_0447.py @ 3927:328869756cf4

plugin XEP-0448: Encryption for stateless file sharing implementation: - registered as a source handle for XEP-0447 - can be used as an attachment - registered as a download handler - only usable when OMEMO2 is active, as we been SCE to hide encryption data fix 379
author Goffi <goffi@goffi.org>
date Thu, 06 Oct 2022 16:02:05 +0200
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