From f42870797d3c8d36f6b428ced10c50f80933e831 Mon Sep 17 00:00:00 2001
From: Matthieu Benoist <matthieu.benoist@randstaddigital.fr>
Date: Fri, 22 Nov 2024 16:09:05 +0100
Subject: [PATCH] update to captchetat v2

---
 app/acfField/GLCaptchEtatField.class.php      | 13 +++---
 app/forms/CaptchEtatForms.class.php           | 32 ++++----------
 app/service/CaptchEtatService.class.php       | 12 +++---
 assets/scripts/gl-captchetat-form.js          | 43 +++++++++++++++----
 .../vendor/captchetat-js/captchetat-js.js     |  1 +
 .../jquery-capcha/jquery-captcha.min.js       |  2 -
 .../jquery-capcha/jquery-captcha.min.js.map   |  1 -
 assets/styles/styles.css                      |  5 +++
 wp-captchetat.php                             | 38 ++++++++--------
 9 files changed, 79 insertions(+), 68 deletions(-)
 create mode 100644 assets/scripts/vendor/captchetat-js/captchetat-js.js
 delete mode 100644 assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js
 delete mode 100644 assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js.map

diff --git a/app/acfField/GLCaptchEtatField.class.php b/app/acfField/GLCaptchEtatField.class.php
index 021b14d..fc1fe37 100644
--- a/app/acfField/GLCaptchEtatField.class.php
+++ b/app/acfField/GLCaptchEtatField.class.php
@@ -36,7 +36,7 @@ class GLCaptchEtatField extends acf_field
 
 		add_filter('acf/load_field/type=CaptchETAT', function($field) {
 			$this->key = $field['key'];
-			$field['key'] = 'captchaFormulaireExtInput' . $this->rand;
+			$field['key'] = 'captchaCode' . $this->rand;
 			$field['prefix'] = '';
 			
 			return $field;
@@ -93,9 +93,8 @@ class GLCaptchEtatField extends acf_field
 	{
 		if (!is_admin()) {
 			if ($this->ceService->getShowCaptcha()) {
-				$html = '<div id="botdetect-captcha'.rand().'" data-captchastylename="captchaFR"></div>
-						<input class="captchetat-acf" id="acf-captchaFormulaireExtInput'.$this->rand.'" name="acf['.$field['key'].']" placeholder="Tapez le code lu ou entendu" type="text" required/>
-						<input id="captchaId'.$this->rand.'" name="captchaId" type="hidden" />';
+				$html = '<div id="captchetat" captchaStyleName="captchaFR" urlBackend="' . rest_url('glcapt/simple-captcha-endpoint') . '"></div>
+						<input type="text" class="captchetat-acf" id="captchaCode" aria-label="Code de vérification" name="acf['.$field['key'].']" placeholder="Tapez le code lu ou entendu" required/>';
 			} else {
 				$html =
 					'<div>'
@@ -139,7 +138,7 @@ class GLCaptchEtatField extends acf_field
 		$form_contains_captcha = false;
 		$valid = false;
 		//if the service captchetat is not available the captcha is not shown so no validation needed
-		if (isset($_SESSION['captchETAT']) && $_SESSION['captchETAT'] == $_POST['BDC_VCID_captchaFR']) {
+		if (isset($_SESSION['captchETAT']) && $_SESSION['captchETAT'] == $_POST['captchetat-uuid']) {
 			unset($_SESSION['captchETAT']);
 			return;
 		}
@@ -149,11 +148,11 @@ class GLCaptchEtatField extends acf_field
 			//			var_dump($field);
 			if ($field['type'] === 'CaptchETAT') {
 				$form_contains_captcha = true; // we have a captcha
-				$valid = $this->ceService->validateCaptcha($value,$_POST['BDC_VCID_captchaFR']); 
+				$valid = $this->ceService->validateCaptcha($value,$_POST['captchetat-uuid']); 
 				if ($valid == true) { 
 					unset($_POST['acf']['$field_key']);
 					if (defined('DOING_AJAX') && DOING_AJAX) {
-						$_SESSION['captchETAT'] = $_POST['BDC_VCID_captchaFR'];
+						$_SESSION['captchETAT'] = $_POST['captchetat-uuid'];
 					}
 					return;
 				}
diff --git a/app/forms/CaptchEtatForms.class.php b/app/forms/CaptchEtatForms.class.php
index 5b611ef..dace676 100644
--- a/app/forms/CaptchEtatForms.class.php
+++ b/app/forms/CaptchEtatForms.class.php
@@ -106,29 +106,15 @@ class CaptchEtatForms
     private function addGLCaptchetaScripts() 
     {
          //captchetat library
-         wp_enqueue_script('captchetat_script', WP_CAPTCHETAT_PLUGIN_URL . 'assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js');
-         //our js 
-         wp_enqueue_script('captchetat_plugin_form_integration', WP_CAPTCHETAT_PLUGIN_URL . 'assets/scripts/gl-captchetat-form.js');
-         
+         wp_enqueue_script('captchetat_script', WP_CAPTCHETAT_PLUGIN_URL . 'assets/scripts/vendor/captchetat-js/captchetat-js.js');
          wp_enqueue_style('captchetat_style', WP_CAPTCHETAT_PLUGIN_URL . 'assets/styles/styles.css');
-         wp_add_inline_script(
-             'captchetat_plugin_form_integration',
-             'const GLCAPTPARAMS = ' .
-                 json_encode(
-                     array(
-                         'backendUrl' => rest_url('glcapt/simple-captcha-endpoint')
-                     )
-                 ),
-             'before'
-         );
     }
 
     private function getGLCaptchetatHtml() 
     {
         ?>
-            <div id="botdetect-captcha" data-captchastylename="captchaFR"></div>
-            <input aria-label="Code de vérification" id="captchaFormulaireExtInput" class = "captchetat-input" name="userEnteredCaptchaCode" type="text" required placeholder="Tapez le code lu ou entendu" />
-            <input id="captchaId" name="captchaId" type="hidden" />
+            <div id="captchetat" captchaStyleName="captchaFR" urlBackend="<?php echo rest_url('glcapt/simple-captcha-endpoint'); ?>"></div>
+            <input type="text" class="captchetat-input" placeholder="Tapez le code lu ou entendu" aria-label="Code de vérification" name="userEnteredCaptchaCode" id="captchaCode" required/>
         <?php
     }
 
@@ -141,11 +127,12 @@ class CaptchEtatForms
         if (is_wp_error($user) && isset($user->errors['empty_username']) && isset($user->errors['empty_password'])) {
             return $user;
         }
-        if (empty($_POST['captchaId'])) {
+
+        if (empty($_POST['captchetat-uuid'])) {
             return new WP_Error('captcha_librairy_error', __('Problème avec le système de validation captchetat'));
         } elseif (empty($_POST['userEnteredCaptchaCode'])) {
             return new WP_Error('captcha_empty', __('Merci de saisir le code de validation'));
-        } elseif (!$this->wpcService->validateCaptcha($_POST['userEnteredCaptchaCode'], $_POST['captchaId'])) {
+        } elseif (!$this->wpcService->validateCaptcha($_POST['userEnteredCaptchaCode'], $_POST['captchetat-uuid'])) {
             return new WP_Error('captcha_invalide', __('Le captcha saisi est invalide'));
         } 
         return $user;
@@ -154,15 +141,15 @@ class CaptchEtatForms
     private function validateCommentCaptcha() 
     {
         $error = new WP_ERROR;
-        if (empty($_POST['captchaId'])) {
+        if (empty($_POST['captchetat-uuid'])) {
             $error->add('captcha_librairy_error', wp_kses_post(__('Problème avec le système de validation captchetat')));
         } elseif (empty($_POST['userEnteredCaptchaCode'])) {
             $error->add('captcha_empty', wp_kses_post(__('Merci de saisir le code (captcha) de validation')));
-        } elseif (!$this->wpcService->validateCaptcha($_POST['userEnteredCaptchaCode'], $_POST['captchaId'])) {
+        } elseif (!$this->wpcService->validateCaptcha($_POST['userEnteredCaptchaCode'], $_POST['captchetat-uuid'])) {
             $error->add('captcha_invalide', wp_kses_post(__('Le captcha saisi est invalide')));
         }
         if ($error->has_errors()) {
-            wp_die($error, "erreur de captcha", ["back_link" => true]);
+            wp_die(__('Le captcha saisi est invalide'), "erreur de captcha", ["back_link" => true]);
         }
     }
 
@@ -181,7 +168,6 @@ class CaptchEtatForms
                     die();
                 },
                 'permission_callback' => function() {return true;},
-
             ]
         );
     }
diff --git a/app/service/CaptchEtatService.class.php b/app/service/CaptchEtatService.class.php
index 926c3e4..033dd20 100644
--- a/app/service/CaptchEtatService.class.php
+++ b/app/service/CaptchEtatService.class.php
@@ -51,7 +51,6 @@ class CaptchEtatService
      */
     protected function _call($url, $method = 'GET', $options = []): array
     {
-
         if ($method === 'GET') {
             $response = wp_remote_get($url, $options);
         } elseif ($method === 'POST') {
@@ -68,6 +67,7 @@ class CaptchEtatService
                 implode('\r ' , $response->get_error_messages()),
                 1);
         }
+     
         if ($response['response']['code'] === 200) {
             return $response;
         } else {
@@ -112,13 +112,12 @@ class CaptchEtatService
      */
     public function getToken(): string
     {
-
         //first, verify if we have a token already registered in wp_options
         $tokenData = $this->wpcPlugin->getTokenData();
         //test s'il en existe déjà un valable
         if (!empty($tokenData) && time() < $tokenData['expire']) {
             return $tokenData['access_token'];
-        } 
+        }
 
         try {
             $apiParams = [
@@ -207,7 +206,7 @@ class CaptchEtatService
                     'Authorization' => 'Bearer ' . $this->getToken(),
                     'Content-Type' => 'application/json'
                 ],
-                'body' => json_encode(['code' => $code, 'id' => $id])
+                'body' => json_encode(['code' => $code, 'uuid' => $id])
             ];
 
             try {
@@ -216,7 +215,10 @@ class CaptchEtatService
                 $return = $response['body'] == 'false' ? false : true;
             } catch (\Exception $e) {
                 // log, display, etc
-                throw new \Exception('validate captcha error '. $e->getCode() . " : " . $e->getMessage(), $e->getCode());
+                error_log('validate captcha error '. $e->getCode() . " : " . $e->getMessage(), $e->getCode());
+                
+                return false;
+               // throw new \Exception('validate captcha error '. $e->getCode() . " : " . $e->getMessage(), $e->getCode());
             }
         }
 
diff --git a/assets/scripts/gl-captchetat-form.js b/assets/scripts/gl-captchetat-form.js
index 9e1b4d0..91213f5 100644
--- a/assets/scripts/gl-captchetat-form.js
+++ b/assets/scripts/gl-captchetat-form.js
@@ -1,15 +1,40 @@
-jQuery(document).ready(function () {
-    if (jQuery('div[id^="botdetect-captcha"').length > 0) {
-        var captcha =
-        jQuery('div[id^="botdetect-captcha"').captcha({
-            captchaEndpoint:  GLCAPTPARAMS.backendUrl
+/* jQuery(document).ready(function () {
+    if (jQuery('div[id^="captchetat"').length > 0) {
+        jQuery('div[id^="captchetat"').submit(function(event) {
+            // Le code entré par l’utilisateur récupéré en backend
+            var captchaCode = document.getElementById('captchaCode').value;
+            // id du captcha que l’utilisateur a tenté de résoudre
+            var captchaUuid = document.getElementById('captchetat-uuid').value;
+            var postData = { uuid: captchaUuid, code: captchaCode };
+            // Envoi des données du captcha côté backend
+            $.ajax({
+                method: 'POST',
+                url: '/glcapt/validateCaptcha',
+                dataType: 'json',
+                contentType: 'application/json; charset=utf-8',
+                data: JSON.stringify(postData),
+                success: function(response) {
+                    if (response.success == false) {
+                        // La validation a échoué. Le captcha est rechargé
+                        window.captchetatComponentModule.refreshCaptcha(); // afficher message d’erreur
+                    }
+                }
+            });
+            
+            event.preventDefault();
         });
-        var glCaptForm = jQuery('div[id^="botdetect-captcha"').closest('form');
+    }
+}); */
+
+jQuery(document).ready(function () {
+    if (jQuery('div[id^="captchetat"').length > 0) {
+        var glCaptForm = jQuery('div[id^="captchetat"').closest('form');
 
        jQuery(glCaptForm).submit(function (event) {
+            // id du captcha que l’utilisateur a tenté de résoudre
+            var captchaUuid = document.getElementById('captchetat-uuid').value;
             // Le code entré par l’utilisateur récupéré en backend
-            jQuery('input[id^="captchaId"').val(captcha.getCaptchaId());
+            jQuery('input[id^="captchaId"').val(captchaUuid);
         });
     }
-});
-
+})
diff --git a/assets/scripts/vendor/captchetat-js/captchetat-js.js b/assets/scripts/vendor/captchetat-js/captchetat-js.js
new file mode 100644
index 0000000..fb59323
--- /dev/null
+++ b/assets/scripts/vendor/captchetat-js/captchetat-js.js
@@ -0,0 +1 @@
+!function(){"use strict";let e,t,n,a,c;async function refreshCaptcha(){let n=e+"?get=image&c="+t;await fetch(n,{method:"GET",headers:{"Content-Type":"application/json"}}).then((e=>{if(!e.ok)throw new Error("La réponse n'est pas OK");return e.json()})).then((e=>{document.getElementById("captchaImage").src=e.imageb64,c=e.uuid,document.getElementById("captchetat-uuid").setAttribute("value",c)})).catch((e=>{console.error("Erreur lors de la récupération du captcha")}))}async function playCaptchaSound(){let n=e+"?get=sound&c="+t+"&t="+c;try{await new Audio(n).play()}catch(e){console.error("Erreur lors de la récupération du son"),await refreshCaptcha()}}window.addEventListener("load",(function(){a=document.getElementById("captchetat"),a&&(e=a.getAttribute("urlBackend"),t=a.getAttribute("captchaStyleName"),n=a.getAttribute("altImage"),async function getCaptcha(){let a=e+"?get=image&c="+t;await fetch(a,{method:"GET",headers:{"Content-Type":"application/json"}}).then((e=>{if(!e.ok)throw new Error("La réponse n'est pas OK");return e.json()})).then((e=>{c=e.uuid,function constructHtml(e){const t=document.createElement("div");t.style.display="flex",t.style.flexDirection="row",t.id="captchetat-container",document.getElementById("captchetat").appendChild(t);const a=document.createElement("img");a.src=`${e}`,a.alt=n??"Recopier le code de sécurité de cette image",a.id="captchaImage",document.getElementById("captchetat-container").appendChild(a);const o=document.createElement("div");o.id="logos",o.style.marginLeft="10px",o.style.display="flex",o.style.flexDirection="column",o.style.justifyContent="space-evenly",document.getElementById("captchetat-container").appendChild(o);const d=document.createElement("button");d.type="button",d.id="playSoundIcon",d.title="Speak the captcha code",d.alt="Enoncer le code du captcha",d.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" version="1.0" width="25" height="25" viewBox="0 0 75 75"\n                     id="iconSound">\n                    <path d="M39.389,13.769 L22.235,28.606 L6,28.606 L6,47.699 L21.989,47.699 L39.389,62.75 L39.389,13.769z"\n                          style="stroke:#111;stroke-width:5;stroke-linejoin:round;fill:#111;"/>\n                    <path d="M48,27.6a19.5,19.5 0 0 1 0,21.4M55.1,20.5a30,30 0 0 1 0,35.6M61.6,14a38.8,38.8 0 0 1 0,48.6"\n                          style="fill:none;stroke:#111;stroke-width:5;stroke-linecap:round"/>\n                </svg>',document.getElementById("logos").appendChild(d),document.getElementById("playSoundIcon").addEventListener("click",playCaptchaSound);const r=document.createElement("button");r.type="button",r.id="reloadCaptchaIcon",r.title="Generate a new captcha",r.alt="Générer un nouveau captcha",r.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 17 20" fill="none"\n                     id="iconReload">\n                    <path d="M9.00003 4.0001C11.1 4.0001 13.1 4.8001 14.6 6.3001C17.7 9.4001 17.7 14.5001 14.6 17.6001C12.8 19.5001 10.3 20.2001 7.90003 19.9001L8.40003 17.9001C10.1 18.1001 11.9 17.5001 13.2 16.2001C15.5 13.9001 15.5 10.1001 13.2 7.7001C12.1 6.6001 10.5 6.0001 9.00003 6.0001V10.6001L4.00003 5.6001L9.00003 0.600098V4.0001ZM3.30003 17.6001C0.700029 15.0001 0.300029 11.0001 2.10003 7.9001L3.60003 9.4001C2.50003 11.6001 2.90003 14.4001 4.80003 16.2001C5.30003 16.7001 5.90003 17.1001 6.60003 17.4001L6.00003 19.4001C5.00003 19.0001 4.10003 18.4001 3.30003 17.6001V17.6001Z"\n                          fill="black"/>\n                </svg>',document.getElementById("logos").appendChild(r),document.getElementById("reloadCaptchaIcon").addEventListener("click",refreshCaptcha);const l=document.createElement("input");l.id="captchetat-uuid",l.type="hidden",l.value=c,l.name="captchetat-uuid",document.getElementById("captchetat").appendChild(l)}(e.imageb64),function setButtonTitle(){t.includes("FR")&&(document.getElementById("playSoundIcon").setAttribute("title","Énoncer le code du captcha"),document.getElementById("reloadCaptchaIcon").setAttribute("title","Générer un nouveau captcha"))}()})).catch((e=>{console.error("Erreur lors de la récupération du captcha")}))}())})),window.captchetatComponentModule={refreshCaptcha}}();
\ No newline at end of file
diff --git a/assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js b/assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js
deleted file mode 100644
index 1159842..0000000
--- a/assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(a){"use strict";a.fn.captcha=function(b){function c(){return a.ajax({method:"GET",url:b.captchaEndpoint,data:{get:"html",c:p}})}function d(b,c){var d=j();a.ajax({method:"GET",url:d.validationUrl,data:{i:b},success:function(a){c(a)}})}function e(){var b=j();a("#"+b.options.userInputID).on("blur",function(){var c=a.trim(a(this).val());if(0!==c.length){var e=this;d(c,function(c){c||b.reloadImage(),a(e).trigger("validatecaptcha",[c])})}})}function f(b,c){return c=a.extend({dataType:"script",cache:!1,url:b},c||{}),a.ajax(c)}function g(){var c=a("#BDC_VCID_"+p).val();f(b.captchaEndpoint+"?get=script-include&c="+p+"&t="+c+"&cs=2").done(function(){setTimeout(i,200)})}function h(){var b=j();return void 0!==a("#"+b.options.userInputID).attr("data-correct-captcha")}function i(){h()&&e()}function j(){return void 0!==window.botdetect?window.botdetect.getInstanceByStyleName(p):null}function k(){var a=b.captchaEndpoint.split("/");return a[a.length-1]}function l(a){var c=b.captchaEndpoint.lastIndexOf(a);return b.captchaEndpoint.substring(0,c)}function m(a){var b=k(),c=l(b);a=a.replace(/<script.*<\/script>/g,"");for(var d,e,f,g=a.match(/(src|href)=\"([^"]+)\"/g),h=a,i=0;i<g.length;i++)d=g[i].slice(0,-1).replace(/src=\"|href=\"/,""),e=new RegExp(".*"+b),f=d.replace(e,c+b),h=h.replace(d,f);return h}function n(){c(b.captchaEndpoint,p).done(function(a){a=m(a),o.html(a),g()})}var o=this;if(0===o.length)throw new Error("Captcha html element cound not be found.");if(!b||!b.captchaEndpoint)throw new Error("The captchaEndpoint setting is required.");b.captchaEndpoint=b.captchaEndpoint.replace(/\/+$/g,"");var p=function(){var a;if(a=o.data("captchastylename"))return a;if(a=o.data("stylename"))return a;throw new Error("The data-captchastylename attribute is not found or its value is not set.")}();return o.init=function(){return n(),o},o.getCaptchaId=function(){return j().captchaId},o.getCaptchaCode=function(){return j().userInput.value},o.getUserEnteredCaptchaCode=function(){return o.getCaptchaCode()},o.reloadImage=function(){j().reloadImage()},o.validateUnsafe=function(b){var c=j();d(a.trim(a("#"+c.options.userInputID).val()),function(a){b(a),h()||a||c.reloadImage()})},o.init()}}(jQuery);
-//# sourceMappingURL=jquery-captcha.min.js.map
\ No newline at end of file
diff --git a/assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js.map b/assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js.map
deleted file mode 100644
index b73f4a1..0000000
--- a/assets/scripts/vendor/jquery-capcha/jquery-captcha.min.js.map
+++ /dev/null
@@ -1 +0,0 @@
-{"version":3,"sources":["../src/jquery-captcha.js"],"names":["$","fn","captcha","settings","_getHtml","ajax","method","url","captchaEndpoint","data","get","c","captchaStyleName","_validateUnsafe","captchaCode","onSuccess","instance","_getInstance","validationUrl","i","success","isCorrect","_registerUserInputBlurValidation","options","userInputID","on","trim","this","val","length","reloadImage","trigger","_getScript","extend","dataType","cache","_loadScriptIncludes","captchaId","done","setTimeout","_onLoadScriptsSuccess","_useUserInputBlurValidation","undefined","attr","window","botdetect","getInstanceByStyleName","_getCaptchaEndpointHandler","splited","split","_getBackendBaseUrl","captchaEndpointHandler","lastIndex","lastIndexOf","substring","_changeRelativeToAbsoluteUrls","originCaptchaHtml","backendUrl","replace","relativeUrl","relativeUrlPrefixPattern","absoluteUrl","relativeUrls","match","changedCaptchaHtml","slice","RegExp","_displayHtml","captchaHtml","element","html","Error","styleName","init","getCaptchaId","getCaptchaCode","userInput","value","getUserEnteredCaptchaCode","validateUnsafe","callback","isHuman","jQuery"],"mappings":"CAAC,SAASA,GACR,YAEAA,GAAEC,GAAGC,QAAU,SAASC,GAoCtB,QAASC,KACP,MAAOJ,GAAEK,MACPC,OAAQ,MACRC,IAAKJ,EAASK,gBACdC,MACEC,IAAK,OACLC,EAAGC,KAMT,QAASC,GAAgBC,EAAaC,GACpC,GAAIC,GAAWC,GAEfjB,GAAEK,MACAC,OAAQ,MACRC,IAAKS,EAASE,cACdT,MACEU,EAAGL,GAELM,QAAS,SAAUC,GACjBN,EAAUM,MAOhB,QAASC,KACP,GAAIN,GAAWC,GAEfjB,GAAE,IAAMgB,EAASO,QAAQC,aAAaC,GAAG,OAAQ,WAC/C,GAAIX,GAAcd,EAAE0B,KAAK1B,EAAE2B,MAAMC,MACjC,IAA2B,IAAvBd,EAAYe,OAAhB,CAEA,GAAIL,GAAcG,IAClBd,GAAgBC,EAAa,SAASO,GAC/BA,GACHL,EAASc,cAEX9B,EAAEwB,GAAaO,QAAQ,mBAAoBV,SAMjD,QAASW,GAAWzB,EAAKgB,GAMvB,MALAA,GAAUvB,EAAEiC,QACVC,SAAU,SACVC,OAAO,EACP5B,IAAKA,GACJgB,OACIvB,EAAEK,KAAKkB,GAIhB,QAASa,KACP,GAAIC,GAAYrC,EAAE,aAAeY,GAAkBgB,KAEnDI,GADuB7B,EAASK,gBAAkB,yBAA2BI,EAAmB,MAAQyB,EAAY,SACvFC,KAAK,WAChCC,WAAWC,EAAuB,OAKtC,QAASC,KACP,GAAIzB,GAAWC,GACf,YAA+EyB,KAAvE1C,EAAE,IAAMgB,EAASO,QAAQC,aAAamB,KAAK,wBAIrD,QAASH,KACHC,KACFnB,IAKJ,QAASL,KAEP,WAAgC,KAArB2B,OAAOC,UACTD,OAAOC,UAAUC,uBAAuBlC,GAFlC,KAUjB,QAASmC,KACP,GAAIC,GAAU7C,EAASK,gBAAgByC,MAAM,IAC7C,OAAOD,GAAQA,EAAQnB,OAAS,GAIlC,QAASqB,GAAmBC,GAC1B,GAAIC,GAAYjD,EAASK,gBAAgB6C,YAAYF,EACrD,OAAOhD,GAASK,gBAAgB8C,UAAU,EAAGF,GAI/C,QAASG,GAA8BC,GACrC,GAAIL,GAAyBJ,IACzBU,EAAaP,EAAmBC,EAEpCK,GAAoBA,EAAkBE,QAAQ,uBAAwB,GAMtE,KAAK,GAHDC,GAAaC,EAA0BC,EAFvCC,EAAeN,EAAkBO,MAAM,2BAGvCC,EAAqBR,EAEhBrC,EAAI,EAAGA,EAAI2C,EAAajC,OAAQV,IACvCwC,EAAcG,EAAa3C,GAAG8C,MAAM,GAAI,GAAGP,QAAQ,iBAAkB,IACrEE,EAA2B,GAAIM,QAAO,KAAOf,GAC7CU,EAAcF,EAAYD,QAAQE,EAA0BH,EAAaN,GACzEa,EAAqBA,EAAmBN,QAAQC,EAAaE,EAG/D,OAAOG,GAIT,QAASG,KACP/D,EAASD,EAASK,gBAAiBI,GAAkB0B,KAAK,SAAS8B,GACjEA,EAAcb,EAA8Ba,GAC5CC,EAAQC,KAAKF,GACbhC,MAjKJ,GAAIiC,GAAU1C,IAEd,IAAuB,IAAnB0C,EAAQxC,OACV,KAAM,IAAI0C,OAAM,2CAGlB,KAAKpE,IAAaA,EAASK,gBACzB,KAAM,IAAI+D,OAAM,2CAIlBpE,GAASK,gBAAkBL,EAASK,gBAAgBkD,QAAQ,QAAS,GAErE,IAAI9C,GAGJ,WACE,GAAI4D,EAGJ,IADAA,EAAYH,EAAQ5D,KAAK,oBAEvB,MAAO+D,EAKT,IADAA,EAAYH,EAAQ5D,KAAK,aAEvB,MAAO+D,EAGT,MAAM,IAAID,OAAM,+EAgLlB,OAxCAF,GAAQI,KAAO,WAEb,MADAN,KACOE,GAITA,EAAQK,aAAe,WAErB,MADezD,KACCoB,WAKlBgC,EAAQM,eAAiB,WAEvB,MADe1D,KACC2D,UAAUC,OAG5BR,EAAQS,0BAA4B,WAClC,MAAOT,GAAQM,kBAIjBN,EAAQvC,YAAc,WACLb,IACNa,eAIXuC,EAAQU,eAAiB,SAASC,GAChC,GAAIhE,GAAWC,GAEfJ,GADkBb,EAAE0B,KAAK1B,EAAE,IAAMgB,EAASO,QAAQC,aAAaI,OAClC,SAASqD,GACpCD,EAASC,GACJxC,KAAkCwC,GACrCjE,EAASc,iBAKRuC,EAAQI,SAGjBS","file":"jquery-captcha.min.js","sourcesContent":["(function($) {\r\n  'use strict';\r\n  \r\n  $.fn.captcha = function(settings) {\r\n    \r\n    var element = this;\r\n    \r\n    if (element.length === 0) {\r\n      throw new Error('Captcha html element cound not be found.');\r\n    }\r\n\r\n    if (!settings || !settings.captchaEndpoint) {\r\n      throw new Error('The captchaEndpoint setting is required.');\r\n    }\r\n    \r\n    // normalize captcha endpoint path\r\n    settings.captchaEndpoint = settings.captchaEndpoint.replace(/\\/+$/g, '');\r\n    \r\n    var captchaStyleName = _getCaptchaStyleName();\r\n  \r\n    // get captcha style name\r\n    function _getCaptchaStyleName() {\r\n      var styleName;\r\n\r\n      styleName = element.data('captchastylename');\r\n      if (styleName) {\r\n        return styleName;\r\n      }\r\n\r\n      // backward compatibility\r\n      styleName = element.data('stylename');\r\n      if (styleName) {\r\n        return styleName;\r\n      }\r\n\r\n      throw new Error('The data-captchastylename attribute is not found or its value is not set.');\r\n    };\r\n    \r\n    // get captcha html markup\r\n    function _getHtml() {\r\n      return $.ajax({\r\n        method: 'GET',\r\n        url: settings.captchaEndpoint,\r\n        data: {\r\n          get: 'html',\r\n          c: captchaStyleName\r\n        }\r\n      });\r\n    };\r\n\r\n    // ajax validate captcha\r\n    function _validateUnsafe(captchaCode, onSuccess) {\r\n      var instance = _getInstance();\r\n\r\n      $.ajax({\r\n        method: 'GET',\r\n        url: instance.validationUrl,\r\n        data: {\r\n          i: captchaCode\r\n        },\r\n        success: function (isCorrect) {\r\n          onSuccess(isCorrect);\r\n        }\r\n      });\r\n    };\r\n    \r\n    // ajax validate captcha on blur event and trigging the \r\n    // custom 'validatecaptcha' event to fire the validation result\r\n    function _registerUserInputBlurValidation() {\r\n      var instance = _getInstance();\r\n\r\n      $('#' + instance.options.userInputID).on('blur', function() {\r\n        var captchaCode = $.trim($(this).val());\r\n        if (captchaCode.length === 0) { return; }\r\n\r\n        var userInputID = this;\r\n        _validateUnsafe(captchaCode, function(isCorrect) {\r\n          if (!isCorrect) {\r\n            instance.reloadImage();\r\n          }\r\n          $(userInputID).trigger('validatecaptcha', [isCorrect]);\r\n        });\r\n      });\r\n    };\r\n    \r\n    // a custom of $.getScript(), which lets changing the options\r\n    function _getScript(url, options) {\r\n      options = $.extend({\r\n        dataType: 'script',\r\n        cache: false,\r\n        url: url\r\n      }, options || {});\r\n      return $.ajax(options);\r\n    };\r\n    \r\n    // load botdetect scripts and execute them\r\n    function _loadScriptIncludes() {\r\n      var captchaId = $('#BDC_VCID_' + captchaStyleName).val();\r\n      var scriptIncludeUrl = settings.captchaEndpoint + '?get=script-include&c=' + captchaStyleName + '&t=' + captchaId + '&cs=2';\r\n      _getScript(scriptIncludeUrl).done(function() {\r\n        setTimeout(_onLoadScriptsSuccess, 200);\r\n      });\r\n    };\r\n    \r\n    // use user input blur validation if the input element has data-correct-captcha attribute\r\n    function _useUserInputBlurValidation() {\r\n      var instance = _getInstance();\r\n      return ($('#' + instance.options.userInputID).attr('data-correct-captcha') !== undefined);\r\n    };\r\n    \r\n    // fire the custom event when botdetect scripts are loaded\r\n    function _onLoadScriptsSuccess() {\r\n      if (_useUserInputBlurValidation()) {\r\n        _registerUserInputBlurValidation();\r\n      }\r\n    }\r\n    \r\n    // get botdetect captcha client-side instance\r\n    function _getInstance() {\r\n      var instance = null;\r\n      if (typeof window.botdetect !== 'undefined') {\r\n        return window.botdetect.getInstanceByStyleName(captchaStyleName);\r\n      }\r\n      return instance;\r\n    };\r\n\r\n    // get captcha endpoint handler from configued captchaEndpoint value,\r\n    // the result can be \"simple-captcha-endpoint.ashx\", \"botdetectcaptcha\",\r\n    // or \"simple-botdetect.php\"\r\n    function _getCaptchaEndpointHandler() {\r\n      var splited = settings.captchaEndpoint.split('/');\r\n      return splited[splited.length - 1];\r\n    };\r\n\r\n    // get backend base url from configued captchaEndpoint value\r\n    function _getBackendBaseUrl(captchaEndpointHandler) {\r\n      var lastIndex = settings.captchaEndpoint.lastIndexOf(captchaEndpointHandler);\r\n      return settings.captchaEndpoint.substring(0, lastIndex);\r\n    };\r\n\r\n    // change relative to absolute urls in captcha html markup\r\n    function _changeRelativeToAbsoluteUrls(originCaptchaHtml) {\r\n      var captchaEndpointHandler = _getCaptchaEndpointHandler();\r\n      var backendUrl = _getBackendBaseUrl(captchaEndpointHandler);\r\n\r\n      originCaptchaHtml = originCaptchaHtml.replace(/<script.*<\\/script>/g, '');\r\n      var relativeUrls = originCaptchaHtml.match(/(src|href)=\\\"([^\"]+)\\\"/g);\r\n      \r\n      var relativeUrl, relativeUrlPrefixPattern, absoluteUrl,\r\n          changedCaptchaHtml = originCaptchaHtml;\r\n\r\n      for (var i = 0; i < relativeUrls.length; i++) {\r\n        relativeUrl = relativeUrls[i].slice(0, -1).replace(/src=\\\"|href=\\\"/, '');\r\n        relativeUrlPrefixPattern = new RegExp(\".*\" + captchaEndpointHandler);\r\n        absoluteUrl = relativeUrl.replace(relativeUrlPrefixPattern, backendUrl + captchaEndpointHandler);\r\n        changedCaptchaHtml = changedCaptchaHtml.replace(relativeUrl, absoluteUrl);\r\n      }\r\n\r\n      return changedCaptchaHtml;\r\n    };\r\n    \r\n    // display captcha html markup in view\r\n    function _displayHtml() {\r\n      _getHtml(settings.captchaEndpoint, captchaStyleName).done(function(captchaHtml) {\r\n        captchaHtml = _changeRelativeToAbsoluteUrls(captchaHtml) ;\r\n        element.html(captchaHtml);\r\n        _loadScriptIncludes();\r\n      });\r\n    }\r\n    \r\n    // plugin initialization - we display the captcha html markup in view\r\n    element.init = function() {\r\n      _displayHtml();\r\n      return element;\r\n    };\r\n    \r\n    // captcha id for validating captcha at server-side\r\n    element.getCaptchaId = function() {\r\n      var instance = _getInstance();\r\n      return instance.captchaId;\r\n    };\r\n\r\n    // get the user entered captcha code\r\n    // keep this function for backward compatibility\r\n    element.getCaptchaCode = function() {\r\n      var instance = _getInstance();\r\n      return instance.userInput.value;\r\n    };\r\n\r\n    element.getUserEnteredCaptchaCode = function() {\r\n      return element.getCaptchaCode();\r\n    };\r\n    \r\n    // reload new captcha image\r\n    element.reloadImage = function() {\r\n      var instance = _getInstance();\r\n      instance.reloadImage();\r\n    };\r\n\r\n    // validate captcha on client-side and execute user callback function on ajax success\r\n    element.validateUnsafe = function(callback) {\r\n      var instance = _getInstance();\r\n      var captchaCode = $.trim($('#' + instance.options.userInputID).val());\r\n      _validateUnsafe(captchaCode, function(isHuman) {\r\n        callback(isHuman);\r\n        if (!_useUserInputBlurValidation() && !isHuman) {\r\n          instance.reloadImage();\r\n        }\r\n      });\r\n    };\r\n\r\n    return element.init();\r\n  };\r\n  \r\n}(jQuery));\r\n"]}
\ No newline at end of file
diff --git a/assets/styles/styles.css b/assets/styles/styles.css
index 1996b10..3a27aef 100644
--- a/assets/styles/styles.css
+++ b/assets/styles/styles.css
@@ -4,6 +4,11 @@
     outline: none;
 }
 
+#captchetat-container {
+    min-height: 90px;
+    margin-bottom: 5px;
+}
+
 .captchetat-input::placeholder {
     opacity: 0.8;
     font-size: 1rem;
diff --git a/wp-captchetat.php b/wp-captchetat.php
index 5650671..f21d682 100644
--- a/wp-captchetat.php
+++ b/wp-captchetat.php
@@ -3,33 +3,20 @@
  * CAPTCHETAT for WordPress by Metropole de Lyon
  * 
  * @copyright Copyright (C) 2023 - Métropole de Lyon
- * @license   ?
+ * @license   GPL
  *
  * @wordpress-plugin
  * Plugin Name: CAPTCHETAT for WordPress by Metropole de Lyon
  * Version:     0.1
  * Description: Implementation of the CaptchEtat API for WordPress (see https://api.gouv.fr/les-api/api-captchetat)
- * Author: Yohan RICCI, Matthieu BENOIST, Randstad Digital France
+ * Author: Yohan RICCI, Matthieu BENOIST, Randstad Digital
  * Author URI:  
- * License:  GPL v3 
+ * License:  GPL
  * Requires at least: 5.2
  * Requires PHP: 7.0
  *
  * WC requires at least: 5.2
- * WC tested up to: 6.2
- *
- * This 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 3 of the License, or
- * (at your option) any later version.
- *
- * This 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, see <http://www.gnu.org/licenses/>.
+ * WC tested up to: 6.1
  */
 
  namespace CaptchEtat;
@@ -44,6 +31,7 @@ use CaptchEtat\AcfField\GLCaptchEtatField;
 	exit;
 }
 
+
 if (!defined('WP_CAPTCHETAT_VERSION')) {
     define ('WP_CAPTCHETAT_VERSION', '0?1');
 }
@@ -69,7 +57,15 @@ if (function_exists('acf_register_field_type') ) {
     });
 }
 
-//admin page
-$admin = CaptchEtatAdmin::register();
-//forms action for displayin and validating captchas with the capchetat library 
-$forms = CaptchEtatForms::register();
+if (class_exists('WpcPlugin') || true) {
+    //$plugin = WpcPlugin::register();
+    //admin page
+    $admin = CaptchEtatAdmin::register();
+    //forms action for displayin and validating captchas with the capchetat library 
+    $forms = CaptchEtatForms::register();
+}
+
+
+
+
+
-- 
GitLab