From 3c159a5729b4b2437c28ee398752d44090d0c387 Mon Sep 17 00:00:00 2001 From: randomuser Date: Tue, 20 Jul 2021 02:35:29 -0500 Subject: [PATCH] move all the functions in the global namespace to the gopherHandler() class --- esgd.py | 192 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/esgd.py b/esgd.py index fa194a6..1e99302 100644 --- a/esgd.py +++ b/esgd.py @@ -3,7 +3,7 @@ import subprocess import os host = "localhost" -port = 71 +port = 77 class GopherError(BaseException): pass class RequestError(GopherError): pass @@ -51,108 +51,108 @@ class GopherLine: self.port ) -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): - if ".." in request: raise RequestError - 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 invalid(context): - context.request.sendall(b"3error: selector contains '..'!\r\n.\r\n") - -def fileToFileArray(file): - fd = open(file, "r") - ret = [i.rstrip() for i in fd.readlines()] - fd.close() - return ret - -def sendFileArray(arr, context): - [context.request.sendall( - (i.rstrip() + "\r\n").encode("utf-8") - ) for i in arr] - context.request.sendall(b".\r\n") - -def cgi(file, query, context): - env = {} - env["QUERY_STRING"] = query - env["SCRIPT_NAME"] = "/" + file - env["REMOTE_ADDR"] = context.client_address[0] - - proc = subprocess.Popen( - [os.getcwd() + "/" + file], - stdout = subprocess.PIPE, - env = env - ) - - try: out, err = proc.communicate(timeout=10) - except TimeoutExpired: - proc.kill() - out, err = proc.communicate() - - return out.decode("utf-8").replace("\r", "").split("\n") - -def gopherRenderer(fileArray): - gopherlines = [] - for i in fileArray: - gopherlines.append(GopherLine(i)) - returned = [] - for i in gopherlines: - returned.append(i.render()) - return returned - -def serveFile(file, query, gph, context): - if fileCGI(file): fa = cgi(file, query, context) - elif fileSendable(file): fa = fileToFileArray(file) - else: - notFound(context) - return - if gph: fa = gopherRenderer(fa) - sendFileArray(fa, context) - class gopherHandler(socketserver.BaseRequestHandler): - def handle(self): - decoded = recieveRequest(self) + def recieveRequest(self): + data = b"" + while data[-2:] != b"\r\n": + data += self.request.recv(1) + decoded = data[:-2].decode("utf-8") + return decoded + + def requestParser(self, request): + if ".." in request: raise RequestError try: - parsed = requestParser(decoded) + 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(self, 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(self, file): return os.access(file, os.F_OK|os.R_OK) + + def fileCGI(self, file): + return os.access(file, os.F_OK|os.R_OK|os.X_OK) + + def notFound(self): + self.request.sendall(b"3error: file not found!\r\n.\r\n") + + def invalid(self): + self.request.sendall(b"3error: selector contains '..'!\r\n.\r\n") + + def fileToFileArray(self, file): + fd = open(file, "r") + ret = [i.rstrip() for i in fd.readlines()] + fd.close() + return ret + + def sendFileArray(self, arr): + [self.request.sendall( + (i.rstrip() + "\r\n").encode("utf-8") + ) for i in arr] + self.request.sendall(b".\r\n") + + def cgi(self, file, query): + env = {} + env["QUERY_STRING"] = query + env["SCRIPT_NAME"] = "/" + file + env["REMOTE_ADDR"] = self.client_address[0] + + proc = subprocess.Popen( + [os.getcwd() + "/" + file], + stdout = subprocess.PIPE, + env = env + ) + + try: out, err = proc.communicate(timeout=10) + except TimeoutExpired: + proc.kill() + out, err = proc.communicate() + + return out.decode("utf-8").replace("\r", "").split("\n") + + def gopherRenderer(self, fileArray): + gopherlines = [] + for i in fileArray: + gopherlines.append(GopherLine(i)) + returned = [] + for i in gopherlines: + returned.append(i.render()) + return returned + + def serveFile(self, file, query, gph): + if self.fileCGI(file): fa = self.cgi(file, query) + elif self.fileSendable(file): fa = self.fileToFileArray(file) + else: + self.notFound() + return + if gph: fa = self.gopherRenderer(fa) + self.sendFileArray(fa) + + def handle(self): + decoded = self.recieveRequest() + try: + parsed = self.requestParser(decoded) except RequestError: - invalid(self) + self.invalid() return - try: file = returnRelative(parsed[0]) + try: file = self.returnRelative(parsed[0]) except RequestError: - notFound(self) + self.notFound() return - serveFile(file[0], parsed[1], file[1], self) + self.serveFile(file[0], parsed[1], file[1]) if __name__ == "__main__": with socketserver.TCPServer((host, port), gopherHandler) as server: