| 83 | | irc_translate_table=string.maketrans( |
|---|
| 84 | | string.ascii_uppercase+"[]\\~", |
|---|
| 85 | | string.ascii_lowercase+"{}|^") |
|---|
| 86 | | |
|---|
| 87 | | def normalize(s): |
|---|
| 88 | | return s.translate(irc_translate_table) |
|---|
| 89 | | |
|---|
| 90 | | class ConnectConfig: |
|---|
| 91 | | def __init__(self,node): |
|---|
| 92 | | self.node=node |
|---|
| 93 | | self.host=node.xpathEval("host")[0].getContent() |
|---|
| 94 | | self.port=int(node.xpathEval("port")[0].getContent()) |
|---|
| 95 | | self.secret=node.xpathEval("secret")[0].getContent() |
|---|
| 96 | | |
|---|
| 97 | | class SPIdentDConfig: |
|---|
| 98 | | def __init__(self,node): |
|---|
| 99 | | node=node.xpathEval("socket")[0] |
|---|
| 100 | | self.socket=node.getContent() |
|---|
| 101 | | |
|---|
| 102 | | class ServerConfig: |
|---|
| 103 | | def __init__(self,node): |
|---|
| 104 | | self.host=node.getContent() |
|---|
| 105 | | self.port=node.prop("port") |
|---|
| 106 | | try: |
|---|
| 107 | | self.port=int(self.port) |
|---|
| 108 | | if self.port<1 or self.port>65535: |
|---|
| 109 | | raise ValueError |
|---|
| 110 | | except ValueError: |
|---|
| 111 | | print >>sys.stderr,"Bad port value: %r, using default: 6667" % (self.port,) |
|---|
| 112 | | self.port=6667 |
|---|
| 113 | | def __repr__(self): |
|---|
| 114 | | return "<ServerConfig %s:%s/>" % (self.host,self.port) |
|---|
| 115 | | |
|---|
| 116 | | class ChannelConfig: |
|---|
| 117 | | def __init__(self,node): |
|---|
| 118 | | self.name=node.getContent() |
|---|
| 119 | | self.encoding=node.prop("encoding") |
|---|
| 120 | | |
|---|
| 121 | | class NetworkConfig: |
|---|
| 122 | | def __init__(self,node): |
|---|
| 123 | | self.node=node |
|---|
| 124 | | self.jid=JID(node.prop("jid")) |
|---|
| 125 | | servers=node.xpathEval("server") |
|---|
| 126 | | self.servers=[] |
|---|
| 127 | | for s in servers: |
|---|
| 128 | | self.servers.append(ServerConfig(s)) |
|---|
| 129 | | channels=node.xpathEval("channel") |
|---|
| 130 | | self.channels={} |
|---|
| 131 | | if channels: |
|---|
| 132 | | for c in channels: |
|---|
| 133 | | ch=ChannelConfig(c) |
|---|
| 134 | | self.channels[normalize(ch.name)]=ch |
|---|
| 135 | | self.default_encoding=node.prop("encoding") |
|---|
| 136 | | self.nicks_8bit=node.prop("nicks_8bit") |
|---|
| 137 | | def get_servers(self): |
|---|
| 138 | | r=self.servers |
|---|
| 139 | | self.servers=self.servers[-1:]+self.servers[1:] |
|---|
| 140 | | return r |
|---|
| 141 | | def get_channel_config(self,channel): |
|---|
| 142 | | return self.channels.get(normalize(channel)) |
|---|
| 143 | | def valid_nick(self,s): |
|---|
| 144 | | if self.nicks_8bit: |
|---|
| 145 | | m=nick8_re.match(s) |
|---|
| 146 | | else: |
|---|
| 147 | | m=nick_re.match(s) |
|---|
| 148 | | if m: |
|---|
| 149 | | return 1 |
|---|
| 150 | | else: |
|---|
| 151 | | return 0 |
|---|
| 152 | | |
|---|
| 153 | | class Config: |
|---|
| 154 | | def __init__(self,filename): |
|---|
| 155 | | self.doc=None |
|---|
| 156 | | parser=libxml2.createFileParserCtxt(filename) |
|---|
| 157 | | parser.validate(1) |
|---|
| 158 | | parser.parseDocument() |
|---|
| 159 | | if not parser.isValid(): |
|---|
| 160 | | raise JJIGWFatalError,"Invalid configuration" |
|---|
| 161 | | self.doc=parser.doc() |
|---|
| 162 | | self.connect=ConnectConfig(self.doc.xpathEval("jjigw/connect")[0]) |
|---|
| 163 | | self.network=NetworkConfig(self.doc.xpathEval("jjigw/network")[0]) |
|---|
| 164 | | spidentd=self.doc.xpathEval("jjigw/spidentd") |
|---|
| 165 | | if spidentd: |
|---|
| 166 | | self.spidentd=SPIdentDConfig(spidentd[0]) |
|---|
| 167 | | else: |
|---|
| 168 | | self.spidentd=None |
|---|
| 169 | | def __del__(self): |
|---|
| 170 | | if self.doc: |
|---|
| 171 | | self.doc.freeDoc() |
|---|
| 172 | | |
|---|
| 173 | | |
|---|
| 174 | | class Request: |
|---|
| 175 | | def __init__(self,command,stanza,args=None): |
|---|
| 176 | | self.command=command |
|---|
| 177 | | self.stanza=stanza |
|---|
| 178 | | self.args=args |
|---|
| 179 | | def match(self,commands,args=None): |
|---|
| 180 | | if type(commands) in (StringType,UnicodeType): |
|---|
| 181 | | commands=[commands] |
|---|
| 182 | | for c in commands: |
|---|
| 183 | | if not self.command==c: |
|---|
| 184 | | continue |
|---|
| 185 | | if args and not self.args==args: |
|---|
| 186 | | continue |
|---|
| 187 | | return 1 |
|---|
| 188 | | return 0 |
|---|
| 189 | | |
|---|
| 190 | | class RequestQueue: |
|---|
| 191 | | def __init__(self,maxsize): |
|---|
| 192 | | self.maxsize=maxsize |
|---|
| 193 | | self.requests=[] |
|---|
| 194 | | def get(self,commands,args=None): |
|---|
| 195 | | for r in self.requests: |
|---|
| 196 | | if r.match(commands): |
|---|
| 197 | | try: |
|---|
| 198 | | self.requests.remove(r) |
|---|
| 199 | | except ValueError: |
|---|
| 200 | | pass |
|---|
| 201 | | return r |
|---|
| 202 | | return None |
|---|
| 203 | | def add(self,command,stanza,args=None): |
|---|
| 204 | | r=Request(command,stanza,args) |
|---|
| 205 | | self.requests.append(r) |
|---|
| 206 | | if len(self.requests)>10: |
|---|
| 207 | | self.requests=self.requests[-10:] |
|---|
| 208 | | |
|---|
| 209 | | class IRCUser: |
|---|
| 210 | | def __init__(self,session,nick,user="",host=""): |
|---|
| 211 | | self.sync_delay=0 |
|---|
| 212 | | self.session=session |
|---|
| 213 | | if "!" in nick: |
|---|
| 214 | | nick,tmp=nick.split("!",1) |
|---|
| 215 | | if "@" in tmp: |
|---|
| 216 | | user,host=tmp.split("@",1) |
|---|
| 217 | | else: |
|---|
| 218 | | user=tmp |
|---|
| 219 | | host="" |
|---|
| 220 | | self.nick=nick |
|---|
| 221 | | self.user=user |
|---|
| 222 | | self.host=host |
|---|
| 223 | | self.mode={} |
|---|
| 224 | | self.channels={} |
|---|
| 225 | | self.current_thread=None |
|---|
| 226 | | |
|---|
| 227 | | def descr(self): |
|---|
| 228 | | if self.user and self.host: |
|---|
| 229 | | return "%s(%s@%s)" % (self.nick,self.user,self.host) |
|---|
| 230 | | else: |
|---|
| 231 | | return self.nick |
|---|
| 232 | | |
|---|
| 233 | | def sync_in_channel(self,channel,status=None): |
|---|
| 234 | | if self.sync_delay>0: |
|---|
| 235 | | return |
|---|
| 236 | | elif self.sync_delay<0: |
|---|
| 237 | | self.debug("Warning: %r.sync_delay<0" % (self,)) |
|---|
| 238 | | return channel.sync_user(self,status=status) |
|---|
| 239 | | |
|---|
| 240 | | def join_channel(self,channel): |
|---|
| 241 | | self.channels[normalize(channel.name)]=channel |
|---|
| 242 | | self.sync_in_channel(channel) |
|---|
| 243 | | |
|---|
| 244 | | def leave_channel(self,channel,status=None): |
|---|
| 245 | | try: |
|---|
| 246 | | del self.channels[normalize(channel.name)] |
|---|
| 247 | | self.sync_in_channel(channel,status=status) |
|---|
| 248 | | except KeyError: |
|---|
| 249 | | pass |
|---|
| 250 | | |
|---|
| 251 | | def leave_all(self): |
|---|
| 252 | | for channel in self.channels.values(): |
|---|
| 253 | | self.leave_channel(channel) |
|---|
| 254 | | |
|---|
| 255 | | def sync_all(self): |
|---|
| 256 | | for channel in self.channels.values(): |
|---|
| 257 | | self.sync_in_channel(channel) |
|---|
| 258 | | |
|---|
| 259 | | def whoreply(self,params): |
|---|
| 260 | | if params[4]!=self.nick: |
|---|
| 261 | | return |
|---|
| 262 | | if len(params)!=7: |
|---|
| 263 | | return |
|---|
| 264 | | channel,user,host,server,nick,flags,rest=params |
|---|
| 265 | | fullname=rest.split(None,1)[1] |
|---|
| 266 | | if channel and channel!="*": |
|---|
| 267 | | channel=self.session.channels.get(normalize(channel)) |
|---|
| 268 | | if not channel: |
|---|
| 269 | | self.debug("Ignoring WHO reply: %r - unknown channel" % (params,)) |
|---|
| 270 | | return |
|---|
| 271 | | else: |
|---|
| 272 | | channel=None |
|---|
| 273 | | self.sync_delay+=1 |
|---|
| 274 | | try: |
|---|
| 275 | | self.nick=nick |
|---|
| 276 | | self.host=host |
|---|
| 277 | | self.user=user |
|---|
| 278 | | if channel: |
|---|
| 279 | | self.join_channel(channel) |
|---|
| 280 | | if "@" in flags: |
|---|
| 281 | | channel.set_mode("o",self) |
|---|
| 282 | | elif "+" in flags: |
|---|
| 283 | | channel.set_mode("v",self) |
|---|
| 284 | | else: |
|---|
| 285 | | channel.reset_mode("o",self) |
|---|
| 286 | | channel.reset_mode("v",self) |
|---|
| 287 | | if "G" in flags: |
|---|
| 288 | | self.mode["a"]=1 |
|---|
| 289 | | else: |
|---|
| 290 | | self.mode["a"]=0 |
|---|
| 291 | | finally: |
|---|
| 292 | | self.sync_delay-=1 |
|---|
| 293 | | if channel: |
|---|
| 294 | | channel.sync_user(self) |
|---|
| 295 | | |
|---|
| 296 | | def jid(self): |
|---|
| 297 | | return JID(nick_to_node(self.nick,self.session.default_encoding), |
|---|
| 298 | | self.session.network.jid.domain, |
|---|
| 299 | | unicode(self.user+'@'+self.host,self.session.default_encoding,"replace")) |
|---|
| 300 | | |
|---|
| 301 | | def __repr__(self): |
|---|
| 302 | | return "<IRCUser %r>" % (self.nick,) |
|---|
| 303 | | |
|---|
| 304 | | def debug(self,msg): |
|---|
| 305 | | return self.session.debug(msg) |
|---|
| 306 | | |
|---|
| 307 | | class Channel: |
|---|
| 308 | | toggle_modes="aimnqpsrt" |
|---|
| 309 | | arg_modes="kl" |
|---|
| 310 | | multiarg_modes="OovbeI" |
|---|
| 311 | | def __init__(self,session,name): |
|---|
| 312 | | if not channel_re.match(name): |
|---|
| 313 | | raise ValueError,"Bad channel name" |
|---|
| 314 | | self.name=name |
|---|
| 315 | | self.session=session |
|---|
| 316 | | self.state=None |
|---|
| 317 | | self.room_jid=None |
|---|
| 318 | | self.config=session.network.get_channel_config(name) |
|---|
| 319 | | if self.config and self.config.encoding: |
|---|
| 320 | | self.encoding=self.config.encoding |
|---|
| 321 | | else: |
|---|
| 322 | | self.encoding=session.default_encoding |
|---|
| 323 | | self.modes={} |
|---|
| 324 | | self.users=[] |
|---|
| 325 | | self.muc=0 |
|---|
| 326 | | self.requests=RequestQueue(10) |
|---|
| 327 | | |
|---|
| 328 | | def sync_user(self,user,status=None): |
|---|
| 329 | | if user.channels.has_key(normalize(self.name)): |
|---|
| 330 | | if user not in self.users: |
|---|
| 331 | | self.users.append(user) |
|---|
| 332 | | else: |
|---|
| 333 | | for m in self.multiarg_modes: |
|---|
| 334 | | ul=self.modes.get(m,[]) |
|---|
| 335 | | if user in ul: |
|---|
| 336 | | ul.remove(user) |
|---|
| 337 | | if user in self.users: |
|---|
| 338 | | self.users.remove(user) |
|---|
| 339 | | self.send_notice_message(u"%s has quit" |
|---|
| 340 | | % (unicode(user.nick,self.encoding,"replace"),)) |
|---|
| 341 | | if self.state: |
|---|
| 342 | | p=self.get_user_presence(user,status=status) |
|---|
| 343 | | self.session.component.send(p) |
|---|
| 344 | | |
|---|
| 345 | | def send_notice_message(self,msg,not_in_muc=1): |
|---|
| 346 | | if not self.state or (self.muc and not_in_muc): |
|---|
| 347 | | return |
|---|
| 348 | | m=Message(fr=self.room_jid.bare(),to=self.session.jid,type="groupchat",body=msg) |
|---|
| 349 | | self.session.component.send(m) |
|---|
| 350 | | |
|---|
| 351 | | def join(self,stanza): |
|---|
| 352 | | if self.state: |
|---|
| 353 | | self.debug("Channel %r not in the initial state, not joining!" % (self.name,)) |
|---|
| 354 | | p=stanza.make_error_response(stanza,"bad-request") |
|---|
| 355 | | self.session.component.send(p) |
|---|
| 356 | | return |
|---|
| 357 | | self.room_jid=stanza.get_to() |
|---|
| 358 | | self.debug("Joining channel %r" % (self.name,)) |
|---|
| 359 | | self.session.send("JOIN %s" % (self.name,)) |
|---|
| 360 | | self.requests.add("JOIN",stanza) |
|---|
| 361 | | self.state="join" |
|---|
| 362 | | if stanza.get_join_info(): |
|---|
| 363 | | self.muc=1 |
|---|
| 364 | | |
|---|
| 365 | | def leave(self,stanza): |
|---|
| 366 | | status=stanza.get_status() |
|---|
| 367 | | if not self.state: |
|---|
| 368 | | self.debug("Channel %r in the initial state - nothing to do." % (self.name,)) |
|---|
| 369 | | else: |
|---|
| 370 | | if status: |
|---|
| 371 | | self.session.send("PART %s" % (self.name,)) |
|---|
| 372 | | else: |
|---|
| 373 | | self.session.send("PART %s :%s" % (self.name, |
|---|
| 374 | | status.encode(self.encoding,"replace"))) |
|---|
| 375 | | self.state=None |
|---|
| 376 | | p=MucPresence(type="unavailable",fr=stanza.get_to(),to=stanza.get_from(),status=status) |
|---|
| 377 | | self.session.component.send(p) |
|---|
| 378 | | for u in self.users: |
|---|
| 379 | | u.leave_room(self) |
|---|
| 380 | | self.state=None |
|---|
| 381 | | |
|---|
| 382 | | def prefix_to_jid(self,prefix): |
|---|
| 383 | | if "!" in prefix: |
|---|
| 384 | | return self.nick_to_jid(prefix.split("!")[0]) |
|---|
| 385 | | return self.nick_to_jid(prefix) |
|---|
| 386 | | |
|---|
| 387 | | def nick_to_jid(self,nick): |
|---|
| 388 | | return JID(self.room_jid.node,self.room_jid.domain, |
|---|
| 389 | | unicode(nick,self.encoding,"replace")) |
|---|
| 390 | | |
|---|
| 391 | | def get_user_presence(self,user,nick=None,actor=None,reason=None,status=None): |
|---|
| 392 | | if self.state and user in self.users: |
|---|
| 393 | | p=MucPresence(fr=self.nick_to_jid(user.nick),to=self.session.jid) |
|---|
| 394 | | else: |
|---|
| 395 | | p=MucPresence(type="unavailable",fr=self.nick_to_jid(user.nick),to=self.session.jid) |
|---|
| 396 | | if self.muc: |
|---|
| 397 | | if user in self.modes.get("o",[]): |
|---|
| 398 | | aff="admin" |
|---|
| 399 | | role="moderator" |
|---|
| 400 | | elif user in self.modes.get("v",[]): |
|---|
| 401 | | aff="member" |
|---|
| 402 | | role="participant" |
|---|
| 403 | | elif self.modes.get("m"): |
|---|
| 404 | | aff="none" |
|---|
| 405 | | role="visitor" |
|---|
| 406 | | elif user in self.users: |
|---|
| 407 | | aff="none" |
|---|
| 408 | | role="participant" |
|---|
| 409 | | else: |
|---|
| 410 | | aff="none" |
|---|
| 411 | | role="none" |
|---|
| 412 | | ui=p.make_muc_userinfo() |
|---|
| 413 | | if nick: |
|---|
| 414 | | nick=unicode(user.nick,self.encoding,"replace") |
|---|
| 415 | | it=MucItem(aff,role,user.jid(),nick=nick,actor=actor,reason=reason) |
|---|
| 416 | | ui.add_item(it) |
|---|
| 417 | | if status: |
|---|
| 418 | | ui.add_item(MucStatus(status)) |
|---|
| 419 | | return p |
|---|
| 420 | | |
|---|
| 421 | | def nick_changed(self,oldnick,user): |
|---|
| 422 | | p_unaval=self.get_user_presence(user,nick=user.nick,status=303) |
|---|
| 423 | | p_unaval.set_type("unavailable") |
|---|
| 424 | | p_unaval.set_show(None) |
|---|
| 425 | | p_unaval.set_status(None) |
|---|
| 426 | | p_unaval.set_from(self.nick_to_jid(oldnick)) |
|---|
| 427 | | p_aval=self.get_user_presence(user,status=303) |
|---|
| 428 | | self.session.component.send(p_unaval) |
|---|
| 429 | | self.session.component.send(p_aval) |
|---|
| 430 | | self.send_notice_message(u"%s is now known as %s" |
|---|
| 431 | | % (unicode(oldnick,self.encoding,"replace"), |
|---|
| 432 | | unicode(user.nick,self.encoding,"replace"))) |
|---|
| 433 | | |
|---|
| 434 | | def set_mode(self,mode,arg): |
|---|
| 435 | | if mode in self.toggle_modes: |
|---|
| 436 | | self.modes[mode]=1 |
|---|
| 437 | | elif mode in self.arg_modes: |
|---|
| 438 | | self.modes[mode]=arg |
|---|
| 439 | | elif mode in self.multiarg_modes: |
|---|
| 440 | | if self.modes.has_key(mode): |
|---|
| 441 | | self.modes[mode].append(arg) |
|---|
| 442 | | else: |
|---|
| 443 | | self.modes[mode]=[arg] |
|---|
| 444 | | |
|---|
| 445 | | def reset_mode(self,mode,arg): |
|---|
| 446 | | try: |
|---|
| 447 | | if mode in self.toggle_modes: |
|---|
| 448 | | del self.modes[mode] |
|---|
| 449 | | elif mode in self.arg_modes: |
|---|
| 450 | | del self.modes[mode] |
|---|
| 451 | | elif mode in self.multiarg_modes: |
|---|
| 452 | | if self.modes.has_key(mode): |
|---|
| 453 | | self.modes[mode].remove(arg) |
|---|
| 454 | | if not self.modes[mode]: |
|---|
| 455 | | del self.modes[mode] |
|---|
| 456 | | except (KeyError,ValueError): |
|---|
| 457 | | pass |
|---|
| 458 | | |
|---|
| 459 | | def irc_cmd_324(self,prefix,command,params): # RPL_CHANNELMODEIS |
|---|
| 460 | | for m in self.toggle_modes: |
|---|
| 461 | | try: |
|---|
| 462 | | del self.modes[m] |
|---|
| 463 | | except KeyError: |
|---|
| 464 | | pass |
|---|
| 465 | | self.irc_mode_changed(prefix,command,params) |
|---|
| 466 | | |
|---|
| 467 | | def irc_cmd_482(self,prefix,command,params): # ERR_CHANOPRIVSNEEDED |
|---|
| 468 | | self.irc_error_response(prefix,command,params,["TOPIC","KICK","MODE"],"forbidden") |
|---|
| 469 | | |
|---|
| 470 | | def irc_cmd_461(self,prefix,command,params): # ERR_NEEDMOREPARAMS |
|---|
| 471 | | self.irc_error_response(prefix,command,params,["TOPIC","KICK","MODE"],"bad-request") |
|---|
| 472 | | |
|---|
| 473 | | def irc_cmd_403(self,prefix,command,params): # ERR_NOSUCHCHANNEL |
|---|
| 474 | | self.irc_error_response(prefix,command,params,["KICK"],"recipient-unavailable") |
|---|
| 475 | | |
|---|
| 476 | | def irc_cmd_476(self,prefix,command,params): # ERR_BADCHANMASK |
|---|
| 477 | | self.irc_error_response(prefix,command,params,["KICK"],"bad-request") |
|---|
| 478 | | |
|---|
| 479 | | def irc_cmd_441(self,prefix,command,params): # ERR_USERNOTINCHANNEL |
|---|
| 480 | | self.irc_error_response(prefix,command,params,["KICK","MODE"],"item-not-found") |
|---|
| 481 | | |
|---|
| 482 | | def irc_cmd_442(self,prefix,command,params): # ERR_NOTONCHANNEL |
|---|
| 483 | | self.irc_error_response(prefix,command,params,["TOPIC","KICK"],"forbidden") |
|---|
| 484 | | |
|---|
| 485 | | def irc_cmd_472(self,prefix,command,params): # ERR_UNKNOWNMODE |
|---|
| 486 | | self.irc_error_response(prefix,command,params,["MODE"],"feature-not-implemented") |
|---|
| 487 | | |
|---|
| 488 | | def irc_cmd_477(self,prefix,command,params): # ERR_NOCHANMODES |
|---|
| 489 | | self.irc_error_response(prefix,command,params,["TOPIC","MODE"],"not-acceptable") |
|---|
| 490 | | |
|---|
| 491 | | def irc_error_response(self,prefix,command,params,requests,condition): |
|---|
| 492 | | r=self.requests.get(requests) |
|---|
| 493 | | if r: |
|---|
| 494 | | m=r.stanza.make_error_response(condition) |
|---|
| 495 | | else: |
|---|
| 496 | | m=Message(fr=self.room_jid.bare(),to=self.session.jid, |
|---|
| 497 | | type="error", error_cond=condition) |
|---|
| 498 | | self.session.component.send(m) |
|---|
| 499 | | |
|---|
| 500 | | def irc_cmd_331(self,prefix,command,params): # RPL_NOTOPIC |
|---|
| 501 | | m=Message(fr=self.room_jid.bare(),to=self.session.jid, type="groupchat", subject=u"") |
|---|
| 502 | | self.session.component.send(m) |
|---|
| 503 | | |
|---|
| 504 | | def irc_cmd_332(self,prefix,command,params): # RPL_TOPIC |
|---|
| 505 | | topic=remove_evil_characters(params[1]) |
|---|
| 506 | | m=Message(fr=self.room_jid.bare(),to=self.session.jid, |
|---|
| 507 | | type="groupchat", subject=unicode(topic,self.encoding,"replace")) |
|---|
| 508 | | self.session.component.send(m) |
|---|
| 509 | | |
|---|
| 510 | | def irc_cmd_TOPIC(self,prefix,command,params): |
|---|
| 511 | | self.requests.get("TOPIC") |
|---|
| 512 | | topic=remove_evil_characters(params[1]) |
|---|
| 513 | | m=Message(fr=self.prefix_to_jid(prefix),to=self.session.jid, |
|---|
| 514 | | type="groupchat", subject=unicode(topic,self.encoding,"replace")) |
|---|
| 515 | | self.session.component.send(m) |
|---|
| 516 | | |
|---|
| 517 | | def irc_cmd_MODE(self,prefix,command,params): |
|---|
| 518 | | if len(params)<2: |
|---|
| 519 | | self.debug("No parameters in received MODE") |
|---|
| 520 | | return |
|---|
| 521 | | params_str=string.join(params[2:]," ").strip() |
|---|
| 522 | | if params_str: |
|---|
| 523 | | params_str=" "+params_str |
|---|
| 524 | | if "!" in prefix: |
|---|
| 525 | | nick,iuser=prefix.split("!",1) |
|---|
| 526 | | iuser="(%s)" % (iuser,) |
|---|
| 527 | | else: |
|---|
| 528 | | nick,iuser=prefix,"" |
|---|
| 529 | | self.send_notice_message(u"Mode change: [%s%s] by %s%s" |
|---|
| 530 | | % (unicode(params[1],self.encoding,"replace"), |
|---|
| 531 | | unicode(params_str,self.encoding,"replace"), |
|---|
| 532 | | unicode(nick,self.encoding,"replace"), |
|---|
| 533 | | unicode(iuser,self.encoding,"replace")), |
|---|
| 534 | | 0) |
|---|
| 535 | | if self.session.check_prefix(prefix) and len(params)>=3: |
|---|
| 536 | | r=self.requests.get("MODE",string.join(params[1:]," ")) |
|---|
| 537 | | if r: |
|---|
| 538 | | reply=r.stanza.make_result_response() |
|---|
| 539 | | self.session.component.send(reply) |
|---|
| 540 | | self.irc_mode_changed(prefix,command,params) |
|---|
| 541 | | |
|---|
| 542 | | def irc_mode_changed(self,prefix,command,params): |
|---|
| 543 | | actor=self.session.get_user(prefix) |
|---|
| 544 | | modes=params[1] |
|---|
| 545 | | params=params[2:] |
|---|
| 546 | | pm=None |
|---|
| 547 | | for m in modes: |
|---|
| 548 | | if m in "+-": |
|---|
| 549 | | pm=m |
|---|
| 550 | | continue |
|---|
| 551 | | elif not pm: |
|---|
| 552 | | self.debug("Not '+' or '-' before '%s' in received MODE" % (m,)) |
|---|
| 553 | | continue |
|---|
| 554 | | elif m in self.arg_modes or m in self.multiarg_modes: |
|---|
| 555 | | if not len(params): |
|---|
| 556 | | self.debug("No argument for mode '%s' in received MODE" % (m,)) |
|---|
| 557 | | continue |
|---|
| 558 | | arg=params.pop(0) |
|---|
| 559 | | elif m in self.toggle_modes: |
|---|
| 560 | | arg=None |
|---|
| 561 | | else: |
|---|
| 562 | | self.debug("Unknown mode '%s' in received MODE" % (m,)) |
|---|
| 563 | | continue |
|---|
| 564 | | if m in "oOv": |
|---|
| 565 | | arg=self.session.get_user(arg) |
|---|
| 566 | | if not arg: |
|---|
| 567 | | continue |
|---|
| 568 | | if pm=="+": |
|---|
| 569 | | self.set_mode(m,arg) |
|---|
| 570 | | else: |
|---|
| 571 | | self.reset_mode(m,arg) |
|---|
| 572 | | if m in "oOv": |
|---|
| 573 | | self.user_mode_changed(arg,actor,m) |
|---|
| 574 | | elif m=="m": |
|---|
| 575 | | for u in self.users: |
|---|
| 576 | | self.sync_user(u) |
|---|
| 577 | | |
|---|
| 578 | | def user_mode_changed(self,user,actor,mode): |
|---|
| 579 | | if actor: |
|---|
| 580 | | actor_jid=self.nick_to_jid(actor.nick) |
|---|
| 581 | | else: |
|---|
| 582 | | actor_jid=None |
|---|
| 583 | | p=self.get_user_presence(user,actor_jid) |
|---|
| 584 | | if actor: |
|---|
| 585 | | by=u" by %s" % (unicode(actor.nick,self.encoding,"replace"),) |
|---|
| 586 | | else: |
|---|
| 587 | | by=u"" |
|---|
| 588 | | self.session.component.send(p) |
|---|
| 589 | | if mode=="v": |
|---|
| 590 | | self.send_notice_message(u"%s was granted voice%s" |
|---|
| 591 | | % (unicode(user.nick,self.encoding,"replace"),by)) |
|---|
| 592 | | elif mode=="o": |
|---|
| 593 | | self.send_notice_message(u"%s was granted operator status%s" |
|---|
| 594 | | % (unicode(user.nick,self.encoding,"replace"),by)) |
|---|
| 595 | | elif mode=="O": |
|---|
| 596 | | self.send_notice_message(u"%s was granted got owner status%s" |
|---|
| 597 | | % (unicode(user.nick,self.encoding,"replace"),by)) |
|---|
| 598 | | |
|---|
| 599 | | def irc_cmd_JOIN(self,prefix,command,params): |
|---|
| 600 | | nprefix=normalize(prefix) |
|---|
| 601 | | nnick=normalize(self.session.nick) |
|---|
| 602 | | if nprefix==nnick or nprefix.startswith(nnick+"!"): |
|---|
| 603 | | if self.state=="join": |
|---|
| 604 | | self.debug("Channel %r joined!" % (self.name,)) |
|---|
| 605 | | self.session.user.sync_delay+=1 |
|---|
| 606 | | try: |
|---|
| 607 | | self.session.user.join_channel(self) |
|---|
| 608 | | finally: |
|---|
| 609 | | self.session.user.sync_delay-=1 |
|---|
| 610 | | self.state="joined" |
|---|
| 611 | | self.requests.get("JOIN") |
|---|
| 612 | | self.session.send("MODE %s" % (self.name,)) |
|---|
| 613 | | self.session.send("WHO %s" % (self.name,)) |
|---|
| 614 | | else: |
|---|
| 615 | | user=self.session.get_user(prefix) |
|---|
| 616 | | user.join_channel(self) |
|---|
| 617 | | self.send_notice_message(u"%s has joined" |
|---|
| 618 | | % (unicode(user.nick,self.encoding,"replace"),)) |
|---|
| 619 | | self.session.send("WHO %s" % (user.nick,)) |
|---|
| 620 | | |
|---|
| 621 | | def irc_cmd_PART(self,prefix,command,params): |
|---|
| 622 | | user=self.session.get_user(prefix) |
|---|
| 623 | | try: |
|---|
| 624 | | self.users.remove(user) |
|---|
| 625 | | except ValueError: |
|---|
| 626 | | pass |
|---|
| 627 | | user.leave_channel(self) |
|---|
| 628 | | self.send_notice_message(u"%s has left" |
|---|
| 629 | | % (unicode(user.nick,self.encoding,"replace"),)) |
|---|
| 630 | | |
|---|
| 631 | | def irc_cmd_KICK(self,prefix,command,params): |
|---|
| 632 | | actor=self.session.get_user(prefix) |
|---|
| 633 | | user=self.session.get_user(params[1]) |
|---|
| 634 | | try: |
|---|
| 635 | | self.users.remove(user) |
|---|
| 636 | | except ValueError: |
|---|
| 637 | | pass |
|---|
| 638 | | self.send_notice_message(u"%s was kicked by %s" |
|---|
| 639 | | % (unicode(user.descr(),self.encoding,"replace"), |
|---|
| 640 | | unicode(actor.descr(),self.encoding,"replace")), |
|---|
| 641 | | 0) |
|---|
| 642 | | user.leave_channel(self,status=307) |
|---|
| 643 | | if user and self.session.check_prefix(prefix): |
|---|
| 644 | | r=self.requests.get("KICK",user.nick) |
|---|
| 645 | | if r: |
|---|
| 646 | | iq=r.stanza.make_result_response() |
|---|
| 647 | | self.session.component.send(iq) |
|---|
| 648 | | |
|---|
| 649 | | def irc_cmd_PRIVMSG(self,prefix,command,params): |
|---|
| 650 | | self.irc_message(prefix,command,params) |
|---|
| 651 | | |
|---|
| 652 | | def irc_cmd_NOTICE(self,prefix,command,params): |
|---|
| 653 | | self.irc_message(prefix,command,params) |
|---|
| 654 | | |
|---|
| 655 | | def irc_message(self,prefix,command,params): |
|---|
| 656 | | if not self.state or len(params)<2: |
|---|
| 657 | | self.debug("ignoring it") |
|---|
| 658 | | return |
|---|
| 659 | | body=unicode(params[1],self.encoding,"replace") |
|---|
| 660 | | if body[0]=="\001" and body[-1]=="\001": |
|---|
| 661 | | self.CTCP(prefix,body[1:-1]) |
|---|
| 662 | | else: |
|---|
| 663 | | m=Message(type="groupchat",fr=self.prefix_to_jid(prefix),to=self.session.jid, |
|---|
| 664 | | body=remove_evil_characters(strip_colors(body))) |
|---|
| 665 | | self.session.component.send(m) |
|---|
| 666 | | |
|---|
| 667 | | def CTCP(self,prefix,command): |
|---|
| 668 | | if " " in command: |
|---|
| 669 | | command,arg=command.split(" ",1) |
|---|
| 670 | | else: |
|---|
| 671 | | arg=None |
|---|
| 672 | | if command=="ACTION": |
|---|
| 673 | | m=Message(type="groupchat",fr=self.prefix_to_jid(prefix),to=self.session.jid, |
|---|
| 674 | | body="/me "+remove_evil_characters(strip_colors(arg))) |
|---|
| 675 | | self.session.component.send(m) |
|---|
| 676 | | else: |
|---|
| 677 | | self.debug("Unknown CTCP command: %r %r" % (command,arg)) |
|---|
| 678 | | |
|---|
| 679 | | def change_topic(self,topic,stanza): |
|---|
| 680 | | topic=topic.encode(self.encoding,"replace") |
|---|
| 681 | | topic=topic.replace("\n"," ").replace("\r"," ") |
|---|
| 682 | | self.session.send("TOPIC %s :%s" % (self.name,topic)) |
|---|
| 683 | | self.requests.add("TOPIC",stanza) |
|---|
| 684 | | |
|---|
| 685 | | def kick_user(self,nick,reason,stanza): |
|---|
| 686 | | nick=nick.encode(self.encoding,"strict") |
|---|
| 687 | | self.session.send("KICK %s %s :%s" % (self.name,nick,reason)) |
|---|
| 688 | | self.requests.add("KICK",stanza,nick) |
|---|
| 689 | | |
|---|
| 690 | | def op_user(self,nick,stanza): |
|---|
| 691 | | nick=nick.encode(self.encoding,"strict") |
|---|
| 692 | | user=self.session.users.get(normalize(nick)) |
|---|
| 693 | | if not user in self.users: |
|---|
| 694 | | r=stanza.make_error_response("item-not-found") |
|---|
| 695 | | self.session.component.send(r) |
|---|
| 696 | | return |
|---|
| 697 | | if user in self.modes.get("o",[]): |
|---|
| 698 | | r=stanza.make_result_response() |
|---|
| 699 | | self.session.component.send(r) |
|---|
| 700 | | return |
|---|
| 701 | | if user in self.modes.get("v",[]): |
|---|
| 702 | | change="-v+o %s %s" % (nick,nick) |
|---|
| 703 | | else: |
|---|
| 704 | | change="+o "+nick |
|---|
| 705 | | self.session.send("MODE %s %s" % (self.name,change)) |
|---|
| 706 | | self.requests.add("MODE",stanza,change) |
|---|
| 707 | | |
|---|
| 708 | | def voice_user(self,nick,stanza): |
|---|
| 709 | | nick=nick.encode(self.encoding,"strict") |
|---|
| 710 | | user=self.session.users.get(normalize(nick)) |
|---|
| 711 | | if not user in self.users: |
|---|
| 712 | | r=stanza.make_error_response("item-not-found") |
|---|
| 713 | | self.session.component.send(r) |
|---|
| 714 | | return |
|---|
| 715 | | if user in self.modes.get("v",[]): |
|---|
| 716 | | r=stanza.make_result_response() |
|---|
| 717 | | self.session.component.send(r) |
|---|
| 718 | | return |
|---|
| 719 | | if user in self.modes.get("o",[]): |
|---|
| 720 | | change="-o+v %s %s" % (nick,nick) |
|---|
| 721 | | else: |
|---|
| 722 | | change="+v "+nick |
|---|
| 723 | | self.session.send("MODE %s %s" % (self.name,change)) |
|---|
| 724 | | self.requests.add("MODE",stanza,change) |
|---|
| 725 | | |
|---|
| 726 | | def devoice_user(self,nick,stanza): |
|---|
| 727 | | nick=nick.encode(self.encoding,"strict") |
|---|
| 728 | | user=self.session.users.get(normalize(nick)) |
|---|
| 729 | | if not user in self.users: |
|---|
| 730 | | r=stanza.make_error_response("item-not-found") |
|---|
| 731 | | self.session.component.send(r) |
|---|
| 732 | | return |
|---|
| 733 | | if user in self.modes.get("v",[]) and user in self.modes.get("o",[]): |
|---|
| 734 | | change="-o-v %s %s" % (nick,nick) |
|---|
| 735 | | elif user in self.modes.get("o",[]): |
|---|
| 736 | | change="-o "+nick |
|---|
| 737 | | elif user in self.modes.get("v",[]): |
|---|
| 738 | | change="-v "+nick |
|---|
| 739 | | else: |
|---|
| 740 | | r=stanza.make_result_response() |
|---|
| 741 | | self.session.component.send(r) |
|---|
| 742 | | return |
|---|
| 743 | | self.session.send("MODE %s %s" % (self.name,change)) |
|---|
| 744 | | self.requests.add("MODE",stanza,change) |
|---|
| 745 | | |
|---|
| 746 | | def __repr__(self): |
|---|
| 747 | | return "<IRCChannel %r>" % (self.name,) |
|---|
| 748 | | |
|---|
| 749 | | def debug(self,msg): |
|---|
| 750 | | return self.session.debug(msg) |
|---|
| 751 | | |
|---|
| 752 | | |
|---|
| 753 | | class IRCSession: |
|---|
| 754 | | commands_dont_show=[] |
|---|
| 755 | | def __init__(self,component,config,jid,nick): |
|---|
| 756 | | self.component=component |
|---|
| 757 | | self.config=config |
|---|
| 758 | | self.network=config.network |
|---|
| 759 | | self.default_encoding=self.network.default_encoding |
|---|
| 760 | | self.conninfo=None |
|---|
| 761 | | nick=nick.encode(self.default_encoding,"strict") |
|---|
| 762 | | if not self.network.valid_nick(nick): |
|---|
| 763 | | raise ValueError,"Bad nickname" |
|---|
| 764 | | self.jid=jid |
|---|
| 765 | | self.nick=nick |
|---|
| 766 | | self.thread=threading.Thread(name=u"%s on %s as %s" % (jid,config.network.jid,nick), |
|---|
| 767 | | target=self.thread_run) |
|---|
| 768 | | self.thread.setDaemon(1) |
|---|
| 769 | | self.exit=None |
|---|
| 770 | | self.exited=0 |
|---|
| 771 | | self.socket=None |
|---|
| 772 | | self.lock=threading.RLock() |
|---|
| 773 | | self.cond=threading.Condition(self.lock) |
|---|
| 774 | | self.servers_left=self.network.get_servers() |
|---|
| 775 | | self.input_buffer="" |
|---|
| 776 | | self.used_for=[] |
|---|
| 777 | | self.server=None |
|---|
| 778 | | self.join_requests=[] |
|---|
| 779 | | self.messages_to_channel=[] |
|---|
| 780 | | self.messages_to_user=[] |
|---|
| 781 | | self.ready=0 |
|---|
| 782 | | self.channels={} |
|---|
| 783 | | self.users={} |
|---|
| 784 | | self.user=IRCUser(self,nick) |
|---|
| 785 | | self.thread.start() |
|---|
| 786 | | |
|---|
| 787 | | def register_user(self,user): |
|---|
| 788 | | self.lock.acquire() |
|---|
| 789 | | try: |
|---|
| 790 | | self.users[normalize(user.nick)]=user |
|---|
| 791 | | finally: |
|---|
| 792 | | self.lock.release() |
|---|
| 793 | | |
|---|
| 794 | | def unregister_user(self,user): |
|---|
| 795 | | self.lock.acquire() |
|---|
| 796 | | try: |
|---|
| 797 | | nnick=normalize(user.nick) |
|---|
| 798 | | if self.users.get(nnick)==user: |
|---|
| 799 | | del self.users[nnick] |
|---|
| 800 | | finally: |
|---|
| 801 | | self.lock.release() |
|---|
| 802 | | |
|---|
| 803 | | def rename_user(self,user,new_nick): |
|---|
| 804 | | self.lock.acquire() |
|---|
| 805 | | try: |
|---|
| 806 | | self.users[normalize(new_nick)]=user |
|---|
| 807 | | try: |
|---|
| 808 | | del self.users[normalize(user.nick)] |
|---|
| 809 | | except KeyError: |
|---|
| 810 | | pass |
|---|
| 811 | | user.nick=new_nick |
|---|
| 812 | | finally: |
|---|
| 813 | | self.lock.release() |
|---|
| 814 | | |
|---|
| 815 | | def get_user(self,prefix,create=1): |
|---|
| 816 | | if "!" in prefix: |
|---|
| 817 | | nick=prefix.split("!",1)[0] |
|---|
| 818 | | else: |
|---|
| 819 | | nick=prefix |
|---|
| 820 | | if not self.network.valid_nick(nick): |
|---|
| 821 | | return None |
|---|
| 822 | | nnick=normalize(nick) |
|---|
| 823 | | if self.users.has_key(nnick): |
|---|
| 824 | | return self.users[nnick] |
|---|
| 825 | | if not create: |
|---|
| 826 | | return None |
|---|
| 827 | | user=IRCUser(self,prefix) |
|---|
| 828 | | self.register_user(user) |
|---|
| 829 | | return user |
|---|
| 830 | | |
|---|
| 831 | | def check_nick(self,nick): |
|---|
| 832 | | nick=nick.encode(self.default_encoding) |
|---|
| 833 | | if normalize(nick)==normalize(self.nick): |
|---|
| 834 | | return 1 |
|---|
| 835 | | else: |
|---|
| 836 | | return 0 |
|---|
| 837 | | |
|---|
| 838 | | def check_prefix(self,prefix): |
|---|
| 839 | | if "!" in prefix: |
|---|
| 840 | | nick=prefix.split("!",1)[0] |
|---|
| 841 | | else: |
|---|
| 842 | | nick=prefix |
|---|
| 843 | | return normalize(nick)==normalize(self.nick) |
|---|
| 844 | | |
|---|
| 845 | | def prefix_to_jid(self,prefix): |
|---|
| 846 | | if channel_re.match(prefix): |
|---|
| 847 | | node=channel_to_node(prefix,self.default_encoding) |
|---|
| 848 | | return JID(node,self.network.jid.domain,None) |
|---|
| 849 | | else: |
|---|
| 850 | | if "!" in prefix: |
|---|
| 851 | | nick,user=prefix.split("!",1) |
|---|
| 852 | | else: |
|---|
| 853 | | nick=prefix |
|---|
| 854 | | user="" |
|---|
| 855 | | node=nick_to_node(nick,self.default_encoding) |
|---|
| 856 | | resource=unicode(user,self.default_encoding,"replace") |
|---|
| 857 | | return JID(node,self.network.jid.domain,resource) |
|---|
| 858 | | |
|---|
| 859 | | def thread_run(self): |
|---|
| 860 | | clean_exit=1 |
|---|
| 861 | | try: |
|---|
| 862 | | self.thread_loop() |
|---|
| 863 | | except: |
|---|
| 864 | | clean_exit=0 |
|---|
| 865 | | self.print_exception() |
|---|
| 866 | | self.lock.acquire() |
|---|
| 867 | | try: |
|---|
| 868 | | if not self.exited and self.socket: |
|---|
| 869 | | if clean_exit and self.component.shutdown: |
|---|
| 870 | | self._send("QUIT :JJIGW shutdown") |
|---|
| 871 | | elif clean_exit and self.exit: |
|---|
| 872 | | self._send("QUIT :%s" % (self.exit.encode(self.default_encoding,"replace"))) |
|---|
| 873 | | else: |
|---|
| 874 | | self._send("QUIT :Internal JJIGW error") |
|---|
| 875 | | self.exited=1 |
|---|
| 876 | | if self.socket: |
|---|
| 877 | | try: |
|---|
| 878 | | self.socket.close() |
|---|
| 879 | | except: |
|---|
| 880 | | pass |
|---|
| 881 | | self.socket=None |
|---|
| 882 | | try: |
|---|
| 883 | | del self.component.irc_sessions[self.jid.as_unicode()] |
|---|
| 884 | | except KeyError: |
|---|
| 885 | | pass |
|---|
| 886 | | finally: |
|---|
| 887 | | self.lock.release() |
|---|
| 888 | | for j in self.used_for: |
|---|
| 889 | | p=Presence(fr=j,to=self.jid,type="unavailable") |
|---|
| 890 | | self.component.send(p) |
|---|
| 891 | | self.used_for=[] |
|---|
| 892 | | |
|---|
| 893 | | def thread_loop(self): |
|---|
| 894 | | self.debug("thread_loop()") |
|---|
| 895 | | while not self.exit and not self.component.shutdown: |
|---|
| 896 | | self.lock.acquire() |
|---|
| 897 | | try: |
|---|
| 898 | | if self.socket is None: |
|---|
| 899 | | self._try_connect() |
|---|
| 900 | | sock=self.socket |
|---|
| 901 | | self.lock.release() |
|---|
| 902 | | if sock is None: |
|---|
| 903 | | continue |
|---|
| 904 | | id,od,ed=select.select([sock],[],[sock],1) |
|---|
| 905 | | self.lock.acquire() |
|---|
| 906 | | if self.socket in id: |
|---|
| 907 | | self.input_buffer+=self.socket.recv(1024) |
|---|
| 908 | | while self.input_buffer.find("\r\n")>-1: |
|---|
| 909 | | input,self.input_buffer=self.input_buffer.split("\r\n",1) |
|---|
| 910 | | self._safe_process_input(input) |
|---|
| 911 | | finally: |
|---|
| 912 | | self.lock.release() |
|---|
| 913 | | self.lock.acquire() |
|---|
| 914 | | try: |
|---|
| 915 | | if self.socket: |
|---|
| 916 | | self.socket.close() |
|---|
| 917 | | self.socket=None |
|---|
| 918 | | if self.conninfo: |
|---|
| 919 | | self.component.unregister_connection(self.conninfo) |
|---|
| 920 | | self.conninfo=None |
|---|
| 921 | | finally: |
|---|
| 922 | | self.lock.release() |
|---|
| 923 | | |
|---|
| 924 | | def _try_connect(self): |
|---|
| 925 | | if not self.servers_left: |
|---|
| 926 | | self.debug("No servers left, quitting") |
|---|
| 927 | | self.exit="No servers left, quitting" |
|---|
| 928 | | return |
|---|
| 929 | | if self.conninfo: |
|---|
| 930 | | self.component.unregister_connection(self.conninfo) |
|---|
| 931 | | self.conninfo=None |
|---|
| 932 | | if self.socket: |
|---|
| 933 | | self.socket.close() |
|---|
| 934 | | self.socket=None |
|---|
| 935 | | server=self.servers_left.pop(0) |
|---|
| 936 | | self.debug("Trying to connect to %r" % (server,)) |
|---|
| 937 | | try: |
|---|
| 938 | | self.socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) |
|---|
| 939 | | self.socket.connect((server.host,server.port)) |
|---|
| 940 | | except (IOError,OSError,socket.error),err: |
|---|
| 941 | | self.debug("Server connect error: %r" % (err,)) |
|---|
| 942 | | if self.socket: |
|---|
| 943 | | try: |
|---|
| 944 | | self.socket.close() |
|---|
| 945 | | if self.conninfo: |
|---|
| 946 | | self.component.unregister_connection(self.conninfo) |
|---|
| 947 | | self.conninfo=None |
|---|
| 948 | | except: |
|---|
| 949 | | pass |
|---|
| 950 | | self.socket=None |
|---|
| 951 | | return |
|---|
| 952 | | self._send("NICK %s" % (self.nick,)) |
|---|
| 953 | | user=md5.new(self.jid.bare().as_string()).hexdigest()[:64] |
|---|
| 954 | | self.conninfo=ConnectionInfo(self.socket,user) |
|---|
| 955 | | self.component.register_connection(self.conninfo) |
|---|
| 956 | | self._send("USER %s 0 * :JJIGW User %s" % (user,user)) |
|---|
| 957 | | self.server=server |
|---|
| 958 | | self.cond.notify() |
|---|
| 959 | | |
|---|
| 960 | | def _send(self,str): |
|---|
| 961 | | if self.socket and not self.exited: |
|---|
| 962 | | self.debug("IRC OUT: %r" % (str,)) |
|---|
| 963 | | self.socket.send(str+"\r\n") |
|---|
| 964 | | else: |
|---|
| 965 | | self.debug("ignoring out: %r" % (str,)) |
|---|
| 966 | | |
|---|
| 967 | | def send(self,str): |
|---|
| 968 | | self.lock.acquire() |
|---|
| 969 | | try: |
|---|
| 970 | | self._send(str) |
|---|
| 971 | | finally: |
|---|
| 972 | | self.lock.release() |
|---|
| 973 | | |
|---|
| 974 | | def _safe_process_input(self,input): |
|---|
| 975 | | try: |
|---|
| 976 | | self._process_input(input) |
|---|
| 977 | | except: |
|---|
| 978 | | self.print_exception() |
|---|
| 979 | | |
|---|
| 980 | | def _process_input(self,input): |
|---|
| 981 | | self.debug("Server message: %r" % (input,)) |
|---|
| 982 | | split=input.split(" ") |
|---|
| 983 | | if split[0].startswith(":"): |
|---|
| 984 | | prefix=split[0][1:] |
|---|
| 985 | | split=split[1:] |
|---|
| 986 | | else: |
|---|
| 987 | | prefix=None |
|---|
| 988 | | if split: |
|---|
| 989 | | command=split[0] |
|---|
| 990 | | split=split[1:] |
|---|
| 991 | | else: |
|---|
| 992 | | command=None |
|---|
| 993 | | params=[] |
|---|
| 994 | | while split: |
|---|
| 995 | | if split[0].startswith(":"): |
|---|
| 996 | | params.append(string.join(split," ")[1:]) |
|---|
| 997 | | break |
|---|
| 998 | | params.append(split[0]) |
|---|
| 999 | | split=split[1:] |
|---|
| 1000 | | if command and numeric_re.match(command): |
|---|
| 1001 | | params=params[1:] |
|---|
| 1002 | | self.lock.release() |
|---|
| 1003 | | try: |
|---|
| 1004 | | f=None |
|---|
| 1005 | | for c in self.channels.keys(): |
|---|
| 1006 | | &nbs |
|---|