#!/usr/bin/env python3
"""FUT roster-update HTTPS server for FIFA 17 (OpenFUT).

The FUT loading flow (checkFUTRostersFlow / state CheckFUTRosterUpdateXML) downloads
a roster-update XML from ROSTERUPDATE_URL (which blaze_responder_v3b.py now serves as
https://127.0.0.1:8081/fifa17/fut/rosterupdate.xml). On download SUCCESS the flow
raises `advance` -> CheckFUTSquadBinFile -> (no squad) -> EnterFUT -> CardsDLL loads.
On FAIL it raises `back` -> abort. So this must return something FIFA ACCEPTS.

We don't have (or need) EA's real roster: the base player DB is baked into CardsDLL;
the roster-update is an optional delta. Start by serving a minimal "no update" body,
LOG every request (path/headers) so we learn exactly what FIFA fetches, and iterate.

HTTPS because EA's value is https and the DirtySDK download mgr may reject http; FIFA's
ProtoSSL cert-verify is patched (autopatch), so our self-signed cert is accepted.
"""
import http.server, ssl, os, sys, datetime

HERE = os.path.dirname(os.path.abspath(__file__))
CERT = os.path.join(HERE, "redir_cert.pem")
KEY = os.path.join(HERE, "redir_key.pem")
LOG = "/tmp/roster_server.log"
ADDR = ("127.0.0.1", 8081)

# Minimal "no update available" roster body. Unknown-format -> iterate from the log.
ROSTER_XML = b'<?xml version="1.0" encoding="utf-8"?>\n<rosterupdate version="0"/>\n'


def log(m):
    line = "[%s] %s" % (datetime.datetime.now().strftime("%H:%M:%S"), m)
    print(line, flush=True)
    with open(LOG, "a") as f:
        f.write(line + "\n")


class H(http.server.BaseHTTPRequestHandler):
    def _handle(self, method):
        log("%s %s from %s" % (method, self.path, self.client_address))
        for k, v in self.headers.items():
            log("    %s: %s" % (k, v))
        body = ROSTER_XML
        self.send_response(200)
        self.send_header("Content-Type", "application/xml")
        self.send_header("Content-Length", str(len(body)))
        self.send_header("Connection", "close")
        self.end_headers()
        if method == "GET":
            self.wfile.write(body)
        log("  -> 200 %dB (%r)" % (len(body), body[:60]))

    def do_GET(self):  self._handle("GET")
    def do_HEAD(self): self._handle("HEAD")
    def do_POST(self):
        n = int(self.headers.get("Content-Length", 0) or 0)
        if n:
            log("  POST body: %r" % self.rfile.read(n)[:200])
        self._handle("POST")

    def log_message(self, *a):  # silence default stderr logging
        pass


def main():
    open(LOG, "a").close()
    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
    ctx.load_cert_chain(CERT, KEY)
    ctx.minimum_version = ssl.TLSVersion.TLSv1
    try:
        ctx.set_ciphers("ALL:@SECLEVEL=0")
    except Exception:
        pass
    httpd = http.server.HTTPServer(ADDR, H)
    httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
    log("=== roster_server https://%s:%d (FUT roster-update) ===" % ADDR)
    httpd.serve_forever()


if __name__ == "__main__":
    main()
