comparison src/plugins/plugin_xep_0077.py @ 807:be4c5e24dab9

plugin XEP-0077, plugin XEP-0100, frontends: gateways have been entirely implemented in backend using the new refactored XMLUI and AdvancedListContainer. The now useless code has been removed from frontends.
author Goffi <goffi@goffi.org>
date Tue, 04 Feb 2014 18:26:03 +0100
parents bfabeedbf32e
children 1fe00f0c9a91
comparison
equal deleted inserted replaced
806:5d6c45d6ee1b 807:be4c5e24dab9
16 16
17 # You should have received a copy of the GNU Affero General Public License 17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from logging import debug, info, error 21 from sat.core import exceptions
22 from logging import debug, info, warning, error
22 from twisted.words.protocols.jabber import jid 23 from twisted.words.protocols.jabber import jid
23 from twisted.words.protocols.jabber.xmlstream import IQ 24 from twisted.words.protocols.jabber.xmlstream import IQ
24 from sat.tools.xml_tools import dataForm2XMLUI 25 from sat.tools import xml_tools
26 from sat.memory import memory
25 27
26 from wokkel import data_form 28 from wokkel import data_form, compat
27 29
28 NS_REG = 'jabber:iq:register' 30 NS_REG = 'jabber:iq:register'
29 31
30 PLUGIN_INFO = { 32 PLUGIN_INFO = {
31 "name": "XEP 0077 Plugin", 33 "name": "XEP 0077 Plugin",
42 44
43 def __init__(self, host): 45 def __init__(self, host):
44 info(_("Plugin XEP_0077 initialization")) 46 info(_("Plugin XEP_0077 initialization"))
45 self.host = host 47 self.host = host
46 self.triggers = {} # used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid 48 self.triggers = {} # used by other protocol (e.g. XEP-0100) to finish registration. key = target_jid
47 host.bridge.addMethod("in_band_register", ".plugin", in_sign='ss', out_sign='s', method=self.in_band_register) 49 host.bridge.addMethod("inBandRegister", ".plugin", in_sign='ss', out_sign='s',
48 host.bridge.addMethod("in_band_submit", ".plugin", in_sign='ssa(ss)s', out_sign='s', method=self.in_band_submit) 50 method=self._inBandRegister,
51 async=True)
49 52
50 def addTrigger(self, target, cb, profile): 53 def _regOk(self, answer, client, post_treat_cb):
51 """Add a callback which is called when registration to target is successful"""
52 self.triggers[target] = (cb, profile)
53
54 def reg_ok(self, answer, profile):
55 """Called after the first get IQ""" 54 """Called after the first get IQ"""
56 try: 55 try:
57 x_elem = filter(lambda x: x.name == "x", answer.firstChildElement().elements())[0] # We only want the "x" element (data form) 56 query_elt = answer.elements(NS_REG, 'query').next()
58 except IndexError: 57 except StopIteration:
59 info(_("No data form found")) 58 raise exceptions.DataError("Can't find expected query element")
60 #TODO: manage registration without data form 59
61 answer_data = {"reason": "unmanaged", "message": _("This gateway can't be managed by SàT, sorry :(")} 60 try:
62 answer_type = "ERROR" 61 x_elem = query_elt.elements(data_form.NS_X_DATA, 'x').next()
63 self.host.bridge.actionResult(answer_type, answer['id'], answer_data, profile) 62 except StopIteration:
64 return 63 # XXX: it seems we have an old service which doesn't manage data forms
64 warning(_("Can't find data form"))
65 raise DataError(_("This gateway can't be managed by SàT, sorry :("))
66
67 def submitForm(data, profile):
68 form_elt = xml_tools.XMLUIResultToElt(data)
69
70 iq_elt = compat.IQ(client.xmlstream, 'set')
71 iq_elt['id'] = answer['id']
72 iq_elt['to'] = answer['from']
73 query_elt = iq_elt.addElement("query", NS_REG)
74 query_elt.addChild(form_elt)
75 d = iq_elt.send()
76 d.addCallback(self._regSuccess, client, post_treat_cb)
77 d.addErrback(self._regFailure, client)
78 return d
65 79
66 form = data_form.Form.fromElement(x_elem) 80 form = data_form.Form.fromElement(x_elem)
67 xml_data = dataForm2XMLUI(form, "").toXml() 81 submit_reg_id = self.host.registerCallback(submitForm, with_data=True, one_shot=True)
68 self.host.bridge.actionResult("XMLUI", answer['id'], {"target": answer["from"], "type": "registration", "xml": xml_data}, profile) 82 return xml_tools.dataForm2XMLUI(form, submit_reg_id)
69 83
70 def reg_err(self, failure, profile): 84 def _regErr(self, failure, client):
71 """Called when something is wrong with registration""" 85 """Called when something is wrong with registration"""
72 info(_("Registration failure: %s") % str(failure.value)) 86 info(_("Registration failure: %s") % str(failure.value))
73 answer_data = {} 87 raise failure
74 answer_data['reason'] = 'unknown'
75 answer_data = {"message": "%s [code: %s]" % (failure.value.condition, unicode(failure.value))}
76 answer_type = "ERROR"
77 self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data, profile)
78 88
79 def unregistrationAnswer(self, answer, profile): 89 def _regSuccess(self, answer, client, post_treat_cb):
80 debug(_("registration answer: %s") % answer.toXml()) 90 debug(_("registration answer: %s") % answer.toXml())
81 answer_type = "SUCCESS" 91 if post_treat_cb is not None:
82 answer_data = {"message": _("Your are now unregistred")} 92 post_treat_cb(jid.JID(answer['from']), client.profile)
83 self.host.bridge.actionResult(answer_type, answer['id'], answer_data, profile) 93 return {}
84 94
85 def unregistrationFailure(self, failure, profile): 95 def _regFailure(self, failure, client):
86 info(_("Unregistration failure: %s") % str(failure.value)) 96 info(_("Registration failure: %s") % str(failure.value))
87 answer_type = "ERROR" 97 if failure.value.condition == 'conflict':
88 answer_data = {} 98 raise exceptions.ConflictError( _("Username already exists, please choose an other one"))
89 answer_data['reason'] = 'unknown' 99 raise failure
90 answer_data = {"message": _("Unregistration failed: %s") % failure.value.condition}
91 self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data, profile)
92 100
93 def registrationAnswer(self, answer, profile): 101 def _inBandRegister(self, to_jid_s, profile_key='@NONE@'):
94 debug(_("registration answer: %s") % answer.toXml()) 102 return self.inBandRegister, jid.JID(to_jid_s, profile_key)
95 answer_type = "SUCCESS"
96 answer_data = {"message": _("Registration successfull")}
97 self.host.bridge.actionResult(answer_type, answer['id'], answer_data, profile)
98 if answer["from"] in self.triggers:
99 callback, profile = self.triggers[answer["from"]]
100 callback(answer["from"], profile)
101 del self.triggers[answer["from"]]
102 103
103 def registrationFailure(self, failure, profile): 104 def inBandRegister(self, to_jid, post_treat_cb=None, profile_key='@NONE@'):
104 info(_("Registration failure: %s") % str(failure.value))
105 print failure.value.stanza.toXml()
106 answer_type = "ERROR"
107 answer_data = {}
108 if failure.value.condition == 'conflict':
109 answer_data['reason'] = 'conflict'
110 answer_data = {"message": _("Username already exists, please choose an other one")}
111 else:
112 answer_data['reason'] = 'unknown'
113 answer_data = {"message": _("Registration failed")}
114 self.host.bridge.actionResult(answer_type, failure.value.stanza['id'], answer_data, profile)
115 if failure.value.stanza["from"] in self.triggers:
116 del self.triggers[failure.value.stanza["from"]]
117
118 def in_band_submit(self, action, target, fields, profile):
119 """Submit a form for registration, using data_form"""
120 id, deferred = self.host.submitForm(action, target, fields, profile)
121 if action == 'CANCEL':
122 deferred.addCallbacks(self.unregistrationAnswer, self.unregistrationFailure, callbackArgs=[profile], errbackArgs=[profile])
123 else:
124 deferred.addCallbacks(self.registrationAnswer, self.registrationFailure, callbackArgs=[profile], errbackArgs=[profile])
125 return id
126
127 def in_band_register(self, target, profile_key='@DEFAULT@'):
128 """register to a target JID""" 105 """register to a target JID"""
129 client = self.host.getClient(profile_key) 106 client = self.host.getClient(profile_key)
130 if not client: 107 if not client:
131 error(_('Asking for an non-existant or not connected profile')) 108 raise exceptions.ProfileUnknownError
132 return ""
133 to_jid = jid.JID(target)
134 debug(_("Asking registration for [%s]") % to_jid.full()) 109 debug(_("Asking registration for [%s]") % to_jid.full())
135 reg_request = IQ(client.xmlstream, 'get') 110 reg_request = IQ(client.xmlstream, 'get')
136 reg_request["from"] = client.jid.full() 111 reg_request["from"] = client.jid.full()
137 reg_request["to"] = to_jid.full() 112 reg_request["to"] = to_jid.full()
138 reg_request.addElement('query', NS_REG) 113 reg_request.addElement('query', NS_REG)
139 reg_request.send(to_jid.full()).addCallbacks(self.reg_ok, self.reg_err, callbackArgs=[client.profile], errbackArgs=[client.profile]) 114 d = reg_request.send(to_jid.full()).addCallbacks(self._regOk, self._regErr, callbackArgs=[client, post_treat_cb], errbackArgs=[client])
140 return reg_request["id"] 115 return d