# HG changeset patch # User Goffi # Date 1594983610 -7200 # Node ID 5887fb414758fd1e6a3fad3eb741a55c5034c176 # Parent 624c60293debe2f65617d108920aed5599aea767 component file sharing: add/parse affiliation when possible diff -r 624c60293deb -r 5887fb414758 sat/plugins/plugin_comp_file_sharing.py --- a/sat/plugins/plugin_comp_file_sharing.py Fri Jul 17 12:58:57 2020 +0200 +++ b/sat/plugins/plugin_comp_file_sharing.py Fri Jul 17 13:00:10 2020 +0200 @@ -23,7 +23,6 @@ import shortuuid import unicodedata from urllib.parse import urljoin, urlparse, quote, unquote -from dataclasses import dataclass from pathlib import Path from sat.core.i18n import _ from sat.core.constants import Const as C @@ -69,6 +68,7 @@ HASH_ALGO = "sha-256" NS_COMMENTS = "org.salut-a-toi.comments" +NS_FS_AFFILIATION = "org.salut-a-toi.file-sharing-affiliation" COMMENT_NODE_PREFIX = "org.salut-a-toi.file_comments/" # Directory used to buffer request body (i.e. file in case of PUT) we use more than one @ # there, to be sure than it's not conflicting with a JID @@ -270,7 +270,7 @@ try: upload_id, filename = self.upload_data except exceptions.DataError as e: - log.warning("Invalid PUT request, we stop here: {e}") + log.warning(f"Invalid PUT request, we stop here: {e}") return self.refuseRequest() try: client, upload_request, timer = self.file_sharing.expected_uploads.pop(upload_id) @@ -343,9 +343,15 @@ self.host.trigger.add( "XEP-0234_fileSendingRequest", self._fileSendingRequestTrigger, priority=1000 ) - self.host.trigger.add("XEP-0234_buildFileElement", self._addFileComments) - self.host.trigger.add("XEP-0234_parseFileElement", self._getFileComments) - self.host.trigger.add("XEP-0329_compGetFilesFromNode", self._addCommentsData) + self.host.trigger.add("XEP-0234_buildFileElement", self._addFileMetadataElts) + self.host.trigger.add("XEP-0234_parseFileElement", self._getFileMetadataElts) + self.host.trigger.add("XEP-0329_compGetFilesFromNode", self._addFileMetadata) + self.host.trigger.add( + "XEP-0329_compGetFilesFromNode_build_directory", + self._addDirectoryMetadataElts) + self.host.trigger.add( + "XEP-0329_parseResult_directory", + self._getDirectoryMetadataElts) self.files_path = self.host.getLocalPath(None, C.FILES_DIR, profile=False) self.http_port = self.host.memory.getConfig( 'component file_sharing', 'http_upload_port', 8888) @@ -353,19 +359,19 @@ 'component file_sharing', 'http_upload_connection_type', 'https') if connection_type not in ('http', 'https'): raise exceptions.ConfigError( - f'bad http_upload_connection_type, you must use one of "http" or "https"' + 'bad http_upload_connection_type, you must use one of "http" or "https"' ) self.server = FileSharingSite(self) self.expected_uploads = {} if connection_type == 'http': reactor.listenTCP(self.http_port, self.server) else: - options = tls.getOptionsFromConfig(self.host.memory.config, "component file_sharing") + options = tls.getOptionsFromConfig( + self.host.memory.config, "component file_sharing") tls.TLSOptionsCheck(options) context_factory = tls.getTLSContextFactory(options) reactor.listenSSL(self.http_port, self.server, context_factory) - def getHandler(self, client): return Comments_handler(self) @@ -581,9 +587,15 @@ ) return slot - ## comments triggers ## + ## metadata triggers ## - def _addFileComments(self, file_elt, extra_args): + def _addFileMetadataElts(self, client, file_elt, extra_args): + # affiliation + affiliation = extra_args.get('affiliation') + if affiliation is not None: + file_elt.addElement((NS_FS_AFFILIATION, "affiliation"), content=affiliation) + + # comments try: comments_url = extra_args.pop("comments_url") except KeyError: @@ -599,16 +611,27 @@ comment_elt["count"] = str(count) return True - def _getFileComments(self, file_elt, file_data): + def _getFileMetadataElts(self, client, file_elt, file_data): + # affiliation + try: + affiliation_elt = next(file_elt.elements(NS_FS_AFFILIATION, "affiliation")) + except StopIteration: + pass + else: + file_data["affiliation"] = str(affiliation_elt) + + # comments try: comments_elt = next(file_elt.elements(NS_COMMENTS, "comments")) except StopIteration: - return - file_data["comments_url"] = str(comments_elt) - file_data["comments_count"] = comments_elt["count"] + pass + else: + file_data["comments_url"] = str(comments_elt) + file_data["comments_count"] = comments_elt["count"] return True - def _addCommentsData(self, client, iq_elt, owner, node_path, files_data): + def _addFileMetadata( + self, client, iq_elt, iq_result_elt, owner, node_path, files_data): for file_data in files_data: file_data["comments_url"] = uri.buildXMPPUri( "pubsub", @@ -617,12 +640,30 @@ ) return True + def _addDirectoryMetadataElts( + self, client, file_data, directory_elt, owner, node_path): + affiliation = file_data.get('affiliation') + if affiliation is not None: + directory_elt.addElement( + (NS_FS_AFFILIATION, "affiliation"), + content=affiliation + ) + + def _getDirectoryMetadataElts( + self, client, elt, file_data): + try: + affiliation_elt = next(elt.elements((NS_FS_AFFILIATION, "affiliation"))) + except StopIteration: + pass + else: + file_data['affiliation'] = str(affiliation_elt) + class Comments_handler(pubsub.PubSubService): """This class is a minimal Pubsub service handling virtual nodes for comments""" def __init__(self, plugin_parent): - super(Comments_handler, self).__init__() # PubsubVirtualResource()) + super(Comments_handler, self).__init__() self.host = plugin_parent.host self.plugin_parent = plugin_parent self.discoIdentity = { diff -r 624c60293deb -r 5887fb414758 sat/plugins/plugin_exp_invitation_file.py --- a/sat/plugins/plugin_exp_invitation_file.py Fri Jul 17 12:58:57 2020 +0200 +++ b/sat/plugins/plugin_exp_invitation_file.py Fri Jul 17 13:00:10 2020 +0200 @@ -79,7 +79,7 @@ type_human = _("file sharing") log.info(_( '{profile} has received an invitation for a files repository ({type_human}) ' - 'with namespace "{namespace}" at path [{path}]').format( + 'with namespace {namespace!r} at path [{path}]').format( profile=client.profile, type_human=type_human, namespace=namespace, path=path) ) return defer.ensureDeferred( diff -r 624c60293deb -r 5887fb414758 sat/plugins/plugin_xep_0234.py --- a/sat/plugins/plugin_xep_0234.py Fri Jul 17 12:58:57 2020 +0200 +++ b/sat/plugins/plugin_xep_0234.py Fri Jul 17 13:00:10 2020 +0200 @@ -105,7 +105,8 @@ # generic methods - def buildFileElement(self, name=None, file_hash=None, hash_algo=None, size=None, + def buildFileElement( + self, client, name=None, file_hash=None, hash_algo=None, size=None, mime_type=None, desc=None, modified=None, transfer_range=None, path=None, namespace=None, file_elt=None, **kwargs): """Generate a element with available metadata @@ -113,17 +114,20 @@ @param file_hash(unicode, None): hash of the file empty string to set element @param hash_algo(unicode, None): hash algorithm used - if file_hash is None and hash_algo is set, a element will be generated + if file_hash is None and hash_algo is set, a element will be + generated @param transfer_range(Range, None): where transfer must start/stop @param modified(int, unicode, None): date of last modification 0 to use current date int to use an unix timestamp - else must be an unicode string which will be used as it (it must be an XMPP time) + else must be an unicode string which will be used as it (it must be an XMPP + time) @param file_elt(domish.Element, None): element to use None to create a new one @param **kwargs: data for plugin extension (ignored by default) @return (domish.Element): generated element - @trigger XEP-0234_buildFileElement(file_elt, extra_args): can be used to extend elements to add + @trigger XEP-0234_buildFileElement(file_elt, extra_args): can be used to extend + elements to add """ if file_elt is None: file_elt = domish.Element((NS_JINGLE_FT, "file")) @@ -159,13 +163,14 @@ file_elt.addChild(self._hash.buildHashElt(file_hash, hash_algo)) elif hash_algo is not None: file_elt.addChild(self._hash.buildHashUsedElt(hash_algo)) - self.host.trigger.point("XEP-0234_buildFileElement", file_elt, extra_args=kwargs) + self.host.trigger.point( + "XEP-0234_buildFileElement", client, file_elt, extra_args=kwargs) if kwargs: for kw in kwargs: log.debug("ignored keyword: {}".format(kw)) return file_elt - def buildFileElementFromDict(self, file_data, **kwargs): + def buildFileElementFromDict(self, client, file_data, **kwargs): """like buildFileElement but get values from a file_data dict @param file_data(dict): metadata to use @@ -174,10 +179,11 @@ if kwargs: file_data = file_data.copy() file_data.update(kwargs) - return self.buildFileElement(**file_data) + return self.buildFileElement(client, **file_data) - def parseFileElement(self, file_elt, file_data=None, given=False, parent_elt=None, - keep_empty_range=False,): + def parseFileElement( + self, client, file_elt, file_data=None, given=False, parent_elt=None, + keep_empty_range=False): """Parse a element and file dictionary accordingly @param file_data(dict, None): dict where the data will be set @@ -268,7 +274,7 @@ except exceptions.NotFound: pass - self.host.trigger.point("XEP-0234_parseFileElement", file_elt, file_data) + self.host.trigger.point("XEP-0234_parseFileElement", client, file_elt, file_data) return file_data @@ -423,7 +429,8 @@ file_data["namespace"] = extra["namespace"] if "path" in extra: file_data["path"] = extra["path"] - self.buildFileElementFromDict(file_data, file_elt=file_elt, file_hash="") + self.buildFileElementFromDict( + client, file_data, file_elt=file_elt, file_hash="") else: # we request a file file_hash = extra.pop("file_hash", "") @@ -440,7 +447,7 @@ file_data["namespace"] = extra["namespace"] if "path" in extra: file_data["path"] = extra["path"] - self.buildFileElementFromDict(file_data, file_elt=file_elt) + self.buildFileElementFromDict(client, file_data, file_elt=file_elt) return desc_elt @@ -474,7 +481,7 @@ self, client, session, content_data, content_name, file_data, file_elt ): """parse file_elt, and handle file retrieving/permission checking""" - self.parseFileElement(file_elt, file_data) + self.parseFileElement(client, file_elt, file_data) content_data["application_data"]["file_data"] = file_data finished_d = content_data["finished_d"] = defer.Deferred() @@ -504,7 +511,7 @@ self, client, session, content_data, content_name, file_data, file_elt ): """parse file_elt, and handle user permission/file opening""" - self.parseFileElement(file_elt, file_data, given=True) + self.parseFileElement(client, file_elt, file_data, given=True) try: hash_algo, file_data["given_file_hash"] = self._hash.parseHashElt(file_elt) except exceptions.NotFound: diff -r 624c60293deb -r 5887fb414758 sat/plugins/plugin_xep_0264.py --- a/sat/plugins/plugin_xep_0264.py Fri Jul 17 12:58:57 2020 +0200 +++ b/sat/plugins/plugin_xep_0264.py Fri Jul 17 13:00:10 2020 +0200 @@ -84,7 +84,7 @@ ## triggers ## - def _addFileThumbnails(self, file_elt, extra_args): + def _addFileThumbnails(self, client, file_elt, extra_args): try: thumbnails = extra_args["extra"][C.KEY_THUMBNAILS] except KeyError: @@ -98,7 +98,7 @@ thumbnail_elt["height"] = str(height) return True - def _getFileThumbnails(self, file_elt, file_data): + def _getFileThumbnails(self, client, file_elt, file_data): thumbnails = [] for thumbnail_elt in file_elt.elements(NS_THUMBS, "thumbnail"): uri = thumbnail_elt["uri"] diff -r 624c60293deb -r 5887fb414758 sat/plugins/plugin_xep_0329.py --- a/sat/plugins/plugin_xep_0329.py Fri Jul 17 12:58:57 2020 +0200 +++ b/sat/plugins/plugin_xep_0329.py Fri Jul 17 13:00:10 2020 +0200 @@ -417,7 +417,8 @@ size = os.path.getsize(path) mime_type = mimetypes.guess_type(path, strict=False)[0] file_elt = self._jf.buildFileElement( - name=name, size=size, mime_type=mime_type, modified=os.path.getmtime(path) + client=client, name=name, size=size, mime_type=mime_type, + modified=os.path.getmtime(path) ) query_elt.addChild(file_elt) @@ -590,16 +591,32 @@ query_elt = iq_result_elt.addElement((NS_FIS, "query")) query_elt["node"] = node_path if not self.host.trigger.point( - "XEP-0329_compGetFilesFromNode", client, iq_elt, owner, node_path, files_data + "XEP-0329_compGetFilesFromNode", + client, + iq_elt, + iq_result_elt, + owner, + node_path, + files_data ): return for file_data in files_data: if file_data['type'] == C.FILE_TYPE_DIRECTORY: directory_elt = query_elt.addElement("directory") directory_elt['name'] = file_data['name'] + self.host.trigger.point( + "XEP-0329_compGetFilesFromNode_build_directory", + client, + file_data, + directory_elt, + owner, + node_path, + ) else: file_elt = self._jf.buildFileElementFromDict( - file_data, modified=file_data.get("modified", file_data["created"]) + client, + file_data, + modified=file_data.get("modified", file_data["created"]) ) query_elt.addChild(file_elt) client.send(iq_result_elt) @@ -609,7 +626,7 @@ client, iq_elt, self._compGetRootNodesCb, self._compGetFilesFromNodeCb ) - def _parseResult(self, iq_elt): + def _parseResult(self, iq_elt, client): query_elt = next(iq_elt.elements(NS_FIS, "query")) files = [] @@ -617,7 +634,7 @@ if elt.name == "file": # we have a file try: - file_data = self._jf.parseFileElement(elt) + file_data = self._jf.parseFileElement(client, elt) except exceptions.DataError: continue file_data["type"] = C.FILE_TYPE_FILE @@ -625,6 +642,12 @@ # we have a directory file_data = {"name": elt["name"], "type": C.FILE_TYPE_DIRECTORY} + self.host.trigger.point( + "XEP-0329_parseResult_directory", + client, + elt, + file_data, + ) else: log.warning( _(f"unexpected element, ignoring: {elt.toXml()}") @@ -665,7 +688,7 @@ if path: query_elt["node"] = path d = iq_elt.send() - d.addCallback(self._parseResult) + d.addCallback(self._parseResult, client) return d def _localSharesGet(self, profile):