Core: created a new core module where xmpp classes are put
This commit is contained in:
parent
ec76bc8011
commit
021d926b27
3 changed files with 285 additions and 258 deletions
0
src/core/__init__.py
Normal file
0
src/core/__init__.py
Normal file
284
src/core/xmpp.py
Normal file
284
src/core/xmpp.py
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
SAT: a jabber client
|
||||
Copyright (C) 2009, 2010, 2011 Jérôme Poisson (goffi@goffi.org)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from twisted.internet import task, defer
|
||||
from twisted.words.protocols.jabber import jid, xmlstream
|
||||
from wokkel import client, disco, xmppim, generic, compat
|
||||
from logging import debug, info, error
|
||||
|
||||
class SatXMPPClient(client.XMPPClient):
|
||||
|
||||
def __init__(self, host_app, profile, user_jid, password, host=None, port=5222):
|
||||
client.XMPPClient.__init__(self, user_jid, password, host, port)
|
||||
self.factory.clientConnectionLost = self.connectionLost
|
||||
self.__connected=False
|
||||
self.profile = profile
|
||||
self.host_app = host_app
|
||||
self.client_initialized = defer.Deferred()
|
||||
|
||||
def _authd(self, xmlstream):
|
||||
if not self.host_app.trigger.point("XML Initialized", xmlstream, self.profile):
|
||||
return
|
||||
client.XMPPClient._authd(self, xmlstream)
|
||||
self.__connected=True
|
||||
info (_("********** [%s] CONNECTED **********") % self.profile)
|
||||
self.streamInitialized()
|
||||
self.host_app.bridge.connected(self.profile) #we send the signal to the clients
|
||||
|
||||
|
||||
def streamInitialized(self):
|
||||
"""Called after _authd"""
|
||||
debug (_("XML stream is initialized"))
|
||||
self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") #Needed to avoid disconnection (specially with openfire)
|
||||
self.keep_alife.start(180)
|
||||
|
||||
self.disco = SatDiscoProtocol(self)
|
||||
self.disco.setHandlerParent(self)
|
||||
self.discoHandler = disco.DiscoHandler()
|
||||
self.discoHandler.setHandlerParent(self)
|
||||
|
||||
if not self.host_app.trigger.point("Disco Handled", self.profile):
|
||||
return
|
||||
|
||||
self.roster.requestRoster()
|
||||
|
||||
self.presence.available()
|
||||
|
||||
self.disco.requestInfo(jid.JID(self.host_app.memory.getParamA("Server", "Connection", profile_key=self.profile))).addCallback(self.host_app.serverDisco, self.profile) #FIXME: use these informations
|
||||
self.disco.requestItems(jid.JID(self.host_app.memory.getParamA("Server", "Connection", profile_key=self.profile))).addCallback(self.host_app.serverDiscoItems, self.disco, self.profile, self.client_initialized)
|
||||
|
||||
def initializationFailed(self, reason):
|
||||
print ("initializationFailed: %s" % reason)
|
||||
self.host_app.bridge.connectionError("AUTH_ERROR", self.profile)
|
||||
try:
|
||||
client.XMPPClient.initializationFailed(self, reason)
|
||||
except:
|
||||
#we already send an error signal, no need to raise an exception
|
||||
pass
|
||||
|
||||
def isConnected(self):
|
||||
return self.__connected
|
||||
|
||||
def connectionLost(self, connector, unused_reason):
|
||||
self.__connected=False
|
||||
info (_("********** [%s] DISCONNECTED **********") % self.profile)
|
||||
try:
|
||||
self.keep_alife.stop()
|
||||
except AttributeError:
|
||||
debug (_("No keep_alife"))
|
||||
self.host_app.bridge.disconnected(self.profile) #we send the signal to the clients
|
||||
|
||||
|
||||
class SatMessageProtocol(xmppim.MessageProtocol):
|
||||
|
||||
def __init__(self, host):
|
||||
xmppim.MessageProtocol.__init__(self)
|
||||
self.host = host
|
||||
|
||||
def onMessage(self, message):
|
||||
debug (_(u"got message from: %s"), message["from"])
|
||||
if not self.host.trigger.point("MessageReceived",message, profile=self.parent.profile):
|
||||
return
|
||||
for e in message.elements():
|
||||
if e.name == "body":
|
||||
mess_type = message['type'] if message.hasAttribute('type') else 'normal'
|
||||
self.host.bridge.newMessage(message["from"], e.children[0], mess_type, message['to'], profile=self.parent.profile)
|
||||
self.host.memory.addToHistory(self.parent.jid, jid.JID(message["from"]), self.parent.jid, "chat", e.children[0])
|
||||
break
|
||||
|
||||
class SatRosterProtocol(xmppim.RosterClientProtocol):
|
||||
|
||||
def __init__(self, host):
|
||||
xmppim.RosterClientProtocol.__init__(self)
|
||||
self.host = host
|
||||
self._groups=set()
|
||||
|
||||
def rosterCb(self, roster):
|
||||
for raw_jid, item in roster.iteritems():
|
||||
self.onRosterSet(item)
|
||||
|
||||
def requestRoster(self):
|
||||
""" ask the server for Roster list """
|
||||
debug("requestRoster")
|
||||
self.getRoster().addCallback(self.rosterCb)
|
||||
|
||||
def removeItem(self, to):
|
||||
"""Remove a contact from roster list"""
|
||||
xmppim.RosterClientProtocol.removeItem(self, to)
|
||||
#TODO: check IQ result
|
||||
|
||||
#XXX: disabled (cf http://wokkel.ik.nu/ticket/56))
|
||||
#def addItem(self, to):
|
||||
#"""Add a contact to roster list"""
|
||||
#xmppim.RosterClientProtocol.addItem(self, to)
|
||||
#TODO: check IQ result"""
|
||||
|
||||
def onRosterSet(self, item):
|
||||
"""Called when a new/update roster item is received"""
|
||||
#TODO: send a signal to frontends
|
||||
item_attr = {'to': str(item.subscriptionTo),
|
||||
'from': str(item.subscriptionFrom),
|
||||
'ask': str(item.ask)
|
||||
}
|
||||
if item.name:
|
||||
item_attr['name'] = item.name
|
||||
info (_("new contact in roster list: %s"), item.jid.full())
|
||||
self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile)
|
||||
self.host.bridge.newContact(item.jid.full(), item_attr, item.groups, self.parent.profile)
|
||||
self._groups.update(item.groups)
|
||||
|
||||
def onRosterRemove(self, entity):
|
||||
"""Called when a roster removal event is received"""
|
||||
#TODO: send a signal to frontends
|
||||
print _("removing %s from roster list") % entity.full()
|
||||
self.host.memory.delContact(entity, self.parent.profile)
|
||||
|
||||
def getGroups(self):
|
||||
"""Return a set of groups"""
|
||||
return self._groups
|
||||
|
||||
class SatPresenceProtocol(xmppim.PresenceClientProtocol):
|
||||
|
||||
def __init__(self, host):
|
||||
xmppim.PresenceClientProtocol.__init__(self)
|
||||
self.host = host
|
||||
|
||||
def availableReceived(self, entity, show=None, statuses=None, priority=0):
|
||||
debug (_("presence update for [%(entity)s] (available, show=%(show)s statuses=%(statuses)s priority=%(priority)d)") % {'entity':entity, 'show':show, 'statuses':statuses, 'priority':priority})
|
||||
|
||||
if statuses.has_key(None): #we only want string keys
|
||||
statuses["default"] = statuses[None]
|
||||
del statuses[None]
|
||||
|
||||
self.host.memory.addPresenceStatus(entity, show or "",
|
||||
int(priority), statuses, self.parent.profile)
|
||||
|
||||
#now it's time to notify frontends
|
||||
self.host.bridge.presenceUpdate(entity.full(), show or "",
|
||||
int(priority), statuses, self.parent.profile)
|
||||
|
||||
def unavailableReceived(self, entity, statuses=None):
|
||||
debug (_("presence update for [%(entity)s] (unavailable, statuses=%(statuses)s)") % {'entity':entity, 'statuses':statuses})
|
||||
if statuses and statuses.has_key(None): #we only want string keys
|
||||
statuses["default"] = statuses[None]
|
||||
del statuses[None]
|
||||
self.host.memory.addPresenceStatus(entity, "unavailable", 0, statuses, self.parent.profile)
|
||||
|
||||
#now it's time to notify frontends
|
||||
self.host.bridge.presenceUpdate(entity.full(), "unavailable", 0, statuses, self.parent.profile)
|
||||
|
||||
|
||||
def available(self, entity=None, show=None, statuses=None, priority=0):
|
||||
if statuses and statuses.has_key('default'):
|
||||
statuses[None] = statuses['default']
|
||||
del statuses['default']
|
||||
xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority)
|
||||
|
||||
def subscribedReceived(self, entity):
|
||||
debug (_("subscription approved for [%s]") % entity.userhost())
|
||||
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile)
|
||||
|
||||
def unsubscribedReceived(self, entity):
|
||||
debug (_("unsubscription confirmed for [%s]") % entity.userhost())
|
||||
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile)
|
||||
|
||||
def subscribeReceived(self, entity):
|
||||
debug (_("subscription request for [%s]") % entity.userhost())
|
||||
self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile)
|
||||
|
||||
def unsubscribeReceived(self, entity):
|
||||
debug (_("unsubscription asked for [%s]") % entity.userhost())
|
||||
self.host.memory.addWaitingSub('unsubscribe', entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile)
|
||||
|
||||
class SatDiscoProtocol(disco.DiscoClientProtocol):
|
||||
def __init__(self, host):
|
||||
disco.DiscoClientProtocol.__init__(self)
|
||||
|
||||
class SatFallbackHandler(generic.FallbackHandler):
|
||||
def __init__(self, host):
|
||||
generic.FallbackHandler.__init__(self)
|
||||
|
||||
def iqFallback(self, iq):
|
||||
if iq.handled == True:
|
||||
return
|
||||
debug (u"iqFallback: xml = [%s]" % (iq.toXml()))
|
||||
generic.FallbackHandler.iqFallback(self, iq)
|
||||
|
||||
class RegisteringAuthenticator(xmlstream.ConnectAuthenticator):
|
||||
|
||||
def __init__(self, host, jabber_host, user_login, user_pass, answer_id):
|
||||
xmlstream.ConnectAuthenticator.__init__(self, jabber_host)
|
||||
self.host = host
|
||||
self.jabber_host = jabber_host
|
||||
self.user_login = user_login
|
||||
self.user_pass = user_pass
|
||||
self.answer_id = answer_id
|
||||
print _("Registration asked for"),user_login, user_pass, jabber_host
|
||||
|
||||
def connectionMade(self):
|
||||
print "connectionMade"
|
||||
|
||||
self.xmlstream.namespace = "jabber:client"
|
||||
self.xmlstream.sendHeader()
|
||||
|
||||
iq = compat.IQ(self.xmlstream, 'set')
|
||||
iq["to"] = self.jabber_host
|
||||
query = iq.addElement(('jabber:iq:register', 'query'))
|
||||
_user = query.addElement('username')
|
||||
_user.addContent(self.user_login)
|
||||
_pass = query.addElement('password')
|
||||
_pass.addContent(self.user_pass)
|
||||
reg = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure)
|
||||
|
||||
def registrationAnswer(self, answer):
|
||||
debug (_("registration answer: %s") % answer.toXml())
|
||||
answer_type = "SUCCESS"
|
||||
answer_data={"message":_("Registration successfull")}
|
||||
self.host.bridge.actionResult(answer_type, self.answer_id, answer_data)
|
||||
self.xmlstream.sendFooter()
|
||||
|
||||
def registrationFailure(self, failure):
|
||||
info (_("Registration failure: %s") % str(failure.value))
|
||||
answer_type = "ERROR"
|
||||
answer_data = {}
|
||||
if failure.value.condition == 'conflict':
|
||||
answer_data['reason'] = 'conflict'
|
||||
answer_data={"message":_("Username already exists, please choose an other one")}
|
||||
else:
|
||||
answer_data['reason'] = 'unknown'
|
||||
answer_data={"message":_("Registration failed (%s)") % str(failure.value.condition)}
|
||||
self.host.bridge.actionResult(answer_type, self.answer_id, answer_data)
|
||||
self.xmlstream.sendFooter()
|
||||
|
||||
class SatVersionHandler(generic.VersionHandler):
|
||||
|
||||
def getDiscoInfo(self, requestor, target, node):
|
||||
#XXX: We need to work around wokkel's behavious (namespace not added if there is a
|
||||
# node) as it cause issues with XEP-0115 & PEP (XEP-0163): there is a node when server
|
||||
# ask for disco info, and not when we generate the key, so the hash is used with different
|
||||
# disco features, and when the server (seen on ejabberd) generate its own hash for security check
|
||||
# it reject our features (resulting in e.g. no notification on PEP)
|
||||
return generic.VersionHandler.getDiscoInfo(self, requestor, target, None)
|
||||
|
||||
259
src/sat.tac
259
src/sat.tac
|
|
@ -48,6 +48,7 @@ from logging import debug, info, error
|
|||
import signal, sys
|
||||
import os.path
|
||||
|
||||
from sat.core.xmpp import SatXMPPClient, SatMessageProtocol, SatRosterProtocol, SatPresenceProtocol, SatDiscoProtocol, SatFallbackHandler, RegisteringAuthenticator, SatVersionHandler
|
||||
from sat.tools.memory import Memory
|
||||
from sat.tools.xml_tools import tupleList2dataForm
|
||||
from sat.tools.misc import TriggerManager
|
||||
|
|
@ -72,264 +73,6 @@ def sat_next_id():
|
|||
sat_id+=1
|
||||
return "sat_id_"+str(sat_id)
|
||||
|
||||
class SatXMPPClient(client.XMPPClient):
|
||||
|
||||
def __init__(self, host_app, profile, user_jid, password, host=None, port=5222):
|
||||
client.XMPPClient.__init__(self, user_jid, password, host, port)
|
||||
self.factory.clientConnectionLost = self.connectionLost
|
||||
self.__connected=False
|
||||
self.profile = profile
|
||||
self.host_app = host_app
|
||||
self.client_initialized = defer.Deferred()
|
||||
|
||||
def _authd(self, xmlstream):
|
||||
if not self.host_app.trigger.point("XML Initialized", xmlstream, self.profile):
|
||||
return
|
||||
client.XMPPClient._authd(self, xmlstream)
|
||||
self.__connected=True
|
||||
info (_("********** [%s] CONNECTED **********") % self.profile)
|
||||
self.streamInitialized()
|
||||
self.host_app.bridge.connected(self.profile) #we send the signal to the clients
|
||||
|
||||
|
||||
def streamInitialized(self):
|
||||
"""Called after _authd"""
|
||||
debug (_("XML stream is initialized"))
|
||||
self.keep_alife = task.LoopingCall(self.xmlstream.send, " ") #Needed to avoid disconnection (specially with openfire)
|
||||
self.keep_alife.start(180)
|
||||
|
||||
self.disco = SatDiscoProtocol(self)
|
||||
self.disco.setHandlerParent(self)
|
||||
self.discoHandler = disco.DiscoHandler()
|
||||
self.discoHandler.setHandlerParent(self)
|
||||
|
||||
if not self.host_app.trigger.point("Disco Handled", self.profile):
|
||||
return
|
||||
|
||||
self.roster.requestRoster()
|
||||
|
||||
self.presence.available()
|
||||
|
||||
self.disco.requestInfo(jid.JID(self.host_app.memory.getParamA("Server", "Connection", profile_key=self.profile))).addCallback(self.host_app.serverDisco, self.profile) #FIXME: use these informations
|
||||
self.disco.requestItems(jid.JID(self.host_app.memory.getParamA("Server", "Connection", profile_key=self.profile))).addCallback(self.host_app.serverDiscoItems, self.disco, self.profile, self.client_initialized)
|
||||
|
||||
def initializationFailed(self, reason):
|
||||
print ("initializationFailed: %s" % reason)
|
||||
self.host_app.bridge.connectionError("AUTH_ERROR", self.profile)
|
||||
try:
|
||||
client.XMPPClient.initializationFailed(self, reason)
|
||||
except:
|
||||
#we already send an error signal, no need to raise an exception
|
||||
pass
|
||||
|
||||
def isConnected(self):
|
||||
return self.__connected
|
||||
|
||||
def connectionLost(self, connector, unused_reason):
|
||||
self.__connected=False
|
||||
info (_("********** [%s] DISCONNECTED **********") % self.profile)
|
||||
try:
|
||||
self.keep_alife.stop()
|
||||
except AttributeError:
|
||||
debug (_("No keep_alife"))
|
||||
self.host_app.bridge.disconnected(self.profile) #we send the signal to the clients
|
||||
|
||||
|
||||
class SatMessageProtocol(xmppim.MessageProtocol):
|
||||
|
||||
def __init__(self, host):
|
||||
xmppim.MessageProtocol.__init__(self)
|
||||
self.host = host
|
||||
|
||||
def onMessage(self, message):
|
||||
debug (_(u"got message from: %s"), message["from"])
|
||||
if not self.host.trigger.point("MessageReceived",message, profile=self.parent.profile):
|
||||
return
|
||||
for e in message.elements():
|
||||
if e.name == "body":
|
||||
mess_type = message['type'] if message.hasAttribute('type') else 'normal'
|
||||
self.host.bridge.newMessage(message["from"], e.children[0], mess_type, message['to'], profile=self.parent.profile)
|
||||
self.host.memory.addToHistory(self.parent.jid, jid.JID(message["from"]), self.parent.jid, "chat", e.children[0])
|
||||
break
|
||||
|
||||
class SatRosterProtocol(xmppim.RosterClientProtocol):
|
||||
|
||||
def __init__(self, host):
|
||||
xmppim.RosterClientProtocol.__init__(self)
|
||||
self.host = host
|
||||
self._groups=set()
|
||||
|
||||
def rosterCb(self, roster):
|
||||
for raw_jid, item in roster.iteritems():
|
||||
self.onRosterSet(item)
|
||||
|
||||
def requestRoster(self):
|
||||
""" ask the server for Roster list """
|
||||
debug("requestRoster")
|
||||
self.getRoster().addCallback(self.rosterCb)
|
||||
|
||||
def removeItem(self, to):
|
||||
"""Remove a contact from roster list"""
|
||||
xmppim.RosterClientProtocol.removeItem(self, to)
|
||||
#TODO: check IQ result
|
||||
|
||||
#XXX: disabled (cf http://wokkel.ik.nu/ticket/56))
|
||||
#def addItem(self, to):
|
||||
#"""Add a contact to roster list"""
|
||||
#xmppim.RosterClientProtocol.addItem(self, to)
|
||||
#TODO: check IQ result"""
|
||||
|
||||
def onRosterSet(self, item):
|
||||
"""Called when a new/update roster item is received"""
|
||||
#TODO: send a signal to frontends
|
||||
item_attr = {'to': str(item.subscriptionTo),
|
||||
'from': str(item.subscriptionFrom),
|
||||
'ask': str(item.ask)
|
||||
}
|
||||
if item.name:
|
||||
item_attr['name'] = item.name
|
||||
info (_("new contact in roster list: %s"), item.jid.full())
|
||||
self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile)
|
||||
self.host.bridge.newContact(item.jid.full(), item_attr, item.groups, self.parent.profile)
|
||||
self._groups.update(item.groups)
|
||||
|
||||
def onRosterRemove(self, entity):
|
||||
"""Called when a roster removal event is received"""
|
||||
#TODO: send a signal to frontends
|
||||
print _("removing %s from roster list") % entity.full()
|
||||
self.host.memory.delContact(entity, self.parent.profile)
|
||||
|
||||
def getGroups(self):
|
||||
"""Return a set of groups"""
|
||||
return self._groups
|
||||
|
||||
class SatPresenceProtocol(xmppim.PresenceClientProtocol):
|
||||
|
||||
def __init__(self, host):
|
||||
xmppim.PresenceClientProtocol.__init__(self)
|
||||
self.host = host
|
||||
|
||||
def availableReceived(self, entity, show=None, statuses=None, priority=0):
|
||||
debug (_("presence update for [%(entity)s] (available, show=%(show)s statuses=%(statuses)s priority=%(priority)d)") % {'entity':entity, 'show':show, 'statuses':statuses, 'priority':priority})
|
||||
|
||||
if statuses.has_key(None): #we only want string keys
|
||||
statuses["default"] = statuses[None]
|
||||
del statuses[None]
|
||||
|
||||
self.host.memory.addPresenceStatus(entity, show or "",
|
||||
int(priority), statuses, self.parent.profile)
|
||||
|
||||
#now it's time to notify frontends
|
||||
self.host.bridge.presenceUpdate(entity.full(), show or "",
|
||||
int(priority), statuses, self.parent.profile)
|
||||
|
||||
def unavailableReceived(self, entity, statuses=None):
|
||||
debug (_("presence update for [%(entity)s] (unavailable, statuses=%(statuses)s)") % {'entity':entity, 'statuses':statuses})
|
||||
if statuses and statuses.has_key(None): #we only want string keys
|
||||
statuses["default"] = statuses[None]
|
||||
del statuses[None]
|
||||
self.host.memory.addPresenceStatus(entity, "unavailable", 0, statuses, self.parent.profile)
|
||||
|
||||
#now it's time to notify frontends
|
||||
self.host.bridge.presenceUpdate(entity.full(), "unavailable", 0, statuses, self.parent.profile)
|
||||
|
||||
|
||||
def available(self, entity=None, show=None, statuses=None, priority=0):
|
||||
if statuses and statuses.has_key('default'):
|
||||
statuses[None] = statuses['default']
|
||||
del statuses['default']
|
||||
xmppim.PresenceClientProtocol.available(self, entity, show, statuses, priority)
|
||||
|
||||
def subscribedReceived(self, entity):
|
||||
debug (_("subscription approved for [%s]") % entity.userhost())
|
||||
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('subscribed', entity.userhost(), self.parent.profile)
|
||||
|
||||
def unsubscribedReceived(self, entity):
|
||||
debug (_("unsubscription confirmed for [%s]") % entity.userhost())
|
||||
self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('unsubscribed', entity.userhost(), self.parent.profile)
|
||||
|
||||
def subscribeReceived(self, entity):
|
||||
debug (_("subscription request for [%s]") % entity.userhost())
|
||||
self.host.memory.addWaitingSub('subscribe', entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('subscribe', entity.userhost(), self.parent.profile)
|
||||
|
||||
def unsubscribeReceived(self, entity):
|
||||
debug (_("unsubscription asked for [%s]") % entity.userhost())
|
||||
self.host.memory.addWaitingSub('unsubscribe', entity.userhost(), self.parent.profile)
|
||||
self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile)
|
||||
|
||||
class SatDiscoProtocol(disco.DiscoClientProtocol):
|
||||
def __init__(self, host):
|
||||
disco.DiscoClientProtocol.__init__(self)
|
||||
|
||||
class SatFallbackHandler(generic.FallbackHandler):
|
||||
def __init__(self, host):
|
||||
generic.FallbackHandler.__init__(self)
|
||||
|
||||
def iqFallback(self, iq):
|
||||
if iq.handled == True:
|
||||
return
|
||||
debug (u"iqFallback: xml = [%s]" % (iq.toXml()))
|
||||
generic.FallbackHandler.iqFallback(self, iq)
|
||||
|
||||
class RegisteringAuthenticator(xmlstream.ConnectAuthenticator):
|
||||
|
||||
def __init__(self, host, jabber_host, user_login, user_pass, answer_id):
|
||||
xmlstream.ConnectAuthenticator.__init__(self, jabber_host)
|
||||
self.host = host
|
||||
self.jabber_host = jabber_host
|
||||
self.user_login = user_login
|
||||
self.user_pass = user_pass
|
||||
self.answer_id = answer_id
|
||||
print _("Registration asked for"),user_login, user_pass, jabber_host
|
||||
|
||||
def connectionMade(self):
|
||||
print "connectionMade"
|
||||
|
||||
self.xmlstream.namespace = "jabber:client"
|
||||
self.xmlstream.sendHeader()
|
||||
|
||||
iq = compat.IQ(self.xmlstream, 'set')
|
||||
iq["to"] = self.jabber_host
|
||||
query = iq.addElement(('jabber:iq:register', 'query'))
|
||||
_user = query.addElement('username')
|
||||
_user.addContent(self.user_login)
|
||||
_pass = query.addElement('password')
|
||||
_pass.addContent(self.user_pass)
|
||||
reg = iq.send(self.jabber_host).addCallbacks(self.registrationAnswer, self.registrationFailure)
|
||||
|
||||
def registrationAnswer(self, answer):
|
||||
debug (_("registration answer: %s") % answer.toXml())
|
||||
answer_type = "SUCCESS"
|
||||
answer_data={"message":_("Registration successfull")}
|
||||
self.host.bridge.actionResult(answer_type, self.answer_id, answer_data)
|
||||
self.xmlstream.sendFooter()
|
||||
|
||||
def registrationFailure(self, failure):
|
||||
info (_("Registration failure: %s") % str(failure.value))
|
||||
answer_type = "ERROR"
|
||||
answer_data = {}
|
||||
if failure.value.condition == 'conflict':
|
||||
answer_data['reason'] = 'conflict'
|
||||
answer_data={"message":_("Username already exists, please choose an other one")}
|
||||
else:
|
||||
answer_data['reason'] = 'unknown'
|
||||
answer_data={"message":_("Registration failed (%s)") % str(failure.value.condition)}
|
||||
self.host.bridge.actionResult(answer_type, self.answer_id, answer_data)
|
||||
self.xmlstream.sendFooter()
|
||||
|
||||
class SatVersionHandler(generic.VersionHandler):
|
||||
|
||||
def getDiscoInfo(self, requestor, target, node):
|
||||
#XXX: We need to work around wokkel's behavious (namespace not added if there is a
|
||||
# node) as it cause issues with XEP-0115 & PEP (XEP-0163): there is a node when server
|
||||
# ask for disco info, and not when we generate the key, so the hash is used with different
|
||||
# disco features, and when the server (seen on ejabberd) generate its own hash for security check
|
||||
# it reject our features (resulting in e.g. no notification on PEP)
|
||||
return generic.VersionHandler.getDiscoInfo(self, requestor, target, None)
|
||||
|
||||
class SAT(service.Service):
|
||||
|
||||
def get_next_id(self):
|
||||
|
|
|
|||
Loading…
Reference in a new issue