<?php

declare(strict_types=1);

/**
 * This file is part of LEPTON Core, released under the GNU GPL
 * Please see LICENSE and COPYING files in your package for details, specially for terms and warranties.
 * 
 * NOTICE:LEPTON CMS Package has several different licenses.
 * Please see the individual license in the header of each single file or info.php of modules and templates.
 *
 * @author          LEPTON Project
 * @copyright       2010-2026 LEPTON Project
 * @link            https://lepton-cms.org
 * @license         https://gnu.org/licenses/gpl.html
 * @license_terms   please see LICENSE and COPYING files in your package
 *
 */

class LEPTON_securecms
{
    public string $_salt = '';
    
    /**
     *	Constructor of the class.
     *
     */
    public function __construct()
    {
        $this->_generate_salt();
    }
    
    /**
     *  Generating the random "salt" string.
     *
     * @return  void
     */
    public function _generate_salt(): void
    {
        LEPTON_handle::register("random_string");

        $salt  = random_string(28);
        $salt .= PHP_VERSION;
        $salt .= (string)time();
        
        $this->_salt = $salt;
    }
    
    /**
     * creates Tokens for CSRF protection
     * @access public
     * @return string
     *
     * requirements: an active session must be available
     * should be called only once for a page!
     */
    public function createLepToken(): string
    {
        if (function_exists('microtime'))
        {
            list($usec, $sec) = explode(" ", microtime());
            $time = (string) ((float) $usec + (float) $sec);
        }
        else
        {
            $time = (string) time();
        }
        
        $token = substr(hash("sha512", $time . $this->_salt), 0, 21) . "z" . substr($time, 0, 10);
        if (isset($_SESSION['LEPTOKENS']))
        {
            $_SESSION['LEPTOKENS'][] = $token;
        }
        else
        {
            $_SESSION['LEPTOKENS'] = [0 => $token];
        }
        return $token;
    }
    
    /**
     * checks received token against session-stored tokens
     * @access public
     * @return bool True if numbers matches against one of the stored tokens.
     *
     * Requirements: an active session must be available
     * this check will prevent from multiple sending a form. history.back() also will never work
     */
    public function checkLepToken(): bool
    {
        if (!LEPTOKEN_LIFETIME)
        {
            return true;
        }
        
        $retval    = false;
        
        if (isset($_GET['leptoken']))
        {
            $currentToken= $_GET['leptoken'];
        }
        elseif (isset($_GET['amp;leptoken']))
        {
            $currentToken= $_GET['amp;leptoken'];
        }
        elseif (isset($_POST['leptoken']))
        {
            $currentToken= $_POST['leptoken'];
        }
        elseif (isset($_POST['amp;leptoken']))
        {
            $currentToken= $_POST['amp;leptoken'];
        }
        else
        {
            return $retval;
        }
        
        if (isset($_SESSION['LEPTOKENS']))
        {
            // Delete out-dated tokens
            if ($this->deleteLepTokensByTimeout())
            {            
                foreach ($_SESSION['LEPTOKENS'] as $index => $value)
                {
                    if ($currentToken == $value)
                    {
                        $retval = true;
                        break;
                    }
                }

                // If none match delete all LEPTOKEN
                if ($retval == false)
                {
                    unset($_SESSION['LEPTOKENS']);
                }
            }
        }

        return $retval;
    }

    /*
     * delete all Tokens in $_SESSION
     * @access public
     * for use in frontend addons to prevent backend access
     *
     * requirements: an active session must be available and LEPTOKEN must be enabled!
     * 
     */
    static public function clearLepTokens(): void
    {
        if (isset($_SESSION['LEPTOKENS']) && isset($_SESSION['GROUPS_ID']))
        {
            $aTemp = explode(", ", $_SESSION['GROUPS_ID']);
            if ((!in_array(1, $aTemp)) && ((false === LEPTON_admin::getUserPermission("settings_backend_access")) && (false === LEPTON_admin::getUserPermission("backend_access"))))
            {
                unset($_SESSION['LEPTOKENS']);
            }
        } 
    }

    /**
     *
     * @return bool
     */
    private function deleteLepTokensByTimeout(): bool
    {
        $timeOut = intval(time() - LEPTOKEN_LIFETIME);
        foreach ($_SESSION['LEPTOKENS'] as $index => $value)
        {
            $tempTerms = explode("z", $value);
            $tokenTime = intval($tempTerms[1]);
            if ($tokenTime < $timeOut)
            {
                unset($_SESSION['LEPTOKENS']);
                return false;
            } 
        }

        return true;
    }
}
