Python 3 port:
/!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
This commit is contained in:
parent
d21a6a660f
commit
fbfe96c505
1 changed files with 6336 additions and 6398 deletions
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# SAT plugin to detect language (experimental)
|
||||
|
|
@ -31,25 +31,25 @@ log = getLogger(__name__)
|
|||
|
||||
|
||||
PLUGIN_INFO = {
|
||||
C.PI_NAME: u"File Sharing Management",
|
||||
C.PI_IMPORT_NAME: u"FILE_SHARING_MANAGEMENT",
|
||||
C.PI_NAME: "File Sharing Management",
|
||||
C.PI_IMPORT_NAME: "FILE_SHARING_MANAGEMENT",
|
||||
C.PI_MODES: [C.PLUG_MODE_COMPONENT],
|
||||
C.PI_TYPE: u"EXP",
|
||||
C.PI_TYPE: "EXP",
|
||||
C.PI_PROTOCOLS: [],
|
||||
C.PI_DEPENDENCIES: [u"XEP-0050", u"XEP-0264"],
|
||||
C.PI_DEPENDENCIES: ["XEP-0050", "XEP-0264"],
|
||||
C.PI_RECOMMENDATIONS: [],
|
||||
C.PI_MAIN: u"FileSharingManagement",
|
||||
C.PI_HANDLER: u"no",
|
||||
C.PI_MAIN: "FileSharingManagement",
|
||||
C.PI_HANDLER: "no",
|
||||
C.PI_DESCRIPTION: _(
|
||||
u"Experimental handling of file management for file sharing. This plugins allows "
|
||||
u"to change permissions of stored files/directories or remove them."
|
||||
"Experimental handling of file management for file sharing. This plugins allows "
|
||||
"to change permissions of stored files/directories or remove them."
|
||||
),
|
||||
}
|
||||
|
||||
NS_FILE_MANAGEMENT = u"https://salut-a-toi.org/protocol/file-management:0"
|
||||
NS_FILE_MANAGEMENT_PERM = u"https://salut-a-toi.org/protocol/file-management:0#perm"
|
||||
NS_FILE_MANAGEMENT_DELETE = u"https://salut-a-toi.org/protocol/file-management:0#delete"
|
||||
NS_FILE_MANAGEMENT_THUMB = u"https://salut-a-toi.org/protocol/file-management:0#thumb"
|
||||
NS_FILE_MANAGEMENT = "https://salut-a-toi.org/protocol/file-management:0"
|
||||
NS_FILE_MANAGEMENT_PERM = "https://salut-a-toi.org/protocol/file-management:0#perm"
|
||||
NS_FILE_MANAGEMENT_DELETE = "https://salut-a-toi.org/protocol/file-management:0#delete"
|
||||
NS_FILE_MANAGEMENT_THUMB = "https://salut-a-toi.org/protocol/file-management:0#thumb"
|
||||
|
||||
|
||||
class WorkflowError(Exception):
|
||||
|
|
@ -68,7 +68,7 @@ class FileSharingManagement(object):
|
|||
# syntax?) should be elaborated and proposed as a standard.
|
||||
|
||||
def __init__(self, host):
|
||||
log.info(_(u"File Sharing Management plugin initialization"))
|
||||
log.info(_("File Sharing Management plugin initialization"))
|
||||
self.host = host
|
||||
self._c = host.plugins["XEP-0050"]
|
||||
self._t = host.plugins["XEP-0264"]
|
||||
|
|
@ -76,17 +76,17 @@ class FileSharingManagement(object):
|
|||
|
||||
def profileConnected(self, client):
|
||||
self._c.addAdHocCommand(
|
||||
client, self._onChangeFile, u"Change Permissions of File(s)",
|
||||
client, self._onChangeFile, "Change Permissions of File(s)",
|
||||
node=NS_FILE_MANAGEMENT_PERM,
|
||||
allowed_magics=C.ENTITY_ALL,
|
||||
)
|
||||
self._c.addAdHocCommand(
|
||||
client, self._onDeleteFile, u"Delete File(s)",
|
||||
client, self._onDeleteFile, "Delete File(s)",
|
||||
node=NS_FILE_MANAGEMENT_DELETE,
|
||||
allowed_magics=C.ENTITY_ALL,
|
||||
)
|
||||
self._c.addAdHocCommand(
|
||||
client, self._onGenThumbnails, u"Generate Thumbnails",
|
||||
client, self._onGenThumbnails, "Generate Thumbnails",
|
||||
node=NS_FILE_MANAGEMENT_THUMB,
|
||||
allowed_magics=C.ENTITY_ALL,
|
||||
)
|
||||
|
|
@ -109,7 +109,7 @@ class FileSharingManagement(object):
|
|||
@return (tuple): arguments to use in defer.returnValue
|
||||
"""
|
||||
status = self._c.STATUS.EXECUTING
|
||||
form = data_form.Form("form", title=u"File Management",
|
||||
form = data_form.Form("form", title="File Management",
|
||||
formNamespace=NS_FILE_MANAGEMENT)
|
||||
|
||||
field = data_form.Field(
|
||||
|
|
@ -136,17 +136,17 @@ class FileSharingManagement(object):
|
|||
"""
|
||||
fields = command_form.fields
|
||||
try:
|
||||
path = fields[u'path'].value.strip()
|
||||
namespace = fields[u'namespace'].value or None
|
||||
path = fields['path'].value.strip()
|
||||
namespace = fields['namespace'].value or None
|
||||
except KeyError:
|
||||
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
|
||||
|
||||
if not path:
|
||||
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
|
||||
|
||||
requestor = session_data[u'requestor']
|
||||
requestor = session_data['requestor']
|
||||
requestor_bare = requestor.userhostJID()
|
||||
path = path.rstrip(u'/')
|
||||
path = path.rstrip('/')
|
||||
parent_path, basename = os.path.split(path)
|
||||
|
||||
# TODO: if parent_path and basename are empty, we ask for root directory
|
||||
|
|
@ -158,31 +158,31 @@ class FileSharingManagement(object):
|
|||
namespace=namespace)
|
||||
found_file = found_files[0]
|
||||
except (exceptions.NotFound, IndexError):
|
||||
raise WorkflowError(self._err(_(u"file not found")))
|
||||
raise WorkflowError(self._err(_("file not found")))
|
||||
except exceptions.PermissionError:
|
||||
raise WorkflowError(self._err(_(u"forbidden")))
|
||||
raise WorkflowError(self._err(_("forbidden")))
|
||||
|
||||
if found_file['owner'] != requestor_bare:
|
||||
# only owner can manage files
|
||||
log.warning(_(u"Only owner can manage files"))
|
||||
raise WorkflowError(self._err(_(u"forbidden")))
|
||||
log.warning(_("Only owner can manage files"))
|
||||
raise WorkflowError(self._err(_("forbidden")))
|
||||
|
||||
session_data[u'found_file'] = found_file
|
||||
session_data[u'namespace'] = namespace
|
||||
session_data['found_file'] = found_file
|
||||
session_data['namespace'] = namespace
|
||||
defer.returnValue(found_file)
|
||||
|
||||
def _updateReadPermission(self, access, allowed_jids):
|
||||
if not allowed_jids:
|
||||
if C.ACCESS_PERM_READ in access:
|
||||
del access[C.ACCESS_PERM_READ]
|
||||
elif allowed_jids == u'PUBLIC':
|
||||
elif allowed_jids == 'PUBLIC':
|
||||
access[C.ACCESS_PERM_READ] = {
|
||||
u"type": C.ACCESS_TYPE_PUBLIC
|
||||
"type": C.ACCESS_TYPE_PUBLIC
|
||||
}
|
||||
else:
|
||||
access[C.ACCESS_PERM_READ] = {
|
||||
u"type": C.ACCESS_TYPE_WHITELIST,
|
||||
u"jids": [j.full() for j in allowed_jids]
|
||||
"type": C.ACCESS_TYPE_WHITELIST,
|
||||
"jids": [j.full() for j in allowed_jids]
|
||||
}
|
||||
|
||||
@defer.inlineCallbacks
|
||||
|
|
@ -192,30 +192,30 @@ class FileSharingManagement(object):
|
|||
@param file_data(dict): metadata of the file
|
||||
@param allowed_jids(list[jid.JID]): list of entities allowed to read the file
|
||||
"""
|
||||
assert file_data[u'type'] == C.FILE_TYPE_DIRECTORY
|
||||
assert file_data['type'] == C.FILE_TYPE_DIRECTORY
|
||||
files_data = yield self.host.memory.getFiles(
|
||||
client, requestor, parent=file_data[u'id'], namespace=namespace)
|
||||
client, requestor, parent=file_data['id'], namespace=namespace)
|
||||
|
||||
for file_data in files_data:
|
||||
if not file_data[u'access'].get(C.ACCESS_PERM_READ, {}):
|
||||
log.debug(u"setting {perm} read permission for {name}".format(
|
||||
perm=allowed_jids, name=file_data[u'name']))
|
||||
if not file_data['access'].get(C.ACCESS_PERM_READ, {}):
|
||||
log.debug("setting {perm} read permission for {name}".format(
|
||||
perm=allowed_jids, name=file_data['name']))
|
||||
yield self.host.memory.fileUpdate(
|
||||
file_data[u'id'], u'access',
|
||||
file_data['id'], 'access',
|
||||
partial(self._updateReadPermission, allowed_jids=allowed_jids))
|
||||
if file_data[u'type'] == C.FILE_TYPE_DIRECTORY:
|
||||
yield self._updateDir(client, requestor, namespace, file_data, u'PUBLIC')
|
||||
if file_data['type'] == C.FILE_TYPE_DIRECTORY:
|
||||
yield self._updateDir(client, requestor, namespace, file_data, 'PUBLIC')
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _onChangeFile(self, client, command_elt, session_data, action, node):
|
||||
try:
|
||||
x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next()
|
||||
x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
|
||||
command_form = data_form.Form.fromElement(x_elt)
|
||||
except StopIteration:
|
||||
command_form = None
|
||||
|
||||
found_file = session_data.get('found_file')
|
||||
requestor = session_data[u'requestor']
|
||||
requestor = session_data['requestor']
|
||||
requestor_bare = requestor.userhostJID()
|
||||
|
||||
if command_form is None or len(command_form.fields) == 0:
|
||||
|
|
@ -230,31 +230,31 @@ class FileSharingManagement(object):
|
|||
defer.returnValue(e.err_args)
|
||||
|
||||
# management request
|
||||
if found_file[u'type'] == C.FILE_TYPE_DIRECTORY:
|
||||
instructions = D_(u"Please select permissions for this directory")
|
||||
if found_file['type'] == C.FILE_TYPE_DIRECTORY:
|
||||
instructions = D_("Please select permissions for this directory")
|
||||
else:
|
||||
instructions = D_(u"Please select permissions for this file")
|
||||
instructions = D_("Please select permissions for this file")
|
||||
|
||||
form = data_form.Form("form", title=u"File Management",
|
||||
form = data_form.Form("form", title="File Management",
|
||||
instructions=[instructions],
|
||||
formNamespace=NS_FILE_MANAGEMENT)
|
||||
field = data_form.Field(
|
||||
"text-multi", "read_allowed", required=False,
|
||||
desc=u'list of jids allowed to read this file (beside yourself), or '
|
||||
u'"PUBLIC" to let a public access'
|
||||
desc='list of jids allowed to read this file (beside yourself), or '
|
||||
'"PUBLIC" to let a public access'
|
||||
)
|
||||
read_access = found_file[u"access"].get(C.ACCESS_PERM_READ, {})
|
||||
access_type = read_access.get(u'type', C.ACCESS_TYPE_WHITELIST)
|
||||
read_access = found_file["access"].get(C.ACCESS_PERM_READ, {})
|
||||
access_type = read_access.get('type', C.ACCESS_TYPE_WHITELIST)
|
||||
if access_type == C.ACCESS_TYPE_PUBLIC:
|
||||
field.values = [u'PUBLIC']
|
||||
field.values = ['PUBLIC']
|
||||
else:
|
||||
field.values = read_access.get('jids', [])
|
||||
form.addField(field)
|
||||
if found_file[u'type'] == C.FILE_TYPE_DIRECTORY:
|
||||
if found_file['type'] == C.FILE_TYPE_DIRECTORY:
|
||||
field = data_form.Field(
|
||||
"boolean", "recursive", value=False, required=False,
|
||||
desc=u"Files under it will be made public to follow this dir "
|
||||
u"permission (only if they don't have already a permission set)."
|
||||
desc="Files under it will be made public to follow this dir "
|
||||
"permission (only if they don't have already a permission set)."
|
||||
)
|
||||
form.addField(field)
|
||||
|
||||
|
|
@ -269,22 +269,22 @@ class FileSharingManagement(object):
|
|||
except KeyError:
|
||||
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
|
||||
|
||||
if read_allowed.value == u'PUBLIC':
|
||||
allowed_jids = u'PUBLIC'
|
||||
elif read_allowed.value.strip() == u'':
|
||||
if read_allowed.value == 'PUBLIC':
|
||||
allowed_jids = 'PUBLIC'
|
||||
elif read_allowed.value.strip() == '':
|
||||
allowed_jids = None
|
||||
else:
|
||||
try:
|
||||
allowed_jids = [jid.JID(v.strip()) for v in read_allowed.values
|
||||
if v.strip()]
|
||||
except RuntimeError as e:
|
||||
log.warning(_(u"Can't use read_allowed values: {reason}").format(
|
||||
log.warning(_("Can't use read_allowed values: {reason}").format(
|
||||
reason=e))
|
||||
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
|
||||
|
||||
if found_file[u'type'] == C.FILE_TYPE_FILE:
|
||||
if found_file['type'] == C.FILE_TYPE_FILE:
|
||||
yield self.host.memory.fileUpdate(
|
||||
found_file[u'id'], u'access',
|
||||
found_file['id'], 'access',
|
||||
partial(self._updateReadPermission, allowed_jids=allowed_jids))
|
||||
else:
|
||||
try:
|
||||
|
|
@ -292,32 +292,32 @@ class FileSharingManagement(object):
|
|||
except KeyError:
|
||||
self._c.adHocError(self._c.ERROR.BAD_PAYLOAD)
|
||||
yield self.host.memory.fileUpdate(
|
||||
found_file[u'id'], u'access',
|
||||
found_file['id'], 'access',
|
||||
partial(self._updateReadPermission, allowed_jids=allowed_jids))
|
||||
if recursive:
|
||||
# we set all file under the directory as public (if they haven't
|
||||
# already a permission set), so allowed entities of root directory
|
||||
# can read them.
|
||||
namespace = session_data[u'namespace']
|
||||
namespace = session_data['namespace']
|
||||
yield self._updateDir(
|
||||
client, requestor_bare, namespace, found_file, u'PUBLIC')
|
||||
client, requestor_bare, namespace, found_file, 'PUBLIC')
|
||||
|
||||
# job done, we can end the session
|
||||
status = self._c.STATUS.COMPLETED
|
||||
payload = None
|
||||
note = (self._c.NOTE.INFO, _(u"management session done"))
|
||||
note = (self._c.NOTE.INFO, _("management session done"))
|
||||
defer.returnValue((payload, status, None, note))
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _onDeleteFile(self, client, command_elt, session_data, action, node):
|
||||
try:
|
||||
x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next()
|
||||
x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
|
||||
command_form = data_form.Form.fromElement(x_elt)
|
||||
except StopIteration:
|
||||
command_form = None
|
||||
|
||||
found_file = session_data.get('found_file')
|
||||
requestor = session_data[u'requestor']
|
||||
requestor = session_data['requestor']
|
||||
requestor_bare = requestor.userhostJID()
|
||||
|
||||
if command_form is None or len(command_form.fields) == 0:
|
||||
|
|
@ -330,18 +330,18 @@ class FileSharingManagement(object):
|
|||
found_file = yield self._getFileData(client, session_data, command_form)
|
||||
except WorkflowError as e:
|
||||
defer.returnValue(e.err_args)
|
||||
if found_file[u'type'] == C.FILE_TYPE_DIRECTORY:
|
||||
msg = D_(u"Are you sure to delete directory {name} and all files and "
|
||||
u"directories under it?").format(name=found_file[u'name'])
|
||||
if found_file['type'] == C.FILE_TYPE_DIRECTORY:
|
||||
msg = D_("Are you sure to delete directory {name} and all files and "
|
||||
"directories under it?").format(name=found_file['name'])
|
||||
else:
|
||||
msg = D_(u"Are you sure to delete file {name}?"
|
||||
.format(name=found_file[u'name']))
|
||||
form = data_form.Form("form", title=u"File Management",
|
||||
msg = D_("Are you sure to delete file {name}?"
|
||||
.format(name=found_file['name']))
|
||||
form = data_form.Form("form", title="File Management",
|
||||
instructions = [msg],
|
||||
formNamespace=NS_FILE_MANAGEMENT)
|
||||
field = data_form.Field(
|
||||
"boolean", "confirm", value=False, required=True,
|
||||
desc=u"check this box to confirm"
|
||||
desc="check this box to confirm"
|
||||
)
|
||||
form.addField(field)
|
||||
status = self._c.STATUS.EXECUTING
|
||||
|
|
@ -357,10 +357,10 @@ class FileSharingManagement(object):
|
|||
if not confirmed:
|
||||
note = None
|
||||
else:
|
||||
recursive = found_file[u'type'] == C.FILE_TYPE_DIRECTORY
|
||||
recursive = found_file['type'] == C.FILE_TYPE_DIRECTORY
|
||||
yield self.host.memory.fileDelete(
|
||||
client, requestor_bare, found_file[u'id'], recursive)
|
||||
note = (self._c.NOTE.INFO, _(u"file deleted"))
|
||||
client, requestor_bare, found_file['id'], recursive)
|
||||
note = (self._c.NOTE.INFO, _("file deleted"))
|
||||
status = self._c.STATUS.COMPLETED
|
||||
payload = None
|
||||
defer.returnValue((payload, status, None, note))
|
||||
|
|
@ -374,16 +374,16 @@ class FileSharingManagement(object):
|
|||
|
||||
@param file_data(dict): metadata of the file
|
||||
"""
|
||||
if file_data[u'type'] == C.FILE_TYPE_DIRECTORY:
|
||||
if file_data['type'] == C.FILE_TYPE_DIRECTORY:
|
||||
sub_files_data = yield self.host.memory.getFiles(
|
||||
client, requestor, parent=file_data[u'id'], namespace=namespace)
|
||||
client, requestor, parent=file_data['id'], namespace=namespace)
|
||||
for sub_file_data in sub_files_data:
|
||||
yield self._genThumbs(client, requestor, namespace, sub_file_data)
|
||||
|
||||
elif file_data[u'type'] == C.FILE_TYPE_FILE:
|
||||
mime_type = file_data[u'mime_type']
|
||||
file_path = os.path.join(self.files_path, file_data[u'file_hash'])
|
||||
if mime_type is not None and mime_type.startswith(u"image"):
|
||||
elif file_data['type'] == C.FILE_TYPE_FILE:
|
||||
mime_type = file_data['mime_type']
|
||||
file_path = os.path.join(self.files_path, file_data['file_hash'])
|
||||
if mime_type is not None and mime_type.startswith("image"):
|
||||
thumbnails = []
|
||||
|
||||
for max_thumb_size in (self._t.SIZE_SMALL, self._t.SIZE_MEDIUM):
|
||||
|
|
@ -395,31 +395,31 @@ class FileSharingManagement(object):
|
|||
60 * 60 * 24 * 31 * 6,
|
||||
)
|
||||
except Exception as e:
|
||||
log.warning(_(u"Can't create thumbnail: {reason}")
|
||||
log.warning(_("Can't create thumbnail: {reason}")
|
||||
.format(reason=e))
|
||||
break
|
||||
thumbnails.append({u"id": thumb_id, u"size": thumb_size})
|
||||
thumbnails.append({"id": thumb_id, "size": thumb_size})
|
||||
|
||||
yield self.host.memory.fileUpdate(
|
||||
file_data[u'id'], u'extra',
|
||||
file_data['id'], 'extra',
|
||||
partial(self._updateThumbs, thumbnails=thumbnails))
|
||||
|
||||
log.info(u"thumbnails for [{file_name}] generated"
|
||||
.format(file_name=file_data[u'name']))
|
||||
log.info("thumbnails for [{file_name}] generated"
|
||||
.format(file_name=file_data['name']))
|
||||
|
||||
else:
|
||||
log.warning(u"unmanaged file type: {type_}".format(type_=file_data[u'type']))
|
||||
log.warning("unmanaged file type: {type_}".format(type_=file_data['type']))
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _onGenThumbnails(self, client, command_elt, session_data, action, node):
|
||||
try:
|
||||
x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next()
|
||||
x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x"))
|
||||
command_form = data_form.Form.fromElement(x_elt)
|
||||
except StopIteration:
|
||||
command_form = None
|
||||
|
||||
found_file = session_data.get('found_file')
|
||||
requestor = session_data[u'requestor']
|
||||
requestor = session_data['requestor']
|
||||
|
||||
if command_form is None or len(command_form.fields) == 0:
|
||||
# root request
|
||||
|
|
@ -432,11 +432,11 @@ class FileSharingManagement(object):
|
|||
except WorkflowError as e:
|
||||
defer.returnValue(e.err_args)
|
||||
|
||||
log.info(u"Generating thumbnails as requested")
|
||||
yield self._genThumbs(client, requestor, found_file[u'namespace'], found_file)
|
||||
log.info("Generating thumbnails as requested")
|
||||
yield self._genThumbs(client, requestor, found_file['namespace'], found_file)
|
||||
|
||||
# job done, we can end the session
|
||||
status = self._c.STATUS.COMPLETED
|
||||
payload = None
|
||||
note = (self._c.NOTE.INFO, _(u"thumbnails generated"))
|
||||
note = (self._c.NOTE.INFO, _("thumbnails generated"))
|
||||
defer.returnValue((payload, status, None, note))
|
||||
|
|
|
|||
Loading…
Reference in a new issue