PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.0
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.0
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
profile-builder / front-end / default-fields / turnstile / turnstile.php

turnstile.php in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 4.0.0, at front-end/default-fields/turnstile/turnstile.php

720 lines 34.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4 /**
5 * Submits an HTTP POST to the Turnstile siteverify server.
6 * Turnstile requires POST, unlike reCAPTCHA which historically allowed GET.
7 *
8 * @param string $path
9 * @param array $data
10 */
11 function _wppb_turnstile_submitHTTPPost($path, $data)
12 {
13 $response = wp_remote_post( $path, array(
14 'body' => $data
15 ) );
16
17 if ( is_wp_error( $response ) ) {
18 return '';
19 }
20
21 return isset( $response['body'] ) ? $response['body'] : '';
22 }
23
24 /**
25 * Gets the challenge HTML wrapper for Turnstile.
26 *
27 * @param string $pubkey A public key for Turnstile
28 * @param string $form_name The name of the form
29 *
30 * @return string - The HTML to be embedded in the user's form.
31 */
32 function wppb_turnstile_get_html ( $pubkey, $form_name='' ){
33 global $wppb_turnstile_forms; // is the counter for the number of forms that have turnstile so we always have unique ids on the element
34 if( is_null( $wppb_turnstile_forms ) )
35 $wppb_turnstile_forms = 0;
36 $wppb_turnstile_forms++;
37
38 if ( empty($pubkey) )
39 echo '<span class="error">'. esc_html__("To use Cloudflare Turnstile you must get a Site Key from", "profile-builder"). " <a href='https://dash.cloudflare.com/?to=/:account/turnstile'>https://dash.cloudflare.com/?to=/:account/turnstile</a></span><br/><br/>";
40
41 $field = wppb_get_turnstile_field();
42 $theme = isset( $field['theme'] ) ? esc_attr( sanitize_text_field( $field['theme'] ) ) : 'auto';
43
44 $output = '<div id="wppb-turnstile-element-'.$form_name.$wppb_turnstile_forms.'" class="wppb-turnstile-element cf-turnstile" data-wppb-sitekey="'.esc_attr( $pubkey ).'" data-wppb-theme="'.$theme.'"></div>';
45
46 // We add a hidden field so we can easily check if Turnstile should be processed on this form
47 $output .= '<input type="hidden" name="wppb-turnstile-present" value="1">';
48
49 if( $form_name == 'pb_login' ) {
50 add_filter( 'wppb_login_submit_button_extra_attributes', 'wppb_turnstile_login_submit_button_extra_attributes' );
51 }
52
53 return $output;
54 }
55
56 /**
57 * Add disabled attribute to login form submit button when Turnstile is used.
58 * Prevent form submission before the script is loaded and a token is received.
59 *
60 * @param string $attributes
61 * @return string
62 */
63 function wppb_turnstile_login_submit_button_extra_attributes( $attributes ) {
64 return $attributes . ' disabled="disabled"';
65 }
66
67 /**
68 * Add Turnstile scripts to both front-end PB forms as well as Default WP forms
69 */
70 function wppb_turnstile_script_footer(){
71 $field = wppb_get_turnstile_field();
72 /* if we do not have a turnstile field do nothing */
73 if( empty( $field ) )
74 return;
75
76 global $wppb_turnstile_present;
77 global $wppb_shortcode_on_front;
78
79 //do not add script on regular frontend pages unless a PB shortcode or Turnstile HTML is present
80 if( current_filter() == 'wp_footer' && ( !isset( $wppb_shortcode_on_front ) || $wppb_shortcode_on_front === false ) && ( !isset( $wppb_turnstile_present ) || $wppb_turnstile_present === false ) )
81 return;
82
83 //do not add script if the html for the field has not been added
84 if( !isset( $wppb_turnstile_present ) || $wppb_turnstile_present === false )
85 return;
86
87 //we don't have jquery on the backend
88 if( current_filter() != 'wp_footer' ) {
89 wp_print_scripts('jquery');
90 }else if(!wp_script_is('jquery')){
91 wp_print_scripts('jquery');
92 }
93
94 //get site key
95 $pubkey = '';
96 if( isset( $field['turnstile-site-key'] ) ) {
97 $pubkey = sanitize_text_field( $field['turnstile-site-key'] );
98 }
99
100 $theme = isset( $field['theme'] ) ? sanitize_text_field( $field['theme'] ) : 'auto';
101
102 // phpcs:disable
103 echo '
104 <script>
105 window.wppbTurnstileCallbackExecuted = false;
106
107 var wppbTurnstileCallback = function() {
108 if( !window.wppbTurnstileCallbackExecuted ){
109 let $elements = jQuery(".wppb-turnstile-element");
110
111 $elements.each(function(){
112 let $turnstileElement = jQuery(this);
113
114 if ( typeof $turnstileElement.data("wppb-turnstile-id") !== "undefined" ) {
115 turnstile.reset( $turnstileElement.data("wppb-turnstile-id") );
116 return;
117 }
118
119 let widgetId = turnstile.render(
120 "#" + $turnstileElement.attr("id"),
121 {
122 "sitekey" : "' . $pubkey . '",
123 "theme": "' . $theme . '"
124 }
125 )
126
127 $turnstileElement.data("wppb-turnstile-id", widgetId);
128 });
129
130 window.wppbTurnstileCallbackExecuted = true;
131
132 // Enable login form submit button initially as Turnstile handles its own disabled state or we wait for callback
133 if( jQuery("#wppb-loginform input[type=submit]").length > 0 ) {
134 jQuery("#wppb-loginform input[type=submit]").attr("disabled", false);
135 }
136 }
137 };
138 </script>';
139 // phpcs:enable
140
141 echo '<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?onload=wppbTurnstileCallback&render=explicit" async defer></script>';
142 echo '<script>
143 /* compatibility with other plugins that may include Turnstile with an onload callback. if their script loads first then our callback will not execute so call it explicitly */
144 jQuery( window ).on( "load", function() {
145 wppbTurnstileCallback();
146 });
147 </script>';
148
149 }
150 add_action('wp_footer', 'wppb_turnstile_script_footer', 9999);
151 add_action('login_footer', 'wppb_turnstile_script_footer');
152 add_action('register_form', 'wppb_turnstile_script_footer');
153 add_action('lost_password', 'wppb_turnstile_script_footer');
154
155 /**
156 * A wppb_TurnstileResponse is returned from wppb_turnstile_check_answer()
157 */
158 class wppb_TurnstileResponse {
159 var $is_valid;
160 }
161
162 /**
163 * Calls an HTTP POST function to verify if the user\'s answer was correct
164 * @param string $privkey
165 * @param string $remoteip
166 * @param string $response
167 * @return wppb_TurnstileResponse
168 */
169 function wppb_turnstile_check_answer ( $privkey, $remoteip, $response ) {
170
171 if ( $remoteip == null || $remoteip == '' )
172 echo '<span class="error">'. esc_html__("For security reasons, you must pass the remote ip to Turnstile!", "profile-builder") .'</span><br/><br/>';
173
174 // Discard empty solution submissions
175 if ($response == null || strlen($response) == 0) {
176 $turnstileResponse = new wppb_TurnstileResponse();
177 $turnstileResponse->is_valid = false;
178
179 return $turnstileResponse;
180 }
181
182 $getResponse = _wppb_turnstile_submitHTTPPost(
183 "https://challenges.cloudflare.com/turnstile/v0/siteverify",
184 array (
185 'secret' => $privkey,
186 'remoteip' => $remoteip,
187 'response' => $response
188 )
189 );
190
191 $answers = json_decode( $getResponse, true );
192 $turnstileResponse = new wppb_TurnstileResponse();
193
194 // Fail closed when the HTTP call fails or the body is not valid JSON.
195 if ( ! is_array( $answers ) || empty( $answers['success'] ) ) {
196 $turnstileResponse->is_valid = false;
197 } else {
198 $turnstileResponse->is_valid = true;
199 }
200
201 return $turnstileResponse;
202
203 }
204
205 /* the function to validate the Turnstile response with the API */
206 function wppb_validate_turnstile_response( $publickey, $privatekey ){
207 /* If the Turnstile keys are not configured the widget cannot work for anyone, so do not enforce -
208 otherwise an incomplete setup would lock every visitor out of the form. These keys are admin-side
209 configuration, not attacker controlled, so this cannot be used to bypass a properly configured Turnstile. */
210 if ( empty( $publickey ) || empty( $privatekey ) ) {
211 return true;
212 }
213
214 if (isset($_POST['cf-turnstile-response'])){
215 $turnstile_response_field = sanitize_textarea_field( $_POST['cf-turnstile-response'] );
216 } else {
217 $turnstile_response_field = '';
218 }
219
220 $already_validated = false;
221 $saved = get_option( 'wppb_turnstile_validations', array() );
222
223 if( isset( $saved[ $turnstile_response_field ] ) && $saved[ $turnstile_response_field ] == true ){
224 $already_validated = true;
225
226 if( !wp_doing_ajax() ){
227 unset( $saved[ $turnstile_response_field ] );
228 update_option( 'wppb_turnstile_validations', $saved, false );
229 }
230 }
231
232 if( !$already_validated ){
233
234 if( isset( $_SERVER["REMOTE_ADDR"] ) ){
235 $resp = wppb_turnstile_check_answer($privatekey, sanitize_text_field( $_SERVER["REMOTE_ADDR"] ), $turnstile_response_field );
236
237 if( isset( $resp ) ){
238 $already_validated = ( ( !$resp->is_valid ) ? false : true );
239 }
240 }
241
242 }
243
244 // Save valid results when they are being triggered from an ajax request
245 if( wp_doing_ajax() && isset( $_POST['action'] ) && $_POST['action'] == 'pms_validate_checkout' ){
246
247 $saved = get_option( 'wppb_turnstile_validations', array() );
248
249 if( $already_validated === true )
250 $saved[ $turnstile_response_field ] = true;
251
252 update_option( 'wppb_turnstile_validations', $saved, false );
253
254 }
255
256 return $already_validated;
257
258 }
259
260 /* the function to add Turnstile to the registration form of PB */
261 function wppb_turnstile_handler ( $output, $form_location, $field, $user_id, $field_check_errors, $request_data ){
262 if ( $field['field'] == 'Turnstile' ){
263 $item_title = apply_filters( 'wppb_'.$form_location.'_turnstile_custom_field_'.$field['id'].'_item_title', wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_'.$field['id'].'_title_translation', $field['field-title'], true ) );
264 $item_description = wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_'.$field['id'].'_description_translation', $field['description'], true );
265
266 wppb_turnstile_set_default_values();
267
268 if ( ($form_location == 'register') && ( isset($field['turnstile-pb-forms']) ) && ( strpos($field['turnstile-pb-forms'],'pb_register') !== false ) ) {
269 $error_mark = ( ( $field['required'] == 'Yes' ) ? '<span class="wppb-required" title="'.wppb_required_field_error($field["field-title"]).'">*</span>' : '' );
270
271 global $wppb_turnstile_present;
272 $wppb_turnstile_present = true;
273
274 if ( array_key_exists( $field['id'], $field_check_errors ) )
275 $error_mark = '<img src="'.WPPB_PLUGIN_URL.'assets/images/pencil_delete.png" title="'.wppb_required_field_error($field["field-title"]).'"/>';
276
277 $publickey = trim( $field['turnstile-site-key'] );
278 $privatekey = trim( $field['turnstile-secret-key'] );
279
280 if ( empty( $publickey ) || empty( $privatekey ) )
281 return '<span class="custom_field_turnstile_error_message" id="'.$field['meta-name'].'_error_message">'.apply_filters( 'wppb_'.$form_location.'_turnstile_custom_field_'.$field['id'].'_error_message', __("To use Cloudflare Turnstile you must get a Site Key and Secret Key from:", "profile-builder"). '<a href="https://dash.cloudflare.com/?to=/:account/turnstile">https://dash.cloudflare.com/?to=/:account/turnstile</a>' ).'</span>';
282
283 $output = '<label for="turnstile_response_field">' . $item_title . $error_mark . '</label>' . wppb_turnstile_get_html($publickey, 'pb_register');
284 if (!empty($item_description))
285 $output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
286
287 return $output;
288
289 }
290 }
291 }
292 add_filter( 'wppb_output_form_field_turnstile', 'wppb_turnstile_handler', 10, 6 );
293
294 /* handle Turnstile field validation on PB Register form */
295 function wppb_check_turnstile_value( $message, $field, $request_data, $form_location ){
296 if( $field['field'] == 'Turnstile' ){
297 if ( ( $form_location == 'register' ) && ( isset($field['turnstile-pb-forms']) ) && ( strpos($field['turnstile-pb-forms'],'pb_register') !== false ) ) {
298 /* theme my login plugin executes the register_errors hook on the frontend on all pages so on our register forms we might have already a turnstile response
299 so do not verify it again or it will fail */
300 global $wppb_turnstile_response;
301 if (!isset($wppb_turnstile_response)){
302 $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
303 }
304 /* Turnstile must fail closed: whenever it is configured to display on this form it has to be
305 verified, regardless of the "required" toggle. A missing/empty token makes
306 wppb_validate_turnstile_response() return false, so bots that omit cf-turnstile-response are blocked. */
307 if ( $wppb_turnstile_response == false ){
308 return __('Cloudflare Turnstile could not be verified. Please try again.', 'profile-builder');
309 }
310 }
311 }
312 return $message;
313 }
314 add_filter( 'wppb_check_form_field_turnstile', 'wppb_check_turnstile_value', 10, 4 );
315
316 // Get the Turnstile field information
317 function wppb_get_turnstile_field(){
318 $wppb_manage_fields = get_option( 'wppb_manage_fields', 'not_found' );
319 $field = array();
320 if ( $wppb_manage_fields != 'not_found' ) {
321 foreach ($wppb_manage_fields as $value) {
322 if ($value['field'] == 'Turnstile'){
323 $field = $value;
324 break;
325 }
326 }
327 }
328 return $field;
329 }
330
331 /* Display Turnstile on PB Recover Password form */
332 function wppb_display_turnstile_recover_password( $output ){
333 $field = wppb_get_turnstile_field();
334
335 if ( !empty($field) ) {
336 $publickey = trim($field['turnstile-site-key']);
337 $item_title = apply_filters('wppb_recover_password_turnstile_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
338 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
339
340 // check where Turnstile should display and add Turnstile html
341 if ( isset($field['turnstile-pb-forms']) && ( strpos( $field['turnstile-pb-forms'],'pb_recover_password' ) !== false ) ) {
342
343 global $wppb_turnstile_present;
344 $wppb_turnstile_present = true;
345
346 $turnstile_output = '<label for="turnstile_response_field">' . $item_title . '</label>' . wppb_turnstile_get_html($publickey, 'pb_recover_password');
347 if (!empty($item_description))
348 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
349
350 $output = str_replace('</ul>', '<li class="wppb-form-field wppb-turnstile">' . $turnstile_output . '</li>' . '</ul>', $output);
351 }
352 }
353 return $output;
354 }
355 add_filter('wppb_recover_password_generate_password_input','wppb_display_turnstile_recover_password');
356
357 /* Function that changes the messageNo from the Recover Password form */
358 function wppb_turnstile_change_recover_password_message_no($messageNo) {
359
360 if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'recover_password') {
361 $field = wppb_get_turnstile_field();
362 if (!empty($field)) {
363
364 global $wppb_turnstile_response;
365 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
366
367 if ( isset($field['turnstile-pb-forms']) && (strpos($field['turnstile-pb-forms'], 'pb_recover_password') !== false) ) {
368
369 if ( $wppb_turnstile_response == false )
370 $messageNo = '';
371 }
372 }
373 }
374
375 return $messageNo;
376 }
377 add_filter('wppb_recover_password_message_no', 'wppb_turnstile_change_recover_password_message_no');
378
379 /* Function that adds the Turnstile error message on the Recover Password form */
380 function wppb_turnstile_recover_password_displayed_message1( $message ) {
381 $field = wppb_get_turnstile_field();
382
383 if ( !empty($field) ){
384 global $wppb_turnstile_response;
385 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
386
387 if ( isset($field['turnstile-pb-forms']) && ( strpos( $field['turnstile-pb-forms'],'pb_recover_password' ) !== false ) && ( $wppb_turnstile_response == false )) {
388
389 $turnstile_error_message = __('Cloudflare Turnstile could not be verified. Please try again.', 'profile-builder');
390
391 if (($message == '<p class="wppb-warning">wppb_turnstile_error</p>') || ($message == '<p class="wppb-warning">wppb_captcha_error</p>'))
392 $message = '<p class="wppb-warning">' . $turnstile_error_message . '</p>';
393 else
394 $message = $message . '<p class="wppb-warning">' . $turnstile_error_message . '</p>';
395
396 }
397 }
398
399 return $message;
400 }
401 add_filter('wppb_recover_password_displayed_message1', 'wppb_turnstile_recover_password_displayed_message1');
402
403 /* Function that changes the default success message to wppb_turnstile_error if it doesn't validate */
404 function wppb_turnstile_recover_password_sent_message_1($message) {
405
406 if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'recover_password') {
407 $field = wppb_get_turnstile_field();
408
409 if (!empty($field)) {
410 global $wppb_turnstile_response;
411 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
412
413 if ( isset($field['turnstile-pb-forms']) && ( strpos($field['turnstile-pb-forms'], 'pb_recover_password') !== false ) && ( $wppb_turnstile_response == false ) ){
414 $message = 'wppb_turnstile_error';
415 }
416 }
417
418 }
419
420 return $message;
421 }
422 add_filter('wppb_recover_password_sent_message1', 'wppb_turnstile_recover_password_sent_message_1');
423
424 /* Display Turnstile html on PB Login form */
425 function wppb_display_turnstile_login_form($form_part, $args) {
426
427 if( !isset( $args['form_id'] ) || $args['form_id'] != 'wppb-loginform' )
428 return $form_part;
429
430 $field = wppb_get_turnstile_field();
431
432 if ( !empty($field) ) {
433 $item_title = apply_filters('wppb_login_turnstile_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
434 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
435
436 if ( isset($field['turnstile-pb-forms']) && ( strpos( $field['turnstile-pb-forms'],'pb_login' ) !== false ) ) { // check where Turnstile should display
437
438 global $wppb_turnstile_present;
439 $wppb_turnstile_present = true;
440
441 $turnstile_output = '<label for="turnstile_response_field">' . $item_title . '</label>' . wppb_turnstile_get_html(trim($field['turnstile-site-key']), 'pb_login');
442 if (!empty($item_description))
443 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
444
445 $form_part .= '<div class="wppb-form-field wppb-turnstile">' . $turnstile_output . '</div>';
446
447 }
448 }
449
450 return $form_part;
451 }
452 add_filter('login_form_middle', 'wppb_display_turnstile_login_form', 10, 2);
453
454 /* Display Turnstile html on default WP Login form */
455 function wppb_display_turnstile_wp_login_form(){
456 $field = wppb_get_turnstile_field();
457
458 if ( !empty($field) ) {
459 $item_title = apply_filters('wppb_login_turnstile_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
460 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
461
462 if ( isset($field['turnstile-wp-forms']) && (strpos( $field['turnstile-wp-forms'],'default_wp_login' ) !== false) ) {
463
464 global $wppb_turnstile_present;
465 $wppb_turnstile_present = true;
466
467 $turnstile_output = '<label for="turnstile_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_turnstile_get_html(trim($field['turnstile-site-key']));
468 if (!empty($item_description))
469 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
470
471 echo '<div class="wppb-form-field wppb-turnstile" style="margin-left:-14px; margin-bottom: 15px;">' . $turnstile_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
472
473 }
474 }
475 }
476 add_action( 'login_form', 'wppb_display_turnstile_wp_login_form' );
477
478 //Show Turnstile error on Login form (both default and PB one)
479 function wppb_turnstile_login_wp_error_message($user){
480 //make sure you\'re on a Login form (WP or PB)
481 if ( isset( $_POST['log'] ) && !is_wp_error($user) && !isset( $_POST['pms_login'] ) ) {
482
483 $field = wppb_get_turnstile_field();
484 if ( !empty($field) ){
485 global $wppb_turnstile_response;
486
487 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
488
489 $turnstile_error_message = __('Cloudflare Turnstile could not be verified. Please try again.','profile-builder');
490
491 //Turnstile error for displaying on the PB login form
492 if ( isset($_POST['wppb_login']) && ($_POST['wppb_login'] == true) ) {
493
494 // it\'s a PB login form, check if we have Turnstile on it and display error if not valid
495 if ((isset($field['turnstile-pb-forms'])) && (strpos($field['turnstile-pb-forms'], 'pb_login') !== false) && ($wppb_turnstile_response == false)) {
496 $user = new WP_Error('wppb_turnstile_error', $turnstile_error_message);
497 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
498 remove_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
499 }
500
501 }
502 else {
503 //Turnstile error for displaying on the default WP login form
504 if (isset($field['turnstile-wp-forms']) && (strpos($field['turnstile-wp-forms'], 'default_wp_login') !== false) && ($wppb_turnstile_response == false)) {
505 $user = new WP_Error('wppb_turnstile_error', $turnstile_error_message);
506 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
507 remove_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
508 }
509
510 }
511 }
512 }
513 return $user;
514 }
515 add_filter('authenticate','wppb_turnstile_login_wp_error_message', 9);
516
517 /**
518 * Add a Turnstile CSS class to the Register form field
519 *
520 * @param $classes - existing field classes
521 * @param $field - field data
522 * @return mixed|string
523 */
524 function wppb_register_form_turnstile_type_class( $classes, $field ){
525
526 if ( isset( $field['field'] ) && $field['field'] == 'Turnstile' )
527 $classes .= ' wppb-turnstile';
528
529 return $classes;
530 }
531 add_filter( 'wppb_field_css_class', 'wppb_register_form_turnstile_type_class', 20, 2);
532
533 // Display Turnstile html on default WP Recover Password form
534 function wppb_display_turnstile_default_wp_recover_password() {
535 $field = wppb_get_turnstile_field();
536
537 if (!empty($field)) {
538 $publickey = trim($field['turnstile-site-key']);
539 $item_title = apply_filters('wppb_recover_password_turnstile_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
540 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
541
542 if ( isset($field['turnstile-wp-forms']) && (strpos( $field['turnstile-wp-forms'], 'default_wp_recover_password') !== false) ) {
543
544 global $wppb_turnstile_present;
545 $wppb_turnstile_present = true;
546
547 $turnstile_output = '<label for="turnstile_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_turnstile_get_html($publickey);
548 if (!empty($item_description))
549 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
550
551 echo '<div class="wppb-form-field wppb-turnstile" style="margin-left:-14px; margin-bottom: 15px;">' . $turnstile_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
552
553 }
554 }
555 }
556 add_action('lostpassword_form','wppb_display_turnstile_default_wp_recover_password');
557
558 // Verify and show Turnstile errors for default WP Recover Password
559 function wppb_verify_turnstile_default_wp_recover_password(){
560
561 // If field \'username or email\' is empty - return
562 if( isset( $_REQUEST['user_login'] ) && "" === $_REQUEST['user_login'] )
563 return;
564
565 $field = wppb_get_turnstile_field();
566 if ( !empty($field) ){
567 global $wppb_turnstile_response;
568 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
569
570 $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder');
571
572 // Fail closed, but only where Turnstile is configured for this form. Gate on turnstile-wp-forms (as the
573 // login path does) instead of isset() of the token, so a missing token is treated as a failed verification
574 // without blocking default WP password recovery on sites that only use Turnstile on PB forms.
575 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_recover_password' ) !== false ) && ( $wppb_turnstile_response == false ) ) {
576 wp_die( esc_html( $turnstile_error_message ) . '<br />' . esc_html__( "Click the BACK button on your browser, and try again.", 'profile-builder' ) ) ;
577 }
578 }
579 }
580 add_action('lostpassword_post','wppb_verify_turnstile_default_wp_recover_password');
581
582 /* Display Turnstile html on default WP Register form */
583 function wppb_display_turnstile_default_wp_register(){
584 $field = wppb_get_turnstile_field();
585
586 if (!empty($field)) {
587
588 $publickey = trim($field['turnstile-site-key']);
589 $item_title = apply_filters('wppb_register_turnstile_custom_field_' . $field['id'] . '_item_title', wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true));
590 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
591
592 wppb_turnstile_set_default_values();
593 if (isset($field['turnstile-wp-forms']) && (strpos($field['turnstile-wp-forms'], 'default_wp_register') !== false)) {
594
595 global $wppb_turnstile_present;
596 $wppb_turnstile_present = true;
597
598 $turnstile_output = '<label for="turnstile_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_turnstile_get_html($publickey);
599 if (!empty($item_description))
600 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
601
602 echo '<div class="wppb-form-field wppb-turnstile" style="margin-left:-14px; margin-bottom: 15px;">' . $turnstile_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
603
604 }
605 }
606 }
607 add_action( 'register_form', 'wppb_display_turnstile_default_wp_register' );
608
609 // Verify and show Turnstile errors for default WP Register form
610 function wppb_verify_turnstile_default_wp_register( $errors ){
611
612 $field = wppb_get_turnstile_field();
613 if ( !empty($field) ){
614 global $wppb_turnstile_response;
615 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
616
617 $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder');
618
619 // Fail closed, but only where Turnstile is configured for this form. Gate on turnstile-wp-forms (as the
620 // login path does) instead of isset() of the token, so a missing token is treated as a failed verification
621 // without blocking default WP registration on sites that only use Turnstile on PB forms.
622 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_register' ) !== false ) && ( $wppb_turnstile_response == false ) ) {
623 $errors->add( 'wppb_turnstile_error', $turnstile_error_message );
624 }
625 }
626
627 return $errors;
628 }
629 add_filter('registration_errors','wppb_verify_turnstile_default_wp_register');
630
631 /* Display Turnstile html on default WP Comments form */
632 function wppb_display_turnstile_default_wp_comments(){
633 $field = wppb_get_turnstile_field();
634
635 if ( !empty( $field ) ) {
636 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_comments' ) !== false ) ) {
637 $publickey = trim( $field['turnstile-site-key'] );
638 $item_title = apply_filters( 'wppb_comments_turnstile_custom_field_' . $field['id'] . '_item_title', wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_title_translation', $field['field-title'], true ) );
639 $item_description = wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true );
640
641 global $wppb_turnstile_present;
642 $wppb_turnstile_present = true;
643
644 $turnstile_output = '<label for="turnstile_response_field">' . $item_title . '</label>' . wppb_turnstile_get_html( $publickey, 'default_wp_comments' );
645 if ( !empty( $item_description ) )
646 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
647
648 echo '<div class="wppb-form-field wppb-turnstile">' . $turnstile_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
649 }
650 }
651 }
652 add_action( 'comment_form_after_fields', 'wppb_display_turnstile_default_wp_comments' );
653 add_action( 'comment_form_logged_in_after', 'wppb_display_turnstile_default_wp_comments' );
654
655 function wppb_get_turnstile_default_wp_comments_error_message(){
656 return __( 'Cloudflare Turnstile could not be verified. Please try again.', 'profile-builder' );
657 }
658
659 function wppb_display_turnstile_default_wp_comments_error(){
660 if ( !isset( $_GET['wppb_comment_turnstile_error'] ) )
661 return;
662
663 $field = wppb_get_turnstile_field();
664
665 if ( empty( $field ) || !isset( $field['turnstile-wp-forms'] ) || ( strpos( $field['turnstile-wp-forms'], 'default_wp_comments' ) === false ) )
666 return;
667
668 echo '<p class="wppb-error wppb-comment-captcha-error" id="wppb_comment_turnstile_error">' . esc_html( wppb_get_turnstile_default_wp_comments_error_message() ) . '</p>';
669 }
670 add_action( 'comment_form_top', 'wppb_display_turnstile_default_wp_comments_error' );
671
672 // Verify Turnstile for default WP Comments form
673 function wppb_verify_turnstile_default_wp_comments( $approved, $commentdata ){
674 if ( !isset( $_POST['comment_post_ID'] ) )
675 return $approved;
676
677 $field = wppb_get_turnstile_field();
678
679 if ( !empty( $field ) ) {
680 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_comments' ) !== false ) ) {
681 global $wppb_turnstile_response;
682 if ( !isset( $wppb_turnstile_response ) )
683 $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
684
685 if ( $wppb_turnstile_response == false ) {
686 $redirect_to = wp_get_referer();
687
688 if ( empty( $redirect_to ) && isset( $commentdata['comment_post_ID'] ) )
689 $redirect_to = get_permalink( absint( $commentdata['comment_post_ID'] ) );
690
691 if ( !empty( $redirect_to ) && !wp_doing_ajax() ) {
692 $redirect_to = preg_replace( '/#.*$/', '', remove_query_arg( array( 'wppb_comment_recaptcha_error', 'wppb_comment_turnstile_error' ), $redirect_to ) );
693 wp_safe_redirect( add_query_arg( 'wppb_comment_turnstile_error', '1', $redirect_to ) . '#respond' );
694 exit;
695 }
696
697 return new WP_Error( 'wppb_turnstile_error', wppb_get_turnstile_default_wp_comments_error_message(), 200 );
698 }
699 }
700 }
701
702 return $approved;
703 }
704 add_filter( 'pre_comment_approved', 'wppb_verify_turnstile_default_wp_comments', 10, 2 );
705
706 // set default values in case there's already an existing Turnstile field in Manage fields (when upgrading)
707 function wppb_turnstile_set_default_values() {
708 $manage_fields = get_option('wppb_manage_fields', 'not_set');
709 if ($manage_fields != 'not_set') {
710 foreach ($manage_fields as $key => $value) {
711 if ($value['field'] == 'Turnstile') {
712 if ( !isset($value['turnstile-pb-forms']) ) $manage_fields[$key]['turnstile-pb-forms'] = 'pb_register';
713 if ( !isset($value['turnstile-wp-forms']) ) $manage_fields[$key]['turnstile-wp-forms'] = 'default_wp_register';
714 if ( !isset($value['theme']) ) $manage_fields[$key]['theme'] = 'auto';
715 }
716 }
717 update_option('wppb_manage_fields', $manage_fields);
718 }
719 }
720