Mercurial > libervia-backend
annotate sat/plugins/plugin_misc_attach.py @ 3202:2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
"path" refers to a local path of a file, we don't want to store it in database as the file
may be in a temporary location, or even be a temporary file. So once the file has been
uploaded, we remove it.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 06 Mar 2020 18:19:03 +0100 |
parents | 883fb4981958 |
children | 2ba602aef90e |
rev | line source |
---|---|
3181 | 1 #!/usr/bin/env python3 |
2 | |
3 # SàT plugin for attaching files | |
4 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org) | |
5 | |
6 # This program is free software: you can redistribute it and/or modify | |
7 # it under the terms of the GNU Affero General Public License as published by | |
8 # the Free Software Foundation, either version 3 of the License, or | |
9 # (at your option) any later version. | |
10 | |
11 # This program is distributed in the hope that it will be useful, | |
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 # GNU Affero General Public License for more details. | |
15 | |
16 # You should have received a copy of the GNU Affero General Public License | |
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 from functools import partial | |
20 from pathlib import Path | |
21 from twisted.internet import defer | |
22 from sat.core.i18n import _ | |
23 from sat.core.constants import Const as C | |
24 from sat.core.log import getLogger | |
25 | |
26 log = getLogger(__name__) | |
27 | |
28 | |
29 PLUGIN_INFO = { | |
30 C.PI_NAME: "File Attach", | |
31 C.PI_IMPORT_NAME: "ATTACH", | |
32 C.PI_TYPE: C.PLUG_TYPE_MISC, | |
33 C.PI_DEPENDENCIES: ["UPLOAD"], | |
34 C.PI_MAIN: "AttachPlugin", | |
35 C.PI_HANDLER: "no", | |
36 C.PI_DESCRIPTION: _("""Attachments handler"""), | |
37 } | |
38 | |
39 | |
40 class AttachPlugin: | |
41 | |
42 def __init__(self, host): | |
43 log.info(_("plugin Attach initialization")) | |
44 self.host = host | |
45 self._u = host.plugins["UPLOAD"] | |
46 host.trigger.add("sendMessage", self._sendMessageTrigger) | |
47 | |
48 def _attachFiles(self, client, data): | |
49 # TODO: handle xhtml-im | |
50 body_elt = next(data["xml"].elements((C.NS_CLIENT, "body"))) | |
51 for attachment in data["extra"][C.MESS_KEY_ATTACHMENTS]: | |
52 body_elt.addContent(f'\n{attachment["url"]}') | |
53 return data | |
54 | |
55 async def uploadFiles(self, client, data): | |
56 uploads_d = [] | |
57 to_delete = [] | |
58 attachments = data["extra"]["attachments"] | |
59 | |
60 for attachment in attachments: | |
61 try: | |
3202
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
62 # we pop path because we don't want it to be stored, as the image can be |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
63 # only in a temporary location |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
64 path = Path(attachment.pop("path")) |
3181 | 65 except KeyError: |
66 log.warning("no path in attachment: {attachment}") | |
67 to_delete.append(attachment) | |
68 continue | |
69 | |
70 if "url" in attachment: | |
3202
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
71 url = attachment.pop('url') |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
72 log.warning( |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
73 f"unexpected URL in attachment: {url!r}\nattachment: {attachment}" |
2e892f9f54f6
plugin attachment: remove "path" from attachment once used:
Goffi <goffi@goffi.org>
parents:
3192
diff
changeset
|
74 ) |
3181 | 75 |
76 try: | |
77 name = attachment["name"] | |
78 except KeyError: | |
79 name = attachment["name"] = path.name | |
80 | |
81 options = {} | |
3182
f2bb57348587
plugin attach, XEP-0363: progress id can now be specified:
Goffi <goffi@goffi.org>
parents:
3181
diff
changeset
|
82 progress_id = attachment.get("progress_id") |
f2bb57348587
plugin attach, XEP-0363: progress id can now be specified:
Goffi <goffi@goffi.org>
parents:
3181
diff
changeset
|
83 if progress_id: |
f2bb57348587
plugin attach, XEP-0363: progress id can now be specified:
Goffi <goffi@goffi.org>
parents:
3181
diff
changeset
|
84 options["progress_id"] = attachment["progress_id"] |
3192
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
85 check_certificate = self.host.memory.getParamA( |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
86 "check_certificate", "Connection", profile_key=client.profile) |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
87 if not check_certificate: |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
88 options['ignore_tls_errors'] = True |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
89 log.warning( |
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
90 _("certificate check disabled for upload, this is dangerous!")) |
3181 | 91 if client.encryption.isEncryptionRequested(data): |
92 # FIXME: we should not use implementation specific value here | |
3192
883fb4981958
plugin attach: disable TLS check if "check_certificate" is disabled
Goffi <goffi@goffi.org>
parents:
3182
diff
changeset
|
93 # but for now it's the only file encryption method available with |
3181 | 94 # with upload. |
95 options['encryption'] = C.ENC_AES_GCM | |
96 | |
97 __, upload_d = await self._u.upload( | |
98 client, | |
99 filepath=path, | |
100 filename=name, | |
3182
f2bb57348587
plugin attach, XEP-0363: progress id can now be specified:
Goffi <goffi@goffi.org>
parents:
3181
diff
changeset
|
101 options=options, |
3181 | 102 ) |
103 uploads_d.append(upload_d) | |
104 | |
105 for attachment in to_delete: | |
106 attachments.remove(attachment) | |
107 | |
108 upload_results = await defer.DeferredList(uploads_d) | |
109 for idx, (success, ret) in enumerate(upload_results): | |
110 attachment = attachments[idx] | |
111 | |
112 if not success: | |
113 # ret is a failure here | |
114 log.warning(f"error while uploading {attachment}: {ret}") | |
115 continue | |
116 | |
117 attachment["url"] = ret | |
118 | |
119 return data | |
120 | |
121 def _uploadFiles(self, client, data): | |
122 return defer.ensureDeferred(self.uploadFiles(client, data)) | |
123 | |
124 def _sendMessageTrigger( | |
125 self, client, mess_data, pre_xml_treatments, post_xml_treatments): | |
126 if mess_data['extra'].get(C.MESS_KEY_ATTACHMENTS): | |
127 pre_xml_treatments.addCallback(partial(self._uploadFiles, client)) | |
128 post_xml_treatments.addCallback(partial(self._attachFiles, client)) | |
129 return True |