<?php

/**
 * 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-2021 LEPTON Project
 * @link            https://lepton-cms.org
 * @license         http://www.gnu.org/licenses/gpl.html
 * @license_terms   please see LICENSE and COPYING files in your package
 *
 */

class LEPTON_session
{
	/**
	 *  @var    object  The reference to the *Singleton* instance of this class.
	 *
	 */
	static $instance;

	/**
	 *  Return the instance of this class.
	 *
	 */
	public static function getInstance()
	{
		if (null === static::$instance)
		{
			static::$instance = new static();
		}
		return static::$instance;
	}

	// Default constructor of the class
	final public function __construct()
	{
		// return the class instance
		return self::getInstance();
	}

	/**
	 *  Static function to initialize a LEPTON-session
	 *
	 */
	public static function init()
	{
	}

	/**
	 *  Static function to set a cookie
	 *
	 *	@params	$name			Name of cookie
	 *	@params	$value			New cookie value
	 *	@params	$options		array with settings, see PHP documentation
	 *	@params	$mustExists		boolean true/false: set cookie only if exists
	 *	@params	$mergeDefault	boolean true/false: merge input options with defaults
	 */
	public static function set_cookie( $name,
										$value,
										$options = array(),
										$mustExists = false,
										$mergeDefault = true )
	{
		// check if name exists in $_COOKIE
		if (( true === $mustExists )
		 && ( false === isset( $_COOKIE[ $name ] )))
		{
			return null;
		}

		// clear options, remove empty settings
		$temp = $options;
		$options = array();
		foreach( $temp as $optkey => $optvalue )
		{
			if ( $optvalue != "" )
				{ $options[ $optkey ] = $optvalue; }
		}
		unset( $temp );

		// merge options array with defaults
		if ( true === $mergeDefault )
		{
			$defaults = self::get_cookie_defaults();
			$options = array_merge( $defaults, $options );
			unset( $defaults );
		}

		// update cookie settings
		if ( version_compare( PHP_VERSION, '7.3.0', ">=" ))
		{
			$return = setcookie( $name,
									$value,
									$options
			);
		}
		else
		{
			// using a PHP < 7.3 bug to set the samesite attribute
			// https://stackoverflow.com/questions/39750906/php-setcookie-samesite-strict
			$return = setcookie( $name,
									$value,
									(int) $options[ "expires" ],
									$options[ "path" ] . ';samesite=' . $options[ "samesite" ],
									$options[ "domain" ],
									$options[ "secure" ],
									$options[ "httponly" ]
			);
		}

		return $return;
	}

	/**
	 *  Static function to delete a cookie
	 *
	 *	@params	$name			Name of cookie
	 *	@params	$value			New cookie value
	 *	@params	$options		array with settings, see PHP documentation
	 */
	public static function delete_cookie( $name,
										$value = "",
										$options = array() )
	{
		// check if name exists in $_COOKIE
		if ( false === isset( $_COOKIE[ $name ] ))
		{
			return null;	// not exists means also cookie not exists
		}

		// overwrite session array
		$_SESSION = array();

		// set/overwrite expire option
		$options[ "expires" ] = 1;	// 01.01.1970 00:00:01

		// delete session cookie if set
		$return = self::set_cookie( $name, $value, $options );

		// overwrite session array again
		$_SESSION = array();

		// delete the session itself
		session_destroy();

		return $return;
	}

	/**
	 *  get cookie default settings
	 *
	 */
	private static function get_cookie_defaults()
	{
		// return the defaults
		return array(
			/* session.cookie_lifetime specifies the lifetime of the cookie in seconds which
			 * is sent to the browser. The value 0 means "until the browser is closed."
			 * Defaults to 0. */
			"expires" => time() + ( 3 * 3600 ), // three hours

			/* session.cookie_path specifies path to set in the session cookie. Defaults to /. */
			"path" => "/",

			/* session.cookie_domain specifies the domain to set in the session cookie.
			* Default is none at all meaning the host name of the server which generated
			* the cookie according to cookies specification. */
			"domain" => "",

			/* session.cookie_secure specifies whether cookies should only be sent over secure
			* connections. Defaults to off. */
			"secure" => ( isset( $_SERVER['HTTPS'] )
					? ( strtolower( $_SERVER[ 'HTTPS' ] )  == "on" )
					: false
					),

			/* session.cookie_httponly Marks the cookie as accessible only through the HTTP protocol.
			* This means that the cookie won't be accessible by scripting languages
			* , such as JavaScript. This setting can effectively help to reduce identity theft
			* through XSS attacks (although it is not supported by all browsers). */
			"httponly" => true,

			/* session.cookie_samesite allows servers to assert that a cookie ought not to be sent
			* along with cross-site requests. This assertion allows user agents to mitigate the
			* risk of cross-origin information leakage, and provides some protection against
			* cross-site request forgery attacks. Note that this is not supported by all browsers.
			* An empty value means that no SameSite cookie attribute will be set.
			* Lax and Strict mean that the cookie will not be sent cross-domain for POST requests;
			* Lax will sent the cookie for cross-domain GET requests, while Strict will not. */
			"samesite" => "Lax"
		);
	}

	/**
	 *  Static funtion to destroy a LEPTON-session
	 *
	 */
	public static function destroy()
	{

	}

	/**
	 *  Static funtion to test a LEPTON-session
	 *
	 */
	public static function test()
	{

	}
}
