esgd/esgd.py

67 lines
1.8 KiB
Python

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()