PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.3
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.3
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.3, at front-end/default-fields/turnstile/turnstile.php

727 lines 35.3 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 that only pre-validates the
245 // credentials, so the same single use token is still accepted on the form submission that follows it
246 if( wppb_is_captcha_prevalidation_request() ){
247
248 $saved = wppb_prune_captcha_prevalidations( get_option( 'wppb_turnstile_validations', array() ) );
249
250 if( $already_validated === true )
251 $saved[ $turnstile_response_field ] = time();
252
253 update_option( 'wppb_turnstile_validations', $saved, false );
254
255 }
256
257 return $already_validated;
258
259 }
260
261 /* the function to add Turnstile to the registration form of PB */
262 function wppb_turnstile_handler ( $output, $form_location, $field, $user_id, $field_check_errors, $request_data ){
263 if ( $field['field'] == 'Turnstile' ){
264 $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 ) );
265 $item_description = wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_'.$field['id'].'_description_translation', $field['description'], true );
266
267 wppb_turnstile_set_default_values();
268
269 if ( ($form_location == 'register') && ( isset($field['turnstile-pb-forms']) ) && ( strpos($field['turnstile-pb-forms'],'pb_register') !== false ) ) {
270 $error_mark = ( ( $field['required'] == 'Yes' ) ? '<span class="wppb-required" title="'.wppb_required_field_error($field["field-title"]).'">*</span>' : '' );
271
272 global $wppb_turnstile_present;
273 $wppb_turnstile_present = true;
274
275 if ( array_key_exists( $field['id'], $field_check_errors ) )
276 $error_mark = '<img src="'.WPPB_PLUGIN_URL.'assets/images/pencil_delete.png" title="'.wppb_required_field_error($field["field-title"]).'"/>';
277
278 $publickey = trim( $field['turnstile-site-key'] );
279 $privatekey = trim( $field['turnstile-secret-key'] );
280
281 if ( empty( $publickey ) || empty( $privatekey ) )
282 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>';
283
284 $output = '<label for="turnstile_response_field">' . $item_title . $error_mark . '</label>' . wppb_turnstile_get_html($publickey, 'pb_register');
285 if (!empty($item_description))
286 $output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
287
288 return $output;
289
290 }
291 }
292 }
293 add_filter( 'wppb_output_form_field_turnstile', 'wppb_turnstile_handler', 10, 6 );
294
295 /* handle Turnstile field validation on PB Register form */
296 function wppb_check_turnstile_value( $message, $field, $request_data, $form_location ){
297 if( $field['field'] == 'Turnstile' ){
298 if ( ( $form_location == 'register' ) && ( isset($field['turnstile-pb-forms']) ) && ( strpos($field['turnstile-pb-forms'],'pb_register') !== false ) ) {
299 /* 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
300 so do not verify it again or it will fail */
301 global $wppb_turnstile_response;
302 if (!isset($wppb_turnstile_response)){
303 $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
304 }
305 /* Turnstile must fail closed: whenever it is configured to display on this form it has to be
306 verified, regardless of the "required" toggle. A missing/empty token makes
307 wppb_validate_turnstile_response() return false, so bots that omit cf-turnstile-response are blocked. */
308 if ( $wppb_turnstile_response == false ){
309 return __('Cloudflare Turnstile could not be verified. Please try again.', 'profile-builder');
310 }
311 }
312 }
313 return $message;
314 }
315 add_filter( 'wppb_check_form_field_turnstile', 'wppb_check_turnstile_value', 10, 4 );
316
317 // Get the Turnstile field information
318 function wppb_get_turnstile_field(){
319 $wppb_manage_fields = get_option( 'wppb_manage_fields', 'not_found' );
320 $field = array();
321 if ( $wppb_manage_fields != 'not_found' ) {
322 foreach ($wppb_manage_fields as $value) {
323 if ($value['field'] == 'Turnstile'){
324 $field = $value;
325 break;
326 }
327 }
328 }
329 return $field;
330 }
331
332 /* Display Turnstile on PB Recover Password form */
333 function wppb_display_turnstile_recover_password( $output ){
334 $field = wppb_get_turnstile_field();
335
336 if ( !empty($field) ) {
337 $publickey = trim($field['turnstile-site-key']);
338 $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));
339 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
340
341 // check where Turnstile should display and add Turnstile html
342 if ( isset($field['turnstile-pb-forms']) && ( strpos( $field['turnstile-pb-forms'],'pb_recover_password' ) !== false ) ) {
343
344 global $wppb_turnstile_present;
345 $wppb_turnstile_present = true;
346
347 $turnstile_output = '<label for="turnstile_response_field">' . $item_title . '</label>' . wppb_turnstile_get_html($publickey, 'pb_recover_password');
348 if (!empty($item_description))
349 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
350
351 $output = str_replace('</ul>', '<li class="wppb-form-field wppb-turnstile">' . $turnstile_output . '</li>' . '</ul>', $output);
352 }
353 }
354 return $output;
355 }
356 add_filter('wppb_recover_password_generate_password_input','wppb_display_turnstile_recover_password');
357
358 /* Function that changes the messageNo from the Recover Password form */
359 function wppb_turnstile_change_recover_password_message_no($messageNo) {
360
361 if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'recover_password') {
362 $field = wppb_get_turnstile_field();
363 if (!empty($field)) {
364
365 global $wppb_turnstile_response;
366 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
367
368 if ( isset($field['turnstile-pb-forms']) && (strpos($field['turnstile-pb-forms'], 'pb_recover_password') !== false) ) {
369
370 if ( $wppb_turnstile_response == false )
371 $messageNo = '';
372 }
373 }
374 }
375
376 return $messageNo;
377 }
378 add_filter('wppb_recover_password_message_no', 'wppb_turnstile_change_recover_password_message_no');
379
380 /* Function that adds the Turnstile error message on the Recover Password form */
381 function wppb_turnstile_recover_password_displayed_message1( $message ) {
382 $field = wppb_get_turnstile_field();
383
384 if ( !empty($field) ){
385 global $wppb_turnstile_response;
386 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
387
388 if ( isset($field['turnstile-pb-forms']) && ( strpos( $field['turnstile-pb-forms'],'pb_recover_password' ) !== false ) && ( $wppb_turnstile_response == false )) {
389
390 $turnstile_error_message = __('Cloudflare Turnstile could not be verified. Please try again.', 'profile-builder');
391
392 if (($message == '<p class="wppb-warning">wppb_turnstile_error</p>') || ($message == '<p class="wppb-warning">wppb_captcha_error</p>'))
393 $message = '<p class="wppb-warning">' . $turnstile_error_message . '</p>';
394 else
395 $message = $message . '<p class="wppb-warning">' . $turnstile_error_message . '</p>';
396
397 }
398 }
399
400 return $message;
401 }
402 add_filter('wppb_recover_password_displayed_message1', 'wppb_turnstile_recover_password_displayed_message1');
403
404 /* Function that changes the default success message to wppb_turnstile_error if it doesn't validate */
405 function wppb_turnstile_recover_password_sent_message_1($message) {
406
407 if (isset($_REQUEST['action']) && $_REQUEST['action'] === 'recover_password') {
408 $field = wppb_get_turnstile_field();
409
410 if (!empty($field)) {
411 global $wppb_turnstile_response;
412 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
413
414 if ( isset($field['turnstile-pb-forms']) && ( strpos($field['turnstile-pb-forms'], 'pb_recover_password') !== false ) && ( $wppb_turnstile_response == false ) ){
415 $message = 'wppb_turnstile_error';
416 }
417 }
418
419 }
420
421 return $message;
422 }
423 add_filter('wppb_recover_password_sent_message1', 'wppb_turnstile_recover_password_sent_message_1');
424
425 /* Display Turnstile html on PB Login form */
426 function wppb_display_turnstile_login_form($form_part, $args) {
427
428 if( !isset( $args['form_id'] ) || $args['form_id'] != 'wppb-loginform' )
429 return $form_part;
430
431 $field = wppb_get_turnstile_field();
432
433 if ( !empty($field) ) {
434 $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));
435 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
436
437 if ( isset($field['turnstile-pb-forms']) && ( strpos( $field['turnstile-pb-forms'],'pb_login' ) !== false ) ) { // check where Turnstile should display
438
439 global $wppb_turnstile_present;
440 $wppb_turnstile_present = true;
441
442 $turnstile_output = '<label for="turnstile_response_field">' . $item_title . '</label>' . wppb_turnstile_get_html(trim($field['turnstile-site-key']), 'pb_login');
443 if (!empty($item_description))
444 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
445
446 $form_part .= '<div class="wppb-form-field wppb-turnstile">' . $turnstile_output . '</div>';
447
448 }
449 }
450
451 return $form_part;
452 }
453 add_filter('login_form_middle', 'wppb_display_turnstile_login_form', 10, 2);
454
455 /* Display Turnstile html on default WP Login form */
456 function wppb_display_turnstile_wp_login_form(){
457 $field = wppb_get_turnstile_field();
458
459 if ( !empty($field) ) {
460 $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));
461 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
462
463 if ( isset($field['turnstile-wp-forms']) && (strpos( $field['turnstile-wp-forms'],'default_wp_login' ) !== false) ) {
464
465 global $wppb_turnstile_present;
466 $wppb_turnstile_present = true;
467
468 $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']));
469 if (!empty($item_description))
470 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
471
472 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 */
473
474 }
475 }
476 }
477 add_action( 'login_form', 'wppb_display_turnstile_wp_login_form' );
478
479 //Show Turnstile error on Login form (both default and PB one)
480 function wppb_turnstile_login_wp_error_message($user){
481 //make sure you\'re on a Login form (WP or PB)
482 if ( isset( $_POST['log'] ) && !is_wp_error($user) && !isset( $_POST['pms_login'] ) ) {
483
484 $field = wppb_get_turnstile_field();
485 if ( !empty($field) ){
486 /* Work out whether Turnstile is enabled for the form that was actually submitted before verifying
487 anything. The Cloudflare token is single use, so verifying it on a form where our widget was never
488 displayed spends a token that belongs to whatever else protects that form, and that plugin\'s own
489 check then fails with timeout-or-duplicate. */
490 if ( isset($_POST['wppb_login']) && ($_POST['wppb_login'] == true) ) {
491 // it\'s a PB login form, check if we have Turnstile on it
492 $turnstile_enabled = ( isset($field['turnstile-pb-forms']) && (strpos($field['turnstile-pb-forms'], 'pb_login') !== false) );
493 }
494 else {
495 // default WP login form
496 $turnstile_enabled = ( isset($field['turnstile-wp-forms']) && (strpos($field['turnstile-wp-forms'], 'default_wp_login') !== false) );
497 }
498
499 if ( $turnstile_enabled ) {
500 global $wppb_turnstile_response;
501
502 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
503
504 $turnstile_error_message = __('Cloudflare Turnstile could not be verified. Please try again.','profile-builder');
505
506 if ( $wppb_turnstile_response == false ) {
507 $user = new WP_Error('wppb_turnstile_error', $turnstile_error_message);
508 remove_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
509 remove_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
510 }
511 }
512 }
513 }
514 return $user;
515 }
516 add_filter('authenticate','wppb_turnstile_login_wp_error_message', 9);
517
518 /**
519 * Add a Turnstile CSS class to the Register form field
520 *
521 * @param $classes - existing field classes
522 * @param $field - field data
523 * @return mixed|string
524 */
525 function wppb_register_form_turnstile_type_class( $classes, $field ){
526
527 if ( isset( $field['field'] ) && $field['field'] == 'Turnstile' )
528 $classes .= ' wppb-turnstile';
529
530 return $classes;
531 }
532 add_filter( 'wppb_field_css_class', 'wppb_register_form_turnstile_type_class', 20, 2);
533
534 // Display Turnstile html on default WP Recover Password form
535 function wppb_display_turnstile_default_wp_recover_password() {
536 $field = wppb_get_turnstile_field();
537
538 if (!empty($field)) {
539 $publickey = trim($field['turnstile-site-key']);
540 $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));
541 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
542
543 if ( isset($field['turnstile-wp-forms']) && (strpos( $field['turnstile-wp-forms'], 'default_wp_recover_password') !== false) ) {
544
545 global $wppb_turnstile_present;
546 $wppb_turnstile_present = true;
547
548 $turnstile_output = '<label for="turnstile_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_turnstile_get_html($publickey);
549 if (!empty($item_description))
550 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
551
552 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 */
553
554 }
555 }
556 }
557 add_action('lostpassword_form','wppb_display_turnstile_default_wp_recover_password');
558
559 // Verify and show Turnstile errors for default WP Recover Password
560 function wppb_verify_turnstile_default_wp_recover_password(){
561
562 // If field \'username or email\' is empty - return
563 if( isset( $_REQUEST['user_login'] ) && "" === $_REQUEST['user_login'] )
564 return;
565
566 $field = wppb_get_turnstile_field();
567 if ( !empty($field) ){
568 /* Only verify where Turnstile is configured for the form being submitted. The Cloudflare token is
569 single use, so verifying it on a form our widget was never displayed on spends a token that another
570 plugin protecting that form still needs, and its own check then fails with timeout-or-duplicate. */
571 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_recover_password' ) !== false ) ) {
572 global $wppb_turnstile_response;
573 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
574
575 $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder');
576
577 // Fail closed: a missing token is treated as a failed verification.
578 if ( $wppb_turnstile_response == false ) {
579 wp_die( esc_html( $turnstile_error_message ) . '<br />' . esc_html__( "Click the BACK button on your browser, and try again.", 'profile-builder' ) ) ;
580 }
581 }
582 }
583 }
584 add_action('lostpassword_post','wppb_verify_turnstile_default_wp_recover_password');
585
586 /* Display Turnstile html on default WP Register form */
587 function wppb_display_turnstile_default_wp_register(){
588 $field = wppb_get_turnstile_field();
589
590 if (!empty($field)) {
591
592 $publickey = trim($field['turnstile-site-key']);
593 $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));
594 $item_description = wppb_icl_t('plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true);
595
596 wppb_turnstile_set_default_values();
597 if (isset($field['turnstile-wp-forms']) && (strpos($field['turnstile-wp-forms'], 'default_wp_register') !== false)) {
598
599 global $wppb_turnstile_present;
600 $wppb_turnstile_present = true;
601
602 $turnstile_output = '<label for="turnstile_response_field" style="padding-left:15px; padding-bottom:7px;">' . $item_title . '</label>' . wppb_turnstile_get_html($publickey);
603 if (!empty($item_description))
604 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
605
606 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 */
607
608 }
609 }
610 }
611 add_action( 'register_form', 'wppb_display_turnstile_default_wp_register' );
612
613 // Verify and show Turnstile errors for default WP Register form
614 function wppb_verify_turnstile_default_wp_register( $errors ){
615
616 $field = wppb_get_turnstile_field();
617 if ( !empty($field) ){
618 /* Only verify where Turnstile is configured for the form being submitted. The Cloudflare token is
619 single use, so verifying it on a form our widget was never displayed on spends a token that another
620 plugin protecting that form still needs, and its own check then fails with timeout-or-duplicate. */
621 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_register' ) !== false ) ) {
622 global $wppb_turnstile_response;
623 if (!isset($wppb_turnstile_response)) $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
624
625 $turnstile_error_message = esc_html__('Cloudflare Turnstile could not be verified. Please try again.','profile-builder');
626
627 // Fail closed: a missing token is treated as a failed verification.
628 if ( $wppb_turnstile_response == false ) {
629 $errors->add( 'wppb_turnstile_error', $turnstile_error_message );
630 }
631 }
632 }
633
634 return $errors;
635 }
636 add_filter('registration_errors','wppb_verify_turnstile_default_wp_register');
637
638 /* Display Turnstile html on default WP Comments form */
639 function wppb_display_turnstile_default_wp_comments(){
640 $field = wppb_get_turnstile_field();
641
642 if ( !empty( $field ) ) {
643 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_comments' ) !== false ) ) {
644 $publickey = trim( $field['turnstile-site-key'] );
645 $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 ) );
646 $item_description = wppb_icl_t( 'plugin profile-builder-pro', 'custom_field_' . $field['id'] . '_description_translation', $field['description'], true );
647
648 global $wppb_turnstile_present;
649 $wppb_turnstile_present = true;
650
651 $turnstile_output = '<label for="turnstile_response_field">' . $item_title . '</label>' . wppb_turnstile_get_html( $publickey, 'default_wp_comments' );
652 if ( !empty( $item_description ) )
653 $turnstile_output .= '<span class="wppb-description-delimiter">' . $item_description . '</span>';
654
655 echo '<div class="wppb-form-field wppb-turnstile">' . $turnstile_output . '</div>'; /* phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped */ /* properly escaped when constructing the var */
656 }
657 }
658 }
659 add_action( 'comment_form_after_fields', 'wppb_display_turnstile_default_wp_comments' );
660 add_action( 'comment_form_logged_in_after', 'wppb_display_turnstile_default_wp_comments' );
661
662 function wppb_get_turnstile_default_wp_comments_error_message(){
663 return __( 'Cloudflare Turnstile could not be verified. Please try again.', 'profile-builder' );
664 }
665
666 function wppb_display_turnstile_default_wp_comments_error(){
667 if ( !isset( $_GET['wppb_comment_turnstile_error'] ) )
668 return;
669
670 $field = wppb_get_turnstile_field();
671
672 if ( empty( $field ) || !isset( $field['turnstile-wp-forms'] ) || ( strpos( $field['turnstile-wp-forms'], 'default_wp_comments' ) === false ) )
673 return;
674
675 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>';
676 }
677 add_action( 'comment_form_top', 'wppb_display_turnstile_default_wp_comments_error' );
678
679 // Verify Turnstile for default WP Comments form
680 function wppb_verify_turnstile_default_wp_comments( $approved, $commentdata ){
681 if ( !isset( $_POST['comment_post_ID'] ) )
682 return $approved;
683
684 $field = wppb_get_turnstile_field();
685
686 if ( !empty( $field ) ) {
687 if ( isset( $field['turnstile-wp-forms'] ) && ( strpos( $field['turnstile-wp-forms'], 'default_wp_comments' ) !== false ) ) {
688 global $wppb_turnstile_response;
689 if ( !isset( $wppb_turnstile_response ) )
690 $wppb_turnstile_response = wppb_validate_turnstile_response( trim( $field['turnstile-site-key'] ), trim( $field['turnstile-secret-key'] ) );
691
692 if ( $wppb_turnstile_response == false ) {
693 $redirect_to = wp_get_referer();
694
695 if ( empty( $redirect_to ) && isset( $commentdata['comment_post_ID'] ) )
696 $redirect_to = get_permalink( absint( $commentdata['comment_post_ID'] ) );
697
698 if ( !empty( $redirect_to ) && !wp_doing_ajax() ) {
699 $redirect_to = preg_replace( '/#.*$/', '', remove_query_arg( array( 'wppb_comment_recaptcha_error', 'wppb_comment_turnstile_error' ), $redirect_to ) );
700 wp_safe_redirect( add_query_arg( 'wppb_comment_turnstile_error', '1', $redirect_to ) . '#respond' );
701 exit;
702 }
703
704 return new WP_Error( 'wppb_turnstile_error', wppb_get_turnstile_default_wp_comments_error_message(), 200 );
705 }
706 }
707 }
708
709 return $approved;
710 }
711 add_filter( 'pre_comment_approved', 'wppb_verify_turnstile_default_wp_comments', 10, 2 );
712
713 // set default values in case there's already an existing Turnstile field in Manage fields (when upgrading)
714 function wppb_turnstile_set_default_values() {
715 $manage_fields = get_option('wppb_manage_fields', 'not_set');
716 if ($manage_fields != 'not_set') {
717 foreach ($manage_fields as $key => $value) {
718 if ($value['field'] == 'Turnstile') {
719 if ( !isset($value['turnstile-pb-forms']) ) $manage_fields[$key]['turnstile-pb-forms'] = 'pb_register';
720 if ( !isset($value['turnstile-wp-forms']) ) $manage_fields[$key]['turnstile-wp-forms'] = 'default_wp_register';
721 if ( !isset($value['theme']) ) $manage_fields[$key]['theme'] = 'auto';
722 }
723 }
724 update_option('wppb_manage_fields', $manage_fields);
725 }
726 }
727