#!/usr/bin/env python3 # See https://docs.python.org/3.2/library/socket.html # for a decscription of python socket and its parameters import socket import os import stat from threading import Thread from argparse import ArgumentParser from urllib.parse import unquote BUFSIZE = 4096 CRLF = '\r\n' NOT_FOUND = 'HTTP/1.1 404 NOT FOUND{}Connection: close{}{}'.format(CRLF, CRLF, CRLF) FORBIDDEN = 'HTTP/1.1 403 FORBIDDEN{}Connection: close{}{}'.format(CRLF, CRLF, CRLF) METHOD_NOT_ALLOWED = 'HTTP/1.1 405 METHOD NOT ALLOWED{}Allow: GET, HEAD, POST {}Connection: close{}{}'.format(CRLF, CRLF, CRLF, CRLF) OK = 'HTTP/1.1 200 OK{}Connection: close{}'.format(CRLF, CRLF) # head request only # check file permissions -is file world readable? def check_perms(resource): stmode = os.stat(resource).st_mode return(getattr(stat, 'S_IROTH') & stmode) > 0 # Puts together the HTML for the POST form return def POST(form): form = unquote(form) form = form.replace("+", " ").split("&") contents = "" if len(form) == 0: return contents for x in form: x = x.split("=") contents = contents + "\n" + x[0] + "\n" + x[1] + "\n\n" table = "" + contents + "
" ret = "\n\n\n\n\nTest\n\n\n

\nFollowing Form Data Submitted Successfully:


\n{}\n\n".format(table) return ret #For Content Type def getType(type): if type == "html": return "text/html" elif type == "css": return "text/css" elif type == "js": return "text/javascript" elif type == "mp3": return "audio/mpeg" elif type == "jpg" or type == "jpeg": return "image/jpeg" elif type == "png": return "image/png" else: raise TypeError def getContents(type, file, contents): if type =="POST": return b"".join( [OK.encode(), "{}".format(CRLF).encode(), POST(contents).encode(), "{}{}".format(CRLF, CRLF).encode()]) returnValue = "".encode() try: if file.split("?")[0] == "redirect": contents = file.split("?")[1].split("=")[-1] return "HTTP/1.1 307 TEMPORARY REDIRECT{}Connection: close{}Location:{}{}{}".format(CRLF, CRLF, "https://youtube.com/results?search_query=" + contents, CRLF, CRLF).encode() if not check_perms(file): raise PermissionError content = open(file, 'rb') except FileNotFoundError: returnValue = NOT_FOUND.encode() with open("404.html", "rb") as fof: returnValue = b"".join( [returnValue, fof.read(), "{}{}".format(CRLF, CRLF).encode()]) except PermissionError: returnValue = FORBIDDEN.encode() with open("403.html", "rb") as forb: returnValue = b"".join( [returnValue, forb.read(), "{}{}".format(CRLF, CRLF).encode()]) else: returnValue = OK.encode() if type == "HEAD": returnValue = b"".join( [returnValue, "{}{}".format(CRLF, CRLF).encode()]) elif type == "GET": ext = getType(file.split(".")[1]) returnValue = b"".join( [returnValue, "Content Type: {}".format(ext).encode(), "{}{}".format(CRLF, CRLF).encode()]) returnValue = b"".join( [returnValue, content.read(), "{}{}".format(CRLF, CRLF).encode()]) else: returnValue= METHOD_NOT_ALLOWED.encode() content.close() return returnValue def client_recv(client_sock, client_addr): print('talking to {}'.format(client_addr)) data = client_sock.recv(BUFSIZE) data = data.decode('utf-8').strip("\r") print(data) data = data.split("\n") request = data[0].split(" ") if len(request) > 1: want = getContents(request[0], request[1][1:], data[-1]) client_sock.send(want) client_sock.shutdown(1) client_sock.close() print('connection closed.') class EchoServer: def __init__(self, host, port): print("Server") print('listening on port {}'.format(port)) self.host = host self.port = port self.setup_socket() self.accept() self.sock.shutdown() self.sock.close() def setup_socket(self): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.bind((self.host, self.port)) self.sock.listen(128) def accept(self): while True: (client, address) = self.sock.accept() th = Thread(target=client_recv, args=(client, address)) th.start() def parse_args(): parser = ArgumentParser() parser.add_argument('--host', type=str, default='localhost', help='specify a host to operate on (default: localhost)') parser.add_argument('-p', '--port', type=int, default=9001, help='specify a port to operate on (default: 9001)') args = parser.parse_args() return (args.host, args.port) if __name__ == '__main__': (host, port) = parse_args() EchoServer(host, port)