comparison sat/plugins/plugin_comp_file_sharing.py @ 3677:02e5e2385a30

component (file-sharing): use `file-sharing` instead of `file_sharing`: a dash is used instead of underscore for entry-point and config section., as it is best practice to use dash on command-line.
author Goffi <goffi@goffi.org>
date Sun, 26 Sep 2021 16:35:56 +0200
parents ab72b8ac3bd2
children 742e466fa000 6d298323eed2
comparison
equal deleted inserted replaced
3676:fc24e611c9aa 3677:02e5e2385a30
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
46 log = getLogger(__name__) 46 log = getLogger(__name__)
47 47
48 48
49 PLUGIN_INFO = { 49 PLUGIN_INFO = {
50 C.PI_NAME: "File sharing component", 50 C.PI_NAME: "File sharing component",
51 C.PI_IMPORT_NAME: "file_sharing", 51 C.PI_IMPORT_NAME: "file-sharing",
52 C.PI_MODES: [C.PLUG_MODE_COMPONENT], 52 C.PI_MODES: [C.PLUG_MODE_COMPONENT],
53 C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT, 53 C.PI_TYPE: C.PLUG_TYPE_ENTRY_POINT,
54 C.PI_PROTOCOLS: [], 54 C.PI_PROTOCOLS: [],
55 C.PI_DEPENDENCIES: [ 55 C.PI_DEPENDENCIES: [
56 "FILE", 56 "FILE",
205 request.content.close() 205 request.content.close()
206 tmp_file_path = Path(request.content.name) 206 tmp_file_path = Path(request.content.name)
207 request.content = None 207 request.content = None
208 208
209 # the 2 following headers are not standard, but useful in the context of file 209 # the 2 following headers are not standard, but useful in the context of file
210 # sharing with HTTP Upload: first one allow uploaded to specify the path 210 # sharing with HTTP Upload: first one allow uploader to specify the path
211 # and second one will disable public exposure of the file through HTTP 211 # and second one will disable public exposure of the file through HTTP
212 path = request.getHeader("Xmpp-File-Path") 212 path = request.getHeader("Xmpp-File-Path")
213 if path: 213 if path:
214 path = unquote(path) 214 path = unquote(path)
215 else: 215 else:
241 super().__init__(*args, **kwargs) 241 super().__init__(*args, **kwargs)
242 self._upload_data = None 242 self._upload_data = None
243 243
244 @property 244 @property
245 def upload_data(self): 245 def upload_data(self):
246 """A tuple with upload_id and filename retrieve from requested path""" 246 """A tuple with upload_id and filename retrieved from requested path"""
247 if self._upload_data is not None: 247 if self._upload_data is not None:
248 return self._upload_data 248 return self._upload_data
249 249
250 # self.path is not available if we are early in the request (e.g. when gotLength 250 # self.path is not available if we are early in the request (e.g. when gotLength
251 # is called), in which case channel._path must be used. On the other hand, when 251 # is called), in which case channel._path must be used. On the other hand, when
367 self.host.trigger.add( 367 self.host.trigger.add(
368 "XEP-0329_parseResult_directory", 368 "XEP-0329_parseResult_directory",
369 self._getDirectoryMetadataElts) 369 self._getDirectoryMetadataElts)
370 self.files_path = self.host.getLocalPath(None, C.FILES_DIR, profile=False) 370 self.files_path = self.host.getLocalPath(None, C.FILES_DIR, profile=False)
371 self.http_port = int(self.host.memory.getConfig( 371 self.http_port = int(self.host.memory.getConfig(
372 'component file_sharing', 'http_upload_port', 8888)) 372 'component file-sharing', 'http_upload_port', 8888))
373 connection_type = self.host.memory.getConfig( 373 connection_type = self.host.memory.getConfig(
374 'component file_sharing', 'http_upload_connection_type', 'https') 374 'component file-sharing', 'http_upload_connection_type', 'https')
375 if connection_type not in ('http', 'https'): 375 if connection_type not in ('http', 'https'):
376 raise exceptions.ConfigError( 376 raise exceptions.ConfigError(
377 'bad http_upload_connection_type, you must use one of "http" or "https"' 377 'bad http_upload_connection_type, you must use one of "http" or "https"'
378 ) 378 )
379 self.server = FileSharingSite(self) 379 self.server = FileSharingSite(self)
380 self.expected_uploads = {} 380 self.expected_uploads = {}
381 if connection_type == 'http': 381 if connection_type == 'http':
382 reactor.listenTCP(self.http_port, self.server) 382 reactor.listenTCP(self.http_port, self.server)
383 else: 383 else:
384 options = tls.getOptionsFromConfig( 384 options = tls.getOptionsFromConfig(
385 self.host.memory.config, "component file_sharing") 385 self.host.memory.config, "component file-sharing")
386 tls.TLSOptionsCheck(options) 386 tls.TLSOptionsCheck(options)
387 context_factory = tls.getTLSContextFactory(options) 387 context_factory = tls.getTLSContextFactory(options)
388 reactor.listenSSL(self.http_port, self.server, context_factory) 388 reactor.listenSSL(self.http_port, self.server, context_factory)
389 389
390 def getHandler(self, client): 390 def getHandler(self, client):
391 return Comments_handler(self) 391 return Comments_handler(self)
392 392
393 def profileConnecting(self, client): 393 def profileConnecting(self, client):
394 self.init() 394 self.init()
395 public_base_url = self.host.memory.getConfig( 395 public_base_url = self.host.memory.getConfig(
396 'component file_sharing', 'http_upload_public_facing_url') 396 'component file-sharing', 'http_upload_public_facing_url')
397 if public_base_url is None: 397 if public_base_url is None:
398 client._file_sharing_base_url = f"https://{client.host}:{self.http_port}" 398 client._file_sharing_base_url = f"https://{client.host}:{self.http_port}"
399 else: 399 else:
400 client._file_sharing_base_url = public_base_url 400 client._file_sharing_base_url = public_base_url
401 path = client.file_tmp_dir = os.path.join( 401 path = client.file_tmp_dir = os.path.join(
407 os.makedirs(path) 407 os.makedirs(path)
408 408
409 def getQuota(self, client, entity): 409 def getQuota(self, client, entity):
410 """Return maximum size allowed for all files for entity""" 410 """Return maximum size allowed for all files for entity"""
411 # TODO: handle special entities like admins 411 # TODO: handle special entities like admins
412 quotas = self.host.memory.getConfig("component file_sharing", "quotas_json", {}) 412 quotas = self.host.memory.getConfig("component file-sharing", "quotas_json", {})
413 entity_bare_s = entity.userhost() 413 entity_bare_s = entity.userhost()
414 try: 414 try:
415 quota = quotas["jids"][entity_bare_s] 415 quota = quotas["jids"][entity_bare_s]
416 except KeyError: 416 except KeyError:
417 quota = quotas.get("users") 417 quota = quotas.get("users")