# Copyright (C) 2021 jahoti # Licensing information is collated in the `copyright` file """ A modular "virtual network" proxy, wrapping the classes in proxy_core.py """ from proxy_core import * from urllib.parse import parse_qs internet = {} # Add info here later mime_types = { "7z": "application/x-7z-compressed", "oga": "audio/ogg", "abw": "application/x-abiword", "ogv": "video/ogg", "arc": "application/x-freearc", "ogx": "application/ogg", "bin": "application/octet-stream", "opus": "audio/opus", "bz": "application/x-bzip", "otf": "font/otf", "bz2": "application/x-bzip2", "pdf": "application/pdf", "css": "text/css", "png": "image/png", "csv": "text/csv", "sh": "application/x-sh", "gif": "image/gif", "svg": "image/svg+xml", "gz": "application/gzip", "tar": "application/x-tar", "htm": "text/html", "ts": "video/mp2t", "html": "text/html", "ttf": "font/ttf", "ico": "image/vnd.microsoft.icon", "txt": "text/plain", "js": "text/javascript", "wav": "audio/wav", "jpeg": "image/jpeg", "weba": "audio/webm", "jpg": "image/jpeg", "webm": "video/webm", "json": "application/json", "woff": "font/woff", "mjs": "text/javascript", "woff2": "font/woff2", "mp3": "audio/mpeg", "xhtml": "application/xhtml+xml", "mp4": "video/mp4", "zip": "application/zip", "mpeg": "video/mpeg", "odp": "application/vnd.oasis.opendocument.presentation", "ods": "application/vnd.oasis.opendocument.spreadsheet", "odt": "application/vnd.oasis.opendocument.text", "xml": "application/xml" # text/xml if readable from casual users } class RequestHijacker(ProxyRequestHandler): certdir = global_certdir def handle_request(self, req_body): path_components = self.path.split('?', maxsplit=1) path = path_components[0] try: # Response format: (status_code, headers (dict. of strings), # body as bytes or filename containing body as string) if path in internet: info = internet[path] if type(info) == tuple: status_code, headers, body_file = info if type(body_file) == str: if 'Content-Type' not in headers and '.' in body_file: ext = body_file.rsplit('.', maxsplit=1)[-1] if ext in mime_types: headers['Content-Type'] = mime_types[ext] with open(body_file, mode='rb') as f: body_file = f.read() else: # A function to evaluate to get the response get_params, post_params = {}, {} if len(path_components) == 2: get_params = parse_qs(path_components[1]) # Parse POST parameters; currently only supports # application/x-www-form-urlencoded if req_body: post_params = parse_qs(req_body.encode()) status_code, headers, body_file = info(self.command, get_params, post_params) if type(body_file) == str: body_file = body_file.encode() if type(status_code) != int or status_code <= 0: raise Exception('Invalid status code %r' % status_code) for header, header_value in headers.items(): if type(header) != str: raise Exception('Invalid header key %r' % header) elif type(header_value) != str: raise Exception('Invalid header value %r' % header_value) else: status_code, headers = 404, {'Content-Type': 'text/plain'} body_file = b'Handler for this URL not found.' except Exception as e: status_code, headers, body_file = 500, {'Content-Type': 'text/plain'}, b'Internal Error:\n' + repr(e).encode() headers['Content-Length'] = str(len(body_file)) self.send_response(status_code) for header, header_value in headers.items(): self.send_header(header, header_value) self.end_headers() self.wfile.write(body_file) def do_an_internet(certdir, port): """Start up the proxy/server""" global global_certdir global_certdir = certdir httpd = ThreadingHTTPServer(('', port), RequestHijacker) httpd.serve_forever()