<?PHP
/**
 * Login script
 *
 * @author Joshua Ramon Enslin <joshua@jrenslin.de>
 */

// Load settings

// Demand HTTPS
if (!isset($_SERVER['HTTPS']) or $_SERVER['HTTPS'] != 'on') header("Location: ../");

// Get available login information

$loginInformation = json_decode(file_get_contents(__DIR__ . '/../data/users.json'), True);
define("loginLogFile", __DIR__ . "/../data/logins.csv");

/**
 * Function for printing the login page
 *
 * @param string $error_msg Error message to print. Optional.
 * @param string $cssFile   CSS file.
 *
 * @return void
 */
function showLoginPasswordProtect($error_msg = "", $cssFile = "themes/default/default.css") {

    echo '<!DOCTYPE html>
    <html id="loginPage">
        <head>
            <meta http-equiv="Content-Security-Policy" content="default-src \'none\'; script-src \'none\'; connect-src \'none\'; style-src \'self\'; font-src \'self\';" />
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <meta http-equiv="content-type" content="text/html;charset=utf-8" />
            <meta charset="UTF-8" />
            <title>Log In</title>
            <link rel="stylesheet" type="text/css" href="' . $cssFile . '" />
        </head>
        <body>
            <h1>Log In</h1>';
    if ($error_msg) echo '<p id="errorMsg">'.$error_msg.'</p>';
    echo '
            <form action="" method="POST">
                <input type="text" name="username" placeholder="Username" required autofocus />
                <input type="password" name="password" placeholder="Password" required />
                <button type="submit">Submit</button>
            </form>
        </body>
    </html>
    ';

    die();

}

/**
 * Logout function: Unsets all relevant session variables.
 *
 * @return void
 */
function logout() {
    $loginVariables = array("username", "userlevel", "userLastLogin", "userLang");
    foreach ($loginVariables as $var) {
        if (isset($_SESSION[$var])) unset($_SESSION[$var]);
    }
    header("Location: ../");
}

/**
 * Function for Logging logins.
 *
 * @return void
 */
function logLogin() {
    file_put_contents(loginLogFile, $_SESSION['username'].'|'.date("Y-m-d H:i:s").PHP_EOL, FILE_APPEND | LOCK_EX);
}

/**
 * Prevent brute force attacks
 *
 * @return void
 */
function preventBruteForce() {

    if (!isset($_SESSION['loginattempt'])) $_SESSION['loginattempt'] = array();

    $_SESSION['loginattempt'][] = date("Y-m-d H:i:s");

    if (count($_SESSION['loginattempt']) > 3) {

        $secondtolastattempt = strtotime($_SESSION['loginattempt'][count($_SESSION['loginattempt']) - 3]);
        $lastattempt = strtotime($_SESSION['loginattempt'][count($_SESSION['loginattempt']) - 2]);

        $logindelay = (intval(count($_SESSION['loginattempt'])) * 20);
        $sincelastlogin = strtotime(date("Y-m-d H:i:s")) - $lastattempt;

        if ($sincelastlogin < $logindelay) showLoginPasswordProtect("You failed logging in too often, try again in $logindelay seconds.");

    }

}

/**
 * Check for validity of username / password combination.
 *
 * @param mixed[] $loginInformation Array containing all login information.
 * @param string  $username         Username to check.
 *
 * @return void
 */
function checkLoginValidity(array $loginInformation, $username) {
    if (!isset($loginInformation[$username])) showLoginPasswordProtect("Incorrect username");
}

// Main part of the script

if (isset($_GET['logout'])) logout(); // Log out if so requested

// Check for expiry

else if (isset($_SESSION['username'])) {

    checkLoginValidity($loginInformation, $_SESSION["username"]);

    // Check for expiry of login
    if (isset($_SESSION["userLastLogin"]) and strtotime(date("Y-m-d H:i:s")) - strtotime($_SESSION["userLastLogin"]) > 3600) logout();

    // Renew last login time
    $_SESSION["userLastLogin"] = date("Y-m-d H:i:s");

}

// If the corresponding POST vars are set, check for

else if (isset($_SERVER['PHP_AUTH_USER']) and isset($_SERVER['PHP_AUTH_PW'])) {

    preventBruteForce();
    checkLoginValidity($loginInformation, $_SERVER['PHP_AUTH_USER']);

    if (password_verify($loginInformation[$_SERVER['PHP_AUTH_USER']]['password'], $_SERVER['PHP_AUTH_PW'])) showLoginPasswordProtect("Incorrect password");

    // Set username
    $_SESSION["username"] = $_SERVER['PHP_AUTH_USER'];

    // Set last access time
    $_SESSION["userLastLogin"] = date("Y-m-d H:i:s");

    if (isset($_SESSION['loginattempt'])) unset($_SESSION['loginattempt']);

    // Log login time
    logLogin();

}
else if (isset($_POST['username']) and isset($_POST['password'])) {

    preventBruteForce();
    checkLoginValidity($loginInformation, $_POST['username']);
    if (password_verify($loginInformation[$_POST['username']]['password'], $_POST['username'])) showLoginPasswordProtect("Incorrect password");

    // Set username
    $_SESSION["username"] = $_POST['username'];

    // Set last access time
    $_SESSION["userLastLogin"] = date("Y-m-d H:i:s");
    if ($loginInformation[$_POST['username']]['admin'] or count($loginInformation) == 1) {
        $_SESSION['admin'] = true;
    }
    else $_SESSION['admin'] = false;

    if (isset($_SESSION['loginattempt'])) unset($_SESSION['loginattempt']);

    // Log login time
    logLogin();

}

// If nothing happens, offer login page

else showLoginPasswordProtect();

// End script

unset($loginInformation);  // Unset array containing login information

?>