# Copyright (c) 2003-2004 Hyriand. All rights reserved.## Based on code from PySoulSeek, original copyright note:# Copyright (c) 2001-2003 Alexander Kanavin. All rights reserved."""This is the actual client code. Actual GUI classes are in the separate modules"""import timeimport slskprotoimport slskmessagesfrom slskmessages import newIdimport transfersimport Queueimport threadingfrom config import *import stringimport typesimport localefrom utils import _import osclass PeerConnection: """ Holds information about a peer connection. Not every field may be set to something. addr is (ip,port) address, conn is a socket object, msgs is a list of outgoing pending messages, token is a reverse-handshake number (protocol feature), init is a PeerInit protocol message. (read slskmessages docstrings for explanation of these) """ def __init__(self, addr = None, username = None, conn = None, msgs = None, token = None, init = None, conntimer = None, tryaddr = None): self.addr = addr self.username = username self.conn = conn self.msgs = msgs self.token = token self.init = init self.conntimer = conntimer self.tryaddr = tryaddrclass ConnectToPeerTimeout: def __init__(self, conn, callback): self.conn = conn self.callback = callback def timeout(self): self.callback([self])class NetworkEventProcessor: """ This class contains handlers for various messages from the networking thread""" def __init__(self,frame,callback, writelog, setstatus, configfile):# self.searchfile = file("searches.txt","a") self.frame=frame self.callback = callback self.logMessage = writelog self.setStatus = setstatus self.config = Config(configfile) self.config.readConfig() self.queue = Queue.Queue(0) self.protothread = slskproto.SlskProtoThread(self.frame.networkcallback,self.queue,self.config.sections["server"]["portrange"]) uselimit = self.config.sections["transfers"]["uselimit"] uploadlimit = self.config.sections["transfers"]["uploadlimit"] limitby = self.config.sections["transfers"]["limitby"] self.queue.put(slskmessages.SetUploadLimit(uselimit,uploadlimit,limitby)) if self.config.sections["transfers"]["geoblock"]: panic = self.config.sections["transfers"]["geopanic"] cc = self.config.sections["transfers"]["geoblockcc"] self.queue.put(slskmessages.SetGeoBlock([panic, cc])) else: self.queue.put(slskmessages.SetGeoBlock(None)) self.serverconn = None self.waitport = None self.peerconns = [] self.users = {} self.chatrooms = None self.privatechat = None self.globallist = None self.userinfo = None self.userbrowse = None self.search = None self.transfers = None self.userlist = None self.servertimer = None self.servertimeout = -1 self.distribcache = {} self.speed = 0 self.translatepunctuation = string.maketrans(string.punctuation,string.join([' ' for i in string.punctuation],'')) try: import GeoIP self.geoip = GeoIP.new(GeoIP.GEOIP_STANDARD) except ImportError: try: import _GeoIP self.geoip = _GeoIP.new(_GeoIP.GEOIP_STANDARD) except ImportError: self.geoip = None self.events = {slskmessages.ConnectToServer:self.ConnectToServer, slskmessages.ConnectError:self.ConnectError, slskmessages.IncPort:self.IncPort, slskmessages.ServerConn:self.ServerConn, slskmessages.ConnClose:self.ConnClose, slskmessages.Login:self.Login, slskmessages.MessageUser:self.MessageUser, slskmessages.ExactFileSearch:self.ExactFileSearch, slskmessages.UserJoinedRoom:self.UserJoinedRoom, slskmessages.SayChatroom:self.SayChatRoom, slskmessages.JoinRoom:self.JoinRoom, slskmessages.UserLeftRoom:self.UserLeftRoom, slskmessages.QueuedDownloads:self.QueuedDownloads, slskmessages.GetPeerAddress:self.GetPeerAddress, slskmessages.OutConn:self.OutConn, slskmessages.UserInfoReply:self.UserInfoReply, slskmessages.UserInfoRequest:self.UserInfoRequest, slskmessages.PierceFireWall:self.PierceFireWall, slskmessages.CantConnectToPeer:self.CantConnectToPeer, slskmessages.PeerTransfer:self.PeerTransfer, slskmessages.SharedFileList:self.SharedFileList, slskmessages.GetSharedFileList:self.GetSharedFileList, slskmessages.FileSearchRequest:self.FileSearchRequest, slskmessages.FileSearchResult:self.FileSearchResult, slskmessages.ConnectToPeer:self.ConnectToPeer, slskmessages.GetUserStatus:self.GetUserStatus, slskmessages.GetUserStats:self.GetUserStats, slskmessages.Relogged:self.Relogged, slskmessages.PeerInit:self.PeerInit, slskmessages.DownloadFile:self.FileDownload, slskmessages.UploadFile:self.FileUpload, slskmessages.FileRequest:self.FileRequest, slskmessages.TransferRequest:self.TransferRequest, slskmessages.TransferResponse:self.TransferResponse, slskmessages.QueueUpload:self.QueueUpload, slskmessages.QueueFailed:self.QueueFailed, slskmessages.UploadFailed:self.UploadFailed, slskmessages.PlaceInQueue:self.PlaceInQueue, slskmessages.FileError:self.FileError, slskmessages.FolderContentsResponse:self.FolderContentsResponse, slskmessages.FolderContentsRequest:self.FolderContentsRequest, slskmessages.RoomList:self.RoomList, slskmessages.LeaveRoom:self.LeaveRoom, slskmessages.GlobalUserList:self.GlobalUserList, slskmessages.AddUser:self.AddUser, slskmessages.PrivilegedUsers:self.PrivilegedUsers, slskmessages.AddToPrivileged:self.AddToPrivileged, slskmessages.CheckPrivileges:self.CheckPrivileges, slskmessages.ServerPing:self.Msg83, slskmessages.Msg83:self.Msg83, slskmessages.Msg84:self.Msg83, slskmessages.Msg85:self.Msg83, slskmessages.Msg12547:self.Msg12547, slskmessages.ParentInactivityTimeout:self.Msg83, slskmessages.SearchInactivityTimeout:self.Msg83, slskmessages.MinParentsInCache:self.Msg83, slskmessages.Msg89:self.Msg83, slskmessages.WishlistInterval:self.WishlistInterval, slskmessages.DistribAliveInterval:self.Msg83, slskmessages.AdminMessage:self.AdminMessage, slskmessages.TunneledMessage:self.TunneledMessage, slskmessages.IncConn:self.IncConn, slskmessages.PlaceholdUpload:self.PlaceholdUpload, slskmessages.PlaceInQueueRequest:self.PlaceInQueueRequest, slskmessages.UploadQueueNotification:self.UploadQueueNotification, slskmessages.SearchRequest:self.SearchRequest, slskmessages.FileSearch:self.SearchRequest, slskmessages.RoomSearch:self.SearchRequest, slskmessages.UserSearch:self.SearchRequest, slskmessages.NetInfo:self.NetInfo, slskmessages.DistribAlive:self.DistribAlive, slskmessages.DistribSearch:self.DistribSearch, ConnectToPeerTimeout:self.ConnectToPeerTimeout, transfers.TransferTimeout:self.TransferTimeout, slskmessages.RescanShares:self.RescanShares, slskmessages.RescanBuddyShares:self.RescanBuddyShares, slskmessages.Notify:self.Notify, slskmessages.GlobalRecommendations:self.GlobalRecommendations, slskmessages.Recommendations:self.Recommendations, slskmessages.ItemRecommendations:self.ItemRecommendations, slskmessages.SimilarUsers:self.SimilarUsers, slskmessages.ItemSimilarUsers:self.ItemSimilarUsers, slskmessages.RoomTickerState:self.RoomTickerState, slskmessages.RoomTickerAdd:self.RoomTickerAdd, slskmessages.RoomTickerRemove:self.RoomTickerRemove, } def ProcessRequestToPeer(self, user, message, window = None, address = None): """ Sends message to a peer and possibly sets up a window to display the result. """ conn = None for i in self.peerconns: if i.username == user and i.init.type == 'P' and message.__class__ is not slskmessages.FileRequest: conn = i break if conn is not None: if conn.conn is not None: message.conn = conn.conn self.queue.put(message) if window is not None: window.InitWindow(conn.username,conn.conn) if message.__class__ is slskmessages.TransferRequest and self.transfers is not None: self.transfers.gotConnect(message.req,conn.conn) return else: conn.msgs.append(message) else: if message.__class__ is slskmessages.FileRequest: type = 'F' elif message.__class__ is slskmessages.DistribConn: type = 'D' else: type = 'P' init = slskmessages.PeerInit(None,self.config.sections["server"]["login"],type,0) firewalled = self.config.sections["server"]["firewalled"] addr = None behindfw = None token = None if self.users.has_key(user): addr = self.users[user].addr behindfw = self.users[user].behindfw elif address is not None: addr = address if firewalled: if addr is None: self.queue.put(slskmessages.GetPeerAddress(user)) elif behindfw is None: self.queue.put(slskmessages.OutConn(None,addr)) else: firewalled = 0 if not firewalled: token = newId() self.queue.put(slskmessages.ConnectToPeer(token,user,type)) conn = PeerConnection(addr = addr, username = user, msgs = [message], token = token, init = init) self.peerconns.append(conn) if token is not None: conntimeout = ConnectToPeerTimeout(self.peerconns[-1],self.frame.callback) timer = threading.Timer(300.0, conntimeout.timeout) self.peerconns[-1].conntimer = timer timer.start() if message.__class__ is slskmessages.TransferRequest and self.transfers is not None: if conn.addr is None: self.transfers.gettingAddress(message.req) elif conn.token is None: self.transfers.gotAddress(message.req) else: self.transfers.gotConnectError(message.req) def setServerTimer(self): if self.servertimeout == -1: self.servertimeout = 15 elif 0 < self.servertimeout < 3600: self.servertimeout = self.servertimeout * 2 self.servertimer = threading.Timer(self.servertimeout, self.ServerTimeout) self.servertimer.start() self.logMessage(_("The server seems to be down or not responding, retrying in %i seconds") %(self.servertimeout)) def ServerTimeout(self): if not self.config.needConfig(): self.frame.callback([slskmessages.ConnectToServer()]) def StopTimers(self): for i in self.peerconns: if i.conntimer is not None: i.conntimer.cancel() def ConnectToServer(self, msg): self.frame.OnConnect(None) def encode(self, str, networkenc = None): if networkenc is None: networkenc = self.config.sections["server"]["enc"] if type(str) is types.UnicodeType: return str.encode(networkenc,'replace') else: return str.decode("utf-8",'replace').encode(networkenc,'replace') def decode(self, string, networkenc = None): if networkenc is None: networkenc = self.config.sections["server"]["enc"] return str(string).decode(networkenc,'replace').encode("utf-8", "replace") def getencodings(self): return [["Latin", 'ascii'], ["US-Canada", 'cp037'], ['Hebrew', 'cp424'], ['US English', 'cp437'], ['International', 'cp500'], ['Greek', 'cp737'], ['Estonian', 'cp775'], ['Western European', 'cp850'], ['Central European', 'cp852'], ['Cyrillic', 'cp855'], ['Cyrillic', 'cp856'], ['Turkish', 'cp857'], ['Portuguese', 'cp860'], ['Icelandic', 'cp861'], ['Hebrew', 'cp862'], ['French Canadian', 'cp863'], ['Arabic', 'cp864'], ['Nordic', 'cp865'], ['Cyrillic', 'cp866'], ['Latin-9', 'cp869'], ['Thai', 'cp874'], ['Greek', 'cp875'], ['Japanese', 'cp932'], ['Chinese Simple', 'cp936'], ['Korean', 'cp949'], ['Chinese Traditional', 'cp950'], ['Urdu', 'cp1006'], ['Turkish', 'cp1026'], ['Latin', 'cp1140'], ['Central European', 'cp1250'], ['Cyrillic', 'cp1251'], ['Latin', 'cp1252'], ['Greek', 'cp1253'], ['Turkish', 'cp1254'], ['Hebrew', 'cp1255'], ['Arabic', 'cp1256'], ['Baltic', 'cp1257'], ['Vietnamese', 'cp1258'], ['Latin', 'iso8859-1'], ['Latin 2', 'iso8859-2'], ['South European', 'iso8859-3'], ['North European', 'iso8859-4'], ['Cyrillic', 'iso8859-5'], ['Arabic', 'iso8859-6'], ['Greek', 'iso8859-7'], ['Hebrew', 'iso8859-8'], ['Turkish', 'iso8859-9'], ['Nordic', 'iso8859-10'], ['Thai', 'iso8859-11'], ['Baltic', 'iso8859-13'], ['Celtic', 'iso8859-14'], ['Western European', 'iso8859-15'], ['South-Eastern European', 'iso8859-16'], ['Cyrillic', 'koi8-r'], ['Latin', 'latin-1'], ['Cyrillic', 'mac-cyrillic'], ['Greek', 'mac-greek'], ['Icelandic', 'mac-iceland'], ['Latin 2', 'mac-latin2'], ['Latin', 'mac-roman'], ['Turkish', 'mac-turkish'], ['International', 'utf-16'], ['International', 'utf-7'], ['International', 'utf-8']] def sendNumSharedFoldersFiles(self): conf = self.config.sections if conf["transfers"]["enablebuddyshares"] and conf["transfers"]["friendsonly"]: shared_db = "bsharedfiles" else: shared_db = "sharedfiles" sharedfolders = len(conf["transfers"][shared_db].keys()) sharedfiles = 0 for i in conf["transfers"][shared_db].keys(): sharedfiles = sharedfiles + len(conf["transfers"][shared_db][i]) self.queue.put(slskmessages.SharedFoldersFiles(sharedfolders,sharedfiles)) def RescanShares(self,msg): import utils utils.frame = self.frame utils.log = self.logMessage files, streams, wordindex, fileindex, mtimes = utils.rescandirs(msg.shared,self.config.sections["transfers"]["sharedmtimes"],self.config.sections["transfers"]["sharedfiles"],self.config.sections["transfers"]["sharedfilesstreams"],msg.yieldfunction) self.frame.RescanFinished([files, streams, wordindex, fileindex, mtimes], "normal") def RescanBuddyShares(self,msg): import utils utils.frame = self.frame utils.log = self.logMessage files, streams, wordindex, fileindex, mtimes = utils.rescandirs(msg.shared,self.config.sections["transfers"]["bsharedmtimes"],self.config.sections["transfers"]["bsharedfiles"],self.config.sections["transfers"]["bsharedfilesstreams"],msg.yieldfunction) self.frame.RescanFinished([files, streams, wordindex, fileindex, mtimes], "buddy") def Notify(self, msg): self.logMessage("%s" % self.decode(msg.msg)) def ConnectError(self,msg): if msg.connobj.__class__ is slskmessages.ServerConn: self.setStatus(_("Can't connect to server %s:%s: %s") % (msg.connobj.addr[0],msg.connobj.addr[1],self.decode(msg.err))) self.setServerTimer() if self.serverconn is not None: self.serverconn = None self.frame.ConnectError(msg) elif msg.connobj.__class__ is slskmessages.OutConn: for i in self.peerconns[:]: if i.addr == msg.connobj.addr and i.conn is None: if i.token is None: i.token = newId() self.queue.put(slskmessages.ConnectToPeer(i.token,i.username,i.init.type)) if self.users.has_key(i.username): self.users[i.username].behindfw = "yes" for j in i.msgs: if j.__class__ is slskmessages.TransferRequest and self.transfers is not None: self.transfers.gotConnectError(j.req) conntimeout = ConnectToPeerTimeout(i,self.frame.callback) timer = threading.Timer(300.0, conntimeout.timeout) timer.start() if i.conntimer is not None: i.conntimer.cancel() i.conntimer = timer else: for j in i.msgs: if j.__class__ in [slskmessages.TransferRequest,slskmessages.FileRequest] and self.transfers is not None: self.transfers.gotCantConnect(j.req) self.logMessage(_("Can't connect to %s, sending notification via the server") %(i.username),1) self.queue.put(slskmessages.CantConnectToPeer(i.token,i.username)) if i.conntimer is not None: i.conntimer.cancel() self.peerconns.remove(i) break else: self.logMessage("%s %s %s" %(msg.err, msg.__class__, vars(msg))) else: self.logMessage("%s %s %s" %(msg.err, msg.__class__, vars(msg)),1) self.ClosedConnection(msg.connobj.conn, msg.connobj.addr) def IncPort(self, msg): self.waitport = msg.port self.setStatus(_("Listening on port %i") %(msg.port)) def ServerConn(self, msg): self.setStatus(_("Connected to server %s:%s, logging in...") %(msg.addr[0],msg.addr[1])) time.sleep(1) self.serverconn = msg.conn self.servertimeout = -1 self.users = {} self.queue.put(slskmessages.Login(self.config.sections["server"]["login"],self.config.sections["server"]["passw"],181)) if self.waitport is not None: self.queue.put(slskmessages.SetWaitPort(self.waitport)) def PeerInit(self, msg):# list = [i for i in self.peerconns if i.conn == msg.conn.conn]# if list == []: self.peerconns.append(PeerConnection(addr = msg.conn.addr, username = msg.user, conn = msg.conn.conn, init = msg, msgs = []))# else:# for i in list:# i.init = msg# i.username = msg.user def ConnClose(self, msg): self.ClosedConnection(msg.conn, msg.addr) def ClosedConnection(self, conn, addr): if conn == self.serverconn: self.setStatus(_("Disconnected from server %s:%s") %(addr[0],addr[1])) if not self.frame.manualdisconnect: self.setServerTimer() else: self.frame.manualdisconnect = 0 self.serverconn = None if self.transfers is not None: self.transfers.AbortTransfers() self.privatechat = self.chatrooms = self.userinfo = self.userbrowse = self.search = self.transfers = self.userlist = None self.frame.ConnClose(conn, addr) else: for i in self.peerconns[:]: if i.conn == conn: self.logMessage(_("Connection closed by peer: %s") % self.decode(vars(i)),1) if i.conntimer is not None: i.conntimer.cancel() if self.transfers is not None: self.transfers.ConnClose(conn, addr) if i == self.GetDistribConn(): self.DistribConnClosed(i) self.peerconns.remove(i) break else: self.logMessage(_("Removed connection closed by peer: %s %s") %(conn, addr),1) def Login(self,msg): self.logintime = time.time() conf = self.config.sections if msg.success: self.setStatus(_("Logged in, getting the list of rooms...")) self.transfers = transfers.Transfers(conf["transfers"]["downloads"],self.peerconns,self.queue, self, self.users) self.privatechat, self.chatrooms, self.userinfo, self.userbrowse, self.search, downloads, uploads, self.userlist = self.frame.InitInterface(msg) self.transfers.setTransferPanels(downloads, uploads) self.sendNumSharedFoldersFiles() self.queue.put(slskmessages.SetStatus((not self.frame.away)+1)) for thing in self.config.sections["interests"]["likes"]: self.queue.put(slskmessages.AddThingILike(self.encode(thing))) for thing in self.config.sections["interests"]["dislikes"]: self.queue.put(slskmessages.AddThingIHate(self.encode(thing))) self.privatechat.Login() else: self.frame.manualdisconnect = 1 self.setStatus(_("Can not log in, reason: %s") %(msg.reason)) self.logMessage(_("Can not log in, reason: %s") %(msg.reason)) def MessageUser(self, msg): status = 0 if time.time() <= self.logintime + 2: # Offline message status = 1 if self.privatechat is not None: self.privatechat.ShowMessage(msg,msg.msg,status=status) self.queue.put(slskmessages.MessageAcked(msg.msgid)) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def UserJoinedRoom(self,msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.UserJoinedRoom(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def JoinRoom(self,msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.JoinRoom(msg) ticker = "" if self.config.sections["ticker"]["rooms"].has_key(msg.room): ticker = self.config.sections["ticker"]["rooms"][msg.room] elif self.config.sections["ticker"]["default"]: ticker = self.config.sections["ticker"]["default"] if ticker: encoding = self.config.sections["server"]["enc"] if self.config.sections["server"]["roomencoding"].has_key(msg.room): encoding = self.config.sections["server"]["roomencoding"][msg.room] self.queue.put(slskmessages.RoomTickerSet(msg.room, self.encode(ticker, encoding))) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def LeaveRoom(self,msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.LeaveRoom(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def SayChatRoom(self,msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.SayChatRoom(msg,msg.msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def AddUser(self,msg): if self.transfers is not None: self.transfers.getAddUser(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def PrivilegedUsers(self,msg): if self.transfers is not None: self.transfers.setPrivilegedUsers(msg.users) self.logMessage(_("%i privileged users") %(len(msg.users))) self.queue.put(slskmessages.HaveNoParent(1)) self.queue.put(slskmessages.GetUserStats(self.config.sections["server"]["login"])) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def AddToPrivileged(self, msg): if self.transfers is not None: self.transfers.addToPrivileged(msg.user) self.logMessage(_("User %s added to privileged list") %(msg.user),1) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def CheckPrivileges(self, msg): mins = msg.days / 60 hours = mins / 60 days = hours / 24 self.logMessage(_("%i days, %i hours, %i minutes, %i seconds of download privileges left") %(days, hours % 24, mins % 60, msg.days % 60)) def AdminMessage(self, msg): self.logMessage("%s" %(msg.msg)) def Msg83(self, msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def Msg12547(self, msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def WishlistInterval(self, msg): if self.search is not None: self.search.SetInterval(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def GetUserStatus(self,msg): self.queue.put(slskmessages.AddUser(msg.user)) if self.users.has_key(msg.user): if msg.status == 0: self.users[msg.user] = UserAddr(status = msg.status) else: self.users[msg.user].status = msg.status else: self.users[msg.user] = UserAddr(status = msg.status) if msg.privileged != None: if msg.privileged == 1: if self.transfers is not None: self.transfers.addToPrivileged(msg.user) self.logMessage(_("User %s added to privileged list") %(msg.user),1) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) self.frame.GetUserStatus(msg) if self.userlist is not None: self.userlist.GetUserStatus(msg) if self.transfers is not None: self.transfers.GetUserStatus(msg) if self.privatechat is not None: self.privatechat.GetUserStatus(msg) if self.userinfo is not None: self.userinfo.GetUserStatus(msg) if self.userbrowse is not None: self.userbrowse.GetUserStatus(msg) if self.chatrooms is not None: self.chatrooms.roomsctrl.GetUserStatus(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def GetUserStats(self,msg): if msg.user == self.config.sections["server"]["login"]: self.speed = msg.avgspeed self.frame.GetUserStats(msg) if self.chatrooms is not None: self.chatrooms.roomsctrl.GetUserStats(msg) if self.userinfo is not None: self.userinfo.GetUserStats(msg) if self.userlist is not None: self.userlist.GetUserStats(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def UserLeftRoom(self,msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.UserLeftRoom(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def QueuedDownloads(self,msg): # if self.chatrooms is not None:# self.chatrooms.roomsctrl.QueuedDownloads(msg) # else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def GetPeerAddress(self,msg): for i in self.peerconns: if i.username == msg.user and i.addr is None: if msg.port != 0 or i.tryaddr == 10: if i.tryaddr == 10: self.logMessage(_("Server reported port 0 for the 10th time for user %s, giving up") %(msg.user),1) elif i.tryaddr is not None: self.logMessage(_("Server reported non-zero port for user %s after %i retries") %(msg.user, i.tryaddr),1) i.addr = (msg.ip, msg.port) i.tryaddr = None self.queue.put(slskmessages.OutConn(None, i.addr)) for j in i.msgs: if j.__class__ is slskmessages.TransferRequest and self.transfers is not None: self.transfers.gotAddress(j.req) else: if i.tryaddr is None: i.tryaddr = 1 self.logMessage(_("Server reported port 0 for user %s, retrying") %(msg.user),1) else: i.tryaddr +=1 self.queue.put(slskmessages.GetPeerAddress(msg.user)) break else: import socket if self.geoip: cc = self.geoip.country_name_by_addr(msg.ip) else: cc = "" if cc: cc = " (%s)" % cc else: cc = "" try: hostname = socket.gethostbyaddr(msg.ip)[0] message = _("IP address of %s is %s, name %s, port %i%s") %(msg.user,msg.ip,hostname,msg.port,cc) except: message = _("IP address of %s is %s, port %i%s") %(msg.user,msg.ip,msg.port,cc) self.logMessage(message) if self.users.has_key(msg.user): self.users[msg.user].addr = (msg.ip,msg.port) def Relogged(self, msg): self.logMessage(_("Someone else is logging in with the same nickname, server is going to disconnect us")) self.frame.manualdisconnect = 1 def OutConn(self, msg): for i in self.peerconns: if i.addr == msg.addr and i.conn is None: if i.token is None: i.init.conn = msg.conn self.queue.put(i.init) else: self.queue.put(slskmessages.PierceFireWall(msg.conn, i.token)) i.conn = msg.conn for j in i.msgs: if j.__class__ is slskmessages.UserInfoRequest and self.userinfo is not None: self.userinfo.InitWindow(i.username,msg.conn) if j.__class__ is slskmessages.GetSharedFileList and self.userbrowse is not None: self.userbrowse.InitWindow(i.username,msg.conn) if j.__class__ is slskmessages.FileRequest and self.transfers is not None: self.transfers.gotFileConnect(j.req,msg.conn) if j.__class__ is slskmessages.TransferRequest and self.transfers is not None: self.transfers.gotConnect(j.req,msg.conn) j.conn = msg.conn self.queue.put(j) i.msgs = [] break self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def IncConn(self,msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def ConnectToPeer(self, msg): init = slskmessages.PeerInit(None,msg.user,msg.type,0) self.queue.put(slskmessages.OutConn(None,(msg.ip,msg.port),init)) self.peerconns.append(PeerConnection(addr = (msg.ip,msg.port), username = msg.user, msgs = [], token = msg.token, init = init)) self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def CheckUser(self, user, geoip, addr): if user in self.config.sections["server"]["banlist"]: if self.config.sections["transfers"]["usecustomban"]: return 0, _("Banned (%s)") % self.config.sections["transfers"]["customban"] else: return 0, _("Banned") if user in [i[0] for i in self.config.sections["server"]["userlist"]] and self.config.sections["transfers"]["enablebuddyshares"]: # For sending buddy-only shares return 2, "" if user in [i[0] for i in self.config.sections["server"]["userlist"]]: return 1, "" if self.config.sections["transfers"]["friendsonly"]: return 0, _("Sorry, friends only") if not geoip or not self.config.sections["transfers"]["geoblock"]: return 1, _("geoip") cc = geoip.country_code_by_addr(addr) if not cc: if self.config.sections["transfers"]["geopanic"]: return 0, _("Sorry, geographical paranoia") else: return 1, "" if self.config.sections["transfers"]["geoblockcc"][0].find(cc) >= 0: return 0, _("Sorry, your country is blocked") return 1, "" def CheckSpoof(self, user, ip, port): if not self.users.has_key(user): return 0 if self.users[user].addr != None: u_ip, u_port = self.users[user].addr print u_ip, ip if u_ip != ip: warning = _("IP %s:%s is spoofing user %s with a peer request, blocking because it does not match IP: %s") %(ip, port, user, u_ip) self.logMessage(warning , None) print warning return 1 return 0 def GetSharedFileList(self,msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) user = ip = port = None # Get peer's username, ip and port for i in self.peerconns: if i.conn is msg.conn.conn: user = i.username ip, port = i.addr break if user == None: # No peer connection return # Check address is spoofed, if possible #if self.CheckSpoof(user, ip, port): # Message IS spoofed # return if user == self.config.sections["server"]["login"]: #self.logMessage(_("%s is making a BrowseShares request, blocking possible spoofing attempt from IP %s port %s") %(user, ip, port), None) return self.logMessage(_("%s is making a BrowseShares request") %(user), None) addr = msg.conn.addr[0] checkuser, reason = self.CheckUser(user, self.geoip, addr) if checkuser == 1: self.queue.put(slskmessages.SharedFileList(msg.conn.conn,self.config.sections["transfers"]["sharedfilesstreams"])) elif checkuser == 2: self.queue.put(slskmessages.SharedFileList(msg.conn.conn,self.config.sections["transfers"]["bsharedfilesstreams"])) else: self.queue.put(slskmessages.SharedFileList(msg.conn.conn,{})) def UserInfoReply(self,msg): for i in self.peerconns: if i.conn is msg.conn.conn and self.userinfo is not None: # probably impossible to do this if i.username != self.config.sections["server"]["login"]: self.userinfo.ShowInfo(i.username, msg) def ClosePeerConnection(self, peerconn): for i in self.peerconns[:]: if i.conn == peerconn: #i.conn.close() #i.conn = None #self.peerconns.remove(i) #del self.protothread._conns[i.conn] #self.ClosedConnection(i.conn, i.addr) #self.queue.put(self.ClosedConnection(i.conn, i.addr)) self.queue.put(self.ConnClose( i)) break def UserInfoRequest(self, msg): user = ip = port = None # Get peer's username, ip and port for i in self.peerconns: if i.conn is msg.conn.conn: user = i.username ip, port = i.addr break if user == None: # No peer connection return # Check address is spoofed, if possible #if self.CheckSpoof(user, ip, port): # Message IS spoofed # return if user == self.config.sections["server"]["login"]: self.logMessage(_("Blocking %s from making a UserInfo request, possible spoofing attempt from IP %s port %s") %(user, ip, port), None) self.ClosePeerConnection(msg.conn.conn) #i.conn.close() #self.peerconns.remove(i) #del self.protothread._conns[i.conn] #self.ClosedConnection(i.conn, i.addr) return if user in self.config.sections["server"]["banlist"]: self.logMessage(_("%s is banned, but is making a UserInfo request") %(user), 1) self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) return try: if sys.platform == "win32": userpic = u"%s" % self.config.sections["userinfo"]["pic"] if not os.path.exists(userpic): userpic = self.config.sections["userinfo"]["pic"] else: userpic = self.config.sections["userinfo"]["pic"] f=open(userpic,'rb') pic = f.read() f.close() except: pic = None descr = self.encode(eval(self.config.sections["userinfo"]["descr"], {})) if self.transfers is not None: totalupl = self.transfers.getTotalUploadsAllowed() queuesize = self.transfers.getUploadQueueSizes()[0] slotsavail = int(not self.transfers.bandwidthLimitReached()) self.queue.put(slskmessages.UserInfoReply(msg.conn.conn,descr,pic,totalupl, queuesize,slotsavail)) self.logMessage(_("%s is making a UserInfo request") %(user), None) self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def SharedFileList(self, msg): for i in self.peerconns: if i.conn is msg.conn.conn and self.userbrowse is not None: if i.username != self.config.sections["server"]["login"]: self.userbrowse.ShowInfo(i.username, msg) def FileSearchResult(self, msg): for i in self.peerconns: if i.conn is msg.conn.conn and self.search is not None: if self.geoip: if i.addr: country = self.geoip.country_code_by_addr(i.addr[0]) else: country = "" else: country = "" self.search.ShowResult(msg, i.username, country) def PierceFireWall(self, msg): for i in self.peerconns: if i.token == msg.token and i.conn is None: if i.conntimer is not None: i.conntimer.cancel() i.init.conn = msg.conn.conn self.queue.put(i.init) i.conn = msg.conn.conn for j in i.msgs: if j.__class__ is slskmessages.UserInfoRequest and self.userinfo is not None: self.userinfo.InitWindow(i.username,msg.conn.conn) if j.__class__ is slskmessages.GetSharedFileList and self.userbrowse is not None: self.userbrowse.InitWindow(i.username,msg.conn.conn) if j.__class__ is slskmessages.FileRequest and self.transfers is not None: self.transfers.gotFileConnect(j.req,msg.conn.conn) if j.__class__ is slskmessages.TransferRequest and self.transfers is not None: self.transfers.gotConnect(j.req,msg.conn.conn) j.conn = msg.conn.conn self.queue.put(j) i.msgs = [] break self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def CantConnectToPeer(self, msg): for i in self.peerconns[:]: if i.token == msg.token: if i.conntimer is not None: i.conntimer.cancel() if i == self.GetDistribConn(): self.DistribConnClosed(i) self.peerconns.remove(i) self.logMessage(_("Can't connect to %s (either way), giving up") % (i.username),1) for j in i.msgs: if j.__class__ in [slskmessages.TransferRequest,slskmessages.FileRequest] and self.transfers is not None: self.transfers.gotCantConnect(j.req) def ConnectToPeerTimeout(self,msg): for i in self.peerconns[:]: if i == msg.conn: if i == self.GetDistribConn(): self.DistribConnClosed(i) self.peerconns.remove(i) self.logMessage(_("User %s does not respond to connect request, giving up") % (i.username),1) for j in i.msgs: if j.__class__ in [slskmessages.TransferRequest,slskmessages.FileRequest] and self.transfers is not None: self.transfers.gotCantConnect(j.req) def TransferTimeout(self, msg): if self.transfers is not None: self.transfers.TransferTimeout(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def FileDownload(self,msg): if self.transfers is not None: self.transfers.FileDownload(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def FileUpload(self,msg): if self.transfers is not None: self.transfers.FileUpload(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def FileRequest(self,msg): if self.transfers is not None: self.transfers.FileRequest(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def FileError(self,msg): if self.transfers is not None: self.transfers.FileError(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def TransferRequest(self,msg): if self.transfers is not None: self.transfers.TransferRequest(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def TransferResponse(self,msg): if self.transfers is not None: self.transfers.TransferResponse(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def QueueUpload(self,msg): if self.transfers is not None: self.transfers.QueueUpload(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def QueueFailed(self,msg): if self.transfers is not None: self.transfers.QueueFailed(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def PlaceholdUpload(self,msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def PlaceInQueueRequest(self, msg): if self.transfers is not None: self.transfers.PlaceInQueueRequest(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def UploadQueueNotification(self, msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) username = None for i in self.peerconns: if i.conn is msg.conn.conn: username = i.username break if username is None: return if username in [i[0] for i in self.config.sections["server"]["userlist"]] and self.config.sections["transfers"]["remotedownloads"] == 1: self.logMessage(_("Your buddy, %s, is attempting to upload file(s) to you.")%(username), None) else: self.queue.put(slskmessages.MessageUser(username, _("[Automatic Message] ")+_("You are not allowed to send me files.")) ) self.logMessage(_("%s is not allowed to send you file(s), but is attempting to, anyway. Warning Sent.")%(username), None) def UploadFailed(self,msg): if self.transfers is not None: self.transfers.UploadFailed(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def PlaceInQueue(self,msg): if self.transfers is not None: self.transfers.PlaceInQueue(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def FolderContentsResponse(self,msg): if self.transfers is not None: for i in self.peerconns: if i.conn is msg.conn.conn: username = i.username # Check for a large number of files many=0 folder = "" files = [] for i in msg.list.keys(): for j in msg.list[i].keys(): if os.path.commonprefix([i,j]) == j: numfiles = len(msg.list[i][j]) if numfiles > 100: many=1 files = msg.list[i][j] folder = j if many: self.frame.download_large_folder(username, folder, files, numfiles, msg) else: self.transfers.FolderContentsResponse(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def FolderContentsRequest(self,msg): username = None checkuser = None for i in self.peerconns: if i.conn is msg.conn.conn: username = i.username checkuser, reason = self.CheckUser(username, None, None) break if not checkuser: self.queue.put(slskmessages.MessageUser(i.username, _("[Automatic Message] ")+reason) ) return else: self.queue.put(slskmessages.MessageUser(i.username, _("Please try browsing me if you get 'File not shared' errors. This is an automatic message, you don't have to reply to it.") ) ) if checkuser == 1: shares = self.config.sections["transfers"]["sharedfiles"] elif checkuser == 2: shares = self.config.sections["transfers"]["bsharedfiles"] else: response = self.queue.put(slskmessages.TransferResponse(msg.conn.conn,0,reason = reason, req=0) ) shares = {} if checkuser: if shares.has_key(msg.dir.replace("\\",os.sep)[:-1]): self.queue.put(slskmessages.FolderContentsResponse(msg.conn.conn, msg.dir, shares[msg.dir.replace("\\",os.sep)[:-1]])) elif shares.has_key(msg.dir.replace("\\",os.sep)): self.queue.put(slskmessages.FolderContentsResponse(msg.conn.conn, msg.dir, shares[msg.dir.replace("\\",os.sep)])) else: if checkuser == 2: shares = self.config.sections["transfers"]["sharedfiles"] if shares.has_key(msg.dir.replace("\\",os.sep)[:-1]): self.queue.put(slskmessages.FolderContentsResponse(msg.conn.conn, msg.dir, shares[msg.dir.replace("\\",os.sep)[:-1]])) elif shares.has_key(msg.dir.replace("\\",os.sep)): self.queue.put(slskmessages.FolderContentsResponse(msg.conn.conn, msg.dir, shares[msg.dir.replace("\\",os.sep)])) self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def RoomList(self,msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.SetRoomList(msg) self.setStatus("") else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def GlobalUserList(self,msg): if self.globallist is not None: self.globallist.setGlobalUsersList(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def PeerTransfer(self,msg): if self.userinfo is not None and msg.msg is slskmessages.UserInfoReply: self.userinfo.UpdateGauge(msg) if self.userbrowse is not None and msg.msg is slskmessages.SharedFileList: self.userbrowse.UpdateGauge(msg) def TunneledMessage(self, msg): if msg.code in self.protothread.peerclasses.keys(): peermsg = self.protothread.peerclasses[msg.code](None) peermsg.parseNetworkMessage(msg.msg) peermsg.tunneleduser = msg.user peermsg.tunneledreq = msg.req peermsg.tunneledaddr = msg.addr self.callback([peermsg]) else: self.logMessage(_("Unknown tunneled message: %s") %(vars(msg))) def ExactFileSearch(self,msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def FileSearchRequest(self, msg): for i in self.peerconns: if i.conn == msg.conn.conn: user = i.username self.processSearchRequest(msg.searchterm, user, msg.searchid, 1) def SearchRequest(self, msg): self.processSearchRequest(msg.searchterm, msg.user, msg.searchid, 0) def DistribSearch(self,msg): self.processSearchRequest(msg.searchterm, msg.user, msg.searchid, 0) def processSearchRequest(self, searchterm, user, searchid, direct = 0): if searchterm is None: return# self.searchfile.write(searchterm+"\n")# self.searchfile.flush() checkuser, reason = self.CheckUser(user, None, None) if not checkuser: return if reason == "geoip": geoip = 1 else: geoip = 0 maxresults = self.config.sections["searches"]["maxresults"] if checkuser == 2: wordindex = self.config.sections["transfers"]["bwordindex"] fileindex = self.config.sections["transfers"]["bfileindex"] else: wordindex = self.config.sections["transfers"]["wordindex"] fileindex = self.config.sections["transfers"]["fileindex"] fifoqueue = self.config.sections["transfers"]["fifoqueue"] if maxresults == 0: return terms = searchterm.translate(self.translatepunctuation).lower().split() list = [wordindex[i][:] for i in terms if wordindex.has_key(i)] if len(list) != len(terms) or len(list) == 0: return min = list[0] for i in list[1:]: if len(i) < len(min): min = i list.remove(min) for i in min[:]: for j in list: if i not in j: min.remove(i) break results = min[:maxresults] if len(results) > 0 and self.transfers is not None: queuesizes = self.transfers.getUploadQueueSizes() slotsavail = int(not self.transfers.bandwidthLimitReached()) if len(results) > 0: message = slskmessages.FileSearchResult(None, user, geoip, searchid,results,fileindex,slotsavail, self.speed, queuesizes, fifoqueue) self.ProcessRequestToPeer(user, message) if direct: self.logMessage(_("User %s is directly searching for %s, returning %i results") %(user,self.decode(searchterm),len(results)),1) else: self.logMessage(_("User %s is searching for %s, returning %i results") %(user,self.decode(searchterm),len(results)),1) def NetInfo(self, msg): self.distribcache.update(msg.list) if len(self.distribcache) > 0: self.queue.put(slskmessages.HaveNoParent(0)) if not self.GetDistribConn(): user = self.distribcache.keys()[0] addr = self.distribcache[user] self.ProcessRequestToPeer(user, slskmessages.DistribConn(),None,addr) self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def DistribAlive(self, msg): self.logMessage("%s %s" %(msg.__class__, vars(msg)),1) def GetDistribConn(self): for i in self.peerconns: if i.init.type == 'D': return i return None def DistribConnClosed(self, conn): del self.distribcache[conn.username] if len(self.distribcache) > 0: user = self.distribcache.keys()[0] addr = self.distribcache[user] self.ProcessRequestToPeer(user, slskmessages.DistribConn(),None,addr) else: self.queue.put(slskmessages.HaveNoParent(1)) def GlobalRecommendations(self, msg): self.frame.GlobalRecommendations(msg) def Recommendations(self, msg): self.frame.Recommendations(msg) def ItemRecommendations(self, msg): self.frame.ItemRecommendations(msg) def SimilarUsers(self, msg): self.frame.SimilarUsers(msg) def ItemSimilarUsers(self, msg): self.frame.ItemSimilarUsers(msg) def RoomTickerState(self, msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.TickerSet(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def RoomTickerAdd(self, msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.TickerAdd(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def RoomTickerRemove(self, msg): if self.chatrooms is not None: self.chatrooms.roomsctrl.TickerRemove(msg) else: self.logMessage("%s %s" %(msg.__class__, vars(msg))) def logTransfer(self, message, toUI = 0): if self.config.sections["logging"]["transfers"]: fn = os.path.join(self.config.sections["logging"]["logsdir"], "transfers.log") try: f = open(fn, "a") f.write(time.strftime("%c")) f.write(" %s\n" % message) f.close() except IOError, error: self.logMessage(_("Couldn't write to transfer log: %s") % error) if toUI: self.logMessage(message)class UserAddr: def __init__(self, addr = None, behindfw = None, status = None): self.addr = addr self.behindfw = behindfw self.status = status