Changeset 74

Show
Ignore:
Timestamp:
05/09/04 18:56:53 (5 years ago)
Author:
jajcus
Message:

- raw channel ("#" conference room) - for debuging
- gateway status accessible selected users (administrators defined in config file) via Disco
- channel leaving implemented
- some fixes

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/jjigw/channel.py

    r71 r74  
    2626from common import channel_re 
    2727from common import normalize,remove_evil_characters,strip_colors 
     28from ircuser import IRCUser 
    2829 
    2930class Channel: 
     
    4445            self.encoding=session.default_encoding 
    4546        self.modes={} 
    46         self.users=[
     47        self.users=[self.session.get_user()
    4748        self.muc=0 
    4849        self.requests=RequestQueue(10) 
     
    9091            self.debug("Channel %r in the initial state - nothing to do." % (self.name,)) 
    9192        else: 
    92             if status: 
     93            if not status: 
    9394                self.session.send("PART %s" % (self.name,)) 
    9495            else: 
     
    99100        self.session.component.send(p) 
    100101        for u in self.users: 
    101             u.leave_room(self) 
     102            u.leave_channel(self) 
    102103        self.state=None 
    103104 
  • trunk/jjigw/component.py

    r71 r74  
    2121import signal 
    2222import threading 
     23import string 
    2324 
    2425import pyxmpp.jabberd 
     
    2627from pyxmpp.jabber.muc import MUC_ADMIN_NS,MUC_NS 
    2728from pyxmpp.jabber.muc import MucPresence,MucIq,MucAdminQuery 
    28 from pyxmpp.jabber.disco import DiscoItems,DiscoInfo,DiscoIdentity 
     29from pyxmpp.jabber.disco import DiscoItems,DiscoItem,DiscoInfo,DiscoIdentity 
    2930 
    3031from ircsession import IRCSession 
     
    3940        signal.signal(signal.SIGINT,self.signal_handler) 
    4041        signal.signal(signal.SIGPIPE,self.signal_handler) 
     42        signal.signal(signal.SIGHUP,self.signal_handler) 
    4143        signal.signal(signal.SIGTERM,self.signal_handler) 
    4244        self.irc_sessions={} 
     
    4850 
    4951    def get_session(self,user_jid,component_jid): 
    50         print `self.irc_sessions` 
    5152        return self.irc_sessions.get((user_jid.as_unicode(),component_jid.domain)) 
     53         
     54    def register_session(self,sess): 
     55        user_jid=sess.jid 
     56        component_jid=sess.network.jid 
     57        self.debug("Registering session: %r on %r for %r" % (sess,component_jid,user_jid)) 
     58        self.irc_sessions[user_jid.as_unicode(),component_jid.domain]=sess 
     59 
     60    def unregister_session(self,sess): 
     61        user_jid=sess.jid 
     62        component_jid=sess.network.jid 
     63        self.debug("Unregistering session: %r on %r for %r" % (sess,component_jid,user_jid)) 
     64        try: 
     65            del self.irc_sessions[user_jid.as_unicode(),component_jid.domain] 
     66        except KeyError: 
     67            self.debug("Session not found!") 
    5268 
    5369    def signal_handler(self,signum,frame): 
     
    269285                self.send(p) 
    270286                return 1 
    271             if to not in sess.used_for: 
    272                 sess.used_for.append(to) 
    273287        else: 
    274288            nick=to.resource 
    275289            if not nick: 
    276290                nick=fr.node 
    277             sess=IRCSession(self,self.config,to,fr,nick) 
    278             sess.used_for.append(to) 
    279             self.irc_sessions[fr.as_unicode(),to.domain]=sess 
     291            try: 
     292                sess=IRCSession(self,self.config,to,fr,nick) 
     293            except ValueError,e: 
     294                print `e` 
     295                e=stanza.make_error_response("bad-request") 
     296                self.send(e) 
     297                return 
     298            self.register_session(sess) 
    280299        if to.node: 
    281300            sess.join(MucPresence(stanza)) 
    282301        else: 
    283             p=Presence( 
    284                 to=stanza.get_from(), 
    285                 fr=stanza.get_to(), 
    286                 show=stanza.get_show(), 
    287                 status=stanza.get_status() 
    288                 ); 
    289             self.send(p) 
     302            sess.login(stanza) 
    290303        return 1 
    291304 
     
    296309        sess=self.get_session(fr,to) 
    297310        if sess: 
    298             try: 
    299                 sess.used_for.remove(to) 
    300             except ValueError: 
    301                 pass 
    302             if not sess.used_for: 
    303                 sess.disconnect(status) 
    304                 try: 
    305                     del self.irc_sessions[fr.as_unicode(),to.domain] 
    306                 except KeyError: 
    307                     pass 
    308         p=Presence( 
    309             type="unavailable", 
    310             to=stanza.get_from(), 
    311             fr=stanza.get_to() 
    312             ); 
    313         self.stream.send(p) 
    314         return 1 
    315  
     311            if to.node: 
     312                disconnected=sess.leave(stanza) 
     313            else: 
     314                disconnected=sess.logout(stanza) 
     315            if disconnected: 
     316                self.unregister_session(sess) 
     317        return 1 
    316318 
    317319    def presence_control(self,stanza): 
     
    335337            return iq.make_error_response("recipient-unavailable") 
    336338        if to.node is None and to.resource is None: 
    337                 di=DiscoInfo() 
     339            di=DiscoInfo() 
     340            if node is None: 
    338341                di.add_feature("jabber:iq:version") 
    339342                di.add_feature("jabber:iq:register") 
     
    344347                    name="IRC gateway" 
    345348                DiscoIdentity(di,name,"gateway","irc") 
    346                 return di 
     349            return di 
     350        elif len(to.node)>1 and to.node[0] in u"&#+!" and to.resource is None: 
     351            di=DiscoInfo() 
     352            di.add_feature(MUC_NS) 
     353            if network.name: 
     354                name="%s channel on %s IRC network" % (to.node,network.name) 
     355            else: 
     356                name="%s IRC channel" % (to.node,) 
     357            DiscoIdentity(di,name ,"conference","text") 
     358            return di 
    347359        return iq.make_error_response("feature-not-implemented") 
    348360 
    349361    def disco_get_items(self,node,iq): 
    350362        to=iq.get_to() 
     363        fr=iq.get_from() 
    351364        try: 
    352365            network=self.config.get_network(to) 
    353366        except KeyError: 
    354367            return iq.make_error_response("recipient-unavailable") 
    355         if to.node is None and to.resource is None: 
    356                 return self.disco_items 
    357         return iq.make_error_response("feature-not-implemented") 
     368        if to.node is not None or to.resource is not None: 
     369            return iq.make_error_response("feature-not-implemented") 
     370        if not node: 
     371            di=DiscoItems() 
     372            print "Requester: %r Admins: %r" % (fr,self.config.admins) 
     373            if fr in self.config.admins or fr.bare() in self.config.admins: 
     374                DiscoItem(di,to,"admin","Administrator tree") 
     375            return di 
     376        if node=="admin" or node.startswith("admin."): 
     377            if fr not in self.config.admins and fr.bare() not in self.config.admins: 
     378                return iq.make_error_response("forbidden") 
     379        else: 
     380            return iq.make_error_response("item-not-found") 
     381        node=node.split(".") 
     382        if node==["admin"]: 
     383            di=DiscoItems() 
     384            DiscoItem(di,to,"admin.sessions","Sessions (jid nick)") 
     385            return di 
     386        if node==["admin","sessions"]: 
     387            di=DiscoItems() 
     388            for sess in self.irc_sessions.values(): 
     389                if not sess.network==network: 
     390                    continue 
     391                DiscoItem(di,to,"admin.sessions.%s" % (id(sess),), 
     392                        u"%r %r" % (sess.jid.as_unicode(),sess.nick)) 
     393            return di 
     394        if len(node)>2 and node[:2]==["admin","sessions"]: 
     395            try: 
     396                sessid=int(node[2]) 
     397            except ValueError: 
     398                return iq.make_error_response("item-not-found") 
     399            sess=None 
     400            for s in self.irc_sessions.values(): 
     401                if id(s)==sessid: 
     402                    sess=s 
     403                    break 
     404            if sess is None: 
     405                return iq.make_error_response("item-not-found") 
     406            if len(node)==3: 
     407                di=DiscoItems() 
     408                DiscoItem(di,sess.jid,None,"Owner") 
     409                DiscoItem(di,to,string.join(node+["used_for"],"."),"Used for") 
     410                DiscoItem(di,to,string.join(node+["users"],"."),"Known IRC users") 
     411                DiscoItem(di,to,string.join(node+["channels"],"."),"Active channels") 
     412                return di 
     413            if len(node)==4 and node[3]=="used_for": 
     414                di=DiscoItems() 
     415                for j in sess.used_for: 
     416                    DiscoItem(di,j,None,j.as_unicode()) 
     417                return di 
     418            if len(node)==4 and node[3]=="users": 
     419                di=DiscoItems() 
     420                for u in sess.users.values(): 
     421                    DiscoItem(di,to,string.join(node+[str(id(u))]),`u.nick`) 
     422                return di 
     423            if len(node)==4 and node[3]=="channels": 
     424                di=DiscoItems() 
     425                for ch in sess.channels.values(): 
     426                    DiscoItem(di,to,string.join(node+[str(id(ch))]),`ch.name`) 
     427                return di 
     428                 
     429        return iq.make_error_response("item-not-found") 
    358430 
    359431# vi: sts=4 et sw=4 
  • trunk/jjigw/ircsession.py

    r71 r74  
    2424import select 
    2525import string 
    26  
    27  
    28 from pyxmpp import Presence 
     26import random 
     27 
     28from pyxmpp import Message,Presence,JID 
    2929from pyxmpp.jabber.muc import MucPresence 
    3030 
     
    3333from common import ConnectionInfo 
    3434from common import node_to_channel,normalize 
     35from common import remove_evil_characters,strip_colors 
    3536from common import channel_re,numeric_re 
    3637 
     
    6061        self.used_for=[] 
    6162        self.server=None 
     63        self.login_requests=[] 
    6264        self.join_requests=[] 
    6365        self.messages_to_channel=[] 
     
    6668        self.channels={} 
    6769        self.users={} 
     70        self.raw_channel=0 
    6871        self.user=IRCUser(self,nick) 
    6972        self.thread.start() 
     
    97100            self.lock.release() 
    98101 
    99     def get_user(self,prefix,create=1): 
    100         if "!" in prefix: 
    101             nick=prefix.split("!",1)[0] 
    102         else: 
    103             nick=prefix 
    104         if not self.network.valid_nick(nick): 
    105             return None 
     102    def get_user(self,prefix=None,create=1): 
     103        if prefix: 
     104            if "!" in prefix: 
     105                nick=prefix.split("!",1)[0] 
     106            else: 
     107                nick=prefix 
     108            if not self.network.valid_nick(nick): 
     109                return None 
     110        else: 
     111            prefix=self.nick 
     112            nick=self.nick 
    106113        nnick=normalize(nick) 
    107114        if self.users.has_key(nnick): 
     
    164171                    pass 
    165172                self.socket=None 
    166             try: 
    167                 del self.component.irc_sessions[self.jid.as_unicode()] 
    168             except KeyError: 
    169                 pass 
     173            self.component.unregister_session(self) 
    170174        finally: 
    171175            self.lock.release() 
     
    221225        server=self.servers_left.pop(0) 
    222226        self.debug("Trying to connect to %r" % (server,)) 
     227        if self.raw_channel: 
     228            self.pass_message_to_raw_channel("Connecting to %s:%s..." % (server.host,server.port)) 
    223229        try: 
    224230            self.socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) 
     
    226232        except (IOError,OSError,socket.error),err: 
    227233            self.debug("Server connect error: %r" % (err,)) 
     234            if self.raw_channel: 
     235                self.pass_message_to_raw_channel("Connect error: %r" % (err,)) 
    228236            if self.socket: 
    229237                try: 
     
    236244            self.socket=None 
    237245            return 
     246        if self.raw_channel: 
     247            self.pass_message_to_raw_channel("Connected.") 
    238248        self._send("NICK %s" % (self.nick,)) 
    239249        user=md5.new(self.jid.bare().as_string()).hexdigest()[:64] 
     
    248258            self.debug("IRC OUT: %r" % (str,)) 
    249259            self.socket.send(str+"\r\n") 
     260            if self.raw_channel: 
     261                self.pass_output_to_raw_channel(str) 
    250262        else: 
    251263            self.debug("ignoring out: %r" % (str,)) 
     
    284296            params.append(split[0]) 
    285297            split=split[1:] 
     298        if self.raw_channel: 
     299            self.pass_input_to_raw_channel(prefix,command,params) 
    286300        if command and numeric_re.match(command): 
    287301            params=params[1:] 
     
    298312            if f: 
    299313                f(prefix,command,params) 
    300             else: 
    301                 for u in self.used_for: 
    302                     if u.bare()==self.network.jid: 
    303                         self.pass_input_to_user(prefix,command,params) 
    304                         break 
    305314        finally: 
    306315            self.lock.acquire() 
     
    326335 
    327336    def irc_message(self,prefix,command,params): 
    328         if len(params)<2
     337        if len(params)<2 or not prefix
    329338            self.debug("ignoring it") 
    330339            return 
     
    347356        try: 
    348357            if join_condition: 
    349                 for s in self.join_requests
     358                for s in self.join_requests+self.login_requests
    350359                    p=s.make_error_response(join_condition) 
    351360                    self.component.send(p) 
     
    355364                        pass 
    356365                self.join_requests=[] 
     366                self.login_requests=[] 
    357367            if message_condition: 
    358368                for s in self.messages_to_user+self.messages_to_channel: 
     
    370380            self.debug("Connected successfully") 
    371381            self.ready=1 
     382            for s in self.login_requests: 
     383                self.login(s) 
    372384            for s in self.join_requests: 
    373385                self.join(s) 
     
    435447            return 
    436448        user=self.get_user(params[4]) 
    437         user.whoreply(params) 
    438         for c in user.channels.keys(): 
    439             channel=user.channels[c] 
    440             self.component.send(channel.get_user_presence(user)) 
     449        if not user: 
     450            self.debug("User: %r not found" % (params[4],)) 
     451        else: 
     452            user.whoreply(params) 
     453            for c in user.channels.keys(): 
     454                channel=user.channels[c] 
     455                self.component.send(channel.get_user_presence(user)) 
    441456 
    442457    def send_error_message(self,source,cond,text): 
     
    457472        self.component.send(m) 
    458473 
    459     def pass_input_to_user(self,prefix,command,params): 
    460         if command in self.commands_dont_show: 
    461             return 
    462         nprefix=normalize(prefix) 
    463         nnick=normalize(self.nick) 
    464         nserver=normalize(self.server.host) 
    465         if nprefix==nnick or prefix and nprefix.startswith(nnick+"!"): 
    466             return 
    467         if nprefix==nserver and len(params)==2 and params[0]==self.nick: 
    468             body=u"(!) %s" % (unicode(params[1],self.default_encoding,"replace"),) 
    469         elif command in ("004","005","252","253","254"): 
    470             p=string.join(params[1:]," ") 
    471             body=u"(!) %s" % (unicode(p,self.default_encoding,"replace"),) 
    472         elif prefix: 
    473             body=u"(%s) %s %r" % (prefix,command,params) 
    474         else: 
    475             body=u"%s %r" % (command,params) 
    476         fr=JID(None,self.network.jid.domain,self.server.host) 
    477         m=Message(to=self.jid,fr=fr,body=body) 
     474    def pass_input_to_raw_channel(self,prefix,command,params): 
     475        body=string.join([command]+params) 
     476        body=`body` 
     477        if body[0] in '"\'': 
     478            body=body[1:-1] 
     479        body=unicode(body,self.default_encoding,"replace") 
     480        if prefix: 
     481            prefix=remove_evil_characters(prefix) 
     482            prefix=`prefix` 
     483            if prefix[0] in '"\'': 
     484                prefix=prefix[1:-1] 
     485            prefix=unicode(prefix,self.default_encoding,"replace") 
     486        else: 
     487            prefix=None 
     488        fr=JID('#',self.network.jid.domain,prefix) 
     489        m=Message(to=self.jid,fr=fr,body=body,type="groupchat") 
    478490        self.component.send(m) 
    479491 
     492    def pass_output_to_raw_channel(self,s): 
     493        body=`s` 
     494        if body[0] in '"\'': 
     495            body=body[1:-1] 
     496        body=unicode(body,self.default_encoding,"replace") 
     497        nick=unicode(self.nick,self.default_encoding,"replace") 
     498        fr=JID('#',self.network.jid.domain,nick) 
     499        m=Message(to=self.jid,fr=fr,body=body,type="groupchat") 
     500        self.component.send(m) 
     501 
     502    def pass_message_to_raw_channel(self,msg): 
     503        fr=JID('#',self.network.jid.domain,None) 
     504        m=Message(to=self.jid,fr=fr,body=msg,type="groupchat") 
     505        self.component.send(m) 
     506 
    480507    def join(self,stanza): 
     508        to=stanza.get_to() 
     509        if to.node=='#': 
     510            return self.join_raw_channel(stanza) 
    481511        self.cond.acquire() 
    482512        try: 
     
    486516        finally: 
    487517            self.cond.release() 
    488         to=stanza.get_to() 
    489         channel=node_to_channel(to.node,self.default_encoding) 
     518        try: 
     519            channel=node_to_channel(to.node,self.default_encoding) 
     520        except ValueError: 
     521            e=stanza.make_error_response("not-acceptable") 
     522            self.component.send(e) 
     523            return 
    490524        if self.channels.has_key(normalize(channel)): 
    491525            return 
     526        if to not in self.used_for: 
     527            self.used_for.append(to) 
    492528        channel=Channel(self,channel) 
    493529        channel.join(stanza) 
    494530        self.channels[normalize(channel.name)]=channel 
     531 
     532    def join_raw_channel(self,stanza): 
     533        self.raw_channel=1 
     534        to=stanza.get_to() 
     535        if to not in self.used_for: 
     536            self.used_for.append(to) 
     537        p=Presence(fr=to,to=stanza.get_from()) 
     538        self.component.send(p) 
     539 
     540    def leave(self,stanza): 
     541        to=stanza.get_to() 
     542        if to.node=='#': 
     543            return self.leave_raw_channel(stanza) 
     544        channel=self.get_channel(stanza.get_to()) 
     545        if channel: 
     546           channel.leave(stanza)  
     547           self.logout(stanza,0) 
     548        else: 
     549           self.logout(stanza) 
     550 
     551    def leave_raw_channel(self,stanza): 
     552        self.raw_channel=0 
     553        self.logout(stanza) 
     554 
     555    def login(self,stanza): 
     556        self.cond.acquire() 
     557        try: 
     558            if not self.ready: 
     559                self.login_requests.append(stanza) 
     560                return 
     561        finally: 
     562            self.cond.release() 
     563        to=stanza.get_to() 
     564        if to not in self.used_for: 
     565            self.used_for.append(to) 
     566        fr=stanza.get_from() 
     567        p=Presence(to=fr,fr=to,status=stanza.get_status(),show=stanza.get_show()) 
     568        self.component.send(p) 
     569 
     570    def logout(self,stanza,send_response=1): 
     571        to=stanza.get_to() 
     572        if to not in self.used_for: 
     573            self.debug("Unavailable presence sent with no matching available presence, ignoring it") 
     574            return 0 
     575        try: 
     576            self.used_for.remove(to) 
     577        except: 
     578            pass 
     579        if send_response: 
     580            p=Presence( 
     581                type="unavailable", 
     582                to=stanza.get_from(), 
     583                fr=stanza.get_to() 
     584                ); 
     585            self.component.send(p) 
     586        if not self.used_for: 
     587            self.disconnect(stanza.get_status()) 
     588            return 1 
     589        else: 
     590            return 0 
     591 
     592    def channel_left(self,channel): 
     593        if not channel.room_jid: 
     594            return 
     595        if channel.room_jid not in self.used_for: 
     596            return 
     597        try: 
     598            self.used_for.remove(channel.room_jid) 
     599        except: 
     600            pass 
     601        if not self.used_for: 
     602            self.disconnect(stanza.get_status()) 
    495603 
    496604    def get_channel(self,jid):