comparison src/core/xmpp.py @ 589:d1b4805124a1

Fix pep8 support in src/core.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 18 Jan 2013 17:55:35 +0100
parents 952322b1d490
children 84a6e83157c2
comparison
equal deleted inserted replaced
588:beaf6bec2fcd 589:d1b4805124a1
20 """ 20 """
21 21
22 from twisted.internet import task, defer 22 from twisted.internet import task, defer
23 from twisted.words.protocols.jabber import jid, xmlstream 23 from twisted.words.protocols.jabber import jid, xmlstream
24 from wokkel import client, disco, xmppim, generic, compat, delay 24 from wokkel import client, disco, xmppim, generic, compat, delay
25 from logging import debug, info, error 25 from logging import debug, info, warning, error
26 from sat.core import exceptions 26 from sat.core import exceptions
27 from calendar import timegm 27 from calendar import timegm
28 28
29 29
30 class SatXMPPClient(client.XMPPClient): 30 class SatXMPPClient(client.XMPPClient):
31 31
32 def __init__(self, host_app, profile, user_jid, password, host=None, port=5222): 32 def __init__(self, host_app, profile, user_jid, password, host=None, port=5222):
33 client.XMPPClient.__init__(self, user_jid, password, host, port) 33 client.XMPPClient.__init__(self, user_jid, password, host, port)
34 self.factory.clientConnectionLost = self.connectionLost 34 self.factory.clientConnectionLost = self.connectionLost
35 self.__connected=False 35 self.__connected = False
36 self.profile = profile 36 self.profile = profile
37 self.host_app = host_app 37 self.host_app = host_app
38 self.client_initialized = defer.Deferred() 38 self.client_initialized = defer.Deferred()
39 self.conn_deferred = defer.Deferred() 39 self.conn_deferred = defer.Deferred()
40 self._waiting_conf = {} #callback called when a confirmation is received 40 self._waiting_conf = {} # callback called when a confirmation is received
41 self._progress_cb_map = {} #callback called when a progress is requested (key = progress id) 41 self._progress_cb_map = {} # callback called when a progress is requested (key = progress id)
42
43 42
44 def getConnectionDeferred(self): 43 def getConnectionDeferred(self):
45 """Return a deferred which fire when the client is connected""" 44 """Return a deferred which fire when the client is connected"""
46 return self.conn_deferred 45 return self.conn_deferred
47 46
48 def _authd(self, xmlstream): 47 def _authd(self, xmlstream):
49 if not self.host_app.trigger.point("XML Initialized", xmlstream, self.profile): 48 if not self.host_app.trigger.point("XML Initialized", xmlstream, self.profile):
50 return 49 return
51 client.XMPPClient._authd(self, xmlstream) 50 client.XMPPClient._authd(self, xmlstream)
52 self.__connected=True 51 self.__connected = True
53 info (_("********** [%s] CONNECTED **********") % self.profile) 52 info(_("********** [%s] CONNECTED **********") % self.profile)
54 self.streamInitialized() 53 self.streamInitialized()
55 self.host_app.bridge.connected(self.profile) #we send the signal to the clients 54 self.host_app.bridge.connected(self.profile) # we send the signal to the clients
56
57 55
58 def streamInitialized(self): 56 def streamInitialized(self):
59 """Called after _authd""" 57 """Called after _authd"""
60 debug (_("XML stream is initialized")) 58 debug(_("XML stream is initialized"))
61 self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") #Needed to avoid disconnection (specially with openfire) 59 self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") # Needed to avoid disconnection (specially with openfire)
62 self.keep_alife.start(180) 60 self.keep_alife.start(180)
63 61
64 self.disco = SatDiscoProtocol(self) 62 self.disco = SatDiscoProtocol(self)
65 self.disco.setHandlerParent(self) 63 self.disco.setHandlerParent(self)
66 self.discoHandler = disco.DiscoHandler() 64 self.discoHandler = disco.DiscoHandler()
71 69
72 self.roster.requestRoster() 70 self.roster.requestRoster()
73 71
74 self.presence.available() 72 self.presence.available()
75 73
76 self.disco.requestInfo(jid.JID(self.jid.host)).addCallback(self.host_app.serverDisco, self.profile) #FIXME: use these informations 74 self.disco.requestInfo(jid.JID(self.jid.host)).addCallback(self.host_app.serverDisco, self.profile) # FIXME: use these informations
77 75
78 self.disco.requestItems(jid.JID(self.jid.host)).addCallback(self.host_app.serverDiscoItems, self.disco, self.profile, self.client_initialized) 76 self.disco.requestItems(jid.JID(self.jid.host)).addCallback(self.host_app.serverDiscoItems, self.disco, self.profile, self.client_initialized)
79 self.conn_deferred.callback(None) 77 self.conn_deferred.callback(None)
80 78
81 def initializationFailed(self, reason): 79 def initializationFailed(self, reason):
82 print ("initializationFailed: %s" % reason) 80 print "initializationFailed: %s" % reason
83 self.host_app.bridge.connectionError("AUTH_ERROR", self.profile) 81 self.host_app.bridge.connectionError("AUTH_ERROR", self.profile)
84 try: 82 try:
85 client.XMPPClient.initializationFailed(self, reason) 83 client.XMPPClient.initializationFailed(self, reason)
86 except: 84 except:
87 #we already send an error signal, no need to raise an exception 85 # we already send an error signal, no need to raise an exception
88 pass 86 pass
89 self.conn_deferred.errback() 87 self.conn_deferred.errback()
90 88
91 def isConnected(self): 89 def isConnected(self):
92 return self.__connected 90 return self.__connected
93 91
94 def connectionLost(self, connector, unused_reason): 92 def connectionLost(self, connector, unused_reason):
95 self.__connected=False 93 self.__connected = False
96 info (_("********** [%s] DISCONNECTED **********") % self.profile) 94 info(_("********** [%s] DISCONNECTED **********") % self.profile)
97 try: 95 try:
98 self.keep_alife.stop() 96 self.keep_alife.stop()
99 except AttributeError: 97 except AttributeError:
100 debug (_("No keep_alife")) 98 debug(_("No keep_alife"))
101 self.host_app.bridge.disconnected(self.profile) #we send the signal to the clients 99 self.host_app.bridge.disconnected(self.profile) # we send the signal to the clients
102 self.host_app.purgeClient(self.profile) #and we remove references to this client 100 self.host_app.purgeClient(self.profile) # and we remove references to this client
103 101
104 102
105 class SatMessageProtocol(xmppim.MessageProtocol): 103 class SatMessageProtocol(xmppim.MessageProtocol):
106 104
107 def __init__(self, host): 105 def __init__(self, host):
108 xmppim.MessageProtocol.__init__(self) 106 xmppim.MessageProtocol.__init__(self)
109 self.host = host 107 self.host = host
110 108
111 def onMessage(self, message): 109 def onMessage(self, message):
112 debug (_(u"got message from: %s"), message["from"]) 110 debug(_(u"got message from: %s"), message["from"])
113 if not self.host.trigger.point("MessageReceived", message, profile=self.parent.profile): 111 if not self.host.trigger.point("MessageReceived", message, profile=self.parent.profile):
114 return 112 return
115 for e in message.elements(): 113 for e in message.elements():
116 if e.name == "body": 114 if e.name == "body":
117 mess_type = message['type'] if message.hasAttribute('type') else 'normal' 115 mess_type = message['type'] if message.hasAttribute('type') else 'normal'
118 mess_body = e.children[0] if e.children else "" 116 mess_body = e.children[0] if e.children else ""
119 try: 117 try:
120 _delay = delay.Delay.fromElement(filter(lambda elm: elm.name == 'delay', message.elements())[0]) 118 _delay = delay.Delay.fromElement(filter(lambda elm: elm.name == 'delay', message.elements())[0])
121 timestamp = timegm(_delay.stamp.utctimetuple()) 119 timestamp = timegm(_delay.stamp.utctimetuple())
122 extra = {"archive": str(timestamp)} 120 extra = {"archive": str(timestamp)}
123 if mess_type != 'groupchat': #XXX: we don't save delayed messages in history for groupchats 121 if mess_type != 'groupchat': # XXX: we don't save delayed messages in history for groupchats
124 #TODO: add delayed messages to history if they aren't already in it 122 #TODO: add delayed messages to history if they aren't already in it
125 self.host.memory.addToHistory(jid.JID(message["from"]), jid.JID(message["to"]), mess_body, mess_type, timestamp, profile=self.parent.profile) 123 self.host.memory.addToHistory(jid.JID(message["from"]), jid.JID(message["to"]), mess_body, mess_type, timestamp, profile=self.parent.profile)
126 except IndexError: 124 except IndexError:
127 extra = {} 125 extra = {}
128 self.host.memory.addToHistory(jid.JID(message["from"]), jid.JID(message["to"]), mess_body, mess_type, profile=self.parent.profile) 126 self.host.memory.addToHistory(jid.JID(message["from"]), jid.JID(message["to"]), mess_body, mess_type, profile=self.parent.profile)
129 self.host.bridge.newMessage(message["from"], mess_body, mess_type, message['to'], extra, profile=self.parent.profile) 127 self.host.bridge.newMessage(message["from"], mess_body, mess_type, message['to'], extra, profile=self.parent.profile)
130 break 128 break
131 129
130
132 class SatRosterProtocol(xmppim.RosterClientProtocol): 131 class SatRosterProtocol(xmppim.RosterClientProtocol):
133 132
134 def __init__(self, host): 133 def __init__(self, host):
135 xmppim.RosterClientProtocol.__init__(self) 134 xmppim.RosterClientProtocol.__init__(self)
136 self.host = host 135 self.host = host
137 self.got_roster = defer.Deferred() 136 self.got_roster = defer.Deferred()
138 #XXX: the two following dicts keep a local copy of the roster 137 #XXX: the two following dicts keep a local copy of the roster
139 self._groups = {} #map from groups to bare jids: key=group value=set of bare jids 138 self._groups = {} # map from groups to bare jids: key=group value=set of bare jids
140 self._jids = {} #map from bare jids to RosterItem: key=jid value=RosterItem 139 self._jids = {} # map from bare jids to RosterItem: key=jid value=RosterItem
141 140
142 def rosterCb(self, roster): 141 def rosterCb(self, roster):
143 for raw_jid, item in roster.iteritems(): 142 for raw_jid, item in roster.iteritems():
144 self.onRosterSet(item) 143 self.onRosterSet(item)
145 144
191 def onRosterSet(self, item): 190 def onRosterSet(self, item):
192 """Called when a new/update roster item is received""" 191 """Called when a new/update roster item is received"""
193 #TODO: send a signal to frontends 192 #TODO: send a signal to frontends
194 if not item.subscriptionTo and not item.subscriptionFrom and not item.ask: 193 if not item.subscriptionTo and not item.subscriptionFrom and not item.ask:
195 #XXX: current behaviour: we don't want contact in our roster list 194 #XXX: current behaviour: we don't want contact in our roster list
196 #if there is no presence subscription 195 # if there is no presence subscription
197 #may change in the future 196 # may change in the future
198 self.removeItem(item.jid) 197 self.removeItem(item.jid)
199 return 198 return
200 info (_("new contact in roster list: %s"), item.jid.full()) 199 info(_("new contact in roster list: %s"), item.jid.full())
201 #self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile) 200 #self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile)
202 201
203 bare_jid = item.jid.userhost() 202 bare_jid = item.jid.userhost()
204 self._jids[bare_jid] = item 203 self._jids[bare_jid] = item
205 for group in item.groups: 204 for group in item.groups:
206 self._groups.setdefault(group,set()).add(bare_jid) 205 self._groups.setdefault(group, set()).add(bare_jid)
207 self.host.bridge.newContact(item.jid.full(), self.getAttributes(item), item.groups, self.parent.profile) 206 self.host.bridge.newContact(item.jid.full(), self.getAttributes(item), item.groups, self.parent.profile)
208 207
209 def onRosterRemove(self, entity): 208 def onRosterRemove(self, entity):
210 """Called when a roster removal event is received""" 209 """Called when a roster removal event is received"""
211 print _("removing %s from roster list") % entity.full() 210 print _("removing %s from roster list") % entity.full()
212 bare_jid = entity.userhost() 211 bare_jid = entity.userhost()
213 212
214 #we first remove item from local cache (self._groups and self._jids) 213 # we first remove item from local cache (self._groups and self._jids)
215 try: 214 try:
216 item = self._jids.pop(bare_jid) 215 item = self._jids.pop(bare_jid)
217 except KeyError: 216 except KeyError:
218 log.warning("Received a roster remove event for an item not in cache") 217 warning("Received a roster remove event for an item not in cache")
219 return 218 return
220 for group in item.groups: 219 for group in item.groups:
221 try: 220 try:
222 jids_set = self._groups[group] 221 jids_set = self._groups[group]
223 jids_set.remove(bare_jid) 222 jids_set.remove(bare_jid)
224 if not jids_set: 223 if not jids_set:
225 del self._groups[group] 224 del self._groups[group]
226 except KeyError: 225 except KeyError:
227 log.warning("there is not cache for the group [%(groups)s] of the removed roster item [%(jid)s]" % 226 warning("there is not cache for the group [%(groups)s] of the removed roster item [%(jid)s]" %
228 {"group": group, "jid": bare_jid}) 227 {"group": group, "jid": bare_jid})
229 228
230 #then we send the bridge signal 229 # then we send the bridge signal
231 self.host.bridge.contactDeleted(entity.userhost(), self.parent.profile) 230 self.host.bridge.contactDeleted(entity.userhost(), self.parent.profile)
232 231
233 def getGroups(self): 232 def getGroups(self):
234 """Return a list of groups""" 233 """Return a list of groups"""
235 return self._groups.keys() 234 return self._groups.keys()
254 253
255 def getJidsFromGroup(self, group): 254 def getJidsFromGroup(self, group):
256 try: 255 try:
257 return self._groups[group] 256 return self._groups[group]
258 except KeyError: 257 except KeyError:
259 return exceptions.UnknownGroupError 258 return exceptions.UnknownGroupError
260 259
261 260
262 class SatPresenceProtocol(xmppim.PresenceClientProtocol): 261 class SatPresenceProtocol(xmppim.PresenceClientProtocol):
263 262
264 def __init__(self, host): 263 def __init__(self, host):
265 xmppim.PresenceClientProtocol.__init__(self) 264 xmppim.PresenceClientProtocol.__init__(self)
266 self.host = host 265 self.host = host
267 266
268 def availableReceived(self, entity, show=None, statuses=None, priority=0): 267 def availableReceived(self, entity, show=None, statuses=None, priority=0):
269 debug (_("presence update for [%(entity)s] (available, show=%(show)s statuses=%(statuses)s priority=%(priority)d)") % {'entity':entity, 'show':show, 'statuses':statuses, 'priority':priority}) 268 debug(_("presence update for [%(entity)s] (available, show=%(show)s statuses=%(statuses)s priority=%(priority)d)") % {'entity': entity, 'show': show, 'statuses': statuses, 'priority': priority})
270 269
271 if not statuses: 270 if not statuses:
272 statuses = {} 271 statuses = {}
273 272
274 if statuses.has_key(None): #we only want string keys 273 if None in statuses: # we only want string keys
275 statuses["default"] = statuses[None] 274 statuses["default"] = statuses[None]
276 del statuses[None] 275 del statuses[None]
277 276
278 self.host.memory.setPresenceStatus(entity, show or "", 277 self.host.memory.setPresenceStatus(entity, show or "",
279 int(priority), statuses, self.parent.profile) 278 int(priority), statuses,
280 279 self.parent.profile)
281 #now it's time to notify frontends 280
282 self.host.bridge.presenceUpdate(entity.full(), show or "", 281 # now it's time to notify frontends
283 int(priority), statuses, self.parent.profile) 282 self.host.bridge.presenceUpdate(entity.full(), show or "",
283 int(priority), statuses,
284 self.parent.profile)
284 285
285 def unavailableReceived(self, entity, statuses=None): 286 def unavailableReceived(self, entity, statuses=None):
286 debug (_("presence update for [%(entity)s] (unavailable, statuses=%(statuses)s)") % {'entity':entity, 'statuses':statuses}) 287 debug(_("presence update for [%(entity)s] (unavailable, statuses=%(statuses)s)") % {'entity': entity, 'statuses': statuses})
287 288
288 if not statuses: 289 if not statuses:
289 statuses = {} 290 statuses = {}
290 291
291 if statuses.has_key(None): #we only want string keys 292 if None in statuses: # we only want string keys
292 statuses["default"] = statuses[None] 293 statuses["default"] = statuses[None]
293 del statuses[None] 294 del statuses[None]
294 self.host.memory.setPresenceStatus(entity, "unavailable", 0, statuses, self.parent.profile) 295 self.host.memory.setPresenceStatus(entity, "unavailable", 0, statuses, self.parent.profile)
295 296
296 #now it's time to notify frontends 297 # now it's time to notify frontends
297 self.host.bridge.presenceUpdate(entity.full(), "unavailable", 0, statuses, self.parent.profile) 298 self.host.bridge.presenceUpdate(entity.full(), "unavailable", 0, statuses, self.parent.profile)
298
299 299
300 def available(self, entity=None, show=None, statuses=None, priority=0): 300 def available(self, entity=None, show=None, statuses=None, priority=0):
301 if not statuses: 301 if not statuses:
302 statuses = {} 302 statuses = {}
303 # default for us is None for wokkel 303 # default for us is None for wokkel
317 317
318 def subscribed(self, entity): 318 def subscribed(self, entity):
319 xmppim.PresenceClientProtocol.subscribed(self, entity) 319 xmppim.PresenceClientProtocol.subscribed(self, entity)
320 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) 320 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
321 item = self.parent.roster.getItem(entity) 321 item = self.parent.roster.getItem(entity)
322 if not item or not item.subscriptionTo: #we automatically subscribe to 'to' presence 322 if not item or not item.subscriptionTo: # we automatically subscribe to 'to' presence
323 debug(_('sending automatic "from" subscription request')) 323 debug(_('sending automatic "from" subscription request'))
324 self.subscribe(entity) 324 self.subscribe(entity)
325 325
326 def unsubscribed(self, entity): 326 def unsubscribed(self, entity):
327 xmppim.PresenceClientProtocol.unsubscribed(self, entity) 327 xmppim.PresenceClientProtocol.unsubscribed(self, entity)
328 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) 328 self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
329 329
330 def subscribedReceived(self, entity): 330 def subscribedReceived(self, entity):
331 debug (_("subscription approved for [%s]") % entity.userhost()) 331 debug(_("subscription approved for [%s]") % entity.userhost())
332 self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile) 332 self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile)
333 333
334 def unsubscribedReceived(self, entity): 334 def unsubscribedReceived(self, entity):
335 debug (_("unsubscription confirmed for [%s]") % entity.userhost()) 335 debug(_("unsubscription confirmed for [%s]") % entity.userhost())
336 self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile) 336 self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile)
337 337
338 def subscribeReceived(self, entity): 338 def subscribeReceived(self, entity):
339 debug (_("subscription request from [%s]") % entity.userhost()) 339 debug(_("subscription request from [%s]") % entity.userhost())
340 item = self.parent.roster.getItem(entity) 340 item = self.parent.roster.getItem(entity)
341 if item and item.subscriptionTo: 341 if item and item.subscriptionTo:
342 #We automatically accept subscription if we are already subscribed to contact presence 342 # We automatically accept subscription if we are already subscribed to contact presence
343 debug(_('sending automatic subscription acceptance')) 343 debug(_('sending automatic subscription acceptance'))
344 self.subscribed(entity) 344 self.subscribed(entity)
345 else: 345 else:
346 self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile) 346 self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile)
347 self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile) 347 self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile)
348 348
349 def unsubscribeReceived(self, entity): 349 def unsubscribeReceived(self, entity):
350 debug (_("unsubscription asked for [%s]") % entity.userhost()) 350 debug(_("unsubscription asked for [%s]") % entity.userhost())
351 item = self.parent.roster.getItem(entity) 351 item = self.parent.roster.getItem(entity)
352 if item and item.subscriptionFrom: #we automatically remove contact 352 if item and item.subscriptionFrom: # we automatically remove contact
353 debug(_('automatic contact deletion')) 353 debug(_('automatic contact deletion'))
354 self.host.delContact(entity.userhost(), self.parent.profile) 354 self.host.delContact(entity.userhost(), self.parent.profile)
355 self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile) 355 self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile)
356 356
357
357 class SatDiscoProtocol(disco.DiscoClientProtocol): 358 class SatDiscoProtocol(disco.DiscoClientProtocol):
358 def __init__(self, host): 359 def __init__(self, host):
359 disco.DiscoClientProtocol.__init__(self) 360 disco.DiscoClientProtocol.__init__(self)
360 361
362
361 class SatFallbackHandler(generic.FallbackHandler): 363 class SatFallbackHandler(generic.FallbackHandler):
362 def __init__(self, host): 364 def __init__(self, host):
363 generic.FallbackHandler.__init__(self) 365 generic.FallbackHandler.__init__(self)
364 366
365 def iqFallback(self, iq): 367 def iqFallback(self, iq):
366 if iq.handled == True: 368 if iq.handled is True:
367 return 369 return
368 debug (u"iqFallback: xml = [%s]" % (iq.toXml())) 370 debug(u"iqFallback: xml = [%s]" % (iq.toXml()))
369 generic.FallbackHandler.iqFallback(self, iq) 371 generic.FallbackHandler.iqFallback(self, iq)
372
370 373
371 class RegisteringAuthenticator(xmlstream.ConnectAuthenticator): 374 class RegisteringAuthenticator(xmlstream.ConnectAuthenticator):
372 375
373 def __init__(self, host, jabber_host, user_login, user_pass, email, answer_id, profile): 376 def __init__(self, host, jabber_host, user_login, user_pass, email, answer_id, profile):
374 xmlstream.ConnectAuthenticator.__init__(self, jabber_host) 377 xmlstream.ConnectAuthenticator.__init__(self, jabber_host)
377 self.user_login = user_login 380 self.user_login = user_login
378 self.user_pass = user_pass 381 self.user_pass = user_pass
379 self.user_email = email 382 self.user_email = email
380 self.answer_id = answer_id 383 self.answer_id = answer_id
381 self.profile = profile 384 self.profile = profile
382 print _("Registration asked for"),user_login, user_pass, jabber_host 385 print _("Registration asked for"), user_login, user_pass, jabber_host
383 386
384 def connectionMade(self): 387 def connectionMade(self):
385 print "connectionMade" 388 print "connectionMade"
386 389
387 self.xmlstream.namespace = "jabber:client" 390 self.xmlstream.namespace = "jabber:client"
398 _email = query.addElement('email') 401 _email = query.addElement('email')
399 _email.addContent(self.user_email) 402 _email.addContent(self.user_email)
400 reg = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure) 403 reg = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure)
401 404
402 def registrationAnswer(self, answer): 405 def registrationAnswer(self, answer):
403 debug (_("registration answer: %s") % answer.toXml()) 406 debug(_("registration answer: %s") % answer.toXml())
404 answer_type = "SUCCESS" 407 answer_type = "SUCCESS"
405 answer_data={"message":_("Registration successfull")} 408 answer_data = {"message": _("Registration successfull")}
406 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data, self.profile) 409 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data, self.profile)
407 self.xmlstream.sendFooter() 410 self.xmlstream.sendFooter()
408 411
409 def registrationFailure(self, failure): 412 def registrationFailure(self, failure):
410 info (_("Registration failure: %s") % str(failure.value)) 413 info(_("Registration failure: %s") % str(failure.value))
411 answer_type = "ERROR" 414 answer_type = "ERROR"
412 answer_data = {} 415 answer_data = {}
413 if failure.value.condition == 'conflict': 416 if failure.value.condition == 'conflict':
414 answer_data['reason'] = 'conflict' 417 answer_data['reason'] = 'conflict'
415 answer_data={"message":_("Username already exists, please choose an other one")} 418 answer_data = {"message": _("Username already exists, please choose an other one")}
416 else: 419 else:
417 answer_data['reason'] = 'unknown' 420 answer_data['reason'] = 'unknown'
418 answer_data={"message":_("Registration failed (%s)") % str(failure.value.condition)} 421 answer_data = {"message": _("Registration failed (%s)") % str(failure.value.condition)}
419 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data, self.profile) 422 self.host.bridge.actionResult(answer_type, self.answer_id, answer_data, self.profile)
420 self.xmlstream.sendFooter() 423 self.xmlstream.sendFooter()
424
421 425
422 class SatVersionHandler(generic.VersionHandler): 426 class SatVersionHandler(generic.VersionHandler):
423 427
424 def getDiscoInfo(self, requestor, target, node): 428 def getDiscoInfo(self, requestor, target, node):
425 #XXX: We need to work around wokkel's behaviour (namespace not added if there is a 429 #XXX: We need to work around wokkel's behaviour (namespace not added if there is a
426 # node) as it cause issues with XEP-0115 & PEP (XEP-0163): there is a node when server 430 # node) as it cause issues with XEP-0115 & PEP (XEP-0163): there is a node when server
427 # ask for disco info, and not when we generate the key, so the hash is used with different 431 # ask for disco info, and not when we generate the key, so the hash is used with different
428 # disco features, and when the server (seen on ejabberd) generate its own hash for security check 432 # disco features, and when the server (seen on ejabberd) generate its own hash for security check
429 # it reject our features (resulting in e.g. no notification on PEP) 433 # it reject our features (resulting in e.g. no notification on PEP)
430 return generic.VersionHandler.getDiscoInfo(self, requestor, target, None) 434 return generic.VersionHandler.getDiscoInfo(self, requestor, target, None)
431