Mercurial > libervia-backend
comparison sat/plugins/plugin_comp_file_sharing.py @ 3681:742e466fa000
merge bookmark `@`
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 26 Sep 2021 16:41:49 +0200 |
parents | 888109774673 02e5e2385a30 |
children | 09f5ac48ffe3 |
comparison
equal
deleted
inserted
replaced
3680:68f2a9c171d1 | 3681:742e466fa000 |
---|---|
1 #!/usr/bin/env python3 | 1 #!/usr/bin/env python3 |
2 | 2 |
3 # SAT plugin for parrot mode (experimental) | 3 # Libervia File Sharing component |
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | 4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) |
5 | 5 |
6 # This program is free software: you can redistribute it and/or modify | 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 | 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 | 8 # the Free Software Foundation, either version 3 of the License, or |
47 log = getLogger(__name__) | 47 log = getLogger(__name__) |
48 | 48 |
49 | 49 |
50 PLUGIN_INFO = { | 50 PLUGIN_INFO = { |
51 C.PI_NAME: "File sharing component", | 51 C.PI_NAME: "File sharing component", |
52 C.PI_IMPORT_NAME: "file_sharing", | 52 C.PI_IMPORT_NAME: "file-sharing", |
53 C.PI_MODES: [C.PLUG_MODE_COMPONENT], | 53 C.PI_MODES: [C.PLUG_MODE_COMPONENT], |
54 C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT, | 54 C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT, |
55 C.PI_PROTOCOLS: [], | 55 C.PI_PROTOCOLS: [], |
56 C.PI_DEPENDENCIES: [ | 56 C.PI_DEPENDENCIES: [ |
57 "FILE", | 57 "FILE", |
206 request.content.close() | 206 request.content.close() |
207 tmp_file_path = Path(request.content.name) | 207 tmp_file_path = Path(request.content.name) |
208 request.content = None | 208 request.content = None |
209 | 209 |
210 # the 2 following headers are not standard, but useful in the context of file | 210 # the 2 following headers are not standard, but useful in the context of file |
211 # sharing with HTTP Upload: first one allow uploaded to specify the path | 211 # sharing with HTTP Upload: first one allow uploader to specify the path |
212 # and second one will disable public exposure of the file through HTTP | 212 # and second one will disable public exposure of the file through HTTP |
213 path = request.getHeader("Xmpp-File-Path") | 213 path = request.getHeader("Xmpp-File-Path") |
214 if path: | 214 if path: |
215 path = unquote(path) | 215 path = unquote(path) |
216 else: | 216 else: |
242 super().__init__(*args, **kwargs) | 242 super().__init__(*args, **kwargs) |
243 self._upload_data = None | 243 self._upload_data = None |
244 | 244 |
245 @property | 245 @property |
246 def upload_data(self): | 246 def upload_data(self): |
247 """A tuple with upload_id and filename retrieve from requested path""" | 247 """A tuple with upload_id and filename retrieved from requested path""" |
248 if self._upload_data is not None: | 248 if self._upload_data is not None: |
249 return self._upload_data | 249 return self._upload_data |
250 | 250 |
251 # self.path is not available if we are early in the request (e.g. when gotLength | 251 # self.path is not available if we are early in the request (e.g. when gotLength |
252 # is called), in which case channel._path must be used. On the other hand, when | 252 # is called), in which case channel._path must be used. On the other hand, when |
368 self.host.trigger.add( | 368 self.host.trigger.add( |
369 "XEP-0329_parseResult_directory", | 369 "XEP-0329_parseResult_directory", |
370 self._getDirectoryMetadataElts) | 370 self._getDirectoryMetadataElts) |
371 self.files_path = self.host.getLocalPath(None, C.FILES_DIR, profile=False) | 371 self.files_path = self.host.getLocalPath(None, C.FILES_DIR, profile=False) |
372 self.http_port = int(self.host.memory.getConfig( | 372 self.http_port = int(self.host.memory.getConfig( |
373 'component file_sharing', 'http_upload_port', 8888)) | 373 'component file-sharing', 'http_upload_port', 8888)) |
374 connection_type = self.host.memory.getConfig( | 374 connection_type = self.host.memory.getConfig( |
375 'component file_sharing', 'http_upload_connection_type', 'https') | 375 'component file-sharing', 'http_upload_connection_type', 'https') |
376 if connection_type not in ('http', 'https'): | 376 if connection_type not in ('http', 'https'): |
377 raise exceptions.ConfigError( | 377 raise exceptions.ConfigError( |
378 'bad http_upload_connection_type, you must use one of "http" or "https"' | 378 'bad http_upload_connection_type, you must use one of "http" or "https"' |
379 ) | 379 ) |
380 self.server = FileSharingSite(self) | 380 self.server = FileSharingSite(self) |
381 self.expected_uploads = {} | 381 self.expected_uploads = {} |
382 if connection_type == 'http': | 382 if connection_type == 'http': |
383 reactor.listenTCP(self.http_port, self.server) | 383 reactor.listenTCP(self.http_port, self.server) |
384 else: | 384 else: |
385 options = tls.getOptionsFromConfig( | 385 options = tls.getOptionsFromConfig( |
386 self.host.memory.config, "component file_sharing") | 386 self.host.memory.config, "component file-sharing") |
387 tls.TLSOptionsCheck(options) | 387 tls.TLSOptionsCheck(options) |
388 context_factory = tls.getTLSContextFactory(options) | 388 context_factory = tls.getTLSContextFactory(options) |
389 reactor.listenSSL(self.http_port, self.server, context_factory) | 389 reactor.listenSSL(self.http_port, self.server, context_factory) |
390 | 390 |
391 def getHandler(self, client): | 391 def getHandler(self, client): |
392 return Comments_handler(self) | 392 return Comments_handler(self) |
393 | 393 |
394 def profileConnecting(self, client): | 394 def profileConnecting(self, client): |
395 self.init() | 395 self.init() |
396 public_base_url = self.host.memory.getConfig( | 396 public_base_url = self.host.memory.getConfig( |
397 'component file_sharing', 'http_upload_public_facing_url') | 397 'component file-sharing', 'http_upload_public_facing_url') |
398 if public_base_url is None: | 398 if public_base_url is None: |
399 client._file_sharing_base_url = f"https://{client.host}:{self.http_port}" | 399 client._file_sharing_base_url = f"https://{client.host}:{self.http_port}" |
400 else: | 400 else: |
401 client._file_sharing_base_url = public_base_url | 401 client._file_sharing_base_url = public_base_url |
402 path = client.file_tmp_dir = os.path.join( | 402 path = client.file_tmp_dir = os.path.join( |
408 os.makedirs(path) | 408 os.makedirs(path) |
409 | 409 |
410 def getQuota(self, client, entity): | 410 def getQuota(self, client, entity): |
411 """Return maximum size allowed for all files for entity""" | 411 """Return maximum size allowed for all files for entity""" |
412 # TODO: handle special entities like admins | 412 # TODO: handle special entities like admins |
413 quotas = self.host.memory.getConfig("component file_sharing", "quotas_json", {}) | 413 quotas = self.host.memory.getConfig("component file-sharing", "quotas_json", {}) |
414 entity_bare_s = entity.userhost() | 414 entity_bare_s = entity.userhost() |
415 try: | 415 try: |
416 quota = quotas["jids"][entity_bare_s] | 416 quota = quotas["jids"][entity_bare_s] |
417 except KeyError: | 417 except KeyError: |
418 quota = quotas.get("users") | 418 quota = quotas.get("users") |