Mercurial > libervia-backend
diff sat/plugins/plugin_xep_0234.py @ 3028:ab2696e34d29
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
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 13 Aug 2019 19:08:41 +0200 |
parents | 69e4716d6268 |
children | fee60f17ebac |
line wrap: on
line diff
--- a/sat/plugins/plugin_xep_0234.py Wed Jul 31 11:31:22 2019 +0200 +++ b/sat/plugins/plugin_xep_0234.py Tue Aug 13 19:08:41 2019 +0200 @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # SAT plugin for Jingle File Transfer (XEP-0234) @@ -24,7 +24,7 @@ log = getLogger(__name__) from sat.core import exceptions from wokkel import disco, iwokkel -from zope.interface import implements +from zope.interface import implementer from sat.tools import utils from sat.tools import stream from sat.tools.common import date_utils @@ -55,7 +55,7 @@ C.PI_DESCRIPTION: _("""Implementation of Jingle File Transfer"""), } -EXTRA_ALLOWED = {u"path", u"namespace", u"file_desc", u"file_hash"} +EXTRA_ALLOWED = {"path", "namespace", "file_desc", "file_hash"} Range = namedtuple("Range", ("offset", "length")) @@ -72,7 +72,7 @@ self._j.registerApplication(NS_JINGLE_FT, self) self._f = host.plugins["FILE"] self._f.register( - NS_JINGLE_FT, self.fileJingleSend, priority=10000, method_name=u"Jingle" + NS_JINGLE_FT, self.fileJingleSend, priority=10000, method_name="Jingle" ) self._hash = self.host.plugins["XEP-0300"] host.bridge.addMethod( @@ -81,7 +81,7 @@ in_sign="ssssa{ss}s", out_sign="", method=self._fileJingleSend, - async=True, + async_=True, ) host.bridge.addMethod( "fileJingleRequest", @@ -89,7 +89,7 @@ in_sign="sssssa{ss}s", out_sign="s", method=self._fileJingleRequest, - async=True, + async_=True, ) def getHandler(self, client): @@ -102,7 +102,7 @@ @param content_name(unicode): name of the content @return (unicode): unique progress id """ - return u"{}_{}".format(session["id"], content_name) + return "{}_{}".format(session["id"], content_name) # generic methods @@ -127,32 +127,32 @@ @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, u"file")) + file_elt = domish.Element((NS_JINGLE_FT, "file")) for name, value in ( - (u"name", name), - (u"size", size), + ("name", name), + ("size", size), ("media-type", mime_type), - (u"desc", desc), - (u"path", path), - (u"namespace", namespace), + ("desc", desc), + ("path", path), + ("namespace", namespace), ): if value is not None: - file_elt.addElement(name, content=unicode(value)) + file_elt.addElement(name, content=str(value)) if modified is not None: if isinstance(modified, int): - file_elt.addElement(u"date", utils.xmpp_date(modified or None)) + file_elt.addElement("date", utils.xmpp_date(modified or None)) else: - file_elt.addElement(u"date", modified) + file_elt.addElement("date", modified) elif "created" in kwargs: - file_elt.addElement(u"date", utils.xmpp_date(kwargs.pop("created"))) + file_elt.addElement("date", utils.xmpp_date(kwargs.pop("created"))) - range_elt = file_elt.addElement(u"range") + range_elt = file_elt.addElement("range") if transfer_range is not None: if transfer_range.offset is not None: - range_elt[u"offset"] = transfer_range.offset + range_elt["offset"] = transfer_range.offset if transfer_range.length is not None: - range_elt[u"length"] = transfer_range.length + range_elt["length"] = transfer_range.length if file_hash is not None: if not file_hash: file_elt.addChild(self._hash.buildHashUsedElt()) @@ -160,7 +160,7 @@ 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(u"XEP-0234_buildFileElement", file_elt, extra_args=kwargs) + self.host.trigger.point("XEP-0234_buildFileElement", file_elt, extra_args=kwargs) if kwargs: for kw in kwargs: log.debug("ignored keyword: {}".format(kw)) @@ -204,68 +204,68 @@ if parent_elt is not None: if file_elt is not None: raise exceptions.InternalError( - u"file_elt must be None if parent_elt is set" + "file_elt must be None if parent_elt is set" ) try: - file_elt = next(parent_elt.elements(NS_JINGLE_FT, u"file")) + file_elt = next(parent_elt.elements(NS_JINGLE_FT, "file")) except StopIteration: raise exceptions.NotFound() else: if not file_elt or file_elt.uri != NS_JINGLE_FT: raise exceptions.DataError( - u"invalid <file> element: {stanza}".format(stanza=file_elt.toXml()) + "invalid <file> element: {stanza}".format(stanza=file_elt.toXml()) ) if file_data is None: file_data = {} - for name in (u"name", u"desc", u"path", u"namespace"): + for name in ("name", "desc", "path", "namespace"): try: - file_data[name] = unicode(next(file_elt.elements(NS_JINGLE_FT, name))) + file_data[name] = str(next(file_elt.elements(NS_JINGLE_FT, name))) except StopIteration: pass - name = file_data.get(u"name") - if name == u"..": + name = file_data.get("name") + if name == "..": # we don't want to go to parent dir when joining to a path - name = u"--" - file_data[u"name"] = name - elif name is not None and u"/" in name or u"\\" in name: - file_data[u"name"] = regex.pathEscape(name) + name = "--" + file_data["name"] = name + elif name is not None and "/" in name or "\\" in name: + file_data["name"] = regex.pathEscape(name) try: - file_data[u"mime_type"] = unicode( - next(file_elt.elements(NS_JINGLE_FT, u"media-type")) + file_data["mime_type"] = str( + next(file_elt.elements(NS_JINGLE_FT, "media-type")) ) except StopIteration: pass try: - file_data[u"size"] = int( - unicode(next(file_elt.elements(NS_JINGLE_FT, u"size"))) + file_data["size"] = int( + str(next(file_elt.elements(NS_JINGLE_FT, "size"))) ) except StopIteration: pass try: - file_data[u"modified"] = date_utils.date_parse( - next(file_elt.elements(NS_JINGLE_FT, u"date")) + file_data["modified"] = date_utils.date_parse( + next(file_elt.elements(NS_JINGLE_FT, "date")) ) except StopIteration: pass try: - range_elt = file_elt.elements(NS_JINGLE_FT, u"range").next() + range_elt = next(file_elt.elements(NS_JINGLE_FT, "range")) except StopIteration: pass else: offset = range_elt.getAttribute("offset") length = range_elt.getAttribute("length") if offset or length or keep_empty_range: - file_data[u"transfer_range"] = Range(offset=offset, length=length) + file_data["transfer_range"] = Range(offset=offset, length=length) - prefix = u"given_" if given else u"" - hash_algo_key, hash_key = u"hash_algo", prefix + u"file_hash" + prefix = "given_" if given else "" + hash_algo_key, hash_key = "hash_algo", prefix + "file_hash" try: file_data[hash_algo_key], file_data[hash_key] = self._hash.parseHashElt( file_elt @@ -273,7 +273,7 @@ except exceptions.NotFound: pass - self.host.trigger.point(u"XEP-0234_parseFileElement", file_elt, file_data) + self.host.trigger.point("XEP-0234_parseFileElement", file_elt, file_data) return file_data @@ -379,12 +379,12 @@ extra = {} if file_hash is not None: if hash_algo is None: - raise ValueError(_(u"hash_algo must be set if file_hash is set")) + raise ValueError(_("hash_algo must be set if file_hash is set")) extra["file_hash"] = file_hash extra["hash_algo"] = hash_algo else: if hash_algo is not None: - raise ValueError(_(u"file_hash must be set if hash_algo is set")) + raise ValueError(_("file_hash must be set if hash_algo is set")) yield self._j.initiate( client, peer_jid, @@ -414,8 +414,8 @@ else: if not EXTRA_ALLOWED.issuperset(extra): raise ValueError( - _(u"only the following keys are allowed in extra: {keys}").format( - keys=u", ".join(EXTRA_ALLOWED) + _("only the following keys are allowed in extra: {keys}").format( + keys=", ".join(EXTRA_ALLOWED) ) ) progress_id_d.callback(self.getProgressId(session, content_name)) @@ -427,38 +427,38 @@ desc_elt = domish.Element((NS_JINGLE_FT, "description")) file_elt = desc_elt.addElement("file") - if content_data[u"senders"] == self._j.ROLE_INITIATOR: + if content_data["senders"] == self._j.ROLE_INITIATOR: # we send a file if name is None: name = os.path.basename(filepath) - file_data[u"date"] = utils.xmpp_date() - file_data[u"desc"] = extra.pop(u"file_desc", u"") - file_data[u"name"] = name + file_data["date"] = utils.xmpp_date() + file_data["desc"] = extra.pop("file_desc", "") + file_data["name"] = name mime_type = mimetypes.guess_type(name, strict=False)[0] if mime_type is not None: - file_data[u"mime_type"] = mime_type - file_data[u"size"] = os.path.getsize(filepath) - if u"namespace" in extra: - file_data[u"namespace"] = extra[u"namespace"] - if u"path" in extra: - file_data[u"path"] = extra[u"path"] - self.buildFileElementFromDict(file_data, file_elt=file_elt, file_hash=u"") + file_data["mime_type"] = mime_type + file_data["size"] = os.path.getsize(filepath) + if "namespace" in extra: + file_data["namespace"] = extra["namespace"] + if "path" in extra: + file_data["path"] = extra["path"] + self.buildFileElementFromDict(file_data, file_elt=file_elt, file_hash="") else: # we request a file - file_hash = extra.pop(u"file_hash", u"") + file_hash = extra.pop("file_hash", "") if not name and not file_hash: - raise ValueError(_(u"you need to provide at least name or file hash")) + raise ValueError(_("you need to provide at least name or file hash")) if name: - file_data[u"name"] = name + file_data["name"] = name if file_hash: - file_data[u"file_hash"] = file_hash - file_data[u"hash_algo"] = extra[u"hash_algo"] + file_data["file_hash"] = file_hash + file_data["hash_algo"] = extra["hash_algo"] else: - file_data[u"hash_algo"] = self._hash.getDefaultAlgo() - if u"namespace" in extra: - file_data[u"namespace"] = extra[u"namespace"] - if u"path" in extra: - file_data[u"path"] = extra[u"path"] + file_data["hash_algo"] = self._hash.getDefaultAlgo() + if "namespace" in extra: + file_data["namespace"] = extra["namespace"] + if "path" in extra: + file_data["path"] = extra["path"] self.buildFileElementFromDict(file_data, file_elt=file_elt) return desc_elt @@ -466,13 +466,13 @@ def jingleRequestConfirmation(self, client, action, session, content_name, desc_elt): """This method request confirmation for a jingle session""" content_data = session["contents"][content_name] - senders = content_data[u"senders"] + senders = content_data["senders"] if senders not in (self._j.ROLE_INITIATOR, self._j.ROLE_RESPONDER): - log.warning(u"Bad sender, assuming initiator") - senders = content_data[u"senders"] = self._j.ROLE_INITIATOR + log.warning("Bad sender, assuming initiator") + senders = content_data["senders"] = self._j.ROLE_INITIATOR # first we grab file informations try: - file_elt = desc_elt.elements(NS_JINGLE_FT, "file").next() + file_elt = next(desc_elt.elements(NS_JINGLE_FT, "file")) except StopIteration: raise failure.Failure(exceptions.DataError) file_data = {"progress_id": self.getProgressId(session, content_name)} @@ -516,7 +516,7 @@ ) defer.returnValue(confirmed) - log.warning(_(u"File continue is not implemented yet")) + log.warning(_("File continue is not implemented yet")) defer.returnValue(False) def _fileReceivingRequestConf( @@ -545,7 +545,7 @@ name = file_data["name"] if "/" in name or "\\" in name: log.warning( - u"File name contain path characters, we replace them: {}".format(name) + "File name contain path characters, we replace them: {}".format(name) ) file_data["name"] = name.replace("/", "_").replace("\\", "_") @@ -574,9 +574,9 @@ if action in (self._j.A_ACCEPTED_ACK,): pass elif action == self._j.A_SESSION_INITIATE: - file_elt = desc_elt.elements(NS_JINGLE_FT, "file").next() + file_elt = next(desc_elt.elements(NS_JINGLE_FT, "file")) try: - file_elt.elements(NS_JINGLE_FT, "range").next() + next(file_elt.elements(NS_JINGLE_FT, "range")) except StopIteration: # initiator doesn't manage <range>, but we do so we advertise it # FIXME: to be checked @@ -586,14 +586,14 @@ assert not "stream_object" in content_data file_data = application_data["file_data"] file_path = application_data["file_path"] - senders = content_data[u"senders"] - if senders != session[u"role"]: + senders = content_data["senders"] + if senders != session["role"]: # we are receiving the file try: # did the responder specified the size of the file? - file_elt = next(desc_elt.elements(NS_JINGLE_FT, u"file")) - size_elt = next(file_elt.elements(NS_JINGLE_FT, u"size")) - size = int(unicode(size_elt)) + file_elt = next(desc_elt.elements(NS_JINGLE_FT, "file")) + size_elt = next(file_elt.elements(NS_JINGLE_FT, "size")) + size = int(str(size_elt)) except (StopIteration, ValueError): size = None # XXX: hash security is not critical here, so we just take the higher mandatory one @@ -624,7 +624,7 @@ args = [client, session, content_name, content_data] finished_d.addCallbacks(self._finishedCb, self._finishedEb, args, None, args) else: - log.warning(u"FIXME: unmanaged action {}".format(action)) + log.warning("FIXME: unmanaged action {}".format(action)) return desc_elt def jingleSessionInfo(self, client, action, session, content_name, jingle_elt): @@ -644,7 +644,7 @@ # we have received the file hash, we need to parse it if content_data["senders"] == session["role"]: log.warning( - u"unexpected checksum received while we are the file sender" + "unexpected checksum received while we are the file sender" ) raise exceptions.DataError info_content_name = elt["name"] @@ -653,13 +653,13 @@ return file_data = content_data["application_data"]["file_data"] try: - file_elt = elt.elements((NS_JINGLE_FT, "file")).next() + file_elt = next(elt.elements((NS_JINGLE_FT, "file"))) except StopIteration: raise exceptions.DataError algo, file_data["given_file_hash"] = self._hash.parseHashElt(file_elt) if algo != file_data.get("hash_algo"): log.warning( - u"Hash algorithm used in given hash ({peer_algo}) doesn't correspond to the one we have used ({our_algo}) [{profile}]".format( + "Hash algorithm used in given hash ({peer_algo}) doesn't correspond to the one we have used ({our_algo}) [{profile}]".format( peer_algo=algo, our_algo=file_data.get("hash_algo"), profile=client.profile, @@ -685,7 +685,7 @@ file_data = content_data["application_data"]["file_data"] hasher = file_data["hash_hasher"] hash_ = hasher.hexdigest() - log.debug(u"Calculated hash: {}".format(hash_)) + log.debug("Calculated hash: {}".format(hash_)) iq_elt, jingle_elt = self._j.buildSessionInfo(client, session) checksum_elt = jingle_elt.addElement((NS_JINGLE_FT, "checksum")) checksum_elt["creator"] = content_data["creator"] @@ -712,7 +712,7 @@ if given_hash is None: if last_try: log.warning( - u"sender didn't sent hash checksum, we can't check the file [{profile}]".format( + "sender didn't sent hash checksum, we can't check the file [{profile}]".format( profile=client.profile ) ) @@ -721,10 +721,10 @@ return True return False hasher = file_data["hash_hasher"] - hash_ = hasher.hexdigest() + hash_ = hasher.hexdigest().encode('utf-8') if hash_ == given_hash: - log.info(u"Hash checked, file was successfully transfered: {}".format(hash_)) + log.info("Hash checked, file was successfully transfered: {}".format(hash_)) progress_metadata = { "hash": hash_, "hash_algo": file_data["hash_algo"], @@ -732,9 +732,9 @@ } error = None else: - log.warning(u"Hash mismatch, the file was not transfered correctly") + log.warning("Hash mismatch, the file was not transfered correctly") progress_metadata = None - error = u"Hash mismatch: given={algo}:{given}, calculated={algo}:{our}".format( + error = "Hash mismatch: given={algo}:{given}, calculated={algo}:{our}".format( algo=file_data["hash_algo"], given=given_hash, our=hash_ ) @@ -748,7 +748,7 @@ return True def _finishedCb(self, __, client, session, content_name, content_data): - log.info(u"File transfer terminated") + log.info("File transfer terminated") if content_data["senders"] != session["role"]: # we terminate the session only if we are the receiver, # as recommanded in XEP-0234 §2 (after example 6) @@ -772,15 +772,15 @@ content_data["stream_object"].close() def _finishedEb(self, failure, client, session, content_name, content_data): - log.warning(u"Error while streaming file: {}".format(failure)) + log.warning("Error while streaming file: {}".format(failure)) content_data["stream_object"].close() self._j.contentTerminate( client, session, content_name, reason=self._j.REASON_FAILED_TRANSPORT ) +@implementer(iwokkel.IDisco) class XEP_0234_handler(XMPPHandler): - implements(iwokkel.IDisco) def getDiscoInfo(self, requestor, target, nodeIdentifier=""): return [disco.DiscoFeature(NS_JINGLE_FT)]