diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..17e15f2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/readme.txt b/readme.txt index 21267c8..c010441 100644 --- a/readme.txt +++ b/readme.txt @@ -1,3 +1,3 @@ -/technically/ standards-compliant http 1.1 server +soon to be a /technically/ standards-compliant http 1.1 server spec'd to RFC 2616 \ No newline at end of file diff --git a/response.py b/response.py index f48e113..4bed08f 100644 --- a/response.py +++ b/response.py @@ -1,3 +1,4 @@ +from pathlib import Path class status: all_valid = { # https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html 200: "OK",# add the rest l8r @@ -11,6 +12,26 @@ class status: @staticmethod def add_status(status_line, code): status_line.append(str(code)+" "+status.all_valid[code]) + @staticmethod + def parse(raw): + return int(raw.split[" "][0]) +class query: + def __init__(self): + self.type = None #dol8r + self.path = "/" + self.vars = {} + @staticmethod + def get(status_line): + q = query() + q.type = status_line[0] + q.path = status_line[1].split("?")[0] + if len(status_line[1].split("?")) < 2: return q + for v in status_line[1].split("?")[1].split("&"): + var_arr = v.split("=") + if type(var_arr) == str or v == "/": + continue + q.vars[var_arr[0]] = var_arr[1] + return q class headers: def __init__(self): self.headers_dict = {} @@ -28,17 +49,32 @@ class request: def text(self): return " ".join(self.status_line)+"\r\n"+self.headers_obj.as_str()+"\r\n"+self.body @staticmethod - def build_response(query): + def build_response(req): r = request() + q = query.get(req.status_line.split(" ")) r.status_line.append("HTTP/1.1") + s_code = 200 + + f = None + try: + query_path_obj = Path("."+q.path).resolve() + jail = Path(".").resolve() + if not(jail in query_path_obj.parents): + r.body = "" + s_code = 403 + else: + f = open("."+q.path, "r+") + r.body = f.read() + f.close() + + except: + r.body = "" + s_code = 404 + # check if query is heckin cute % valid/returnable # always 200 for static testing - status.add_status(r.status_line, 200) - - f = open(query, "r") - r.body = f.read() - f.close() + status.add_status(r.status_line, s_code) # manual for now r.headers_obj.headers_dict["Server"] = "shttpile" @@ -47,3 +83,19 @@ class request: r.headers_obj.headers_dict["X-Clacks-Overhead"] = "GNU Terry Pratchett, Aaron Swartz, Norm Macdonald" return r + @staticmethod + def parse(raw): + r = request() + raw_lines = raw.split("\n") + + r.status_line = raw_lines[0] + + for line in raw_lines[1:]: + if line == "\r": + break + header_line = line.split(": ") + r.headers_obj.headers_dict[header_line[0]] = header_line[1] + + r.body = raw.split("\r\n\r\n")[1] + + return r \ No newline at end of file diff --git a/server.py b/server.py index 1daf550..527a494 100644 --- a/server.py +++ b/server.py @@ -1,13 +1,16 @@ import socket import response +import sys +import os s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(("0.0.0.0", 1337)) s.listen() while True: c, c_add = s.accept() print(c_add) - print(c.recv(1024).decode("ascii")) - r = response.request.build_response("body.html") + raw_req = c.recv(2048).decode("ascii") + print(raw_req) + r = response.request.build_response(response.request.parse(raw_req)) c.sendall(r.text().encode("ascii")) c.close() s.close()