<?php
require_once('.rtmp_auth/.config.php');

/**
 * @author Gernot WALZL
 */
class Authenticator {

    protected $config = null;

    function __construct($config) {
        $this->config = $config;
    }

    function authenticate() {
        header('WWW-Authenticate: Basic');
        header('HTTP/1.0 401 Unauthorized');
        return false;
    }

    function verify($username, $password) {
        $result = false;
        if (isset($this->config->pass_hashes[$username])) {
            $pass_hash = $this->config->pass_hashes[$username];
            $result = password_verify($password, $pass_hash);
        }
        return $result;
    }

}

/**
 * @author Gernot WALZL
 */
class RtmpAuthDAO {

    function authorize_addr($user, $addr) {
        if (false !== strpos($user, '..')) {
            return false;
        }
        $filename = dirname(__FILE__).'/.rtmp_auth/'.$user.'.addr';
        $result = false;
        $fp = fopen($filename, 'w');
        if ($fp) {
            if (fwrite($fp, $addr."\n") > 0) {
                $result = true;
            }
            fclose($fp);
        }
        return $result;
    }

    function get_addr($user) {
        if (false !== strpos($user, '..')) {
            return null;
        }
        $filepath = dirname(__FILE__).'/.rtmp_auth/'.$user.'.addr';
        $result = null;
        if (is_file($filepath)) {
            $result = trim(file_get_contents($filepath));
        }
        return $result;
    }

    function is_authorized_addr($addr) {
        $result = false;
        $path = dirname(__FILE__).'/.rtmp_auth';
        if ($handle = opendir($path)) {
            while (false !== ($entry = readdir($handle))) {
                $filepath = $path.'/'.$entry;
                if (is_file($filepath)) {
                    $path_parts = pathinfo($filepath);
                    if ($path_parts['extension'] === 'addr') {
                        if ($addr == $this->get_addr($path_parts['filename'])) {
                            $result = true;
                            break;
                        }
                    }
                }
            }
            closedir($handle);
        }
        return $result;
    }

}

/**
 * @author Gernot WALZL
 */
class RtmpAuthHTML {

    function println($msg) {
        print($msg."\n");
    }

    function print_head($title='RTMP Authentication') {
        $this->println('<!DOCTYPE html>');
        $this->println('<html lang="en">');
        $this->println('<head>');
        $this->println('<meta charset="utf-8" />');
        $this->println('<title>'.$title.'</title>');
        $this->println('<meta name="viewport" '.
            'content="width=device-width, initial-scale=1.0" />');
        $this->println('</head>');
        $this->println('<body>');
        $this->println('<h1>'.$title.'</h1>');
    }

    function print_foot() {
        $this->println('</body>');
        $this->println('</html>');
    }

    function print_unauthorized() {
        $this->println('<p>This server could not verify that you are '.
            'authorized to access the document requested.</p>');
    }

    function print_authorized($user, $addr) {
        $this->println('<p>User <em>'.$user.'</em> has authorized<br />');
        $this->println('the address <code>'.$addr.'</code><br />');
        $this->println('for RTMP.</p>');
    }

}


if (isset($_POST['call'])) {  // nginx-rtmp-module always sets call
    if (isset($_POST['addr'])) {
        $addr = $_POST['addr'];
        $dao = new RtmpAuthDAO();
        if ($dao->is_authorized_addr($addr)) {
            http_response_code(200);
        } else {
            http_response_code(401);
        }
    } else {
        http_response_code(401);
    }
} else {
    if (!isset($_SERVER['HTTPS'])) {
        header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
        exit();
    }
    $config = new RtmpAuthConfig();
    $html = new RtmpAuthHTML();
    $auth = new Authenticator($config);
    $user = '';
    if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
        if ($auth->verify($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])) {
            $user = $_SERVER['PHP_AUTH_USER'];
        }
    }
    if (empty($user)) {
        if (!$auth->authenticate()) {
            $html->print_head('401 Unauthorized');
            $html->print_unauthorized();
            $html->print_foot();
        }
    } else {
        $dao = new RtmpAuthDAO();
        $dao->authorize_addr($user, $_SERVER['REMOTE_ADDR']);
        $html->print_head();
        $html->print_authorized($user, $dao->get_addr($user));
        $html->print_foot();
    }
}

?>