<?php
#-------------------------------------------------------------------------
# Module: Captcha - Enables CAPTCHA support for use in other modules.
#-------------------------------------------------------------------------
# Version 1.0
# maintained by Fernando Morgado AKA Jo Morg since 2017
#-------------------------------------------------------------------------
# Original Author: Dick Ittmann
#-------------------------------------------------------------------------
#
# Captcha is a CMS Made Simple module that enables the web developer to create
# multiple lists throughout a site. It can be duplicated and given friendly
# names for easier client maintenance.
#
#-------------------------------------------------------------------------
# BEGIN_LICENSE
#-------------------------------------------------------------------------
#
# This file is part of Captcha
# Captcha program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Captcha program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Or read it online: http://www.gnu.org/licenses/licenses.html#GPL
#
#-------------------------------------------------------------------------
# END_LICENSE
#-------------------------------------------------------------------------
/**
 * recaptcha
 * @see class.captchalib.php
 * @see CaptchaLib
 * @package Captcha
*/
namespace Captcha;
/**
 * @extends CaptchaLib
*/
class recaptcha_invisible extends \Captcha\cm_plugin_base
{
  
  private $_reCaptcha;
  
	/**
	* Class constructor
	*/
	function __construct()
	{
		// call the parent constructor
		parent::__construct();
    $this->setIncludeFiles( array('invisible_recaptchalib.php') );
    $this->setFriendlyName('Invisible reCaptcha');
    $options[] = new plugin_option('site_key' , 'string', '');
    $options[] = new plugin_option('secret' , 'string', '');
    $options[] = new plugin_option('badge' , 'string', 'bottomright');
    $options[] = new plugin_option('theme' , 'string', 'light');
    $options[] = new plugin_option('error-callback' , 'string', '');
    foreach($options as $opt) $this->AddOption($opt);
	}
	
	function getCaptcha($options = array())
	{
		$this->load();
    $mod = \cms_utils::get_module('Captcha');
    
    if( !is_object($mod) ) return false;
    
    if( empty($options['site_key']) )
    {
      $mod->Audit(0, 'recaptcha plugin', 'site_key is missing'); 
      return false; 
    }
    
    $token = bin2hex( openssl_random_pseudo_bytes(4) );
    
    $ids = \cms_utils::get_app_data('___CAPTCHA_RECAPTCHA_IDS');
    
    if( empty($ids) )
    {
      $ids = array();
    }
    
    $ids[] =  $token;
    
    \cms_utils::set_app_data('___CAPTCHA_RECAPTCHA_IDS', $ids);
    
    if( empty($options['badge']) )
    {
      $options['badge'] = 'bottomright';
    }
    
    $callback = 'renderInvisibleReCaptcha' . $token;
    $error_callback = trim($options['error-callback']);
    
    $html = '<div id="' . $token . '" class="recaptcha-holder"></div>';
    $html .= '<script src="https://www.google.com/recaptcha/api.js?onload=' . $callback . '&render=explicit" async defer></script>';
    $html .= '<script type="text/javascript">

    var renderInvisibleReCaptcha' . $token .' = function()
    {
      holder = document.getElementById("' . $token . '");
      var node = holder;
      while (node.nodeName != "FORM" && node.parentNode)
      {
        node = node.parentNode;
      }
      
      var form = node;
      
      (function(frm)
      {

        var holderId = grecaptcha.render(holder,
        {
          \'sitekey\': \'' . $options['site_key'] . '\',
          \'size\': \'invisible\',
          \'badge\': \'' . trim($options['badge']) . '\',
          \'theme\': \'' . trim($options['theme']) . '\',
          \'callback\': function (recaptchaToken)
          {
            HTMLFormElement.prototype.submit.call(frm);
          }';
    
    if( !empty($error_callback) )
    {
      $html .= ',
          \'error-callback\': ' . $error_callback;
    }
    
    $html .= '
        });
        
        frm.onsubmit = function (evt)
        {
          var event = document.createEvent(\'Event\');
          evt.preventDefault();
          event.initEvent(\'validate\', true, true);
          event.holderId = holderId;
          var validateform = frm.dispatchEvent(event);
          if(validateform)
          {
            grecaptcha.execute(holderId);
          }
        };

      })(form);
  };
</script>';
    
    
    return $html;
	}
  
  function checkAvailability() 
  {
    $this->setIsAvailable(TRUE);
    return TRUE;
  }
	
	function checkCaptcha($input, $options = array()) 
	{
		$this->load();
    $mod = \cms_utils::get_module('Captcha');
    
    if(empty($options['secret'])) 
    {
      $mod->Audit(0, 'recaptcha plugin', 'secret is missing'); 
      return false; 
    }
    
    $this->_reCaptcha = new \InvisibleReCaptcha($options['secret']);
        
    if ($_POST["g-recaptcha-response"]) 
    {
      $resp = $this->_reCaptcha->verifyResponse(
                                                  $_SERVER["REMOTE_ADDR"],
                                                  $_POST["g-recaptcha-response"]
                                                );
      
      return $resp->success;
    }
    
    return false;
	}
	
}
?>
