diff src/sat.tac @ 330:608a4a2ba94e

Core: created a new core module where xmpp classes are put
author Goffi <goffi@goffi.org>
date Mon, 23 May 2011 21:18:58 +0200
parents b069055320b1
children 0a8eb0461f31
line wrap: on
line diff
--- a/src/sat.tac	Mon May 23 01:01:44 2011 +0200
+++ b/src/sat.tac	Mon May 23 21:18:58 2011 +0200
@@ -48,6 +48,7 @@
 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 @@
     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):