| Index: third_party/twisted_8_1/twisted/words/protocols/toc.py
|
| diff --git a/third_party/twisted_8_1/twisted/words/protocols/toc.py b/third_party/twisted_8_1/twisted/words/protocols/toc.py
|
| deleted file mode 100644
|
| index 1e46646abf5a27983f08b885203077c101c61d07..0000000000000000000000000000000000000000
|
| --- a/third_party/twisted_8_1/twisted/words/protocols/toc.py
|
| +++ /dev/null
|
| @@ -1,1615 +0,0 @@
|
| -# -*- test-case-name: twisted.words.test -*-
|
| -# Copyright (c) 2001-2005 Twisted Matrix Laboratories.
|
| -# See LICENSE for details.
|
| -
|
| -
|
| -"""
|
| -Implements a AOL Instant Messenger TOC server and client, using the Twisted
|
| -framework.
|
| -
|
| -TODO:
|
| -info,dir: see how gaim connects for this...it may never work if it tries to
|
| -connect to the aim server automatically
|
| -
|
| -This module is deprecated.
|
| -
|
| -Maintainer: U{Paul Swartz<mailto:z3p@twistedmatrix.com>}
|
| -"""
|
| -
|
| -# twisted imports
|
| -from twisted.internet import reactor, protocol
|
| -from twisted.python import log
|
| -
|
| -# base imports
|
| -import struct
|
| -import string
|
| -import time
|
| -import base64
|
| -import os
|
| -import StringIO
|
| -
|
| -SIGNON,DATA,ERROR,SIGNOFF,KEEP_ALIVE=range(1,6)
|
| -PERMITALL,DENYALL,PERMITSOME,DENYSOME=range(1,5)
|
| -
|
| -DUMMY_CHECKSUM = -559038737 # 0xdeadbeef
|
| -
|
| -def quote(s):
|
| - rep=['\\','$','{','}','[',']','(',')','"']
|
| - for r in rep:
|
| - s=string.replace(s,r,"\\"+r)
|
| - return "\""+s+"\""
|
| -
|
| -def unquote(s):
|
| - if s=="": return ""
|
| - if s[0]!='"': return s
|
| - r=string.replace
|
| - s=s[1:-1]
|
| - s=r(s,"\\\\","\\")
|
| - s=r(s,"\\$","$")
|
| - s=r(s,"\\{","{")
|
| - s=r(s,"\\}","}")
|
| - s=r(s,"\\[","[")
|
| - s=r(s,"\\]","]")
|
| - s=r(s,"\\(","(")
|
| - s=r(s,"\\)",")")
|
| - s=r(s,"\\\"","\"")
|
| - return s
|
| -
|
| -def unquotebeg(s):
|
| - for i in range(1,len(s)):
|
| - if s[i]=='"' and s[i-1]!='\\':
|
| - q=unquote(s[:i+1])
|
| - return [q,s[i+2:]]
|
| -
|
| -def unroast(pw):
|
| - roaststring="Tic/Toc"
|
| - pw=string.lower(pw[2:])
|
| - r=""
|
| - count=0
|
| - hex=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]
|
| - while pw:
|
| - st,pw=pw[:2],pw[2:]
|
| - value=(16*hex.index(st[0]))+hex.index(st[1])
|
| - xor=ord(roaststring[count])
|
| - count=(count+1)%len(roaststring)
|
| - r=r+chr(value^xor)
|
| - return r
|
| -
|
| -def roast(pw):
|
| - # contributed by jemfinch on #python
|
| - key="Tic/Toc"
|
| - ro="0x"
|
| - i=0
|
| - ascii=map(ord,pw)
|
| - for c in ascii:
|
| - ro=ro+'%02x'%(c^ord(key[i%len(key)]))
|
| - i=i+1
|
| - return string.lower(ro)
|
| -
|
| -def checksum(b):
|
| - return DUMMY_CHECKSUM # do it like gaim does, since the checksum
|
| - # formula doesn't work
|
| -## # used in file transfers
|
| -## check0 = check1 = 0x00ff
|
| -## for i in range(len(b)):
|
| -## if i%2:
|
| -## if ord(b[i])>check1:
|
| -## check1=check1+0x100 # wrap
|
| -## if check0==0:
|
| -## check0=0x00ff
|
| -## if check1==0x100:
|
| -## check1=check1-1
|
| -## else:
|
| -## check0=check0-1
|
| -## check1=check1-ord(b[i])
|
| -## else:
|
| -## if ord(b[i])>check0: # wrap
|
| -## check0=check0+0x100
|
| -## if check1==0:
|
| -## check1=0x00ff
|
| -## if check0==0x100:
|
| -## check0=check0-1
|
| -## else:
|
| -## check1=check1-1
|
| -## check0=check0-ord(b[i])
|
| -## check0=check0 & 0xff
|
| -## check1=check1 & 0xff
|
| -## checksum=(long(check0)*0x1000000)+(long(check1)*0x10000)
|
| -## return checksum
|
| -
|
| -def checksum_file(f):
|
| - return DUMMY_CHECKSUM # do it like gaim does, since the checksum
|
| - # formula doesn't work
|
| -## check0=check1=0x00ff
|
| -## i=0
|
| -## while 1:
|
| -## b=f.read()
|
| -## if not b: break
|
| -## for char in b:
|
| -## i=not i
|
| -## if i:
|
| -## if ord(char)>check1:
|
| -## check1=check1+0x100 # wrap
|
| -## if check0==0:
|
| -## check0=0x00ff
|
| -## if check1==0x100:
|
| -## check1=check1-1
|
| -## else:
|
| -## check0=check0-1
|
| -## check1=check1-ord(char)
|
| -## else:
|
| -## if ord(char)>check0: # wrap
|
| -## check0=check0+0x100
|
| -## if check1==0:
|
| -## check1=0x00ff
|
| -## if check0==0x100:
|
| -## check0=check0-1
|
| -## else:
|
| -## check1=check1-1
|
| -## check0=check0-ord(char)
|
| -## check0=check0 & 0xff
|
| -## check1=check1 & 0xff
|
| -## checksum=(long(check0)*0x1000000)+(long(check1)*0x10000)
|
| -## return checksum
|
| -
|
| -def normalize(s):
|
| - s=string.lower(s)
|
| - s=string.replace(s," ","")
|
| - return s
|
| -
|
| -
|
| -class TOCParseError(ValueError):
|
| - pass
|
| -
|
| -
|
| -class TOC(protocol.Protocol):
|
| - users={}
|
| -
|
| - def connectionMade(self):
|
| - # initialization of protocol
|
| - self._buf=""
|
| - self._ourseqnum=0L
|
| - self._theirseqnum=0L
|
| - self._mode="Flapon"
|
| - self._onlyflaps=0
|
| - self._laststatus={} # the last status for a user
|
| - self.username=None
|
| - self.permitmode=PERMITALL
|
| - self.permitlist=[]
|
| - self.denylist=[]
|
| - self.buddylist=[]
|
| - self.signontime=0
|
| - self.idletime=0
|
| - self.userinfo="<br>"
|
| - self.userclass=" O"
|
| - self.away=""
|
| - self.saved=None
|
| -
|
| - def _debug(self,data):
|
| - log.msg(data)
|
| -
|
| - def connectionLost(self, reason):
|
| - self._debug("dropped connection from %s" % self.username)
|
| - try:
|
| - del self.factory.users[self.username]
|
| - except:
|
| - pass
|
| - for k in self.factory.chatroom.keys():
|
| - try:
|
| - self.factory.chatroom[k].leave(self)
|
| - except TOCParseError:
|
| - pass
|
| - if self.saved:
|
| - self.factory.savedusers[self.username]=self.saved
|
| - self.updateUsers()
|
| -
|
| - def sendFlap(self,type,data):
|
| - """
|
| - send a FLAP to the client
|
| - """
|
| - send="*"
|
| - self._debug(data)
|
| - if type==DATA:
|
| - data=data+"\000"
|
| - length=len(data)
|
| - send=send+struct.pack("!BHH",type,self._ourseqnum,length)
|
| - send=send+data
|
| - self._ourseqnum=self._ourseqnum+1
|
| - if self._ourseqnum>(256L**4):
|
| - self._ourseqnum=0
|
| - self.transport.write(send)
|
| -
|
| - def dataReceived(self,data):
|
| - self._buf=self._buf+data
|
| - try:
|
| - func=getattr(self,"mode%s"%self._mode)
|
| - except:
|
| - return
|
| - self._mode=func()
|
| - if self._onlyflaps and self.isFlap(): self.dataReceived("")
|
| -
|
| - def isFlap(self):
|
| - """
|
| - tests to see if a flap is actually on the buffer
|
| - """
|
| - if self._buf=='': return 0
|
| - if self._buf[0]!="*": return 0
|
| - if len(self._buf)<6: return 0
|
| - foo,type,seqnum,length=struct.unpack("!BBHH",self._buf[:6])
|
| - if type not in range(1,6): return 0
|
| - if len(self._buf)<6+length: return 0
|
| - return 1
|
| -
|
| - def readFlap(self):
|
| - """
|
| - read the first FLAP off self._buf, raising errors if it isn't in the right form.
|
| - the FLAP is the basic TOC message format, and is logically equivilant to a packet in TCP
|
| - """
|
| - if self._buf=='': return None
|
| - if self._buf[0]!="*":
|
| - raise TOCParseError
|
| - if len(self._buf)<6: return None
|
| - foo,type,seqnum,length=struct.unpack("!BBHH",self._buf[:6])
|
| - if len(self._buf)<6+length: return None
|
| - data=self._buf[6:6+length]
|
| - self._buf=self._buf[6+length:]
|
| - if data and data[-1]=="\000":
|
| - data=data[:-1]
|
| - self._debug([type,data])
|
| - return [type,data]
|
| -
|
| - #def modeWeb(self):
|
| - # try:
|
| - # line,rest=string.split(self._buf,"\n",1)
|
| - # get,username,http=string.split(line," ",2)
|
| - # except:
|
| - # return "Web" # not enough data
|
| - # foo,type,username=string.split(username,"/")
|
| - # if type=="info":
|
| - # user=self.factory.users[username]
|
| - # text="<HTML><HEAD><TITLE>User Information for %s</TITLE></HEAD><BODY>Username: <B>%s</B><br>\nWarning Level: <B>%s%</B><br>\n Online Since: <B>%s</B><br>\nIdle Minutes: <B>%s</B><br>\n<hr><br>\n%s\n<hr><br>\n"%(user.saved.nick, user.saved.nick, user.saved.evilness, time.asctime(user.signontime), int((time.time()-user.idletime)/60), user.userinfo)
|
| - # self.transport.write("HTTP/1.1 200 OK\n")
|
| - # self.transport.write("Content-Type: text/html\n")
|
| - # self.transport.write("Content-Length: %s\n\n"%len(text))
|
| - # self.transport.write(text)
|
| - # self.loseConnection()
|
| -
|
| - def modeFlapon(self):
|
| - #if self._buf[:3]=="GET": self.modeWeb() # TODO: get this working
|
| - if len(self._buf)<10: return "Flapon" # not enough bytes
|
| - flapon,self._buf=self._buf[:10],self._buf[10:]
|
| - if flapon!="FLAPON\r\n\r\n":
|
| - raise TOCParseError
|
| - self.sendFlap(SIGNON,"\000\000\000\001")
|
| - self._onlyflaps=1
|
| - return "Signon"
|
| -
|
| - def modeSignon(self):
|
| - flap=self.readFlap()
|
| - if flap==None:
|
| - return "Signon"
|
| - if flap[0]!=SIGNON: raise TOCParseError
|
| - version,tlv,unlength=struct.unpack("!LHH",flap[1][:8])
|
| - if version!=1 or tlv!=1 or unlength+8!=len(flap[1]):
|
| - raise TOCParseError
|
| - self.username=normalize(flap[1][8:])
|
| - if self.username in self.factory.savedusers.keys():
|
| - self.saved=self.factory.savedusers[self.username]
|
| - else:
|
| - self.saved=SavedUser()
|
| - self.saved.nick=self.username
|
| - return "TocSignon"
|
| -
|
| - def modeTocSignon(self):
|
| - flap=self.readFlap()
|
| - if flap==None:
|
| - return "TocSignon"
|
| - if flap[0]!=DATA: raise TOCParseError
|
| - data=string.split(flap[1]," ")
|
| - if data[0]!="toc_signon": raise TOCParseError
|
| - for i in data:
|
| - if not i:data.remove(i)
|
| - password=unroast(data[4])
|
| - if not(self.authorize(data[1],int(data[2]),data[3],password)):
|
| - self.sendError(BAD_NICKNAME)
|
| - self.transport.loseConnection()
|
| - return
|
| - self.sendFlap(DATA,"SIGN_ON:TOC1.0")
|
| - self.sendFlap(DATA,"NICK:%s"%self.saved.nick)
|
| - self.sendFlap(DATA,"CONFIG:%s"%self.saved.config)
|
| - # sending user configuration goes here
|
| - return "Connected"
|
| -
|
| - def authorize(self,server,port,username,password):
|
| - if self.saved.password=="":
|
| - self.saved.password=password
|
| - return 1
|
| - else:
|
| - return self.saved.password==password
|
| -
|
| - def modeConnected(self):
|
| - flap=self.readFlap()
|
| - while flap!=None:
|
| - if flap[0] not in [DATA,KEEP_ALIVE]: raise TOCParseError
|
| - flapdata=string.split(flap[1]," ",1)
|
| - tocname=flapdata[0][4:]
|
| - if len(flapdata)==2:
|
| - data=flapdata[1]
|
| - else:
|
| - data=""
|
| - func=getattr(self,"toc_"+tocname,None)
|
| - if func!=None:
|
| - func(data)
|
| - else:
|
| - self.toc_unknown(tocname,data)
|
| - flap=self.readFlap()
|
| - return "Connected"
|
| -
|
| - def toc_unknown(self,tocname,data):
|
| - self._debug("unknown! %s %s" % (tocname,data))
|
| -
|
| - def toc_init_done(self,data):
|
| - """
|
| - called when all the setup is done.
|
| -
|
| - toc_init_done
|
| - """
|
| - self.signontime=int(time.time())
|
| - self.factory.users[self.username]=self
|
| - self.updateUsers()
|
| -
|
| - def toc_add_permit(self,data):
|
| - """
|
| - adds users to the permit list. if the list is null, then set the mode to DENYALL
|
| - """
|
| - if data=="":
|
| - self.permitmode=DENYALL
|
| - self.permitlist=[]
|
| - self.denylist=[]
|
| - else:
|
| - self.permitmode=PERMITSOME
|
| - self.denylist=[]
|
| - users=string.split(data," ")
|
| - map(self.permitlist.append,users)
|
| - self.updateUsers()
|
| -
|
| - def toc_add_deny(self,data):
|
| - """
|
| - adds users to the deny list. if the list is null, then set the mode to PERMITALL
|
| - """
|
| - if data=="":
|
| - self.permitmode=PERMITALL
|
| - self.permitlist=[]
|
| - self.denylist=[]
|
| - else:
|
| - self.permitmode=DENYSOME
|
| - self.permitlist=[]
|
| - users=string.split(data," ")
|
| - map(self.denylist.append,users)
|
| - self.updateUsers()
|
| -
|
| - def toc_evil(self,data):
|
| - """
|
| - warns a user.
|
| -
|
| - toc_evil <username> <anon|norm>
|
| - """
|
| - username,nora=string.split(data," ")
|
| - if nora=="anon":
|
| - user=""
|
| - else:
|
| - user=self.saved.nick
|
| - if not(self.factory.users.has_key(username)):
|
| - self.sendError(CANT_WARN,username)
|
| - return
|
| - if self.factory.users[username].saved.evilness>=100:
|
| - self.sendError(CANT_WARN,username)
|
| - return
|
| - self.factory.users[username].evilFrom(user)
|
| -
|
| - def toc_add_buddy(self,data):
|
| - """
|
| - adds users to the buddy list
|
| -
|
| - toc_add_buddy <buddyname1> [<buddyname2>] [<buddyname3>]...
|
| - """
|
| - buddies=map(normalize,string.split(data," "))
|
| - for b in buddies:
|
| - if b not in self.buddylist:
|
| - self.buddylist.append(b)
|
| - for buddy in buddies:
|
| - try:
|
| - buddy=self.factory.users[buddy]
|
| - except:
|
| - pass
|
| - else:
|
| - self.buddyUpdate(buddy)
|
| -
|
| - def toc_remove_buddy(self,data):
|
| - """
|
| - removes users from the buddy list
|
| -
|
| - toc_remove_buddy <buddyname1> [<buddyname2>] [<buddyname3>]...
|
| - """
|
| - buddies=string.split(data," ")
|
| - for buddy in buddies:
|
| - try:
|
| - self.buddylist.remove(normalize(buddy))
|
| - except: pass
|
| -
|
| - def toc_send_im(self,data):
|
| - """
|
| - incoming instant message
|
| -
|
| - toc_send_im <screenname> <quoted message> [auto]
|
| - """
|
| - username,data=string.split(data," ",1)
|
| - auto=0
|
| - if data[-4:]=="auto":
|
| - auto=1
|
| - data=data[:-5]
|
| - data=unquote(data)
|
| - if not(self.factory.users.has_key(username)):
|
| - self.sendError(NOT_AVAILABLE,username)
|
| - return
|
| - user=self.factory.users[username]
|
| - if not(self.canContact(user)):
|
| - self.sendError(NOT_AVAILABLE,username)
|
| - return
|
| - user.hearWhisper(self,data,auto)
|
| -
|
| - def toc_set_info(self,data):
|
| - """
|
| - set the users information, retrivable with toc_get_info
|
| -
|
| - toc_set_info <user info (quoted)>
|
| - """
|
| - info=unquote(data)
|
| - self._userinfo=info
|
| -
|
| - def toc_set_idle(self,data):
|
| - """
|
| - set/unset idle
|
| -
|
| - toc_set_idle <seconds>
|
| - """
|
| - seconds=int(data)
|
| - self.idletime=time.time()-seconds # time when they started being idle
|
| - self.updateUsers()
|
| -
|
| - def toc_set_away(self,data):
|
| - """
|
| - set/unset away message
|
| -
|
| - toc_set_away [<away message>]
|
| - """
|
| - away=unquote(data)
|
| - if not self.away and away: # setting an away message
|
| - self.away=away
|
| - self.userclass=self.userclass+'U'
|
| - self.updateUsers()
|
| - elif self.away and not away: # coming back
|
| - self.away=""
|
| - self.userclass=self.userclass[:2]
|
| - self.updateUsers()
|
| - else:
|
| - raise TOCParseError
|
| -
|
| - def toc_chat_join(self,data):
|
| - """
|
| - joins the chat room.
|
| -
|
| - toc_chat_join <exchange> <room name>
|
| - """
|
| - exchange,name=string.split(data," ",1)
|
| - self.factory.getChatroom(int(exchange),unquote(name)).join(self)
|
| -
|
| - def toc_chat_invite(self,data):
|
| - """
|
| - invite others to the room.
|
| -
|
| - toc_chat_invite <room id> <invite message> <buddy 1> [<buddy2>]...
|
| - """
|
| - id,data=string.split(data," ",1)
|
| - id=int(id)
|
| - message,data=unquotebeg(data)
|
| - buddies=string.split(data," ")
|
| - for b in buddies:
|
| - room=self.factory.chatroom[id]
|
| - bud=self.factory.users[b]
|
| - bud.chatInvite(room,self,message)
|
| -
|
| - def toc_chat_accept(self,data):
|
| - """
|
| - accept an invitation.
|
| -
|
| - toc_chat_accept <room id>
|
| - """
|
| - id=int(data)
|
| - self.factory.chatroom[id].join(self)
|
| -
|
| - def toc_chat_send(self,data):
|
| - """
|
| - send a message to the chat room.
|
| -
|
| - toc_chat_send <room id> <message>
|
| - """
|
| - id,message=string.split(data," ",1)
|
| - id=int(id)
|
| - message=unquote(message)
|
| - self.factory.chatroom[id].say(self,message)
|
| -
|
| - def toc_chat_whisper(self,data):
|
| - id,user,message=string.split(data," ",2)
|
| - id=int(id)
|
| - room=self.factory.chatroom[id]
|
| - message=unquote(message)
|
| - self.factory.users[user].chatWhisper(room,self,message)
|
| -
|
| - def toc_chat_leave(self,data):
|
| - """
|
| - leave the room.
|
| -
|
| - toc_chat_leave <room id>
|
| - """
|
| - id=int(data)
|
| - self.factory.chatroom[id].leave(self)
|
| -
|
| - def toc_set_config(self,data):
|
| - """
|
| - set the saved config. this gets send when you log in.
|
| -
|
| - toc_set_config <config>
|
| - """
|
| - self.saved.config=unquote(data)
|
| -
|
| - def toc_get_info(self,data):
|
| - """
|
| - get the user info for a user
|
| -
|
| - toc_get_info <username>
|
| - """
|
| - if not self.factory.users.has_key(data):
|
| - self.sendError(901,data)
|
| - return
|
| - self.sendFlap(2,"GOTO_URL:TIC:info/%s"%data)
|
| -
|
| - def toc_format_nickname(self,data):
|
| - """
|
| - change the format of your nickname.
|
| -
|
| - toc_format_nickname <new format>
|
| - """
|
| - # XXX may not work
|
| - nick=unquote(data)
|
| - if normalize(nick)==self.username:
|
| - self.saved.nick=nick
|
| - self.sendFlap(2,"ADMIN_NICK_STATUS:0")
|
| - else:
|
| - self.sendError(BAD_INPUT)
|
| -
|
| - def toc_change_passwd(self,data):
|
| - orig,data=unquotebeg(data)
|
| - new=unquote(data)
|
| - if orig==self.saved.password:
|
| - self.saved.password=new
|
| - self.sendFlap(2,"ADMIN_PASSWD_STATUS:0")
|
| - else:
|
| - self.sendError(BAD_INPUT)
|
| -
|
| - def sendError(self,code,*varargs):
|
| - """
|
| - send an error to the user. listing of error messages is below.
|
| - """
|
| - send="ERROR:%s"%code
|
| - for v in varargs:
|
| - send=send+":"+v
|
| - self.sendFlap(DATA,send)
|
| -
|
| - def updateUsers(self):
|
| - """
|
| - Update the users who have us on their buddylist.
|
| - Called when the user changes anything (idle,away) so people can get updates.
|
| - """
|
| - for user in self.factory.users.values():
|
| - if self.username in user.buddylist and self.canContact(user):
|
| - user.buddyUpdate(self)
|
| -
|
| - def getStatus(self,user):
|
| - if self.canContact(user):
|
| - if self in self.factory.users.values():ol='T'
|
| - else: ol='F'
|
| - idle=0
|
| - if self.idletime:
|
| - idle=int((time.time()-self.idletime)/60)
|
| - return (self.saved.nick,ol,self.saved.evilness,self.signontime,idle,self.userclass)
|
| - else:
|
| - return (self.saved.nick,'F',0,0,0,self.userclass)
|
| -
|
| - def canContact(self,user):
|
| - if self.permitmode==PERMITALL: return 1
|
| - elif self.permitmode==DENYALL: return 0
|
| - elif self.permitmode==PERMITSOME:
|
| - if user.username in self.permitlist: return 1
|
| - else: return 0
|
| - elif self.permitmode==DENYSOME:
|
| - if user.username in self.denylist: return 0
|
| - else: return 1
|
| - else:
|
| - assert 0,"bad permitmode %s" % self.permitmode
|
| -
|
| - def buddyUpdate(self,user):
|
| - """
|
| - Update the buddy. Called from updateUsers()
|
| - """
|
| - if not self.canContact(user): return
|
| - status=user.getStatus(self)
|
| - if not self._laststatus.has_key(user):
|
| - self._laststatus[user]=()
|
| - if self._laststatus[user]!=status:
|
| - send="UPDATE_BUDDY:%s:%s:%s:%s:%s:%s"%status
|
| - self.sendFlap(DATA,send)
|
| - self._laststatus[user]=status
|
| -
|
| - def hearWhisper(self,user,data,auto=0):
|
| - """
|
| - Called when you get an IM. If auto=1, it's an autoreply from an away message.
|
| - """
|
| - if not self.canContact(user): return
|
| - if auto: auto='T'
|
| - else: auto='F'
|
| - send="IM_IN:%s:%s:%s"%(user.saved.nick,auto,data)
|
| - self.sendFlap(DATA,send)
|
| -
|
| - def evilFrom(self,user):
|
| - if user=="":
|
| - percent=0.03
|
| - else:
|
| - percent=0.1
|
| - self.saved.evilness=self.saved.evilness+int((100-self.saved.evilness)*percent)
|
| - self.sendFlap(2,"EVILED:%s:%s"%(self.saved.evilness,user))
|
| - self.updateUsers()
|
| -
|
| - def chatJoin(self,room):
|
| - self.sendFlap(2,"CHAT_JOIN:%s:%s"%(room.id,room.name))
|
| - f="CHAT_UPDATE_BUDDY:%s:T"%room.id
|
| - for u in room.users:
|
| - if u!=self:
|
| - u.chatUserUpdate(room,self)
|
| - f=f+":"+u.saved.nick
|
| - self.sendFlap(2,f)
|
| -
|
| - def chatInvite(self,room,user,message):
|
| - if not self.canContact(user): return
|
| - self.sendFlap(2,"CHAT_INVITE:%s:%s:%s:%s"%(room.name,room.id,user.saved.nick,message))
|
| -
|
| - def chatUserUpdate(self,room,user):
|
| - if user in room.users:
|
| - inroom='T'
|
| - else:
|
| - inroom='F'
|
| - self.sendFlap(2,"CHAT_UPDATE_BUDDY:%s:%s:%s"%(room.id,inroom,user.saved.nick))
|
| -
|
| - def chatMessage(self,room,user,message):
|
| - if not self.canContact(user): return
|
| - self.sendFlap(2,"CHAT_IN:%s:%s:F:%s"%(room.id,user.saved.nick,message))
|
| -
|
| - def chatWhisper(self,room,user,message):
|
| - if not self.canContact(user): return
|
| - self.sendFlap(2,"CHAT_IN:%s:%s:T:%s"%(room.id,user.saved.nick,message))
|
| -
|
| - def chatLeave(self,room):
|
| - self.sendFlap(2,"CHAT_LEFT:%s"%(room.id))
|
| -
|
| -
|
| -class Chatroom:
|
| - def __init__(self,fac,exchange,name,id):
|
| - self.exchange=exchange
|
| - self.name=name
|
| - self.id=id
|
| - self.factory=fac
|
| - self.users=[]
|
| -
|
| - def join(self,user):
|
| - if user in self.users:
|
| - return
|
| - self.users.append(user)
|
| - user.chatJoin(self)
|
| -
|
| - def leave(self,user):
|
| - if user not in self.users:
|
| - raise TOCParseError
|
| - self.users.remove(user)
|
| - user.chatLeave(self)
|
| - for u in self.users:
|
| - u.chatUserUpdate(self,user)
|
| - if len(self.users)==0:
|
| - self.factory.remChatroom(self)
|
| -
|
| - def say(self,user,message):
|
| - for u in self.users:
|
| - u.chatMessage(self,user,message)
|
| -
|
| -
|
| -class SavedUser:
|
| - def __init__(self):
|
| - self.config=""
|
| - self.nick=""
|
| - self.password=""
|
| - self.evilness=0
|
| -
|
| -
|
| -class TOCFactory(protocol.Factory):
|
| - def __init__(self):
|
| - self.users={}
|
| - self.savedusers={}
|
| - self.chatroom={}
|
| - self.chatroomid=0
|
| -
|
| - def buildProtocol(self,addr):
|
| - p=TOC()
|
| - p.factory=self
|
| - return p
|
| -
|
| - def getChatroom(self,exchange,name):
|
| - for i in self.chatroom.values():
|
| - if normalize(i.name)==normalize(name):
|
| - return i
|
| - self.chatroom[self.chatroomid]=Chatroom(self,exchange,name,self.chatroomid)
|
| - self.chatroomid=self.chatroomid+1
|
| - return self.chatroom[self.chatroomid-1]
|
| -
|
| - def remChatroom(self,room):
|
| - id=room.id
|
| - del self.chatroom[id]
|
| -
|
| -MAXARGS={}
|
| -MAXARGS["CONFIG"]=0
|
| -MAXARGS["NICK"]=0
|
| -MAXARGS["IM_IN"]=2
|
| -MAXARGS["UPDATE_BUDDY"]=5
|
| -MAXARGS["ERROR"]=-1
|
| -MAXARGS["EVILED"]=1
|
| -MAXARGS["CHAT_JOIN"]=1
|
| -MAXARGS["CHAT_IN"]=3
|
| -MAXARGS["CHAT_UPDATE_BUDDY"]=-1
|
| -MAXARGS["CHAT_INVITE"]=3
|
| -MAXARGS["CHAT_LEFT"]=0
|
| -MAXARGS["ADMIN_NICK_STATUS"]=0
|
| -MAXARGS["ADMIN_PASSWD_STATUS"]=0
|
| -
|
| -
|
| -class TOCClient(protocol.Protocol):
|
| - def __init__(self,username,password,authhost="login.oscar.aol.com",authport=5190):
|
| -
|
| - self.username=normalize(username) # our username
|
| - self._password=password # our password
|
| - self._mode="SendNick" # current mode
|
| - self._ourseqnum=19071 # current sequence number (for sendFlap)
|
| - self._authhost=authhost # authorization host
|
| - self._authport=authport # authorization port
|
| - self._online=0 # are we online?
|
| - self._buddies=[] # the current buddy list
|
| - self._privacymode=PERMITALL # current privacy mode
|
| - self._permitlist=[] # list of users on the permit list
|
| - self._roomnames={} # the names for each of the rooms we're in
|
| - self._receivedchatmembers={} # have we gotten who's in our room yet?
|
| - self._denylist=[]
|
| - self._cookies={} # for file transfers
|
| - self._buf='' # current data buffer
|
| - self._awaymessage=''
|
| -
|
| - def _debug(self,data):
|
| - log.msg(data)
|
| -
|
| - def sendFlap(self,type,data):
|
| - if type==DATA:
|
| - data=data+"\000"
|
| - length=len(data)
|
| - s="*"
|
| - s=s+struct.pack("!BHH",type,self._ourseqnum,length)
|
| - s=s+data
|
| - self._ourseqnum=self._ourseqnum+1
|
| - if self._ourseqnum>(256*256+256):
|
| - self._ourseqnum=0
|
| - self._debug(data)
|
| - self.transport.write(s)
|
| -
|
| - def isFlap(self):
|
| - """
|
| - tests to see if a flap is actually on the buffer
|
| - """
|
| - if self._buf=='': return 0
|
| - if self._buf[0]!="*": return 0
|
| - if len(self._buf)<6: return 0
|
| - foo,type,seqnum,length=struct.unpack("!BBHH",self._buf[:6])
|
| - if type not in range(1,6): return 0
|
| - if len(self._buf)<6+length: return 0
|
| - return 1
|
| -
|
| - def readFlap(self):
|
| - if self._buf=='': return None
|
| - if self._buf[0]!="*":
|
| - raise TOCParseError
|
| - if len(self._buf)<6: return None
|
| - foo,type,seqnum,length=struct.unpack("!BBHH",self._buf[:6])
|
| - if len(self._buf)<6+length: return None
|
| - data=self._buf[6:6+length]
|
| - self._buf=self._buf[6+length:]
|
| - if data and data[-1]=="\000":
|
| - data=data[:-1]
|
| - return [type,data]
|
| -
|
| - def connectionMade(self):
|
| - self._debug("connection made! %s" % self.transport)
|
| - self.transport.write("FLAPON\r\n\r\n")
|
| -
|
| - def connectionLost(self, reason):
|
| - self._debug("connection lost!")
|
| - self._online=0
|
| -
|
| - def dataReceived(self,data):
|
| - self._buf=self._buf+data
|
| - while self.isFlap():
|
| - flap=self.readFlap()
|
| - func=getattr(self,"mode%s"%self._mode)
|
| - func(flap)
|
| -
|
| - def modeSendNick(self,flap):
|
| - if flap!=[1,"\000\000\000\001"]: raise TOCParseError
|
| - s="\000\000\000\001\000\001"+struct.pack("!H",len(self.username))+self.username
|
| - self.sendFlap(1,s)
|
| - s="toc_signon %s %s %s %s english \"penguin\""%(self._authhost,\
|
| - self._authport,self.username,roast(self._password))
|
| - self.sendFlap(2,s)
|
| - self._mode="Data"
|
| -
|
| - def modeData(self,flap):
|
| - if not flap[1]:
|
| - return
|
| - if not ':' in flap[1]:
|
| - self._debug("bad SNAC:%s"%(flap[1]))
|
| - return
|
| - command,rest=string.split(flap[1],":",1)
|
| - if MAXARGS.has_key(command):
|
| - maxsplit=MAXARGS[command]
|
| - else:
|
| - maxsplit=-1
|
| - if maxsplit==-1:
|
| - l=tuple(string.split(rest,":"))
|
| - elif maxsplit==0:
|
| - l=(rest,)
|
| - else:
|
| - l=tuple(string.split(rest,":",maxsplit))
|
| - self._debug("%s %s"%(command,l))
|
| - try:
|
| - func=getattr(self,"toc%s"%command)
|
| - self._debug("calling %s"%func)
|
| - except:
|
| - self._debug("calling %s"%self.tocUNKNOWN)
|
| - self.tocUNKNOWN(command,l)
|
| - return
|
| - func(l)
|
| -
|
| - def tocUNKNOWN(self,command,data):
|
| - pass
|
| -
|
| - def tocSIGN_ON(self,data):
|
| - if data!=("TOC1.0",): raise TOCParseError
|
| - self._debug("Whee, signed on!")
|
| - if self._buddies: self.add_buddy(self._buddies)
|
| - self._online=1
|
| - self.onLine()
|
| -
|
| - def tocNICK(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - NICK:<format of nickname>
|
| - """
|
| - self.username=data[0]
|
| -
|
| - def tocCONFIG(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - CONFIG:<config>
|
| -
|
| - Format of config data:
|
| -
|
| - - g: group. all users until next g or end of config are in this group
|
| - - b: buddy
|
| - - p: person on the permit list
|
| - - d: person on the deny list
|
| - - m: permit/deny mode (1: permit all, 2: deny all, 3: permit some, 4: deny some)
|
| - """
|
| - data=data[0]
|
| - if data and data[0]=="{":data=data[1:-1]
|
| - lines=string.split(data,"\n")
|
| - buddylist={}
|
| - currentgroup=""
|
| - permit=[]
|
| - deny=[]
|
| - mode=1
|
| - for l in lines:
|
| - if l:
|
| - code,data=l[0],l[2:]
|
| - if code=='g': # group
|
| - currentgroup=data
|
| - buddylist[currentgroup]=[]
|
| - elif code=='b':
|
| - buddylist[currentgroup].append(data)
|
| - elif code=='p':
|
| - permit.append(data)
|
| - elif code=='d':
|
| - deny.append(data)
|
| - elif code=='m':
|
| - mode=int(data)
|
| - self.gotConfig(mode,buddylist,permit,deny)
|
| -
|
| - def tocIM_IN(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - IM_IN:<user>:<autoreply T|F>:message
|
| - """
|
| - user=data[0]
|
| - autoreply=(data[1]=='T')
|
| - message=data[2]
|
| - self.hearMessage(user,message,autoreply)
|
| -
|
| - def tocUPDATE_BUDDY(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - UPDATE_BUDDY:<username>:<online T|F>:<warning level>:<signon time>:<idle time (minutes)>:<user class>
|
| - """
|
| - data=list(data)
|
| - online=(data[1]=='T')
|
| - if len(data[5])==2:
|
| - data[5]=data[5]+" "
|
| - away=(data[5][-1]=='U')
|
| - if data[5][-1]=='U':
|
| - data[5]=data[5][:-1]
|
| - self.updateBuddy(data[0],online,int(data[2]),int(data[3]),int(data[4]),data[5],away)
|
| -
|
| - def tocERROR(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - ERROR:<error code>:<misc. data>
|
| - """
|
| - code,args=data[0],data[1:]
|
| - self.hearError(int(code),args)
|
| -
|
| - def tocEVILED(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - EVILED:<current warning level>:<user who warned us>
|
| - """
|
| - self.hearWarning(data[0],data[1])
|
| -
|
| - def tocCHAT_JOIN(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - CHAT_JOIN:<room id>:<room name>
|
| - """
|
| - #self.chatJoined(int(data[0]),data[1])
|
| - self._roomnames[int(data[0])]=data[1]
|
| - self._receivedchatmembers[int(data[0])]=0
|
| -
|
| - def tocCHAT_UPDATE_BUDDY(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - CHAT_UPDATE_BUDDY:<room id>:<in room? T/F>:<user 1>:<user 2>...
|
| - """
|
| - roomid=int(data[0])
|
| - inroom=(data[1]=='T')
|
| - if self._receivedchatmembers[roomid]:
|
| - for u in data[2:]:
|
| - self.chatUpdate(roomid,u,inroom)
|
| - else:
|
| - self._receivedchatmembers[roomid]=1
|
| - self.chatJoined(roomid,self._roomnames[roomid],list(data[2:]))
|
| -
|
| - def tocCHAT_IN(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - CHAT_IN:<room id>:<username>:<whisper T/F>:<message>
|
| -
|
| - whisper isn't used
|
| - """
|
| - whisper=(data[2]=='T')
|
| - if whisper:
|
| - self.chatHearWhisper(int(data[0]),data[1],data[3])
|
| - else:
|
| - self.chatHearMessage(int(data[0]),data[1],data[3])
|
| -
|
| - def tocCHAT_INVITE(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - CHAT_INVITE:<room name>:<room id>:<username>:<message>
|
| - """
|
| - self.chatInvited(int(data[1]),data[0],data[2],data[3])
|
| -
|
| - def tocCHAT_LEFT(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - CHAT_LEFT:<room id>
|
| - """
|
| - self.chatLeft(int(data[0]))
|
| - del self._receivedchatmembers[int(data[0])]
|
| - del self._roomnames[int(data[0])]
|
| -
|
| - def tocRVOUS_PROPOSE(self,data):
|
| - """
|
| - Handle a message that looks like::
|
| -
|
| - RVOUS_PROPOSE:<user>:<uuid>:<cookie>:<seq>:<rip>:<pip>:<vip>:<port>
|
| - [:tlv tag1:tlv value1[:tlv tag2:tlv value2[:...]]]
|
| - """
|
| - user,uid,cookie,seq,rip,pip,vip,port=data[:8]
|
| - cookie=base64.decodestring(cookie)
|
| - port=int(port)
|
| - tlvs={}
|
| - for i in range(8,len(data),2):
|
| - key=data[i]
|
| - value=base64.decodestring(data[i+1])
|
| - tlvs[key]=value
|
| - name=UUIDS[uid]
|
| - try:
|
| - func=getattr(self,"toc%s"%name)
|
| - except:
|
| - self._debug("no function for UID %s" % uid)
|
| - return
|
| - func(user,cookie,seq,pip,vip,port,tlvs)
|
| -
|
| - def tocSEND_FILE(self,user,cookie,seq,pip,vip,port,tlvs):
|
| - if tlvs.has_key('12'):
|
| - description=tlvs['12']
|
| - else:
|
| - description=""
|
| - subtype,numfiles,size=struct.unpack("!HHI",tlvs['10001'][:8])
|
| - name=tlvs['10001'][8:-4]
|
| - while name[-1]=='\000':
|
| - name=name[:-1]
|
| - self._cookies[cookie]=[user,SEND_FILE_UID,pip,port,{'name':name}]
|
| - self.rvousProposal("send",cookie,user,vip,port,description=description,
|
| - name=name,files=numfiles,size=size)
|
| -
|
| - def tocGET_FILE(self,user,cookie,seq,pip,vip,port,tlvs):
|
| - return
|
| - # XXX add this back in
|
| - #reactor.clientTCP(pip,port,GetFileTransfer(self,cookie,os.path.expanduser("~")))
|
| - #self.rvous_accept(user,cookie,GET_FILE_UID)
|
| -
|
| - def onLine(self):
|
| - """
|
| - called when we are first online
|
| - """
|
| - pass
|
| -
|
| - def gotConfig(self,mode,buddylist,permit,deny):
|
| - """
|
| - called when we get a configuration from the server
|
| - mode := permit/deny mode
|
| - buddylist := current buddylist
|
| - permit := permit list
|
| - deny := deny list
|
| - """
|
| - pass
|
| -
|
| - def hearError(self,code,args):
|
| - """
|
| - called when an error is received
|
| - code := error code
|
| - args := misc. arguments (username, etc.)
|
| - """
|
| - pass
|
| -
|
| - def hearWarning(self,newamount,username):
|
| - """
|
| - called when we get warned
|
| - newamount := the current warning level
|
| - username := the user who warned us, or '' if it's anonymous
|
| - """
|
| - pass
|
| -
|
| - def hearMessage(self,username,message,autoreply):
|
| - """
|
| - called when you receive an IM
|
| - username := the user who the IM is from
|
| - message := the message
|
| - autoreply := true if the message is an autoreply from an away message
|
| - """
|
| - pass
|
| -
|
| - def updateBuddy(self,username,online,evilness,signontime,idletime,userclass,away):
|
| - """
|
| - called when a buddy changes state
|
| - username := the user whos state changed
|
| - online := true if the user is online
|
| - evilness := the users current warning level
|
| - signontime := the time the user signed on (UNIX epoch)
|
| - idletime := the time the user has been idle (minutes)
|
| - away := true if the user is away
|
| - userclass := the class of the user (generally " O")
|
| - """
|
| - pass
|
| -
|
| - def chatJoined(self,roomid,roomname,users):
|
| - """
|
| - we just joined a chat room
|
| - roomid := the AIM id for the room
|
| - roomname := the name for the room
|
| - users := a list of the users already in the room
|
| - """
|
| - pass
|
| -
|
| - def chatUpdate(self,roomid,username,inroom):
|
| - """
|
| - a user has joined the room
|
| - roomid := the AIM id for the room
|
| - username := the username
|
| - inroom := true if the user is in the room
|
| - """
|
| - pass
|
| -
|
| - def chatHearMessage(self,roomid,username,message):
|
| - """
|
| - a message was sent to the room
|
| - roomid := the AIM id for the room
|
| - username := the user who sent the message
|
| - message := the message
|
| - """
|
| - pass
|
| -
|
| - def chatHearWhisper(self,roomid,username,message):
|
| - """
|
| - someone whispered to us in a chatroom
|
| - roomid := the AIM for the room
|
| - username := the user who whispered to us
|
| - message := the message
|
| - """
|
| - pass
|
| -
|
| - def chatInvited(self,roomid,roomname,username,message):
|
| - """
|
| - we were invited to a chat room
|
| - roomid := the AIM id for the room
|
| - roomname := the name of the room
|
| - username := the user who invited us
|
| - message := the invite message
|
| - """
|
| - pass
|
| -
|
| - def chatLeft(self,roomid):
|
| - """
|
| - we left the room
|
| - roomid := the AIM id for the room
|
| - """
|
| - pass
|
| -
|
| - def rvousProposal(self,type,cookie,user,vip,port,**kw):
|
| - """
|
| - we were asked for a rondevouz
|
| - type := the type of rondevous. currently, one of ["send"]
|
| - cookie := the cookie. pass this to rvous_accept()
|
| - user := the user who asked us
|
| - vip := their verified_ip
|
| - port := the port they want us to conenct to
|
| - kw := misc. args
|
| - """
|
| - pass #self.rvous_accept(cookie)
|
| -
|
| - def receiveBytes(self,user,file,chunk,sofar,total):
|
| - """
|
| - we received part of a file from a file transfer
|
| - file := the name of the file
|
| - chunk := the chunk of data
|
| - sofar := how much data we've gotten so far
|
| - total := the total amount of data
|
| - """
|
| - pass #print user,file,sofar,total
|
| -
|
| - def isaway(self):
|
| - """
|
| - return our away status
|
| - """
|
| - return len(self._awaymessage)>0
|
| -
|
| - def set_config(self,mode,buddylist,permit,deny):
|
| - """
|
| - set the server configuration
|
| - mode := permit mode
|
| - buddylist := buddy list
|
| - permit := permit list
|
| - deny := deny list
|
| - """
|
| - s="m %s\n"%mode
|
| - for g in buddylist.keys():
|
| - s=s+"g %s\n"%g
|
| - for u in buddylist[g]:
|
| - s=s+"b %s\n"%u
|
| - for p in permit:
|
| - s=s+"p %s\n"%p
|
| - for d in deny:
|
| - s=s+"d %s\n"%d
|
| - #s="{\n"+s+"\n}"
|
| - self.sendFlap(2,"toc_set_config %s"%quote(s))
|
| -
|
| - def add_buddy(self,buddies):
|
| - s=""
|
| - if type(buddies)==type(""): buddies=[buddies]
|
| - for b in buddies:
|
| - s=s+" "+normalize(b)
|
| - self.sendFlap(2,"toc_add_buddy%s"%s)
|
| -
|
| - def del_buddy(self,buddies):
|
| - s=""
|
| - if type(buddies)==type(""): buddies=[buddies]
|
| - for b in buddies:
|
| - s=s+" "+b
|
| - self.sendFlap(2,"toc_remove_buddy%s"%s)
|
| -
|
| - def add_permit(self,users):
|
| - if type(users)==type(""): users=[users]
|
| - s=""
|
| - if self._privacymode!=PERMITSOME:
|
| - self._privacymode=PERMITSOME
|
| - self._permitlist=[]
|
| - for u in users:
|
| - u=normalize(u)
|
| - if u not in self._permitlist:self._permitlist.append(u)
|
| - s=s+" "+u
|
| - if not s:
|
| - self._privacymode=DENYALL
|
| - self._permitlist=[]
|
| - self._denylist=[]
|
| - self.sendFlap(2,"toc_add_permit"+s)
|
| -
|
| - def del_permit(self,users):
|
| - if type(users)==type(""): users=[users]
|
| - p=self._permitlist[:]
|
| - for u in users:
|
| - u=normalize(u)
|
| - if u in p:
|
| - p.remove(u)
|
| - self.add_permit([])
|
| - self.add_permit(p)
|
| -
|
| - def add_deny(self,users):
|
| - if type(users)==type(""): users=[users]
|
| - s=""
|
| - if self._privacymode!=DENYSOME:
|
| - self._privacymode=DENYSOME
|
| - self._denylist=[]
|
| - for u in users:
|
| - u=normalize(u)
|
| - if u not in self._denylist:self._denylist.append(u)
|
| - s=s+" "+u
|
| - if not s:
|
| - self._privacymode=PERMITALL
|
| - self._permitlist=[]
|
| - self._denylist=[]
|
| - self.sendFlap(2,"toc_add_deny"+s)
|
| -
|
| - def del_deny(self,users):
|
| - if type(users)==type(""): users=[users]
|
| - d=self._denylist[:]
|
| - for u in users:
|
| - u=normalize(u)
|
| - if u in d:
|
| - d.remove(u)
|
| - self.add_deny([])
|
| - if d:
|
| - self.add_deny(d)
|
| -
|
| - def signon(self):
|
| - """
|
| - called to finish the setup, and signon to the network
|
| - """
|
| - self.sendFlap(2,"toc_init_done")
|
| - self.sendFlap(2,"toc_set_caps %s" % (SEND_FILE_UID,)) # GET_FILE_UID)
|
| -
|
| - def say(self,user,message,autoreply=0):
|
| - """
|
| - send a message
|
| - user := the user to send to
|
| - message := the message
|
| - autoreply := true if the message is an autoreply (good for away messages)
|
| - """
|
| - if autoreply: a=" auto"
|
| - else: a=''
|
| - self.sendFlap(2,"toc_send_im %s %s%s"%(normalize(user),quote(message),a))
|
| -
|
| - def idle(self,idletime=0):
|
| - """
|
| - change idle state
|
| - idletime := the seconds that the user has been away, or 0 if they're back
|
| - """
|
| - self.sendFlap(2,"toc_set_idle %s" % int(idletime))
|
| -
|
| - def evil(self,user,anon=0):
|
| - """
|
| - warn a user
|
| - user := the user to warn
|
| - anon := if true, an anonymous warning
|
| - """
|
| - self.sendFlap(2,"toc_evil %s %s"%(normalize(user), (not anon and "anon") or "norm"))
|
| -
|
| - def away(self,message=''):
|
| - """
|
| - change away state
|
| - message := the message, or '' to come back from awayness
|
| - """
|
| - self._awaymessage=message
|
| - if message:
|
| - message=' '+quote(message)
|
| - self.sendFlap(2,"toc_set_away%s"%message)
|
| -
|
| - def chat_join(self,exchange,roomname):
|
| - """
|
| - join a chat room
|
| - exchange := should almost always be 4
|
| - roomname := room name
|
| - """
|
| - roomname=string.replace(roomname," ","")
|
| - self.sendFlap(2,"toc_chat_join %s %s"%(int(exchange),roomname))
|
| -
|
| - def chat_say(self,roomid,message):
|
| - """
|
| - send a message to a chatroom
|
| - roomid := the AIM id for the room
|
| - message := the message to send
|
| - """
|
| - self.sendFlap(2,"toc_chat_send %s %s"%(int(roomid),quote(message)))
|
| -
|
| - def chat_whisper(self,roomid,user,message):
|
| - """
|
| - whisper to another user in a chatroom
|
| - roomid := the AIM id for the room
|
| - user := the user to whisper to
|
| - message := the message to send
|
| - """
|
| - self.sendFlap(2,"toc_chat_whisper %s %s %s"%(int(roomid),normalize(user),quote(message)))
|
| -
|
| - def chat_leave(self,roomid):
|
| - """
|
| - leave a chat room.
|
| - roomid := the AIM id for the room
|
| - """
|
| - self.sendFlap(2,"toc_chat_leave %s" % int(roomid))
|
| -
|
| - def chat_invite(self,roomid,usernames,message):
|
| - """
|
| - invite a user[s] to the chat room
|
| - roomid := the AIM id for the room
|
| - usernames := either a string (one username) or a list (more than one)
|
| - message := the message to invite them with
|
| - """
|
| - if type(usernames)==type(""): # a string, one username
|
| - users=usernames
|
| - else:
|
| - users=""
|
| - for u in usernames:
|
| - users=users+u+" "
|
| - users=users[:-1]
|
| - self.sendFlap(2,"toc_chat_invite %s %s %s" % (int(roomid),quote(message),users))
|
| -
|
| - def chat_accept(self,roomid):
|
| - """
|
| - accept an invite to a chat room
|
| - roomid := the AIM id for the room
|
| - """
|
| - self.sendFlap(2,"toc_chat_accept %s"%int(roomid))
|
| -
|
| - def rvous_accept(self,cookie):
|
| - user,uuid,pip,port,d=self._cookies[cookie]
|
| - self.sendFlap(2,"toc_rvous_accept %s %s %s" % (normalize(user),
|
| - cookie,uuid))
|
| - if uuid==SEND_FILE_UID:
|
| - protocol.ClientCreator(reactor, SendFileTransfer,self,cookie,user,d["name"]).connectTCP(pip,port)
|
| -
|
| - def rvous_cancel(self,cookie):
|
| - user,uuid,pip,port,d=self._cookies[cookie]
|
| - self.sendFlap(2,"toc_rvous_accept %s %s %s" % (normalize(user),
|
| - cookie,uuid))
|
| - del self._cookies[cookie]
|
| -
|
| -
|
| -class SendFileTransfer(protocol.Protocol):
|
| - header_fmt="!4s2H8s6H10I32s3c69s16s2H64s"
|
| -
|
| - def __init__(self,client,cookie,user,filename):
|
| - self.client=client
|
| - self.cookie=cookie
|
| - self.user=user
|
| - self.filename=filename
|
| - self.hdr=[0,0,0]
|
| - self.sofar=0
|
| -
|
| - def dataReceived(self,data):
|
| - if not self.hdr[2]==0x202:
|
| - self.hdr=list(struct.unpack(self.header_fmt,data[:256]))
|
| - self.hdr[2]=0x202
|
| - self.hdr[3]=self.cookie
|
| - self.hdr[4]=0
|
| - self.hdr[5]=0
|
| - self.transport.write(apply(struct.pack,[self.header_fmt]+self.hdr))
|
| - data=data[256:]
|
| - if self.hdr[6]==1:
|
| - self.name=self.filename
|
| - else:
|
| - self.name=self.filename+self.hdr[-1]
|
| - while self.name[-1]=="\000":
|
| - self.name=self.name[:-1]
|
| - if not data: return
|
| - self.sofar=self.sofar+len(data)
|
| - self.client.receiveBytes(self.user,self.name,data,self.sofar,self.hdr[11])
|
| - if self.sofar==self.hdr[11]: # end of this file
|
| - self.hdr[2]=0x204
|
| - self.hdr[7]=self.hdr[7]-1
|
| - self.hdr[9]=self.hdr[9]-1
|
| - self.hdr[19]=DUMMY_CHECKSUM # XXX really calculate this
|
| - self.hdr[18]=self.hdr[18]+1
|
| - self.hdr[21]="\000"
|
| - self.transport.write(apply(struct.pack,[self.header_fmt]+self.hdr))
|
| - self.sofar=0
|
| - if self.hdr[7]==0:
|
| - self.transport.loseConnection()
|
| -
|
| -
|
| -class GetFileTransfer(protocol.Protocol):
|
| - header_fmt="!4s 2H 8s 6H 10I 32s 3c 69s 16s 2H 64s"
|
| - def __init__(self,client,cookie,dir):
|
| - self.client=client
|
| - self.cookie=cookie
|
| - self.dir=dir
|
| - self.buf=""
|
| -
|
| - def connectionMade(self):
|
| - def func(f,path,names):
|
| - names.sort(lambda x,y:cmp(string.lower(x),string.lower(y)))
|
| - for n in names:
|
| - name=os.path.join(path,n)
|
| - lt=time.localtime(os.path.getmtime(name))
|
| - size=os.path.getsize(name)
|
| - f[1]=f[1]+size
|
| - f.append("%02d/%02d/%4d %02d:%02d %8d %s" %
|
| - (lt[1],lt[2],lt[0],lt[3],lt[4],size,name[f[0]:]))
|
| - f=[len(self.dir)+1,0]
|
| - os.path.walk(self.dir,func,f)
|
| - size=f[1]
|
| - self.listing=string.join(f[2:],"\r\n")+"\r\n"
|
| - open("\\listing.txt","w").write(self.listing)
|
| - hdr=["OFT2",256,0x1108,self.cookie,0,0,len(f)-2,len(f)-2,1,1,size,
|
| - len(self.listing),os.path.getmtime(self.dir),
|
| - checksum(self.listing),0,0,0,0,0,0,"OFT_Windows ICBMFT V1.1 32",
|
| - "\002",chr(0x1a),chr(0x10),"","",0,0,""]
|
| - self.transport.write(apply(struct.pack,[self.header_fmt]+hdr))
|
| -
|
| - def dataReceived(self,data):
|
| - self.buf=self.buf+data
|
| - while len(self.buf)>=256:
|
| - hdr=list(struct.unpack(self.header_fmt,self.buf[:256]))
|
| - self.buf=self.buf[256:]
|
| - if hdr[2]==0x1209:
|
| - self.file=StringIO.StringIO(self.listing)
|
| - self.transport.registerProducer(self,0)
|
| - elif hdr[2]==0x120b: pass
|
| - elif hdr[2]==0x120c: # file request
|
| - file=hdr[-1]
|
| - for k,v in [["\000",""],["\001",os.sep]]:
|
| - file=string.replace(file,k,v)
|
| - self.name=os.path.join(self.dir,file)
|
| - self.file=open(self.name,'rb')
|
| - hdr[2]=0x0101
|
| - hdr[6]=hdr[7]=1
|
| - hdr[10]=hdr[11]=os.path.getsize(self.name)
|
| - hdr[12]=os.path.getmtime(self.name)
|
| - hdr[13]=checksum_file(self.file)
|
| - self.file.seek(0)
|
| - hdr[18]=hdr[19]=0
|
| - hdr[21]=chr(0x20)
|
| - self.transport.write(apply(struct.pack,[self.header_fmt]+hdr))
|
| - log.msg("got file request for %s"%file,hex(hdr[13]))
|
| - elif hdr[2]==0x0202:
|
| - log.msg("sending file")
|
| - self.transport.registerProducer(self,0)
|
| - elif hdr[2]==0x0204:
|
| - log.msg("real checksum: %s"%hex(hdr[19]))
|
| - del self.file
|
| - elif hdr[2]==0x0205: # resume
|
| - already=hdr[18]
|
| - if already:
|
| - data=self.file.read(already)
|
| - else:
|
| - data=""
|
| - log.msg("restarting at %s"%already)
|
| - hdr[2]=0x0106
|
| - hdr[19]=checksum(data)
|
| - self.transport.write(apply(struct.pack,[self.header_fmt]+hdr))
|
| - elif hdr[2]==0x0207:
|
| - self.transport.registerProducer(self,0)
|
| - else:
|
| - log.msg("don't understand 0x%04x"%hdr[2])
|
| - log.msg(hdr)
|
| -
|
| - def resumeProducing(self):
|
| - data=self.file.read(4096)
|
| - log.msg(len(data))
|
| - if not data:
|
| - self.transport.unregisterProducer()
|
| - self.transport.write(data)
|
| -
|
| - def pauseProducing(self): pass
|
| -
|
| - def stopProducing(self): del self.file
|
| -
|
| -# UUIDs
|
| -SEND_FILE_UID = "09461343-4C7F-11D1-8222-444553540000"
|
| -GET_FILE_UID = "09461348-4C7F-11D1-8222-444553540000"
|
| -UUIDS={
|
| - SEND_FILE_UID:"SEND_FILE",
|
| - GET_FILE_UID:"GET_FILE"
|
| -}
|
| -
|
| -# ERRORS
|
| -# general
|
| -NOT_AVAILABLE=901
|
| -CANT_WARN=902
|
| -MESSAGES_TOO_FAST=903
|
| -# admin
|
| -BAD_INPUT=911
|
| -BAD_ACCOUNT=912
|
| -REQUEST_ERROR=913
|
| -SERVICE_UNAVAILABLE=914
|
| -# chat
|
| -NO_CHAT_IN=950
|
| -# im and info
|
| -SEND_TOO_FAST=960
|
| -MISSED_BIG_IM=961
|
| -MISSED_FAST_IM=962
|
| -# directory
|
| -DIR_FAILURE=970
|
| -TOO_MANY_MATCHES=971
|
| -NEED_MORE_QUALIFIERS=972
|
| -DIR_UNAVAILABLE=973
|
| -NO_EMAIL_LOOKUP=974
|
| -KEYWORD_IGNORED=975
|
| -NO_KEYWORDS=976
|
| -BAD_LANGUAGE=977
|
| -BAD_COUNTRY=978
|
| -DIR_FAIL_UNKNOWN=979
|
| -# authorization
|
| -BAD_NICKNAME=980
|
| -SERVICE_TEMP_UNAVAILABLE=981
|
| -WARNING_TOO_HIGH=982
|
| -CONNECTING_TOO_QUICK=983
|
| -UNKNOWN_SIGNON=989
|
| -
|
| -STD_MESSAGE={}
|
| -STD_MESSAGE[NOT_AVAILABLE]="%s not currently available"
|
| -STD_MESSAGE[CANT_WARN]="Warning of %s not currently available"
|
| -STD_MESSAGE[MESSAGES_TOO_FAST]="A message has been dropped, you are exceeding the server speed limit"
|
| -STD_MESSAGE[BAD_INPUT]="Error validating input"
|
| -STD_MESSAGE[BAD_ACCOUNT]="Invalid account"
|
| -STD_MESSAGE[REQUEST_ERROR]="Error encountered while processing request"
|
| -STD_MESSAGE[SERVICE_UNAVAILABLE]="Service unavailable"
|
| -STD_MESSAGE[NO_CHAT_IN]="Chat in %s is unavailable"
|
| -STD_MESSAGE[SEND_TOO_FAST]="You are sending messages too fast to %s"
|
| -STD_MESSAGE[MISSED_BIG_IM]="You missed an IM from %s because it was too big"
|
| -STD_MESSAGE[MISSED_FAST_IM]="You missed an IM from %s because it was sent too fast"
|
| -# skipping directory for now
|
| -STD_MESSAGE[BAD_NICKNAME]="Incorrect nickname or password"
|
| -STD_MESSAGE[SERVICE_TEMP_UNAVAILABLE]="The service is temporarily unavailable"
|
| -STD_MESSAGE[WARNING_TOO_HIGH]="Your warning level is currently too high to sign on"
|
| -STD_MESSAGE[CONNECTING_TOO_QUICK]="You have been connecting and disconnecting too frequently. Wait 10 minutes and try again. If you continue to try, you will need to wait even longer."
|
| -STD_MESSAGE[UNKNOWN_SIGNON]="An unknown signon error has occurred %s"
|
|
|