Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0077.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 | 8018cf9aa55b |
children | 9d0df638c8b4 |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SAT plugin for managing xep-0077 | 4 # SAT plugin for managing xep-0077 |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 6 |
49 # while XEP recommand to use it | 49 # while XEP recommand to use it |
50 # FIXME: doesn't handle data form or oob | 50 # FIXME: doesn't handle data form or oob |
51 namespace = 'jabber:client' | 51 namespace = 'jabber:client' |
52 | 52 |
53 def __init__(self, jid_, password, email=None, check_certificate=True): | 53 def __init__(self, jid_, password, email=None, check_certificate=True): |
54 log.debug(_(u"Registration asked for {jid}").format(jid=jid_)) | 54 log.debug(_("Registration asked for {jid}").format(jid=jid_)) |
55 xmlstream.ConnectAuthenticator.__init__(self, jid_.host) | 55 xmlstream.ConnectAuthenticator.__init__(self, jid_.host) |
56 self.jid = jid_ | 56 self.jid = jid_ |
57 self.password = password | 57 self.password = password |
58 self.email = email | 58 self.email = email |
59 self.check_certificate = check_certificate | 59 self.check_certificate = check_certificate |
68 tls_init.required = False | 68 tls_init.required = False |
69 tls_init.check_certificate = self.check_certificate | 69 tls_init.check_certificate = self.check_certificate |
70 xs.initializers.append(tls_init) | 70 xs.initializers.append(tls_init) |
71 | 71 |
72 def register(self, xmlstream): | 72 def register(self, xmlstream): |
73 log.debug(_(u"Stream started with {server}, now registering" | 73 log.debug(_("Stream started with {server}, now registering" |
74 .format(server=self.jid.host))) | 74 .format(server=self.jid.host))) |
75 iq = XEP_0077.buildRegisterIQ(self.xmlstream, self.jid, self.password, self.email) | 75 iq = XEP_0077.buildRegisterIQ(self.xmlstream, self.jid, self.password, self.email) |
76 d = iq.send(self.jid.host).addCallbacks(self.registrationCb, self.registrationEb) | 76 d = iq.send(self.jid.host).addCallbacks(self.registrationCb, self.registrationEb) |
77 d.chainDeferred(self.registered) | 77 d.chainDeferred(self.registered) |
78 | 78 |
79 def registrationCb(self, answer): | 79 def registrationCb(self, answer): |
80 log.debug(_(u"Registration answer: {}").format(answer.toXml())) | 80 log.debug(_("Registration answer: {}").format(answer.toXml())) |
81 self.xmlstream.sendFooter() | 81 self.xmlstream.sendFooter() |
82 | 82 |
83 def registrationEb(self, failure_): | 83 def registrationEb(self, failure_): |
84 log.info(_("Registration failure: {}").format(unicode(failure_.value))) | 84 log.info(_("Registration failure: {}").format(str(failure_.value))) |
85 self.xmlstream.sendFooter() | 85 self.xmlstream.sendFooter() |
86 raise failure_ | 86 raise failure_ |
87 | 87 |
88 | 88 |
89 class ServerRegister(xmlstream.XmlStreamFactory): | 89 class ServerRegister(xmlstream.XmlStreamFactory): |
95 def clientConnectionLost(self, connector, reason): | 95 def clientConnectionLost(self, connector, reason): |
96 connector.disconnect() | 96 connector.disconnect() |
97 | 97 |
98 def _disconnected(self, reason): | 98 def _disconnected(self, reason): |
99 if not self.authenticator.registered.called: | 99 if not self.authenticator.registered.called: |
100 err = jabber_error.StreamError(u"Server unexpectedly closed the connection") | 100 err = jabber_error.StreamError("Server unexpectedly closed the connection") |
101 try: | 101 try: |
102 if reason.value.args[0][0][2] == "certificate verify failed": | 102 if reason.value.args[0][0][2] == "certificate verify failed": |
103 err = exceptions.InvalidCertificate() | 103 err = exceptions.InvalidCertificate() |
104 except (IndexError, TypeError): | 104 except (IndexError, TypeError): |
105 pass | 105 pass |
114 "inBandRegister", | 114 "inBandRegister", |
115 ".plugin", | 115 ".plugin", |
116 in_sign="ss", | 116 in_sign="ss", |
117 out_sign="", | 117 out_sign="", |
118 method=self._inBandRegister, | 118 method=self._inBandRegister, |
119 async=True, | 119 async_=True, |
120 ) | 120 ) |
121 host.bridge.addMethod( | 121 host.bridge.addMethod( |
122 "inBandAccountNew", | 122 "inBandAccountNew", |
123 ".plugin", | 123 ".plugin", |
124 in_sign="ssssi", | 124 in_sign="ssssi", |
125 out_sign="", | 125 out_sign="", |
126 method=self._registerNewAccount, | 126 method=self._registerNewAccount, |
127 async=True, | 127 async_=True, |
128 ) | 128 ) |
129 host.bridge.addMethod( | 129 host.bridge.addMethod( |
130 "inBandUnregister", | 130 "inBandUnregister", |
131 ".plugin", | 131 ".plugin", |
132 in_sign="ss", | 132 in_sign="ss", |
133 out_sign="", | 133 out_sign="", |
134 method=self._unregister, | 134 method=self._unregister, |
135 async=True, | 135 async_=True, |
136 ) | 136 ) |
137 host.bridge.addMethod( | 137 host.bridge.addMethod( |
138 "inBandPasswordChange", | 138 "inBandPasswordChange", |
139 ".plugin", | 139 ".plugin", |
140 in_sign="ss", | 140 in_sign="ss", |
141 out_sign="", | 141 out_sign="", |
142 method=self._changePassword, | 142 method=self._changePassword, |
143 async=True, | 143 async_=True, |
144 ) | 144 ) |
145 | 145 |
146 @staticmethod | 146 @staticmethod |
147 def buildRegisterIQ(xmlstream_, jid_, password, email=None): | 147 def buildRegisterIQ(xmlstream_, jid_, password, email=None): |
148 iq_elt = xmlstream.IQ(xmlstream_, "set") | 148 iq_elt = xmlstream.IQ(xmlstream_, "set") |
158 return iq_elt | 158 return iq_elt |
159 | 159 |
160 def _regCb(self, answer, client, post_treat_cb): | 160 def _regCb(self, answer, client, post_treat_cb): |
161 """Called after the first get IQ""" | 161 """Called after the first get IQ""" |
162 try: | 162 try: |
163 query_elt = answer.elements(NS_REG, "query").next() | 163 query_elt = next(answer.elements(NS_REG, "query")) |
164 except StopIteration: | 164 except StopIteration: |
165 raise exceptions.DataError("Can't find expected query element") | 165 raise exceptions.DataError("Can't find expected query element") |
166 | 166 |
167 try: | 167 try: |
168 x_elem = query_elt.elements(data_form.NS_X_DATA, "x").next() | 168 x_elem = next(query_elt.elements(data_form.NS_X_DATA, "x")) |
169 except StopIteration: | 169 except StopIteration: |
170 # XXX: it seems we have an old service which doesn't manage data forms | 170 # XXX: it seems we have an old service which doesn't manage data forms |
171 log.warning(_("Can't find data form")) | 171 log.warning(_("Can't find data form")) |
172 raise exceptions.DataError( | 172 raise exceptions.DataError( |
173 _("This gateway can't be managed by SàT, sorry :(") | 173 _("This gateway can't be managed by SàT, sorry :(") |
192 ) | 192 ) |
193 return xml_tools.dataForm2XMLUI(form, submit_reg_id) | 193 return xml_tools.dataForm2XMLUI(form, submit_reg_id) |
194 | 194 |
195 def _regEb(self, failure, client): | 195 def _regEb(self, failure, client): |
196 """Called when something is wrong with registration""" | 196 """Called when something is wrong with registration""" |
197 log.info(_("Registration failure: %s") % unicode(failure.value)) | 197 log.info(_("Registration failure: %s") % str(failure.value)) |
198 raise failure | 198 raise failure |
199 | 199 |
200 def _regSuccess(self, answer, client, post_treat_cb): | 200 def _regSuccess(self, answer, client, post_treat_cb): |
201 log.debug(_(u"registration answer: %s") % answer.toXml()) | 201 log.debug(_("registration answer: %s") % answer.toXml()) |
202 if post_treat_cb is not None: | 202 if post_treat_cb is not None: |
203 post_treat_cb(jid.JID(answer["from"]), client.profile) | 203 post_treat_cb(jid.JID(answer["from"]), client.profile) |
204 return {} | 204 return {} |
205 | 205 |
206 def _regFailure(self, failure, client): | 206 def _regFailure(self, failure, client): |
207 log.info(_(u"Registration failure: %s") % unicode(failure.value)) | 207 log.info(_("Registration failure: %s") % str(failure.value)) |
208 if failure.value.condition == "conflict": | 208 if failure.value.condition == "conflict": |
209 raise exceptions.ConflictError( | 209 raise exceptions.ConflictError( |
210 _("Username already exists, please choose an other one") | 210 _("Username already exists, please choose an other one") |
211 ) | 211 ) |
212 raise failure | 212 raise failure |
219 | 219 |
220 @param to_jid(jid.JID): jid of the service to register to | 220 @param to_jid(jid.JID): jid of the service to register to |
221 """ | 221 """ |
222 # FIXME: this post_treat_cb arguments seems wrong, check it | 222 # FIXME: this post_treat_cb arguments seems wrong, check it |
223 client = self.host.getClient(profile_key) | 223 client = self.host.getClient(profile_key) |
224 log.debug(_(u"Asking registration for {}").format(to_jid.full())) | 224 log.debug(_("Asking registration for {}").format(to_jid.full())) |
225 reg_request = client.IQ(u"get") | 225 reg_request = client.IQ("get") |
226 reg_request["from"] = client.jid.full() | 226 reg_request["from"] = client.jid.full() |
227 reg_request["to"] = to_jid.full() | 227 reg_request["to"] = to_jid.full() |
228 reg_request.addElement("query", NS_REG) | 228 reg_request.addElement("query", NS_REG) |
229 d = reg_request.send(to_jid.full()).addCallbacks( | 229 d = reg_request.send(to_jid.full()).addCallbacks( |
230 self._regCb, | 230 self._regCb, |
243 if port: | 243 if port: |
244 kwargs["port"] = port | 244 kwargs["port"] = port |
245 return self.registerNewAccount(jid.JID(jid_), password, **kwargs) | 245 return self.registerNewAccount(jid.JID(jid_), password, **kwargs) |
246 | 246 |
247 def registerNewAccount( | 247 def registerNewAccount( |
248 self, jid_, password, email=None, host=u"127.0.0.1", port=C.XMPP_C2S_PORT | 248 self, jid_, password, email=None, host="127.0.0.1", port=C.XMPP_C2S_PORT |
249 ): | 249 ): |
250 """register a new account on a XMPP server | 250 """register a new account on a XMPP server |
251 | 251 |
252 @param jid_(jid.JID): request jid to register | 252 @param jid_(jid.JID): request jid to register |
253 @param password(unicode): password of the account | 253 @param password(unicode): password of the account |
254 @param email(unicode): email of the account | 254 @param email(unicode): email of the account |
255 @param host(unicode): host of the server to register to | 255 @param host(unicode): host of the server to register to |
256 @param port(int): port of the server to register to | 256 @param port(int): port of the server to register to |
257 """ | 257 """ |
258 check_certificate = host != u"127.0.0.1" | 258 check_certificate = host != "127.0.0.1" |
259 authenticator = RegisteringAuthenticator( | 259 authenticator = RegisteringAuthenticator( |
260 jid_, password, email, check_certificate=check_certificate) | 260 jid_, password, email, check_certificate=check_certificate) |
261 registered_d = authenticator.registered | 261 registered_d = authenticator.registered |
262 server_register = ServerRegister(authenticator) | 262 server_register = ServerRegister(authenticator) |
263 reactor.connectTCP(host, port, server_register) | 263 reactor.connectTCP(host, port, server_register) |
288 DELETE THE XMPP ACCOUNT WITHOUT WARNING | 288 DELETE THE XMPP ACCOUNT WITHOUT WARNING |
289 @param to_jid(jid.JID): jid of the service or server | 289 @param to_jid(jid.JID): jid of the service or server |
290 """ | 290 """ |
291 iq_elt = client.IQ() | 291 iq_elt = client.IQ() |
292 iq_elt["to"] = to_jid.full() | 292 iq_elt["to"] = to_jid.full() |
293 query_elt = iq_elt.addElement((NS_REG, u"query")) | 293 query_elt = iq_elt.addElement((NS_REG, "query")) |
294 query_elt.addElement(u"remove") | 294 query_elt.addElement("remove") |
295 return iq_elt.send() | 295 return iq_elt.send() |