<?php
/** 
 * @package     VikRestaurants
 * @subpackage  core
 * @author      E4J s.r.l.
 * @copyright   Copyright (C) 2023 E4J s.r.l. All Rights Reserved.
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
 * @link        https://vikwp.com
 */

namespace E4J\VikRestaurants\Http;

// No direct access
defined('ABSPATH') or die('No script kiddies please!');

/**
 * HTTP authentication helper class.
 * 
 * @since 1.11.1
 */
class AuthenticationHelper
{
	/** 
     * Searches for a basic authentication login.
     * 
     * @param   mixed  $app  The application instance.
     * 
     * @return  mixed  The login array (with "username" and "password")
     *                 on success, false otherwise.
     */
    public static function getBasicAuth($app = null)
    {
        if (!$app)
        {
            $app = \JFactory::getApplication();
        }

        $credentials = [];

        // try to extract credentials from headers (HTTP BASIC AUTH)
        $credentials['username'] = $app->input->server->getString('PHP_AUTH_USER');
        $credentials['password'] = $app->input->server->getString('PHP_AUTH_PW');

        if (!is_null($credentials['username']) || !is_null($credentials['password']))
        {
            // credentials found
            return $credentials;
        }

        // fallback to default authorization header
        $auth = static::getAuthorizationHeader($app);

        if (!$auth)
        {
            // unable to detect basic auth
            return false;
        }

        // extract digest from header, if any
        if (!preg_match("/^Basic\s+([A-Z0-9\/+=]+)$/i", $auth, $match))
        {
            // invalid authentication method
            return false;
        }

        $digest = base64_decode(end($match));
        $usernamePassword = explode(':', $digest);

		// auto-populate client ID and client Secret
		$credentials['username'] = $usernamePassword[0] ?? null;
		$credentials['password'] = $usernamePassword[1] ?? null;

        return $credentials;
    }

    /** 
     * Searches for a bearer authentication login.
     * 
     * @param   mixed  $app  The application instance.
     * 
     * @return  mixed  The bearer token on success, false otherwise.
     */
    public static function getBearer($app = null)
    {
        // get authorization directive
        $auth = static::getAuthorizationHeader($app);

        if (!$auth)
        {
            // unable to detect bearer auth
            return false;
        }

        if (!preg_match("/^Bearer\s+(\S+)$/i", $auth, $matches))
        {
            // invalid bearer
            return false;
        }

        // return extracted token
        return end($matches);
    }

    /** 
     * Tries to extract the authorization from the server headers.
     * 
     * @param   mixed  $app  The application instance.
     * 
     * @return  mixed  The auth header if specified, false if missing.
     */
    protected static function getAuthorizationHeader($app = null)
    {
        if (!$app)
        {
            $app = \JFactory::getApplication();
        }

        // search on default header
        $header = $app->input->server->getString('Authorization');

        if (!is_null($header))
        {
            return trim($header);
        }

        // try with Nginx or fast CGI
        $header = $app->input->server->getString('HTTP_AUTHORIZATION');

        if (!is_null($header))
        {
            return trim($header);
        }

        // try with a different CGI option
        $header = $app->input->server->getString('REDIRECT_HTTP_AUTHORIZATION');

        if (!is_null($header))
        {
            return trim($header);
        }

        // fallback to apache request headers
        if (function_exists('apache_request_headers'))
        {
            // extract headers from request
            $requestHeaders = apache_request_headers();

            // scan all headers in search of "authorization"
            foreach ($requestHeaders as $k => $v)
            {
                if (preg_match("/^Authorization$/i", $k))
                {
                    // authorization header found, return matching value
                    return trim($v);
                }
            }
        }

        // unable to detect authorization from server headers
        return false;
    }
}
