#!/usr/bin/env python3
# A SAMPLE web server to validate X-Edg-Signature-256 or X-Edg-Auth-Token header.
#
# Usage: ./webserver
#        ./webserver 0.0.0.0:5000
import hashlib
import hmac
import zlib

from base64 import b64encode
from http.server import HTTPServer, BaseHTTPRequestHandler
from sys import argv


BIND_HOST = 'localhost'
PORT = 8090
# Replace with your secret key (Settings->General->Live Events->Webhook Secret Token).
SECRET = 'XXXXX='

# two types of token types are supported.  Decide which one is best for you.  Recommendation
# is to use X-Edg-Signature-256 with SSL
TOKEN_TYPE_AUTH_TOKEN = 'X-Edg-Auth-Token'
TOKEN_TYPE_SIGNATURE_256 = 'X-Edg-Signature-256'


class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
    def callbackFunc(self, content, token_type):
        print(f"{token_type} HAS BEEN VALIDATED")
        print("CALLBACK FUNCTION HAS BEEN EXECUTED")
        print("Content:", content)
        # Implement your own code for how you want to handle the content
        # being posted to your server

    def validate_signature_256(self, content, callback):
        msg = b64encode(zlib.compress(content.encode('utf8'), 9)).strip()
        sig = hmac.new(SECRET.encode('utf-8'), msg, hashlib.sha256).hexdigest()
        header_sig = self.headers.get(TOKEN_TYPE_SIGNATURE_256)
        if sig == header_sig:
            callback(content, TOKEN_TYPE_SIGNATURE_256)

    def validate_authentication_token(self, content, callback):
        header_sig = self.headers.get(TOKEN_TYPE_AUTH_TOKEN)
        if SECRET == header_sig:
            callback(content, TOKEN_TYPE_AUTH_TOKEN)

    def do_GET(self):
        self.write_response(b'')

    def do_POST(self):
        content_length = int(self.headers.get('content-length', 0))
        body = self.rfile.read(content_length)

        self.write_response(body)
        self.validate_signature_256(body.decode('utf-8'), self.callbackFunc)
        self.validate_authentication_token(body.decode('utf-8'), self.callbackFunc)

    def write_response(self, content):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(content)


if len(argv) > 1:
    arg = argv[1].split(':')
    BIND_HOST = arg[0]
    PORT = int(arg[1])

print(f'Listening on http://{BIND_HOST}:{PORT}\n')

httpd = HTTPServer((BIND_HOST, PORT), SimpleHTTPRequestHandler)
httpd.serve_forever()