def handleChatInvite(server, user, packet): ref = packet.getNumber(DATA_CHATID, 0) uid = packet.getNumber(DATA_UID, 0) chat = server.getChat(ref) who = server.getUser(uid) if not who: raise HLException("Invalid user.") if not chat: raise HLException("Invalid chat.") if uid == user.uid: # Ignore self invitations. return if chat.hasInvite(who): # Ignore all invitations after the first. return if not chat.hasUser(user): raise HLException("You are not in this chat.") if chat.hasUser(who): # The specified user is already in the chat. return chat.addInvite(who) # Send the invitation to the specified user. invite = HLPacket(HTLS_HDR_CHAT_INVITE) invite.addInt32(DATA_CHATID, chat.id) invite.addNumber(DATA_UID, user.uid) invite.addString(DATA_NICK, user.nick) server.sendPacket(invite, who)
def handleChatJoin(server, user, packet): ref = packet.getNumber(DATA_CHATID, 0) chat = server.getChat(ref) if not chat: raise HLException("Invalid chat.") if not chat.hasInvite(user): raise HLException("You were not invited to this chat.") # Send a join packet to everyone in the chat. join = HLPacket(HTLS_HDR_CHAT_USER_CHANGE) join.addInt32(DATA_CHATID, chat.id) join.addNumber(DATA_UID, user.uid) join.addString(DATA_NICK, user.nick) join.addNumber(DATA_ICON, user.icon) join.addNumber(DATA_STATUS, user.status) if user.color >= 0: join.addInt32(DATA_COLOR, user.color) for u in chat.users: server.sendPacket(join, u) # Add the joiner to the chat. chat.addUser(user) chat.removeInvite(user) # Send the userlist back to the joiner. list = packet.response() for u in chat.users: list.addBinary(DATA_USER, u.flatten()) list.addString(DATA_SUBJECT, chat.subject) server.sendPacket(list, user)
def handleFileUpload(server, user, packet): dir = parseDir(packet.getBinary(DATA_DIR)) name = packet.getString(DATA_FILENAME, "") size = packet.getNumber(DATA_XFERSIZE, 0) # options = packet.getNumber(DATA_XFEROPTIONS, 0) path = buildPath(user.account.fileRoot, dir, name) if os.path.exists(path): raise HLException("File already exists.") if (not user.hasPriv(PRIV_UPLOAD_ANYWHERE)) and ( path.upper().find("UPLOAD") < 0 or path.upper().find("DROP BOX") < 0): raise HLException( "You must upload to an upload directory or drop box.") # Make sure we have enough disk space to accept the file. upDir = buildPath(user.account.fileRoot, dir) info = os.statvfs(upDir) free = info.f_bavail * info.f_frsize if size >= free: raise HLException("Insufficient disk space.") file = HLFile(path) xfer = server.fileserver.addUpload(user, file) xfer.total = size reply = packet.response() reply.addNumber(DATA_XFERID, xfer.id) if file.exists(): reply.addBinary(DATA_RESUME, file.resumeData().flatten()) server.sendPacket(reply, user)
def handleLogin(server, user, packet): login = HLDecode(packet.getBinary(DATA_LOGIN, HLEncode("guest"))) password = HLDecode(packet.getBinary(DATA_PASSWORD, b"")) # Check for temporary and permanent bans. reason = server.checkForBan(user.ip) if reason: raise HLException("You are banned: %s" % reason, True) # Load and configure the account information. user.account = server.database.loadAccount(login) if not user.account: raise HLException("Login is incorrect.", True) if user.account.password != hashlib.md5(password.encode('utf-8')).hexdigest(): raise HLException("Password is incorrect.", True) # Handle the nickname/icon/color stuff, broadcast the join packet. handleUserChange(server, user, packet) user.valid = True user.account.lastLogin = datetime.now() dispatcher.send(signal=user_login, sender=server, server=server, user=user) info = packet.response() info.addString(DATA_SERVERNAME, conf.SERVER_NAME) info.addNumber(DATA_OPTION, CAPABILITY_NEWS) info.addNumber(DATA_UID, user.uid) server.sendPacket(info, user) logging.info("[login] successful login for %s", user)
def handleUserInfo(server, user, packet): uid = packet.getNumber(DATA_UID, 0) who = server.getUser(uid) if not who: raise HLException("Invalid user.") fmt = "nickname: %s\r uid: %s\r login: %s\rrealname: %s\r address: %s\r idle: %s\r" idle = formatElapsedTime(time.time() - who.lastPacketTime) info = fmt % (who.nick, who.uid, who.account.login, who.account.name, who.ip, idle) info += "--------------------------------\r" num = 0 for xfer in server.fileserver.transfers: if xfer.owner == uid: info += str(xfer) + "\r" num += 1 if num < 1: info += "No file transfers.\r" info += "--------------------------------\r" reply = packet.response() reply.addNumber(DATA_UID, who.uid) reply.addString(DATA_NICK, who.nick) reply.addString(DATA_STRING, info) server.sendPacket(reply, user)
def handleAccountDelete(server, user, packet): login = HLDecode(packet.getBinary(DATA_LOGIN, b"")) acct = server.database.loadAccount(login) if not acct: raise HLException("Invalid account.") server.database.deleteAccount(acct) server.sendPacket(packet.response(), user) logging.info("[account] %s deleted by %s", login, user)
def handleFolderCreate(server, user, packet): dir = parseDir(packet.getBinary(DATA_DIR)) name = packet.getString(DATA_FILENAME, "") path = buildPath(user.account.fileRoot, dir, name) if os.path.exists(path): raise HLException("Specified directory already exists.") os.mkdir(path, conf.DIR_UMASK) server.sendPacket(packet.response(), user)
def handleFileMove(server, user, packet): oldDir = parseDir(packet.getBinary(DATA_DIR)) newDir = parseDir(packet.getBinary(DATA_NEWDIR)) name = packet.getString(DATA_FILENAME, "") oldPath = buildPath(user.account.fileRoot, oldDir, name) newPath = buildPath(user.account.fileRoot, newDir, name) if not os.path.exists(oldPath): raise HLException("Invalid file or directory.") if os.path.exists(newPath): raise HLException("The specified file already exists in the new location.") file = HLFile(oldPath) file.rename(newPath) server.sendPacket(packet.response(), user)
def handleIconGet(server, user, packet): uid = packet.getNumber(DATA_UID, 0) info = server.getUser(uid) if not info: raise HLException("Invalid user.") icon = packet.response() icon.addNumber(DATA_UID, info.uid) icon.addBinary(DATA_GIFICON, info.gif) server.sendPacket(icon, user)
def handleFileList(server, user, packet): dir = parseDir(packet.getBinary(DATA_DIR)) path = buildPath(user.account.fileRoot, dir) if not os.path.exists(path): raise HLException("The specified directory does not exist.") if not os.path.isdir(path): raise HLException("The specified path is not a directory.") if (not user.hasPriv(PRIV_VIEW_DROPBOXES)) and (path.upper().find("DROP BOX") >= 0): raise HLException("You are not allowed to view drop boxes.") reply = packet.response() files = os.listdir(path) files.sort() for fname in files: if conf.SHOW_DOTFILES or (fname[0] != '.'): # Only list files starting with . if SHOW_DOTFILES is True. file = HLFile(os.path.join(path, fname)) reply.addBinary(DATA_FILE, file.flatten()) server.sendPacket(reply, user)
def certifyIcon(data): if len(data) > conf.MAX_GIF_SIZE: raise HLException("GIF icon too large.") return False # try to make sure the icon data is a 232x18 pixel GIF try: import Image import StringIO im = Image.open(StringIO.StringIO(data)) if im.format != 'GIF': raise HLException("Icon must be in GIF format.") if im.size != (232, 18): raise HLException("GIF icon must be 232x18 pixels.") except ImportError: pass except IOError: return False return True
def handleFileSetInfo(server, user, packet): dir = parseDir(packet.getBinary(DATA_DIR)) oldName = packet.getString(DATA_FILENAME, "") newName = packet.getString(DATA_NEWFILE, oldName) comment = packet.getString(DATA_COMMENT, "") if (oldName != newName) and (not user.hasPriv(PRIV_RENAME_FILES)): raise HLException("You cannot rename files.") oldPath = buildPath(user.account.fileRoot, dir, oldName) newPath = buildPath(user.account.fileRoot, dir, newName) if not os.path.exists(oldPath): raise HLException("Invalid file or directory.") if (oldPath != newPath) and os.path.exists(newPath): raise HLException("The specified file already exists.") file = HLFile(oldPath) file.rename(newPath) file.setComment(comment) server.sendPacket(packet.response(), user)
def handleAccountRead(server, user, packet): login = packet.getString(DATA_LOGIN, "") acct = server.database.loadAccount(login) if not acct: raise HLException("Error loading account.") reply = packet.response() reply.addBinary(DATA_LOGIN, HLEncode(acct.login)) reply.addBinary(DATA_PASSWORD, HLEncode(acct.password)) reply.addString(DATA_NICK, acct.name) reply.addInt64(DATA_PRIVS, acct.privs) server.sendPacket(reply, user)
def handleUserInfoUnformatted(server, user, packet): uid = packet.getNumber(DATA_UID, 0) who = server.getUser(uid) if not who: raise HLException("Invalid user.") reply = packet.response() reply.addNumber(DATA_UID, who.uid) reply.addString(DATA_NICK, who.nick) reply.addString(DATA_LOGIN, who.account.login) reply.addString(DATA_STRING, who.account.name) reply.addString(DATA_IP, who.ip) server.sendPacket(reply, user)
def handleFileDelete(server, user, packet): dir = parseDir(packet.getBinary(DATA_DIR)) name = packet.getString(DATA_FILENAME, "") path = buildPath(user.account.fileRoot, dir, name) if not os.path.exists(path): raise HLException("Specified file or directory does not exist.") if os.path.isdir(path): if not user.hasPriv(PRIV_DELETE_FOLDERS): raise HLException("You are not allowed to delete folders.") # First, recursively delete everything inside the directory. for (root, dirs, files) in os.walk(path, topdown=False): for name in files: os.unlink(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) # Then delete the directory itself. os.rmdir(path) else: if not user.hasPriv(PRIV_DELETE_FILES): raise HLException("You are not allowed to delete files.") file = HLFile(path) file.delete() server.sendPacket(packet.response(), user)
def handleUserKick(server, user, packet): uid = packet.getNumber(DATA_UID, 0) ban = packet.getNumber(DATA_BAN, 0) who = server.getUser(uid) if not who: raise HLException("Invalid user.") me_login = user.account.login.lower() you_login = who.account.login.lower() if not user.hasPriv(PRIV_KICK_USERS): # users without kick privs can disconnect themselves or their ghosts as long as they are not guests if (me_login != you_login) or (me_login == "guest"): raise HLException("You do not have permission to disconnect users.") if (me_login != you_login) and who.hasPriv(PRIV_KICK_PROTECT): raise HLException("%s cannot be disconnected." % who.nick) if ban: server.addTempBan(who.ip, "Temporary ban.") server.disconnectUser(who) server.sendPacket(packet.response(), user) logging.info("[kick] %s disconnected by %s", who, user)
def handleAccountCreate(server, user, packet): login = HLDecode(packet.getBinary(DATA_LOGIN, b"")) passwd = HLDecode(packet.getBinary(DATA_PASSWORD, b"")) name = packet.getString(DATA_NICK, "") privs = packet.getNumber(DATA_PRIVS, 0) if server.database.loadAccount(login): raise HLException("Login already exists.") acct = HLAccount(login) acct.password = hashlib.md5(passwd.encode('utf-8')).hexdigest() acct.name = name acct.privs = privs server.database.saveAccount(acct) server.sendPacket(packet.response(), user) logging.info("[account] %s created by %s", login, user)
def handleAccountModify(server, user, packet): login = HLDecode(packet.getBinary(DATA_LOGIN, b"")) pw_data = packet.getBinary(DATA_PASSWORD, b"") name = packet.getString(DATA_NICK, "") privs = packet.getNumber(DATA_PRIVS, 0) acct = server.database.loadAccount(login) if not acct: raise HLException("Invalid account.") acct.name = name acct.privs = privs if pw_data != "\x00": acct.password = hashlib.md5( HLDecode(pw_data).encode('utf-8')).hexdigest() server.database.saveAccount(acct) server.sendPacket(packet.response(), user) # server.updateAccounts( acct ) logging.info("[account] %s modified by %s", login, user)
def handleFileDownload(server, user, packet): dir = parseDir(packet.getBinary(DATA_DIR)) name = packet.getString(DATA_FILENAME, "") resume = HLResumeData(packet.getBinary(DATA_RESUME)) # options = packet.getNumber(DATA_XFEROPTIONS, 0) path = buildPath(user.account.fileRoot, dir, name) if not os.path.exists(path): raise HLException("Specified file does not exist.") file = HLFile(path) xfer = server.fileserver.addDownload(user, file, resume) dataSize = file.size() - resume.totalOffset() reply = packet.response() reply.addNumber(DATA_XFERSIZE, xfer.total) reply.addNumber(DATA_FILESIZE, dataSize) reply.addNumber(DATA_XFERID, xfer.id) server.sendPacket(reply, user)
def handleFileGetInfo(server, user, packet): dir = parseDir(packet.getBinary(DATA_DIR)) name = packet.getString(DATA_FILENAME, b"") path = buildPath(user.account.fileRoot, dir, name) if not os.path.exists(path): raise HLException("No such file or directory.") file = HLFile(path) d = datetime.fromtimestamp(os.path.getmtime(path)) info = packet.response() info.addString(DATA_FILENAME, name) info.addNumber(DATA_FILESIZE, file.size()) info.addNumber(DATA_FILETYPE, file.getType()) info.addNumber(DATA_FILECREATOR, file.getCreator()) info.addBinary(DATA_DATECREATED, HLEncodeDate(d)) info.addBinary(DATA_DATEMODIFIED, HLEncodeDate(d)) info.addString(DATA_COMMENT, file.getComment()) server.sendPacket(info, user)
def _checkperm(signal, sender, *args, **kwargs): user = kwargs.get('user', None) if user and not user.hasPriv(perm): raise HLException("You do not have permission to %s." % action) return handler_func(*args, **kwargs)