/home/mip/mip/public/img/credit/datatables/biscolab.tar
laravel-recaptcha/LICENSE000064400000002072151235006450011131 0ustar00MIT License

Copyright (c) 2017 - present Roberto Belotti

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
laravel-recaptcha/src/helpers.php000075500000006061151235006450013073 0ustar00<?php

/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - helpers.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 12/9/2018
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

use Biscolab\ReCaptcha\Facades\ReCaptcha;

if (!function_exists('recaptcha')) {
    /**
     * @return Biscolab\ReCaptcha\ReCaptchaBuilder|\Biscolab\ReCaptcha\ReCaptchaBuilderV2|\Biscolab\ReCaptcha\ReCaptchaBuilderInvisible|\Biscolab\ReCaptcha\ReCaptchaBuilderV3
     */
    function recaptcha(): \Biscolab\ReCaptcha\ReCaptchaBuilder
    {

        return app('recaptcha');
    }
}

/**
 * call ReCaptcha::htmlScriptTagJsApi()
 * Write script HTML tag in you HTML code
 * Insert before </head> tag
 *
 * @param $config ['form_id'] required if you are using invisible ReCaptcha
 */
if (!function_exists('htmlScriptTagJsApi')) {

    /**
     * @param array|null $config
     *
     * @return string
     */
    function htmlScriptTagJsApi(?array $config = []): string
    {

        return ReCaptcha::htmlScriptTagJsApi($config);
    }
}

/**
 * call ReCaptcha::htmlFormButton()
 * Write HTML <button> tag in your HTML code
 * Insert before </form> tag
 *
 * Warning! Using only with ReCAPTCHA INVISIBLE
 *
 * @param $buttonInnerHTML What you want to write on the submit button
 */
if (!function_exists('htmlFormButton')) {

    /**
     * @param null|string $button_label
     * @param array|null  $properties
     *
     * @return string
     */
    function htmlFormButton(?string $button_label = 'Submit', ?array $properties = []): string
    {

        return ReCaptcha::htmlFormButton($button_label, $properties);
    }
}

/**
 * call ReCaptcha::htmlFormSnippet()
 * Write ReCAPTCHA HTML tag in your FORM
 * Insert before </form> tag
 *
 * Warning! Using only with ReCAPTCHA v2
 */
if (!function_exists('htmlFormSnippet')) {

    /**
     * @param null|array $attributes
     * @return string
     */
    function htmlFormSnippet(?array $attributes = []): string
    {

        return ReCaptcha::htmlFormSnippet($attributes);
    }
}

/**
 * call ReCaptcha::getFormId()
 * return the form ID
 * Warning! Using only with ReCAPTCHA invisible
 */
if (!function_exists('getFormId')) {

    /**
     * @return string
     */
    function getFormId(): string
    {

        return ReCaptcha::getFormId();
    }
}

/**
 * return ReCaptchaBuilder::DEFAULT_RECAPTCHA_RULE_NAME value ("recaptcha")
 * Use V2 (checkbox and invisible)
 */
if (!function_exists('recaptchaRuleName')) {

    /**
     * @return string
     */
    function recaptchaRuleName(): string
    {

        return \Biscolab\ReCaptcha\ReCaptchaBuilder::DEFAULT_RECAPTCHA_RULE_NAME;
    }
}

/**
 * return ReCaptchaBuilder::DEFAULT_RECAPTCHA_FIELD_NAME value "g-recaptcha-response"
 * Use V2 (checkbox and invisible)
 */
if (!function_exists('recaptchaFieldName')) {

    /**
     * @return string
     */
    function recaptchaFieldName(): string
    {

        return \Biscolab\ReCaptcha\ReCaptchaBuilder::DEFAULT_RECAPTCHA_FIELD_NAME;
    }
}
laravel-recaptcha/src/ReCaptchaBuilder.php000075500000021213151235006450014566 0ustar00<?php

/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - ReCaptchaBuilder.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 12/9/2018
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha;

use Illuminate\Support\Arr;
use Symfony\Component\HttpFoundation\IpUtils;

/**
 * Class ReCaptchaBuilder
 * @package Biscolab\ReCaptcha
 */
class ReCaptchaBuilder
{

    /**
     * @var string
     */
    const DEFAULT_API_VERSION = 'v2';

    /**
     * @var int
     */
    const DEFAULT_CURL_TIMEOUT = 10;

    /**
     * @var string
     */
    const DEFAULT_ONLOAD_JS_FUNCTION = 'biscolabOnloadCallback';

    /**
     * @var string
     */
    const DEFAULT_RECAPTCHA_RULE_NAME = 'recaptcha';

    /**
     * @var string
     */
    const DEFAULT_RECAPTCHA_FIELD_NAME = 'g-recaptcha-response';

    /**
     * @var string
     */
    const DEFAULT_RECAPTCHA_API_DOMAIN = 'www.google.com';

    /**
     * The Site key
     * please visit https://developers.google.com/recaptcha/docs/start
     * @var string
     */
    protected $api_site_key;

    /**
     * The Secret key
     * please visit https://developers.google.com/recaptcha/docs/start
     * @var string
     */
    protected $api_secret_key;

    /**
     * The chosen ReCAPTCHA version
     * please visit https://developers.google.com/recaptcha/docs/start
     * @var string
     */
    protected $version;

    /**
     * Whether is true the ReCAPTCHA is inactive
     * @var boolean
     */
    protected $skip_by_ip = false;

    /**
     * The API domain (default: retrieved from config file)
     * @var string
     */
    protected $api_domain = '';

    /**
     * The API request URI
     * @var string
     */
    protected $api_url = '';

    /**
     * The URI of the API Javascript file to embed in you pages
     * @var string
     */
    protected $api_js_url = '';

    /**
     * ReCaptchaBuilder constructor.
     *
     * @param string      $api_site_key
     * @param string      $api_secret_key
     * @param null|string $version
     */
    public function __construct(
        string $api_site_key,
        string $api_secret_key,
        ?string $version = self::DEFAULT_API_VERSION
    ) {

        $this->setApiSiteKey($api_site_key);
        $this->setApiSecretKey($api_secret_key);
        $this->setVersion($version);
        $this->setSkipByIp($this->skipByIp());
        $this->setApiDomain();
        $this->setApiUrls();
    }

    /**
     * @param string $api_site_key
     *
     * @return ReCaptchaBuilder
     */
    public function setApiSiteKey(string $api_site_key): ReCaptchaBuilder
    {

        $this->api_site_key = $api_site_key;

        return $this;
    }

    /**
     * @param string $api_secret_key
     *
     * @return ReCaptchaBuilder
     */
    public function setApiSecretKey(string $api_secret_key): ReCaptchaBuilder
    {

        $this->api_secret_key = $api_secret_key;

        return $this;
    }

    /**
     * @return int
     */
    public function getCurlTimeout(): int
    {

        return config('recaptcha.curl_timeout', self::DEFAULT_CURL_TIMEOUT);
    }

    /**
     * @param string $version
     *
     * @return ReCaptchaBuilder
     */
    public function setVersion(string $version): ReCaptchaBuilder
    {

        $this->version = $version;

        return $this;
    }

    /**
     * @return string
     */
    public function getVersion(): string
    {

        return $this->version;
    }

    /**
     * @param bool $skip_by_ip
     *
     * @return ReCaptchaBuilder
     */
    public function setSkipByIp(bool $skip_by_ip): ReCaptchaBuilder
    {

        $this->skip_by_ip = $skip_by_ip;

        return $this;
    }

    /**
     * @param null|string $api_domain
     *
     * @return ReCaptchaBuilder
     */
    public function setApiDomain(?string $api_domain = null): ReCaptchaBuilder
    {

        $this->api_domain = $api_domain ?? config('recaptcha.api_domain', self::DEFAULT_RECAPTCHA_API_DOMAIN);

        return $this;
    }

    /**
     * @return string
     */
    public function getApiDomain(): string
    {

        return $this->api_domain;
    }

    /**
     * @return ReCaptchaBuilder
     */
    public function setApiUrls(): ReCaptchaBuilder
    {

        $this->api_url = 'https://' . $this->api_domain . '/recaptcha/api/siteverify';
        $this->api_js_url = 'https://' . $this->api_domain . '/recaptcha/api.js';

        return $this;
    }

    /**
     * @return array|mixed
     */
    public function getIpWhitelist()
    {

        $whitelist = config('recaptcha.skip_ip', []);

        if (!is_array($whitelist)) {
            $whitelist = explode(',', $whitelist);
        }

        $whitelist = array_map(function ($item) {

            return trim($item);
        }, $whitelist);

        return $whitelist;
    }

    /**
     * Checks whether the user IP address is among IPs "to be skipped"
     *
     * @return boolean
     */
    public function skipByIp(): bool
    {
        return IpUtils::checkIp(request()->ip(), $this->getIpWhitelist());
    }

    /**
     * Write script HTML tag in you HTML code
     * Insert before </head> tag
     *
     * @param array|null $configuration
     *
     * @return string
     * @throws \Exception
     */
    public function htmlScriptTagJsApi(?array $configuration = []): string
    {

        $query = [];
        $html = '';

        // Language: "hl" parameter
        // resources $configuration parameter overrides default language
        $language = Arr::get($configuration, 'lang');
        if (!$language) {
            $language = config('recaptcha.default_language', null);
        }
        if ($language) {
            Arr::set($query, 'hl', $language);
        }

        // Onload JS callback function: "onload" parameter
        // "render" parameter set to "explicit"
        if (config('recaptcha.explicit', null) && $this->version === 'v2') {
            Arr::set($query, 'render', 'explicit');
            Arr::set($query, 'onload', self::DEFAULT_ONLOAD_JS_FUNCTION);

            /** @scrutinizer ignore-call */
            $html = $this->getOnLoadCallback();
        }

        // Create query string
        $query = ($query) ? '?' . http_build_query($query) : "";
        $html .= "<script src=\"" . $this->api_js_url .  $query . "\" async defer></script>";

        return $html;
    }

    /**
     * Call out to reCAPTCHA and process the response
     *
     * @param string $response
     *
     * @return boolean|array
     */
    public function validate($response)
    {

        if ($this->skip_by_ip) {
            if ($this->returnArray()) {
                // Add 'skip_by_ip' field to response
                return [
                    'skip_by_ip' => true,
                    'score'      => 0.9,
                    'success'    => true
                ];
            }

            return true;
        }

        $params = http_build_query([
            'secret'   => $this->api_secret_key,
            'remoteip' => request()->getClientIp(),
            'response' => $response,
        ]);

        $url = $this->api_url . '?' . $params;

        if (function_exists('curl_version')) {

            $curl = curl_init($url);
            curl_setopt($curl, CURLOPT_HEADER, false);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_TIMEOUT, $this->getCurlTimeout());
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            $curl_response = curl_exec($curl);
        } else {
            $curl_response = file_get_contents($url);
        }

        if (is_null($curl_response) || empty($curl_response)) {
            if ($this->returnArray()) {
                // Add 'error' field to response
                return [
                    'error'   => 'cURL response empty',
                    'score'   => 0.1,
                    'success' => false
                ];
            }

            return false;
        }
        $response = json_decode(trim($curl_response), true);

        if ($this->returnArray()) {
            return $response;
        }

        return $response['success'];
    }

    /**
     * @return string
     */
    public function getApiSiteKey(): string
    {

        return $this->api_site_key;
    }

    /**
     * @return string
     */
    public function getApiSecretKey(): string
    {

        return $this->api_secret_key;
    }

    /**
     * @return bool
     */
    protected function returnArray(): bool
    {

        return ($this->version == 'v3');
    }

    /**
     * @return string
     */
    public function getOnLoadCallback(): string
    {

        return "";
    }
}
laravel-recaptcha/src/Controllers/ReCaptchaController.php000064400000001337151235006450017633 0ustar00<?php
/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - ReCaptchaController.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 4/2/2019
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha\Controllers;

use Illuminate\Routing\Controller;

/**
 * Class ReCaptchaController
 * @package Biscolab\ReCaptcha\Controllers
 */
class ReCaptchaController extends Controller
{

	/**
	 * @return array
	 */
	public function validateV3(): array
	{

		$token = request()->input(config('recaptcha.default_token_parameter_name', 'token'), '');

		return recaptcha()->validate($token);
	}
}laravel-recaptcha/src/Facades/ReCaptcha.php000064400000001630151235006450014603 0ustar00<?php
/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - ReCaptcha.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 12/9/2018
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha\Facades;

use Illuminate\Support\Facades\Facade;

/**
 * Class ReCaptcha
 * @package Biscolab\ReCaptcha\Facades
 *
 * @method static string htmlScriptTagJsApi(?array $config = [])
 * @method static string htmlFormButton(?string $button_label = '', ?array $properties = [])
 * @method static string htmlFormSnippet()
 * @method static string getFormId()
 */
class ReCaptcha extends Facade
{

    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {

        return 'recaptcha';
    }
}
laravel-recaptcha/src/ReCaptchaBuilderInvisible.php000064400000006445151235006450016442 0ustar00<?php
/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - ReCaptchaBuilderInvisible.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 12/9/2018
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha;

use Biscolab\ReCaptcha\Exceptions\InvalidConfigurationException;
use Illuminate\Support\Arr;

/**
 * Class ReCaptchaBuilderInvisible
 * @package Biscolab\ReCaptcha
 */
class ReCaptchaBuilderInvisible extends ReCaptchaBuilder
{

    /**
     * @var null|string
     */
    protected $form_id = null;

    /**
     * ReCaptchaBuilderInvisible constructor.
     *
     * @param string $api_site_key
     * @param string $api_secret_key
     */
    public function __construct(string $api_site_key, string $api_secret_key)
    {

        parent::__construct($api_site_key, $api_secret_key, 'invisible');
    }

    /**
     * Write HTML <button> tag in your HTML code
     * Insert before </form> tag
     *
     * @param string     $button_label
     * @param array|null $properties
     *
     * @return string
     */
    public function htmlFormButton($button_label = 'Submit', ?array $properties = []): string
    {

        $tag_properties = '';

        $properties = array_merge([
            'data-callback' => 'biscolabLaravelReCaptcha',
        ], $properties, 
        [
            'data-sitekey'  => $this->api_site_key
        ]);

        if (empty($properties['class'])) {
            $properties['class'] = 'g-recaptcha';
        } else {
            $properties['class'] .= ' g-recaptcha';
        }

        ksort($properties);

        if ($properties) {
//            $tag_properties = str_replace("=", '="',
//                    http_build_query($properties, null, '" ', PHP_QUERY_RFC3986)) . '"';
            $temp_properties = [];
            foreach ($properties as $k => $v) {
                $temp_properties[] = $k . '="' . $v . '"';
            }

            $tag_properties = implode(" ", $temp_properties);
        }

        return ($this->version == 'invisible') ? '<button ' . $tag_properties . '>' . $button_label . '</button>' : '';
    }

    /**
     * Write script HTML tag in you HTML code
     * Insert before </head> tag
     *
     * @param array|null $configuration
     *
     * @return string
     * @throws \Exception
     */
    public function htmlScriptTagJsApi(?array $configuration = []): string
    {

        $html = parent::htmlScriptTagJsApi();

        $form_id = Arr::get($configuration, 'form_id');
        if (!$form_id) {
            $form_id = $this->getFormId();
        } else {
            $this->form_id = $form_id;
        }
        $html .= '<script>
		       function biscolabLaravelReCaptcha(token) {
		         document.getElementById("' . $form_id . '").submit();
		       }
		     </script>';

        return $html;
    }

    /**
     * @return string
     * @throws \Exception
     */
    public function getFormId(): string
    {

        if (!$this->form_id) {
            $form_id = config('recaptcha.default_form_id');
        } else {
            $form_id = $this->form_id;
        }
        if (!$form_id) {
            throw new InvalidConfigurationException("formId required");
        }

        return $form_id;
    }
}

laravel-recaptcha/src/ReCaptchaServiceProvider.php000075500000006077151235006450016326 0ustar00<?php

/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - ReCaptchaServiceProvider.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 12/9/2018
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha;

use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;

/**
 * Class ReCaptchaServiceProvider
 * @package Biscolab\ReCaptcha
 */
class ReCaptchaServiceProvider extends ServiceProvider
{

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;

    /**
     *
     */
    public function boot()
    {

        $this->addValidationRule();
        $this->registerRoutes();
        $this->publishes([
            __DIR__ . '/../config/recaptcha.php' => config_path('recaptcha.php'),
        ], 'config');
    }

    /**
     * Extends Validator to include a recaptcha type
     */
    public function addValidationRule()
    {
        $message = null;

        if (!config('recaptcha.empty_message')) {
            $message = trans(config('recaptcha.error_message_key'));
        }
        Validator::extendImplicit(recaptchaRuleName(), function ($attribute, $value) {

            return app('recaptcha')->validate($value);
        }, $message);
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {

        $this->mergeConfigFrom(
            __DIR__ . '/../config/recaptcha.php',
            'recaptcha'
        );

        $this->registerReCaptchaBuilder();
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides(): array
    {

        return ['recaptcha'];
    }

    /**
     * @return ReCaptchaServiceProvider
     *
     * @since v3.4.1
     */
    protected function registerRoutes(): ReCaptchaServiceProvider
    {

        Route::get(
            config('recaptcha.default_validation_route', 'biscolab-recaptcha/validate'),
            ['uses' => 'Biscolab\ReCaptcha\Controllers\ReCaptchaController@validateV3']
        )->middleware('web');

        return $this;
    }

    /**
     * Register the HTML builder instance.
     *
     * @return void
     */
    protected function registerReCaptchaBuilder()
    {

        $this->app->singleton('recaptcha', function ($app) {

            $recaptcha_class = '';

            switch (config('recaptcha.version')) {
                case 'v3':
                    $recaptcha_class = ReCaptchaBuilderV3::class;
                    break;
                case 'v2':
                    $recaptcha_class = ReCaptchaBuilderV2::class;
                    break;
                case 'invisible':
                    $recaptcha_class = ReCaptchaBuilderInvisible::class;
                    break;
            }

            return new $recaptcha_class(config('recaptcha.api_site_key'), config('recaptcha.api_secret_key'));
        });
    }
}
laravel-recaptcha/src/ReCaptchaBuilderV3.php000064400000006706151235006450015006 0ustar00<?php

/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - ReCaptchaBuilderV3.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 22/1/2019
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha;

use Illuminate\Support\Arr;

/**
 * Class ReCaptchaBuilderV3
 * @package Biscolab\ReCaptcha
 */
class ReCaptchaBuilderV3 extends ReCaptchaBuilder
{

    /**
     * ReCaptchaBuilderV3 constructor.
     *
     * @param string $api_site_key
     * @param string $api_secret_key
     */
    public function __construct(string $api_site_key, string $api_secret_key)
    {

        parent::__construct($api_site_key, $api_secret_key, 'v3');
    }

    public function getTokenParameterName(): string
    {
        return config(
            'recaptcha.default_token_parameter_name',
            'token'
        );
    }

    public function getValidationUrl(): string
    {
        return url(config(
            'recaptcha.default_validation_route',
            'biscolab-recaptcha/validate'
        ));
    }

    public function getValidationUrlWithToken(): string
    {
        return implode(
            "?",
            [
                $this->getValidationUrl(),
                $this->getTokenParameterName()
            ]
        );
    }

    /**
     * Write script HTML tag in you HTML code
     * Insert before </head> tag
     *
     * @param array|null $configuration
     *
     * @return string
     */
    public function htmlScriptTagJsApi(?array $configuration = []): string
    {

        if ($this->skip_by_ip) {
            return '';
        }

        $html = "<script src=\"" . $this->api_js_url . "?render={$this->api_site_key}\"></script>";

        $action = Arr::get($configuration, 'action', 'homepage');

        $js_custom_validation = Arr::get($configuration, 'custom_validation', '');

        // Check if set custom_validation. That function will override default fetch validation function
        if ($js_custom_validation) {

            $validate_function = ($js_custom_validation) ? "{$js_custom_validation}(token);" : '';
        } else {

            $js_then_callback = Arr::get($configuration, 'callback_then', '');
            $js_callback_catch = Arr::get($configuration, 'callback_catch', '');

            $js_then_callback = ($js_then_callback) ? "{$js_then_callback}(response)" : '';
            $js_callback_catch = ($js_callback_catch) ? "{$js_callback_catch}(err)" : '';

            $validate_function = "
                fetch('" . $this->getValidationUrlWithToken() . "=' + token, {
                    headers: {
                        \"X-Requested-With\": \"XMLHttpRequest\",
                        \"X-CSRF-TOKEN\": csrfToken.content
                    }
                })
                .then(function(response) {
                   	{$js_then_callback}
                })
                .catch(function(err) {
                    {$js_callback_catch}
                });";
        }

        $html .= "<script>
                    var csrfToken = document.head.querySelector('meta[name=\"csrf-token\"]');
                  grecaptcha.ready(function() {
                      grecaptcha.execute('{$this->api_site_key}', {action: '{$action}'}).then(function(token) {
                        {$validate_function}
                      });
                  });
		     </script>";

        return $html;
    }
}
laravel-recaptcha/src/ReCaptchaBuilderV2.php000064400000007202151235006450014775 0ustar00<?php

/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - ReCaptchaBuilderV2.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 12/9/2018
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha;

use Biscolab\ReCaptcha\Exceptions\InvalidConfigurationException;
use Illuminate\Support\Arr;

/**
 * Class ReCaptchaBuilderV2
 * @package Biscolab\ReCaptcha
 */
class ReCaptchaBuilderV2 extends ReCaptchaBuilder
{

    protected static $allowed_data_attribute = [
        "theme",
        "size",
        "tabindex",
        "callback",
        "expired-callback",
        "error-callback",
    ];

    /**
     * ReCaptchaBuilderV2 constructor.
     *
     * @param string $api_site_key
     * @param string $api_secret_key
     */
    public function __construct(string $api_site_key, string $api_secret_key)
    {

        parent::__construct($api_site_key, $api_secret_key, 'v2');
    }

    /**
     * Write ReCAPTCHA HTML tag in your FORM
     * Insert before </form> tag
     * 
     * @param null|array $attributes
     * @return string
     */
    public function htmlFormSnippet(?array $attributes = []): string
    {

        $data_attributes = [];
        $config_data_attributes = array_merge($this->getTagAttributes(), self::cleanAttributes($attributes));
        ksort($config_data_attributes);
        foreach ($config_data_attributes as $k => $v) {
            if ($v) {
                $data_attributes[] = 'data-' . $k . '="' . $v . '"';
            }
        }

        $html = '<div class="g-recaptcha" ' . implode(" ", $data_attributes) . ' id="recaptcha-element"></div>';

        return $html;
    }

    /**
     * @return array
     * @throws InvalidConfigurationException
     */
    public function getTagAttributes(): array
    {

        $tag_attributes = [
            'sitekey' => $this->api_site_key
        ];

        $tag_attributes = array_merge($tag_attributes, config('recaptcha.tag_attributes', []));

        if (Arr::get($tag_attributes, 'callback') === ReCaptchaBuilder::DEFAULT_ONLOAD_JS_FUNCTION) {
            throw new InvalidConfigurationException('Property "callback" ("data-callback") must be different from "' . ReCaptchaBuilder::DEFAULT_ONLOAD_JS_FUNCTION . '"');
        }

        if (Arr::get($tag_attributes, 'expired-callback') === ReCaptchaBuilder::DEFAULT_ONLOAD_JS_FUNCTION) {
            throw new InvalidConfigurationException('Property "expired-callback" ("data-expired-callback") must be different from "' . ReCaptchaBuilder::DEFAULT_ONLOAD_JS_FUNCTION . '"');
        }

        if (Arr::get($tag_attributes, 'error-callback') === ReCaptchaBuilder::DEFAULT_ONLOAD_JS_FUNCTION) {
            throw new InvalidConfigurationException('Property "error-callback" ("data-error-callback") must be different from "' . ReCaptchaBuilder::DEFAULT_ONLOAD_JS_FUNCTION . '"');
        }

        return $tag_attributes;
    }

    /**
     * @return string
     */
    public function getOnLoadCallback(): string
    {

        $attributes = $this->getTagAttributes();

        return "<script>var biscolabOnloadCallback = function() {grecaptcha.render('recaptcha-element', " . json_encode($attributes) . ");};</script>";
    }

    /**
     * Compare given attributes with allowed attributes
     *
     * @param array|null $attributes
     * @return array
     */
    public static function cleanAttributes(?array $attributes = []): array
    {
        return array_filter($attributes, function ($k) {
            return in_array($k, self::$allowed_data_attribute);
        }, ARRAY_FILTER_USE_KEY);
    }
}
laravel-recaptcha/src/Exceptions/InvalidConfigurationException.php000064400000000661151235006450021544 0ustar00<?php
/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - InvalidConfigurationException.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 4/9/2019
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

namespace Biscolab\ReCaptcha\Exceptions;

class InvalidConfigurationException extends \Exception
{

}laravel-recaptcha/phpunit.xml.dist000064400000001460151235006450013277 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
  <coverage processUncoveredFiles="true">
    <include>
      <directory suffix=".php">./src</directory>
    </include>
    <exclude>
      <directory suffix=".php">./vendor</directory>
      <directory suffix=".php">./config</directory>
    </exclude>
  </coverage>
  <testsuites>
    <testsuite name="Unit">
      <directory>./tests</directory>
    </testsuite>
  </testsuites>
</phpunit>
laravel-recaptcha/composer.json000075500000003065151235006450012654 0ustar00{
    "name": "biscolab/laravel-recaptcha",
    "description": "Simple and painless Google reCAPTCHA package for Laravel framework",
    "license": "MIT",
    "type": "library",
    "keywords": [
        "recaptcha",
        "captcha",
        "laravel",
        "validation"
    ],
    "homepage": "https://biscolab.com/laravel-recaptcha",
    "authors": [
        {
            "name": "Roberto Belotti",
            "email": "roby.belotti@gmail.com",
            "homepage": "https://biscolab.com",
            "role": "Developer"
        }
    ],
    "require": {
        "php": "^7.3|^8.0",
        "illuminate/routing": "^7.0|^8.0|^9.0|^10.0|^11.0",
        "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0"
    },
    "require-dev": {
        "orchestra/testbench": "5.*|6.*|^7.0|^8.0|^9.0",
        "phpunit/phpunit": "^9.1|^10.5"
    },
    "autoload": {
        "psr-4": {
            "Biscolab\\ReCaptcha\\": "src/"
        },
        "files": [
            "src/helpers.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Biscolab\\ReCaptcha\\Tests\\": "tests/"
        }
    },
    "scripts": {
        "test": "vendor/bin/phpunit --colors=always"
    },
    "suggest": {
        "biscolab/laravel-authlog": "It allows to handle logged-in users and force log-out if needed"
    },
    "extra": {
        "laravel": {
            "providers": [
                "Biscolab\\ReCaptcha\\ReCaptchaServiceProvider"
            ],
            "aliases": {
                "ReCaptcha": "Biscolab\\ReCaptcha\\Facades\\ReCaptcha"
            }
        }
    }
}
laravel-recaptcha/config/recaptcha.php000064400000011671151235006450014041 0ustar00<?php

/**
 * Copyright (c) 2017 - present
 * LaravelGoogleRecaptcha - recaptcha.php
 * author: Roberto Belotti - roby.belotti@gmail.com
 * web : robertobelotti.com, github.com/biscolab
 * Initial version created on: 12/9/2018
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
 */

/**
 * To configure correctly please visit https://developers.google.com/recaptcha/docs/start
 */
return [

    /**
     *
     * The site key
     * get site key @ www.google.com/recaptcha/admin
     *
     */
    'api_site_key'                 => env('RECAPTCHA_SITE_KEY', ''),

    /**
     *
     * The secret key
     * get secret key @ www.google.com/recaptcha/admin
     *
     */
    'api_secret_key'               => env('RECAPTCHA_SECRET_KEY', ''),

    /**
     *
     * ReCATCHA version
     * Supported: "v2", "invisible", "v3",
     *
     * get more info @ https://developers.google.com/recaptcha/docs/versions
     *
     */
    'version'                      => 'v2',

    /**
     *
     * The curl timout in seconds to validate a recaptcha token
     * @since v3.5.0
     *
     */
    'curl_timeout'                 => 10,

    /**
     *
     * IP addresses for which validation will be skipped
     * IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed
     *
     */
    'skip_ip'                      => env('RECAPTCHA_SKIP_IP', []),

    /**
     *
     * Default route called to check the Google reCAPTCHA token
     * @since v3.2.0
     *
     */
    'default_validation_route'     => 'biscolab-recaptcha/validate',

    /**
     *
     * The name of the parameter used to send Google reCAPTCHA token to verify route
     * @since v3.2.0
     *
     */
    'default_token_parameter_name' => 'token',

    /**
     *
     * The default Google reCAPTCHA language code
     * It has no effect with v3
     * @see   https://developers.google.com/recaptcha/docs/language
     * @since v3.6.0
     *
     */
    'default_language'             => null,

    /**
     *
     * The default form ID. Only for "invisible" reCAPTCHA
     * @since v4.0.0
     *
     */
    'default_form_id'              => 'biscolab-recaptcha-invisible-form',

    /**
     *
     * Deferring the render can be achieved by specifying your onload callback function and adding parameters to the JavaScript resource.
     * It has no effect with v3 and invisible
     * @see   https://developers.google.com/recaptcha/docs/display#explicit_render
     * @since v4.0.0
     * Supported true, false
     *
     */
    'explicit'                     => false,

    /**
     *
     * Set API domain. You can use "www.recaptcha.net" in case "www.google.com" is not accessible.
     * (no check will be made on the entered value)
     * @see   https://developers.google.com/recaptcha/docs/faq#can-i-use-recaptcha-globally
     * @since v4.3.0
     * Default 'www.google.com' (ReCaptchaBuilder::DEFAULT_RECAPTCHA_API_DOMAIN)
     *
     */
    'api_domain'                   => 'www.google.com',

    /**
     *
     * Set `true` when the error message must be null
     * @since v5.1.0
     * Default false
     *
     */
    'empty_message' => false,

    /**
     *
     * Set either the error message or the errom message translation key
     * @since v5.1.0
     * Default 'validation.recaptcha'
     *
     */
    'error_message_key' => 'validation.recaptcha',

    /**
     *
     * g-recaptcha tag attributes and grecaptcha.render parameters (v2 only)
     * @see   https://developers.google.com/recaptcha/docs/display#render_param
     * @since v4.0.0
     */
    'tag_attributes'               => [

        /**
         * The color theme of the widget.
         * Supported "light", "dark"
         */
        'theme'            => 'light',

        /**
         * The size of the widget.
         * Supported "normal", "compact"
         */
        'size'             => 'normal',

        /**
         * The tabindex of the widget and challenge.
         * If other elements in your page use tabindex, it should be set to make user navigation easier.
         */
        'tabindex'         => 0,

        /**
         * The name of your callback function, executed when the user submits a successful response.
         * The g-recaptcha-response token is passed to your callback.
         * DO NOT SET "biscolabOnloadCallback"
         */
        'callback'         => null,

        /**
         * The name of your callback function, executed when the reCAPTCHA response expires and the user needs to re-verify.
         * DO NOT SET "biscolabOnloadCallback"
         */
        'expired-callback' => null,

        /**
         * The name of your callback function, executed when reCAPTCHA encounters an error (usually network connectivity) and cannot continue until connectivity is restored.
         * If you specify a function here, you are responsible for informing the user that they should retry.
         * DO NOT SET "biscolabOnloadCallback"
         */
        'error-callback'   => null,
    ]
];