diff --git a/esgd.py b/esgd.py new file mode 100644 index 0000000..2e688c6 --- /dev/null +++ b/esgd.py @@ -0,0 +1,66 @@ +import socketserver +import os + +class GopherError(BaseException): pass +class RequestError(GopherError): pass + +def recieveRequest(context): + data = b'' + while data[-2:] != b'\r\n': + data += context.request.recv(1) + decoded = data[:-2].decode('utf-8') + return decoded + +def requestParser(request): + try: + if request[0] == '/': request = request[1:] + except IndexError: pass + request = request.replace('?', '\t').split('\t') + try: return (request[0], request[1]) + except IndexError: return (request[0], "") + +def returnRelative(file): + gph = False + if file == "": + ret = "gophermap" + gph = True + elif os.path.isdir(file): + ret = file + "/gophermap" + gph = True + elif os.path.isfile(file): ret = file + else: raise RequestError('unreachable state') + return (ret, gph) + +def fileSendable(file): return os.access(file, os.F_OK|os.R_OK) + +def fileCGI(file): + return os.access(file, os.F_OK|os.R_OK|os.X_OK) + +def notFound(context): + context.request.sendall(b"3error: file not found!\r\n.\r\n") + +def sendFile(file, context): + with open(file, "r") as fd: + [context.request.sendall( + (i.rstrip() + "\r\n").encode("utf-8") + ) for i in fd.readlines()] + context.request.sendall(b".\r\n") + +class gopherHandler(socketserver.BaseRequestHandler): + def handle(self): + decoded = recieveRequest(self) + parsed = requestParser(decoded) + + try: file = returnRelative(parsed[0]) + except RequestError: + notFound(self) + return + + if fileSendable(file[0]): sendFile(file[0], self) + else: notFound(self) + +if __name__ == "__main__": + HOST, PORT = "localhost", 85 + + with socketserver.TCPServer((HOST, PORT), gopherHandler) as server: + server.serve_forever()