Changeset 74
- Timestamp:
- 05/09/04 18:56:53 (5 years ago)
- Files:
-
- trunk/jjigw/channel.py (modified) (4 diffs)
- trunk/jjigw/component.py (modified) (8 diffs)
- trunk/jjigw/ircsession.py (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/jjigw/channel.py
r71 r74 26 26 from common import channel_re 27 27 from common import normalize,remove_evil_characters,strip_colors 28 from ircuser import IRCUser 28 29 29 30 class Channel: … … 44 45 self.encoding=session.default_encoding 45 46 self.modes={} 46 self.users=[ ]47 self.users=[self.session.get_user()] 47 48 self.muc=0 48 49 self.requests=RequestQueue(10) … … 90 91 self.debug("Channel %r in the initial state - nothing to do." % (self.name,)) 91 92 else: 92 if status:93 if not status: 93 94 self.session.send("PART %s" % (self.name,)) 94 95 else: … … 99 100 self.session.component.send(p) 100 101 for u in self.users: 101 u.leave_ room(self)102 u.leave_channel(self) 102 103 self.state=None 103 104 trunk/jjigw/component.py
r71 r74 21 21 import signal 22 22 import threading 23 import string 23 24 24 25 import pyxmpp.jabberd … … 26 27 from pyxmpp.jabber.muc import MUC_ADMIN_NS,MUC_NS 27 28 from pyxmpp.jabber.muc import MucPresence,MucIq,MucAdminQuery 28 from pyxmpp.jabber.disco import DiscoItems,DiscoI nfo,DiscoIdentity29 from pyxmpp.jabber.disco import DiscoItems,DiscoItem,DiscoInfo,DiscoIdentity 29 30 30 31 from ircsession import IRCSession … … 39 40 signal.signal(signal.SIGINT,self.signal_handler) 40 41 signal.signal(signal.SIGPIPE,self.signal_handler) 42 signal.signal(signal.SIGHUP,self.signal_handler) 41 43 signal.signal(signal.SIGTERM,self.signal_handler) 42 44 self.irc_sessions={} … … 48 50 49 51 def get_session(self,user_jid,component_jid): 50 print `self.irc_sessions`51 52 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!") 52 68 53 69 def signal_handler(self,signum,frame): … … 269 285 self.send(p) 270 286 return 1 271 if to not in sess.used_for:272 sess.used_for.append(to)273 287 else: 274 288 nick=to.resource 275 289 if not nick: 276 290 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) 280 299 if to.node: 281 300 sess.join(MucPresence(stanza)) 282 301 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) 290 303 return 1 291 304 … … 296 309 sess=self.get_session(fr,to) 297 310 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 316 318 317 319 def presence_control(self,stanza): … … 335 337 return iq.make_error_response("recipient-unavailable") 336 338 if to.node is None and to.resource is None: 337 di=DiscoInfo() 339 di=DiscoInfo() 340 if node is None: 338 341 di.add_feature("jabber:iq:version") 339 342 di.add_feature("jabber:iq:register") … … 344 347 name="IRC gateway" 345 348 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 347 359 return iq.make_error_response("feature-not-implemented") 348 360 349 361 def disco_get_items(self,node,iq): 350 362 to=iq.get_to() 363 fr=iq.get_from() 351 364 try: 352 365 network=self.config.get_network(to) 353 366 except KeyError: 354 367 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") 358 430 359 431 # vi: sts=4 et sw=4 trunk/jjigw/ircsession.py
r71 r74 24 24 import select 25 25 import string 26 27 28 from pyxmpp import Presence26 import random 27 28 from pyxmpp import Message,Presence,JID 29 29 from pyxmpp.jabber.muc import MucPresence 30 30 … … 33 33 from common import ConnectionInfo 34 34 from common import node_to_channel,normalize 35 from common import remove_evil_characters,strip_colors 35 36 from common import channel_re,numeric_re 36 37 … … 60 61 self.used_for=[] 61 62 self.server=None 63 self.login_requests=[] 62 64 self.join_requests=[] 63 65 self.messages_to_channel=[] … … 66 68 self.channels={} 67 69 self.users={} 70 self.raw_channel=0 68 71 self.user=IRCUser(self,nick) 69 72 self.thread.start() … … 97 100 self.lock.release() 98 101 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 106 113 nnick=normalize(nick) 107 114 if self.users.has_key(nnick): … … 164 171 pass 165 172 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) 170 174 finally: 171 175 self.lock.release() … … 221 225 server=self.servers_left.pop(0) 222 226 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)) 223 229 try: 224 230 self.socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) … … 226 232 except (IOError,OSError,socket.error),err: 227 233 self.debug("Server connect error: %r" % (err,)) 234 if self.raw_channel: 235 self.pass_message_to_raw_channel("Connect error: %r" % (err,)) 228 236 if self.socket: 229 237 try: … … 236 244 self.socket=None 237 245 return 246 if self.raw_channel: 247 self.pass_message_to_raw_channel("Connected.") 238 248 self._send("NICK %s" % (self.nick,)) 239 249 user=md5.new(self.jid.bare().as_string()).hexdigest()[:64] … … 248 258 self.debug("IRC OUT: %r" % (str,)) 249 259 self.socket.send(str+"\r\n") 260 if self.raw_channel: 261 self.pass_output_to_raw_channel(str) 250 262 else: 251 263 self.debug("ignoring out: %r" % (str,)) … … 284 296 params.append(split[0]) 285 297 split=split[1:] 298 if self.raw_channel: 299 self.pass_input_to_raw_channel(prefix,command,params) 286 300 if command and numeric_re.match(command): 287 301 params=params[1:] … … 298 312 if f: 299 313 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 break305 314 finally: 306 315 self.lock.acquire() … … 326 335 327 336 def irc_message(self,prefix,command,params): 328 if len(params)<2 :337 if len(params)<2 or not prefix: 329 338 self.debug("ignoring it") 330 339 return … … 347 356 try: 348 357 if join_condition: 349 for s in self.join_requests :358 for s in self.join_requests+self.login_requests: 350 359 p=s.make_error_response(join_condition) 351 360 self.component.send(p) … … 355 364 pass 356 365 self.join_requests=[] 366 self.login_requests=[] 357 367 if message_condition: 358 368 for s in self.messages_to_user+self.messages_to_channel: … … 370 380 self.debug("Connected successfully") 371 381 self.ready=1 382 for s in self.login_requests: 383 self.login(s) 372 384 for s in self.join_requests: 373 385 self.join(s) … … 435 447 return 436 448 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)) 441 456 442 457 def send_error_message(self,source,cond,text): … … 457 472 self.component.send(m) 458 473 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") 478 490 self.component.send(m) 479 491 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 480 507 def join(self,stanza): 508 to=stanza.get_to() 509 if to.node=='#': 510 return self.join_raw_channel(stanza) 481 511 self.cond.acquire() 482 512 try: … … 486 516 finally: 487 517 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 490 524 if self.channels.has_key(normalize(channel)): 491 525 return 526 if to not in self.used_for: 527 self.used_for.append(to) 492 528 channel=Channel(self,channel) 493 529 channel.join(stanza) 494 530 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()) 495 603 496 604 def get_channel(self,jid):
