move all the functions in the global namespace to the gopherHandler() class
This commit is contained in:
parent
a2ac3369e4
commit
3c159a5729
192
esgd.py
192
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:
|
||||
|
|
Loading…
Reference in New Issue