import SocketServer class FTPMessage: def __init__(self,cmd,parameter): self.cmd = cmd self.parameter = parameter def generate(self): return "%s %s\r\n" % (self.cmd.upper(), self.parameter) def __str__(self): return self.generate() @staticmethod def parse(line): pos = line.find(" ") if pos == -1: cmd = line param = None else: cmd = line[:pos] param = line[pos+1:] return FTPMessage(cmd.upper(),param) class GeneralState: @staticmethod def handle(self, message): if message.cmd == "QUIT": self.debug("Client wants to quit") self.send(FTPMessage("221","Goodbye.")) self.handler.running = False else: self.debug("Unknown command %s" % message.cmd) self.send(FTPMessage("500", "%s not understood" % message.cmd )) class UserState: @staticmethod def handle(self, message): if message.cmd == "USER": self.debug("Initiating login for user %s" % message.parameter) self.send(FTPMessage("331","Password required for %s" % message.parameter)) self.state = PassState else: GeneralState.handle(self, message) class PassState: @staticmethod def handle(self, message): if message.cmd == "PASS": self.debug("Denying access with password %s" % message.parameter) self.send(FTPMessage("530","Login incorrect.")) self.state = UserState else: GeneralState.handle(self, message) class FTPMessageHandler: def __init__(self, handler): self.state = UserState self.handler = handler def send(self,data): return self.handler.request.send( str(data) ) def debug(self,text): self.handler.debug(text) def handle(self, message): self.state.handle(self, message) class LineReader: def __init__(self): self.buf = "" def push(self,data): self.buf += data def get_lines(self): pos = self.buf.find("\n") while pos != -1: line = self.buf[:pos] if line[-1] == "\r": line = line[:-2] yield line self.buf = self.buf[pos+1:] pos = self.buf.find("\n") class FTPHandler(SocketServer.BaseRequestHandler): def debug(self, text): print ("[%s] " % self.client_address[0]) + text def handle(self): self.messagehandler = FTPMessageHandler(self) self.debug("Client connected"); self.request.send(FTPMessage("220","FTP Server ready").generate()) linereader = LineReader() self.running = True while self.running: data = self.request.recv(1024) if len(data) == 0: break linereader.push(data) for line in linereader.get_lines(): message = FTPMessage.parse(line) self.messagehandler.handle(message) self.debug("Client disconnected") server = SocketServer.ThreadingTCPServer(("",1234),FTPHandler) server.serve_forever()