<?php
/**
* @package RSForm! Pro
* @copyright (C) 2007-2023 www.rsjoomla.com
* @license GPL, http://www.gnu.org/copyleft/gpl.html
*/

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\Utilities\IpHelper;
use Joomla\CMS\Language\Text;

require_once JPATH_ADMINISTRATOR.'/components/com_rsform/helpers/field.php';

class RSFormProFieldHashcash extends RSFormProField
{
	// backend preview
	public function getPreviewInput()
	{
		return '<span class="rsficon rsficon-shield"></span> ' . $this->getProperty('LABEL', '');
	}
	
	public function getFormInput()
	{
		$this->addScript(HTMLHelper::_('script', 'com_rsform/hashcash/sha256.js', array('pathOnly' => true, 'relative' => true)));
		$this->addScript(HTMLHelper::_('script', 'com_rsform/hashcash/hashcash.js', array('pathOnly' => true, 'relative' => true)));

		$session    = Factory::getSession();
		$prefix     = 'com_rsform.hashcash' . $this->formId;
		$time       = $session->get($prefix . '.request_time', Factory::getDate()->toUnix());
		$ip         = $session->get($prefix . '.remote_addr', IpHelper::getIp());
		$name		= $this->getName();
		$id			= $this->getId();
		$attr		= $this->getAttributes();
		$label		= $this->getProperty('LABEL', '');
		$type 		= 'button';
		$additional = '';

		// Reset data
		$session->set($prefix . '.request_time', $time);
		$session->set($prefix . '.remote_addr', $ip);

		// Start building the HTML input
		$html = '<button';
		// Parse Additional Attributes
		if ($attr) {
			foreach ($attr as $key => $values) {
				// @new feature - Some HTML attributes (type) can be overwritten
				// directly from the Additional Attributes area
				if ($key == 'type' && strlen($values)) {
					${$key} = $values;
					continue;
				}
				$additional .= $this->attributeToHtml($key, $values);
			}
		}
		// Set the type
		$html .= ' type="'.$this->escape($type).'"';
		// ID
		$html .= ' id="'.$this->escape($id).'"';
		// Additional HTML
		$html .= $additional;
		$html .= ' data-rsfp-hashcash';
		$html .= ' data-hashcash-level="' . (int) $this->getProperty('DIFFICULTY', 4) . '"';
		$html .= ' data-hashcash-text="' . $this->escape(md5($ip  . $time)) . '"';
		$html .= ' data-hashcash-name="' . $this->escape($name) . '"';

		// Close the tag
		$html .= '>';

		$html .= '<svg class="hashcash__pending hashcash" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"><circle class="hashcash__circle" cx="26" cy="26" r="25" fill="none"/><path class="hashcash__check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/></svg><span class="hashcash__text">' . $this->escape($label) . '</span></button>';

		return $html;
	}

	public function processValidation($validationType = 'form', $submissionId = 0)
	{
		// Skip directory editing since it makes no sense
		if ($validationType == 'directory')
		{
			return true;
		}

		// Logged in users don't need to pass Captcha if this option is enabled on the form.
		$form = RSFormProHelper::getForm($this->formId);
		if (Factory::getUser()->id && $form->RemoveCaptchaLogged)
		{
			return true;
		}

		$app      = Factory::getApplication();
		$task	  = strtolower($app->input->get('task', ''));
		$option	  = strtolower($app->input->get('option', ''));
		$isAjax	  = $option === 'com_rsform' && $task === 'ajaxvalidate';

		if ($isAjax)
		{
			return true;
		}

		$session = Factory::getSession();
		$prefix  = 'com_rsform.hashcash' . $this->formId;
		$value   = $this->getValue();
		$time    = $session->get($prefix . '.request_time');
		$ip      = $session->get($prefix . '.remote_addr');

		$session->set($prefix . '.request_time', null);
		$session->set($prefix . '.remote_addr', null);

		try
		{
			if (!$value)
			{
				throw new Exception(Text::_('COM_RSFORM_HASHCASH_MISSING_VALUE'));
			}

			if (!$time || !$ip)
			{
				throw new Exception(Text::_('COM_RSFORM_HASHCASH_MISSING_SESSION_DATA'));
			}

			$sha256 = hash('sha256', md5($ip . $time) . $value, false);
			$valid = preg_match('/^0{' . (int) $this->getProperty('DIFFICULTY', 4) . '}/', $sha256);

			if (!$valid)
			{
				throw new Exception(Text::_('COM_RSFORM_HASHCASH_VALIDATION_FAILED'));
			}

			return $valid;
		}
		catch (Exception $e)
		{
			$properties =& RSFormProHelper::getComponentProperties($this->componentId);
			$properties['VALIDATIONMESSAGE'] = $e->getMessage();
			return false;
		}
	}

	public function processBeforeStore($submissionId, &$post, &$files)
	{
		unset($post[$this->name]);
	}
}