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")