Skip to content

Commit df0e106

Browse files
author
Gravity Forms
committed
Updates to 1.5.0
1 parent 3b59410 commit df0e106

File tree

10 files changed

+117
-48
lines changed

10 files changed

+117
-48
lines changed

change_log.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1+
## 1.5.0 | 2024-04-30
2+
- Fixed an issue where duplicate entries are created when using Conversational Forms with reCAPTCHA v3.
3+
- Fixed an issue where form submission hangs after Stripe 3DS validation.
4+
- Fixed an issue where all REST API submissions are marked as spam.
5+
- Note: If used alongside the Stripe Add-On, this version of the reCAPTCHA Add-On requires version 5.5.0 or later of the Stripe Add-On.
6+
17
## 1.4.0 | 2024-01-17
28
- Fixed an issue where reCaptcha v3 validation is not triggered when using the Stripe Payment Element.
39
- Fixed the PHP 8.2 creation of dynamic property deprecation notice that occurs on form submission.
10+
11+
## 1.3.0 | 2023-11-09
412
- Fixed an issue where a JavaScript error can occur on the front-end if the page also includes custom or third-party forms.
513
- Fixed an issue where the v3 settings aren't populated by the GF_RECAPTCHA_V3_SITE_KEY and GF_RECAPTCHA_V3_SECRET_KEY constants.
614

class-gf-recaptcha.php

Lines changed: 79 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -550,20 +550,31 @@ public function get_plugin_settings_instance() {
550550
* @return bool
551551
*/
552552
private function initialize_api() {
553+
static $result;
554+
555+
if ( is_bool( $result ) ) {
556+
return $result;
557+
}
558+
559+
$result = false;
553560
$site_key = $this->plugin_settings->get_recaptcha_key( 'site_key_v3' );
554561
$secret_key = $this->plugin_settings->get_recaptcha_key( 'secret_key_v3' );
555562

556563
if ( ! ( $site_key && $secret_key ) ) {
557-
$this->log_debug( __METHOD__ . '(): missing v3 key configuration. Please check the add-on settings.' );
564+
$this->log_debug( __METHOD__ . '(): Missing v3 key configuration. Please check the add-on settings.' );
565+
558566
return false;
559567
}
560568

561569
if ( '1' !== $this->get_plugin_setting( 'recaptcha_keys_status_v3' ) ) {
562-
$this->log_debug( __METHOD__ . '(): could not initialize reCAPTCHA v3 because site and/or secret key is invalid.' );
570+
$this->log_debug( __METHOD__ . '(): Could not initialize reCAPTCHA v3 because site and/or secret key is invalid.' );
571+
563572
return false;
564573
}
565574

566-
$this->log_debug( __METHOD__ . '(): Initializing API.' );
575+
$result = true;
576+
$this->log_debug( __METHOD__ . '(): API Initialized.' );
577+
567578
return true;
568579
}
569580

@@ -763,25 +774,39 @@ public function add_recaptcha_meta_box( $data ) {
763774
*/
764775
public function check_for_spam_entry( $is_spam, $form, $entry ) {
765776

766-
if ( $is_spam || $this->is_disabled_by_form_setting( $form ) || ! $this->initialize_api() || $this->is_preview() ) {
777+
if ( $is_spam ) {
778+
$this->log_debug( __METHOD__ . '(): Skipping, entry has already been identified as spam by another anti-spam solution.' );
767779
return $is_spam;
768780
}
769781

770-
$is_spam = (float) $this->get_score_from_entry( $entry ) <= $this->get_spam_score_threshold();
782+
$is_spam = $this->is_spam_submission( $form, $entry );
771783
$this->log_debug( __METHOD__ . '(): Is submission considered spam? ' . ( $is_spam ? 'Yes.' : 'No.' ) );
772784

773785
return $is_spam;
774786
}
775787

776-
public function is_spam_submission( $form ) {
777-
if ( $this->is_disabled_by_form_setting( $form ) || $this->is_preview() || ! $this->initialize_api() ) {
788+
/**
789+
* Determines if the submission is spam by comparing its score with the threshold.
790+
*
791+
* @since 1.4
792+
* @since 1.5 Added the optional $entry param.
793+
*
794+
* @param array $form The form being processed.
795+
* @param array $entry The entry being processed.
796+
*
797+
* @return bool
798+
*/
799+
public function is_spam_submission( $form, $entry = array() ) {
800+
if ( $this->should_skip_validation( $form ) ) {
801+
$this->log_debug( __METHOD__ . '(): Score check skipped.' );
802+
778803
return false;
779804
}
780805

781-
$score = $this->token_verifier->get_score();
782-
$threashold = $this->get_spam_score_threshold();
806+
$score = empty( $entry ) ? $this->token_verifier->get_score() : $this->get_score_from_entry( $entry );
807+
$threshold = $this->get_spam_score_threshold();
783808

784-
return (float) $score <= (float) $threashold;
809+
return (float) $score <= (float) $threshold;
785810
}
786811
/**
787812
* Get the Recaptcha score from the entry details.
@@ -812,6 +837,12 @@ private function get_score_from_entry( $entry ) {
812837
* @return float
813838
*/
814839
private function get_spam_score_threshold() {
840+
static $value;
841+
842+
if ( ! empty( $value ) ) {
843+
return $value;
844+
}
845+
815846
$value = (float) $this->get_plugin_setting( 'score_threshold_v3' );
816847
if ( empty( $value ) ) {
817848
$value = 0.5;
@@ -846,8 +877,8 @@ private function is_disabled_by_form_setting( $form ) {
846877
public function validate_submission( $submission_data ) {
847878
$this->log_debug( __METHOD__ . '(): Validating form (#' . rgars( $submission_data, 'form/id' ) . ') submission.' );
848879

849-
if ( $this->should_skip_validation( $submission_data ) ) {
850-
$this->log_debug( __METHOD__ . '(): Validation skipped. reCAPTCHA v3 is misconfigured, disabled, or the form was submitted in preview mode.' );
880+
if ( $this->should_skip_validation( rgar( $submission_data, 'form' ) ) ) {
881+
$this->log_debug( __METHOD__ . '(): Validation skipped.' );
851882

852883
return $submission_data;
853884
}
@@ -864,24 +895,55 @@ public function validate_submission( $submission_data ) {
864895
* we want to skip the reCaptcha validation so it isn't triggered twice, as this will make it always fail.
865896
*
866897
* @since 1.4
898+
* @since 1.5 Changed param to $form array.
867899
*
868-
* @param array $submission_data The submitted form data.
900+
* @param array $form The form being processed.
869901
*
870902
* @return bool
871903
*/
872-
public function should_skip_validation( $submission_data ) {
904+
public function should_skip_validation( $form ) {
905+
static $result = array();
906+
907+
$form_id = rgar( $form, 'id' );
908+
if ( isset( $result[ $form_id ] ) ) {
909+
return $result[ $form_id ];
910+
}
911+
912+
$result[ $form_id ] = true;
913+
914+
if ( $this->is_preview() ) {
915+
$this->log_debug( __METHOD__ . '(): Yes! Form preview page.' );
916+
917+
return true;
918+
}
919+
920+
if ( ! $this->initialize_api() ) {
921+
$this->log_debug( __METHOD__ . '(): Yes! API not initialized.' );
922+
923+
return true;
924+
}
925+
926+
if ( $this->is_disabled_by_form_setting( $form ) ) {
927+
$this->log_debug( __METHOD__ . '(): Yes! Disabled by form setting.' );
928+
929+
return true;
930+
}
931+
932+
if ( defined( 'REST_REQUEST' ) && REST_REQUEST && ! isset( $_POST[ $this->field->get_input_name( $form_id ) ] ) ) {
933+
$this->log_debug( __METHOD__ . '(): Yes! REST request without input.' );
873934

874-
$is_recaptcha_configured = $this->initialize_api() && ! $this->is_disabled_by_form_setting( rgar( $submission_data, 'form' ) );
875-
// Skip validation if reCaptcha is not configured or if the form is in preview mode.
876-
if ( ! $is_recaptcha_configured || $this->is_preview() ) {
877935
return true;
878936
}
879937

880938
// For older versions of Stripe, skip the first validation attempt and only validate on the second attempt. Newer versions of Stripe will validate twice without a problem.
881939
if ( $this->is_stripe_validation() && version_compare( gf_stripe()->get_version(), '5.4.3', '<' ) ) {
940+
$this->log_debug( __METHOD__ . '(): Yes! Older Stripe validation.' );
941+
882942
return true;
883943
}
884944

945+
$result[ $form_id ] = false;
946+
885947
return false;
886948
}
887949

includes/class-gf-field-recaptcha.php

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,10 @@ public function get_field_input( $form, $value = '', $entry = null ) {
9393
public function validation_check( $validation_data ) {
9494
$this->formId = absint( rgars( $validation_data, 'form/id' ) );
9595

96-
if ( defined( 'REST_REQUEST' ) && REST_REQUEST && ! isset( $_POST[ $this->get_input_name() ] ) ) {
97-
gf_recaptcha()->log_debug( __METHOD__ . '(): Aborting; REST request.' );
98-
99-
return $validation_data;
100-
}
101-
10296
if ( $this->is_valid_field_data() ) {
10397

10498
// Set is_spam value.
105-
$validation_data['is_spam'] = gf_recaptcha()->is_spam_submission( GFAPI::get_form( $this->formId ) );
99+
$validation_data['is_spam'] = gf_recaptcha()->is_spam_submission( rgar( $validation_data, 'form' ) );
106100

107101
return $validation_data;
108102
}

includes/class-token-verifier.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,16 +180,16 @@ public function verify_submission( $token ) {
180180

181181
$data = \GFCache::get( 'recaptcha_' . $token, $found );
182182
if ( $found ) {
183-
$this->addon->log_debug( __METHOD__ . '() using cached reCAPTCHA result: ' . print_r( $data, true ) );
183+
$this->addon->log_debug( __METHOD__ . '(): Using cached reCAPTCHA result: ' . print_r( $data, true ) );
184184
$this->recaptcha_result = $data;
185185

186186
return true;
187187
}
188188

189-
$this->addon->log_debug( __METHOD__ . '(): verifying reCAPTCHA submission.' );
189+
$this->addon->log_debug( __METHOD__ . '(): Verifying reCAPTCHA submission.' );
190190

191191
if ( empty( $token ) ) {
192-
$this->addon->log_debug( __METHOD__ . '() could not verify the submission because no token was found.' . PHP_EOL );
192+
$this->addon->log_debug( __METHOD__ . '(): Could not verify the submission because no token was found.' . PHP_EOL );
193193
return false;
194194
}
195195

@@ -209,15 +209,15 @@ public function verify_submission( $token ) {
209209

210210
if ( ! $this->validate_response_data( $data ) ) {
211211
$this->addon->log_debug(
212-
__METHOD__ . '() could not validate the token request from the reCAPTCHA service. ' . PHP_EOL
212+
__METHOD__ . '(): Could not validate the token request from the reCAPTCHA service. ' . PHP_EOL
213213
. "token: {$token}" . PHP_EOL
214214
. "response: " . print_r( $data, true ) . PHP_EOL // @codingStandardsIgnoreLine
215215
);
216216
return false;
217217
}
218218

219219
// @codingStandardsIgnoreLine
220-
$this->addon->log_debug( __METHOD__ . '() validated reCAPTCHA: ' . print_r( $data, true ) );
220+
$this->addon->log_debug( __METHOD__ . '(): Validated reCAPTCHA: ' . print_r( $data, true ) );
221221
$this->recaptcha_result = $data;
222222

223223
// Caching result for 1 hour.
@@ -294,7 +294,7 @@ private function verify_hostname( $hostname ) {
294294
* @return bool
295295
*/
296296
private function verify_action( $action ) {
297-
$this->addon->log_debug( __METHOD__ . '(): verifying action from reCAPTCHA response.' );
297+
$this->addon->log_debug( __METHOD__ . '(): Verifying action from reCAPTCHA response.' );
298298

299299
return $this->action === $action;
300300
}
@@ -309,7 +309,7 @@ private function verify_action( $action ) {
309309
* @return bool
310310
*/
311311
private function verify_score( $score ) {
312-
$this->addon->log_debug( __METHOD__ . '(): verifying score from reCAPTCHA response.' );
312+
$this->addon->log_debug( __METHOD__ . '(): Verifying score from reCAPTCHA response.' );
313313

314314
return is_float( $score ) && $score >= 0.0 && $score <= 1.0;
315315
}
@@ -328,7 +328,7 @@ private function verify_score( $score ) {
328328
* @return bool
329329
*/
330330
private function verify_timestamp( $challenge_ts ) {
331-
$this->addon->log_debug( __METHOD__ . '(): verifying timestamp from reCAPTCHA response.' );
331+
$this->addon->log_debug( __METHOD__ . '(): Verifying timestamp from reCAPTCHA response.' );
332332

333333
return ( gmdate( time() ) - strtotime( $challenge_ts ) ) <= 24 * HOUR_IN_SECONDS;
334334
}

includes/settings/class-plugin-settings.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ public function verify_v3_keys() {
509509
$this->apply_status_changes( $result );
510510

511511
if ( is_wp_error( $result ) ) {
512-
$this->addon->log_debug( __METHOD__ . '(): failed to verify reCAPTCHA token. ' . $result->get_error_message() );
512+
$this->addon->log_debug( __METHOD__ . '(): Failed to verify reCAPTCHA token. ' . $result->get_error_message() );
513513

514514
wp_send_json_error();
515515
}

js/frontend.js

Lines changed: 9 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)