<?php

/**
 * This file is part of an ADDON for use with LEPTON Core.
 * This ADDON is released under the GNU GPL.
 * Additional license terms can be seen in the info.php of this module.
 *
 *
 *	@module			captcha
 *	@version		see info.php of this module
 *	@authors		LEPTON Project, W. Studer
 *	@copyright		2020-2021 LEPTON Project
 *	@link			https://lepton-cms.org
 *	@license		http://www.gnu.org/licenses/gpl.html
 *	@license_terms	please see info.php of this module
 *	@platform		see info.php of this module
 *
 *
 */


// include the trait(s)
require_once( LEPTON_PATH . "/modules/captcha_control/classes/plugin_trait.php" );

// create plugin class
class google_recaptcha
{
	// last validation response
	public $last_reponse = "";

	// use trait(s)
	use plugin_trait;

	/* ===============================================================================
	 * define defaults for build_captcha
	 *
	 * scope:	frontend,backend
	 * access:	private
	 * param:	none
	 * output:	none
	 */
	private function define_defaults()
	{
		// set plugin specific defaults
		$defaults = array(
			"TEXT_ATTR"		=> array(),
			"IMAGE_ATTR"	=> array(),
			"INPUT_ATTR"	=> array(),
			"COMPARE_CHAR"	=> ""
		);

		// merge plugin specific defaults with generic defaults
		$this->defaults = $this->merge_arrays( $defaults, $this->defaults );

		// define the captcha input field
		$this->captcha_field = array( "KEY" => "g-recaptcha-response",
									 "REQUEST" => array ('type' => 'string_clean', 'default' => "" ));

		// define list of supported actions
		$this->supported_actions = array( "all" );

		// mark plugin as deprecated
		$this->is_deprecated = false;

		// define if plugin is useable in current configuration
		$this->is_useable = true;

		// no playground in test
		$this->show_playground = false;
	}

	/* ===============================================================================
	 * get fields for captcha maintenance in admin module captcha_control
	 *
	 * scope:	backend
	 * access:	public
	 * param:	none
	 * output:	array containing list of fields shown in backend gui
	 */
	public function get_control_fieldset()
	{
		// get db fields
		$db_fieldset = $this->get_db_fields();

		// return array of field definition(s)
		$fieldset = array(
			"language"		=> $this->language,
			"SITEKEY"		=> array(
					"VALUE"		=> $db_fieldset[ "sitekey" ][ "default" ]
			),
			"SECUREKEY"		=> array(
					"VALUE"		=> $db_fieldset[ "securekey" ][ "default" ]
			),
			"CAPTCHALABEL"	=> array(
					"VALUE"		=> $db_fieldset[ "captchalabel" ][ "default" ]
			),

			"RECAPTCHA_VERSION"	=> array(
					"VALUE"		=> $db_fieldset[ "recaptcha_version" ][ "default" ],
					"LIST"		=> array(
						"V3"			=> $this->get_translation( 'CCL_ITEM_V3' ),
						"V2_checkbox"	=> $this->get_translation( 'CCL_ITEM_V2_CHECKBOX' ),
						"V2_invisible"	=> $this->get_translation( 'CCL_ITEM_V2_INVISIBLE' )
					)
			),
			"RECAPTCHA_THEME"	=> array(
					"VALUE"		=> $db_fieldset[ "recaptcha_theme" ][ "default" ],
					"LIST"		=> array(
						"light"		=> $this->get_translation( 'CCL_ITEM_V2_LIGHT' ),
						"dark"		=> $this->get_translation( 'CCL_ITEM_V2_DARK' )
					)
			),
			"RECAPTCHA_SIZE"	=> array(
					"VALUE"		=> $db_fieldset[ "recaptcha_size" ][ "default" ],
					"LIST"		=> array(
						"normal"	=> $this->get_translation( 'CCL_ITEM_V2_NORMAL' ),
						"compact"	=> $this->get_translation( 'CCL_ITEM_V2_COMPACT' )
					)
			)
		);

		return $fieldset;
	}

	/* ===============================================================================
	 * get captcha maintenance fields saved in db
	 *
	 * scope:	backend
	 * access:	public
	 * param:	none
	 * output:	array containing db related fields and their input validations
	 */
	public function get_db_fields()
	{
		$sitekey		= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "sitekey", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "sitekey" ]
								: "" );
		$securekey		= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "securekey", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "securekey" ]
								: "" );
		$captchalabel	= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "captchalabel", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "captchalabel" ]
								: "" );
		$version		= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "recaptcha_version", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "recaptcha_version" ]
								: "" );
		$theme			= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "recaptcha_theme", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "recaptcha_theme" ]
								: "light" );
		$size			= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "recaptcha_size", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "recaptcha_size" ]
								: "normal" );

		// return array of fields and their input validation
		$fieldset = array(
			"sitekey"				=> array( "type" => "string_clean", "default" => $sitekey ),
			"securekey"				=> array( "type" => "string_clean", "default" => $securekey ),
			"captchalabel"			=> array( "type" => "string_clean", "default" => $captchalabel ),
			"recaptcha_version"		=> array( "type" => "string_clean", "default" => $version ),
			"recaptcha_theme"		=> array( "type" => "string_clean", "default" => $theme ),
			"recaptcha_size"		=> array( "type" => "string_clean", "default" => $size )
		);

		return $fieldset;
	}

	/* ===============================================================================
	 * calculate the captcha string
	 *
	 * scope:	frontend
	 * access:	public
	 * param:	array with attributes
	 * output:	the captcha
	 */
	public function calculate_captcha( $params )
	{
		$captcha = array();
		$section_id = $_SESSION[ 'captcha_id' ];

		// prepare for reload and speech
		$_SESSION['captcharequest' . $section_id] = array(
			"RESULT"  => "",
			"CAPTCHA" => "",
			"SPEECH"  => ""
		);

		return $captcha;
	}

	/* ===============================================================================
	 * build the captcha parameterset
	 *
	 * scope:	frontend
	 * access:	private
	 * param:	array with attributes
	 * output:	array with all captcha related settings
	 */
	private function build_captcha_paramset( $params = array() )
	{
		// get db fields
		$db_fieldset = $this->get_db_fields();

		// overwrite with params
		$version	= $db_fieldset[ "recaptcha_version" ][ "default" ];
		$theme		= ( array_key_exists( "RECAPTCHA_THEME", $params )
						? $params[ "RECAPTCHA_THEME" ]
						: $db_fieldset[ "recaptcha_theme" ][ "default" ] );
		$size		= ( array_key_exists( "RECAPTCHA_SIZE", $params )
						? $params[ "RECAPTCHA_SIZE" ]
						: $db_fieldset[ "recaptcha_size" ][ "default" ] );
		if ( $version == "v2_invisible" )
			{ $size = "invisible"; }

		// build complete parameter set
		$paramset = array();
		switch( $params[ "ACTION" ] )
		{
			case "all":
				$paramset[ "RECAPTCHA_VERSION" ]= $version;
				$paramset[ "SITEKEY" ]			= $db_fieldset[ "sitekey" ][ "default" ];
				$paramset[ "RECAPTCHA_THEME" ]	= $theme;
				$paramset[ "RECAPTCHA_SIZE" ]	= $size;
				$paramset[ "CAPTCHALABEL" ]		= $db_fieldset[ "captchalabel" ][ "default" ];
				break;
		}

		return $paramset;
	}

	/* ===============================================================================
	 * Test the resposnse value agains the google-api
	 *
	 * scope:	frontend
	 * access:	public
	 * param:	$value, $section_id		value = The resonse from the captcha to test
	 * output:	Assoc. array with the test-result from the google-api
	 */
	public function test_captcha( $value, $section_id )
	{
		// start verify
		$url = "https://www.google.com/recaptcha/api/siteverify";

		$version		= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "recaptcha_version", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "recaptcha_version" ]
								: "" );

		$secretKey		= ( array_key_exists( "PLUGIN", $this->settings )
							&& array_key_exists( "securekey", $this->settings[ "PLUGIN" ] )
								? $this->settings[ "PLUGIN" ][ "securekey" ]
								: "" );

		if ( $version == "V3" )
		{
			$oREQUEST = LEPTON_request::getInstance();
			$input_fields = array (
				"gr_token"		=> array( "type" => "string", "default" => "" ),
				"gr_action"	=> array( "type" => "string_clean", "default" => "" )
			);
			$valid_fields = $oREQUEST->testPostValues($input_fields);

			if ( $valid_fields[ "gr_token" ]  == "" )
				{ return false; }

			$curlData = array(
				'secret'	=> $secretKey,
				'response'	=> $valid_fields[ "gr_token" ]
			);
		}
		else
		{
			// get falue if not passed as parameter
			if ( false === $value )
			{
				$oREQUEST = LEPTON_request::getInstance();
				$input_fields = array (
					$this->captcha_field["KEY"]	=> $this->captcha_field["REQUEST"]
				);
				$valid_fields = $oREQUEST->testPostValues($input_fields);
				$value = $valid_fields[ $this->captcha_field["KEY"] ];
			}

			$curlData = array(
				'secret'	=> $secretKey,
				'response'	=> $value,
				'remoteip'	=> $_SERVER['REMOTE_ADDR']
			);
		}

		// start verify
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query( $curlData ));
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		$curlResponse = curl_exec($ch);
		curl_close($ch);

		$this->last_reponse = json_decode($curlResponse, true);

		if ( $version == "V3" )
		{
			if (( $this->last_reponse['success']	=== true )
			 && ( $this->last_reponse['action']		== $valid_fields[ "gr_action" ] )
			 && ( $this->last_reponse['score']		>= 0.5 )
			 && ( $this->last_reponse['hostname']	== $_SERVER['SERVER_NAME'] ))
			 	{ return $this->last_reponse[ "success" ]; }
			 
			// this will be a bot action
			return false;
		}
		else
		{
			return $this->last_reponse[ "success" ];
		}
	}

}

?>
