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
← All changes | features/functions.php +341 -70 3.9.94.0.3 View file →
@@ -55,8 +55,24 @@
55 55 }
56 56 }
57 57
58 58
59 +/**
60 + * Whether Profile Builder should load style-block-themes-front-end.css.
61 + */
62 +function wppb_should_load_block_theme_stylesheet() {
63 + $is_block_theme_context = version_compare( get_bloginfo( 'version' ), '5.9', '>=' )
64 + && function_exists( 'wp_is_block_theme' )
65 + && wp_is_block_theme();
66 +
67 + /**
68 + * Filter whether to load the block theme front-end stylesheet.
69 + *
70 + * @param bool $load_block_theme_stylesheet True when WordPress is 5.9+ and the active theme is a block theme.
71 + */
72 + return (bool) apply_filters( 'wppb_load_block_theme_stylesheet', $is_block_theme_context );
73 +}
74 +
59 75 function wppb_add_plugin_stylesheet() {
60 76 $wppb_generalSettings = get_option( 'wppb_general_settings' );
61 77
62 78 if ( ( file_exists( WPPB_PLUGIN_DIR . '/assets/css/style-front-end.css' ) ) && ( isset( $wppb_generalSettings['extraFieldsLayout'] ) && ( $wppb_generalSettings['extraFieldsLayout'] == 'default' ) ) ){
@@ -62,8 +78,9 @@
62 78 if ( ( file_exists( WPPB_PLUGIN_DIR . '/assets/css/style-front-end.css' ) ) && ( isset( $wppb_generalSettings['extraFieldsLayout'] ) && ( $wppb_generalSettings['extraFieldsLayout'] == 'default' ) ) ){
63 79 wp_register_style( 'wppb_stylesheet', WPPB_PLUGIN_URL . 'assets/css/style-front-end.css', array(), PROFILE_BUILDER_VERSION );
64 80 wp_enqueue_style( 'wppb_stylesheet' );
65 81 }
82 +
66 83 if( is_rtl() ) {
67 84 if ( ( file_exists( WPPB_PLUGIN_DIR . '/assets/css/rtl.css' ) ) && ( isset( $wppb_generalSettings['extraFieldsLayout'] ) && ( $wppb_generalSettings['extraFieldsLayout'] == 'default' ) ) ){
68 85 wp_register_style( 'wppb_stylesheet_rtl', WPPB_PLUGIN_URL . 'assets/css/rtl.css', array(), PROFILE_BUILDER_VERSION );
69 86 wp_enqueue_style( 'wppb_stylesheet_rtl' );
@@ -68,8 +85,17 @@
68 85 wp_register_style( 'wppb_stylesheet_rtl', WPPB_PLUGIN_URL . 'assets/css/rtl.css', array(), PROFILE_BUILDER_VERSION );
69 86 wp_enqueue_style( 'wppb_stylesheet_rtl' );
70 87 }
71 88 }
89 +
90 + if ( wppb_should_load_block_theme_stylesheet() ) {
91 + $active_design = function_exists( 'wppb_get_active_form_design' ) ? wppb_get_active_form_design() : 'form-style-default';
92 +
93 + if ( $active_design === 'form-style-default' && file_exists( WPPB_PLUGIN_DIR . 'assets/css/style-block-themes-front-end.css' ) ) {
94 + wp_register_style( 'wppb_block_themes_front_end_stylesheet', WPPB_PLUGIN_URL . 'assets/css/style-block-themes-front-end.css', array(), PROFILE_BUILDER_VERSION );
95 + wp_enqueue_style( 'wppb_block_themes_front_end_stylesheet' );
96 + }
97 + }
72 98 }
73 99
74 100
75 101 function wppb_show_admin_bar($content){
@@ -81,20 +107,63 @@
81 107 $show = null;
82 108
83 109 if ( $general_settings != 'not_found' && $current_user->ID && !empty( $selected_roles ) )
84 110 foreach ( $current_user->roles as $role_key ) {
85 - if ( empty( $GLOBALS['wp_roles']->roles[$role_key] ) )
111 + if( $role_key == 'administrator' && current_user_can( 'manage_options' ) && !in_array( 'allUserRoles', $selected_roles ) )
112 + break;
113 + else if ( empty( $GLOBALS['wp_roles']->roles[$role_key] ) )
86 114 continue;
115 +
87 116 $role = $GLOBALS['wp_roles']->roles[$role_key];
88 117
89 - if ( !empty( $selected_roles ) && in_array( $role['name'], $selected_roles ) && $show === null )
118 + if ( !empty( $selected_roles ) && ( in_array( $role['name'], $selected_roles ) || in_array( 'allUserRoles', $selected_roles ) || in_array( 'allUserRolesExceptAdmin', $selected_roles ) ) && $show === null )
90 119 $show = false;
120 + }
121 + return $show === null ? $content : $show;
122 +}
91 123
124 +function wppb_has_international_tel_input_field() {
125 + $manage_fields = get_option( 'wppb_manage_fields', array() );
126 +
127 + if ( ! is_array( $manage_fields ) ) {
128 + return false;
129 + }
130 +
131 + foreach ( $manage_fields as $field ) {
132 + if ( ! empty( $field['field'] ) && $field['field'] === 'International Telephone Input' ) {
133 + return true;
92 134 }
93 - return $show === null ? $content : $show;
135 + }
136 +
137 + return false;
94 138 }
95 139
140 +function wppb_maybe_add_international_tel_input_notice() {
141 + if ( ! class_exists( 'WPPB_Plugin_Notifications' ) ) {
142 + return;
143 + }
96 144
145 + if ( ! wppb_has_international_tel_input_field() ) {
146 + return;
147 + }
148 +
149 + if ( function_exists( 'wppb_international_tel_input_handler' ) ) {
150 + return;
151 + }
152 +
153 + $notification_id = 'wppb_intl_tel_input_paid_update_notice';
154 + $message = '<p>';
155 + $message .= __( 'The <strong>International Telephone Input</strong> field is currently used on this site, but it now requires the <strong>paid Profile Builder plugin</strong> to be updated as well.', 'profile-builder' );
156 + $message .= ' ';
157 + $message .= __( 'Please update the paid plugin to the latest version so this field can continue to load and validate correctly.', 'profile-builder' );
158 + $message .= '</p>';
159 + $message .= '<a href="' . wp_nonce_url( add_query_arg( array( 'wppb_dismiss_admin_notification' => $notification_id ) ), 'wppb_plugin_notice_dismiss' ) . '" type="button" class="notice-dismiss"><span class="screen-reader-text">' . __( 'Dismiss this notice.', 'profile-builder' ) . '</span></a>';
160 +
161 + WPPB_Plugin_Notifications::get_instance()->add_notification( $notification_id, $message, 'wppb-notice notice notice-warning is-dismissible', false, array(), true );
162 +}
163 +
164 +add_action( 'admin_init', 'wppb_maybe_add_international_tel_input_notice' );
165 +
97 166 if(!function_exists('wppb_curpageurl')){
98 167 function wppb_curpageurl(){
99 168 $req_uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( $_SERVER['REQUEST_URI'] ) : '';
100 169
@@ -292,12 +361,12 @@
292 361 $activation_landing_page_id = ( ( isset( $wppb_generalSettings['activationLandingPage'] ) && ( trim( $wppb_generalSettings['activationLandingPage'] ) != '' ) ) ? $wppb_generalSettings['activationLandingPage'] : 'not_set' );
293 362
294 363 if ( $activation_landing_page_id != 'not_set' ){
295 364 //an activation page was selected, but we still need to check if the current page doesn't already have the registration shortcode
296 - if ( strpos( $post->post_content, '[wppb-register' ) === false )
365 + if ( strpos( $post->post_content, '[wppb-register' ) === false && !has_block( 'wppb/register', $post->post_content ) )
297 366 add_filter( 'the_content', 'wppb_add_activation_message' );
298 367
299 - }elseif ( strpos( $post->post_content, '[wppb-register' ) === false ){
368 + }elseif ( strpos( $post->post_content, '[wppb-register' ) === false && !has_block( 'wppb/register', $post->post_content ) ){
300 369 //no activation page was selected, and the sent link pointed to the home url
301 370 nocache_headers();
302 371 wp_redirect( apply_filters( 'wppb_activatate_account_redirect_url', WPPB_PLUGIN_URL.'assets/misc/fallback-page.php?activation_key='.urlencode( $activation_key ).'&site_name='.urlencode( get_bloginfo( 'name' ) ).'&message='.urlencode( $activation_message = wppb_activate_signup( $activation_key ) ), $activation_key, $activation_message ) );
303 372 exit;
@@ -323,9 +392,9 @@
323 392 'menu_slug' => 'profile-builder',
324 393 'page_type' => 'menu_page',
325 394 'position' => '70.69',
326 395 'priority' => 1,
327 - 'icon_url' => WPPB_PLUGIN_URL . 'assets/images/pb-menu-icon.png'
396 + 'icon_url' => WPPB_PLUGIN_URL . 'assets/images/pb-menu-icon.svg'
328 397 );
329 398 new WCK_Page_Creator_PB( $args );
330 399
331 400 /**
@@ -358,9 +427,9 @@
358 427 wp_enqueue_script( 'wppb-select2', WPPB_PLUGIN_URL . 'assets/js/select2/select2.min.js', array(), PROFILE_BUILDER_VERSION, true );
359 428 wp_enqueue_style( 'wppb-select2-style', WPPB_PLUGIN_URL . 'assets/css/select2/select2.min.css', false, PROFILE_BUILDER_VERSION );
360 429 }
361 430
362 - if ( $hook == 'admin_page_profile-builder-private-website' ){
431 + if ( $hook == 'profile-builder_page_profile-builder-private-website' ){
363 432 wp_enqueue_script( 'wppb-select2', WPPB_PLUGIN_URL . 'assets/js/select2/select2.min.js', array(), PROFILE_BUILDER_VERSION, true );
364 433 wp_enqueue_script( 'wppb-select2-compat', WPPB_PLUGIN_URL . 'assets/js/select2-compat.js', array(), PROFILE_BUILDER_VERSION, true );
365 434 wp_enqueue_style( 'wppb-select2-style', WPPB_PLUGIN_URL . 'assets/css/select2/select2.min.css', false, PROFILE_BUILDER_VERSION );
366 435 }
@@ -382,11 +451,10 @@
382 451 ( $hook == 'profile-builder_page_user-email-customizer') ||
383 452 ( $hook == 'profile-builder_page_profile-builder-content_restriction' ) ||
384 453 ( strpos( $hook, 'profile-builder_page_' ) === 0 ) ||
385 454 ( $hook == 'edit.php' && ( isset( $_GET['post_type'] ) && $_GET['post_type'] === 'wppb-roles-editor' ) ) ||
386 - ( $hook == 'admin_page_profile-builder-pms-promo') ||
387 455 ( $hook == 'toplevel_page_profile-builder-register') || //multisite register version page
388 - ( $hook == 'admin_page_profile-builder-private-website') ) {
456 + ( $hook == 'admin_page_profile-builder-pms-promo') ) {
389 457 wp_enqueue_style( 'wppb-back-end-style', WPPB_PLUGIN_URL . 'assets/css/style-back-end.css', false, PROFILE_BUILDER_VERSION );
390 458 }
391 459
392 460 if ( $hook == 'profile-builder_page_profile-builder-general-settings' )
@@ -398,8 +466,11 @@
398 466 wp_enqueue_style( 'thickbox' );
399 467 wp_enqueue_script( 'thickbox' );
400 468 }
401 469
470 + if ( $hook == 'profile-builder_page_profile-builder-dashboard' )
471 + wp_enqueue_script( 'jquery-pb-dashboard', WPPB_PLUGIN_URL . 'assets/js/jquery-pb-dashboard.js', array(), PROFILE_BUILDER_VERSION, true );
472 +
402 473 if ( isset( $_GET['post_type'] ) || isset( $_GET['post'] ) ){
403 474 if ( isset( $_GET['post_type'] ) )
404 475 $post_type = sanitize_text_field( $_GET['post_type'] );
405 476
@@ -408,8 +479,9 @@
408 479
409 480 if ( ( 'wppb-epf-cpt' == $post_type ) || ( 'wppb-rf-cpt' == $post_type ) || ( 'wppb-ul-cpt' == $post_type ) ){
410 481 wp_enqueue_style( 'wppb-back-end-style', WPPB_PLUGIN_URL . 'assets/css/style-back-end.css', false, PROFILE_BUILDER_VERSION );
411 482 wp_enqueue_script( 'wppb-epf-rf', WPPB_PLUGIN_URL . 'assets/js/jquery-epf-rf.js', array(), PROFILE_BUILDER_VERSION, true );
483 + wp_localize_script( 'wppb-epf-rf', 'wppbEpfRf', array( 'nonce' => wp_create_nonce( 'wppb-epf-rf-id-change' ) ) );
412 484 }
413 485 else if( 'wppb-roles-editor' == $post_type ){
414 486 wp_enqueue_style( 'wppb-back-end-style', WPPB_PLUGIN_URL . 'assets/css/style-back-end.css', array(), PROFILE_BUILDER_VERSION );
415 487 }
@@ -417,11 +489,19 @@
417 489 else if ( isset( $_GET['page'] ) ) {
418 490 wp_enqueue_style( 'wppb-back-end-style', WPPB_PLUGIN_URL . 'assets/css/style-back-end.css', array(), PROFILE_BUILDER_VERSION );
419 491 }
420 492
493 + if ( $hook == 'user-edit.php' ) {
494 + wp_enqueue_style( 'wppb-back-end-edit-user-style', WPPB_PLUGIN_URL . 'assets/css/style-back-end-edit-user.css', array(), PROFILE_BUILDER_VERSION );
495 + }
421 496
422 -
423 497 wp_enqueue_script( 'wppb-sitewide', WPPB_PLUGIN_URL . 'assets/js/jquery-pb-sitewide.js', array(), PROFILE_BUILDER_VERSION, true );
498 + wp_localize_script( 'wppb-sitewide', 'wppbDeactivationData', array(
499 + 'deactivationReasonNonce' => wp_create_nonce( 'wppb_deactivation_reason' ),
500 + 'deactivationReasonRequired' => __( 'Please select a reason before deactivating.', 'profile-builder' ),
501 + 'deactivationReasonInput' => __( 'Please complete the required field before deactivating.', 'profile-builder' ),
502 + 'deactivationReasonSaveError' => __( 'We could not save your feedback. Please try again.', 'profile-builder' ),
503 + ) );
424 504
425 505 wp_enqueue_style( 'wppb-serial-notice-css', WPPB_PLUGIN_URL . 'assets/css/serial-notice.css', false, PROFILE_BUILDER_VERSION );
426 506 }
427 507 add_action( 'admin_enqueue_scripts', 'wppb_print_cpt_script', 9 );
@@ -429,12 +509,11 @@
429 509 /**
430 510 * Highlight the settings page under Profile Builder in the admin menu for these pages
431 511 */
432 512 //add add_action( "admin_footer-$hook", "wppb_make_setting_menu_item_highlighted" ); for other pages that don't have a parent
433 -add_action( "admin_footer-admin_page_profile-builder-private-website", "wppb_make_setting_menu_item_highlighted" );
513 +add_action( "admin_footer-profile-builder_page_profile-builder-private-website", "wppb_make_setting_menu_item_highlighted" );
434 514 add_action( "admin_footer-profile-builder_page_profile-builder-admin-bar-settings", "wppb_make_setting_menu_item_highlighted" );
435 515 add_action( "admin_footer-profile-builder_page_profile-builder-content_restriction", "wppb_make_setting_menu_item_highlighted" );
436 -add_action( "admin_footer-profile-builder_page_profile-builder-content_restriction", "wppb_make_setting_menu_item_highlighted" );
437 516 add_action( "admin_footer-profile-builder_page_admin-email-customizer", "wppb_make_setting_menu_item_highlighted" );
438 517 add_action( "admin_footer-profile-builder_page_user-email-customizer", "wppb_make_setting_menu_item_highlighted" );
439 518 add_action( "admin_footer-profile-builder_page_profile-builder-toolbox-settings", "wppb_make_setting_menu_item_highlighted" );
440 519 add_action( "admin_footer-profile-builder_page_profile-builder-two-factor-authentication", "wppb_make_setting_menu_item_highlighted" );
@@ -713,18 +792,29 @@
713 792 // add a hook to delete the user from the _signups table if either the email confirmation is activated, or it is a wpmu installation
714 793 function wppb_delete_user_from_signups_table($user_id) {
715 794 global $wpdb;
716 795
717 - $userLogin = $wpdb->get_var( $wpdb->prepare( "SELECT user_login, user_email FROM " . $wpdb->users . " WHERE ID = %d LIMIT 1", $user_id ) );
718 - if ( is_multisite() )
719 - $delete = $wpdb->delete( $wpdb->signups, array( 'user_login' => $userLogin ) );
720 - else {
721 - $table_name = $wpdb->prefix . 'signups';
722 - $val = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) );
723 - if ( $val ){
724 - $delete = $wpdb->delete($wpdb->prefix . 'signups', array('user_login' => $userLogin));
725 - }
726 - }
796 + $user = get_userdata( $user_id );
797 +
798 + if ( empty( $user ) ) {
799 + return;
800 + }
801 +
802 + // Delete signup rows by both email and login so activated entries do not remain orphaned in the signups table
803 + // - the signup row can preserve the originally submitted username, while the actual WP user_login may be regenerated from the submitted email address on activation
804 + // - the signup row can also preserve the email address used at registration time, while the actual WP user_email may later change after activation
805 + // - deleting by both keys covers both mismatch cases and keeps stale signups rows from blocking future registrations or other flows
806 + if ( is_multisite() ) {
807 + $wpdb->delete( $wpdb->signups, array( 'user_email' => $user->user_email ), array( '%s' ) );
808 + $wpdb->delete( $wpdb->signups, array( 'user_login' => $user->user_login ), array( '%s' ) );
809 + } else {
810 + $table_name = $wpdb->prefix . 'signups';
811 + $val = $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s", $table_name ) );
812 + if ( $val ) {
813 + $wpdb->delete( $table_name, array( 'user_email' => $user->user_email ), array( '%s' ) );
814 + $wpdb->delete( $table_name, array( 'user_login' => $user->user_login ), array( '%s' ) );
815 + }
816 + }
727 817 }
728 818
729 819 $wppb_generalSettings = get_option( 'wppb_general_settings' );
730 820 if ( !empty( $wppb_generalSettings['emailConfirmation'] ) && ( $wppb_generalSettings['emailConfirmation'] == 'yes' ) ) {
@@ -750,8 +840,22 @@
750 840 return apply_filters( 'wppb_user_meta_exists_meta_name', $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->usermeta WHERE user_id = %d AND meta_key = %s", $id, $meta_name ) ), $id, $meta_name );
751 841 }
752 842
753 843
844 +/**
845 + * Sanitize a URL from request input. Non-string values (e.g. arrays from bracket notation) return ''.
846 + *
847 + * @param mixed $url Candidate URL.
848 + * @return string
849 + */
850 +function wppb_sanitize_request_url( $url ) {
851 + if ( ! is_string( $url ) || $url === '' ) {
852 + return '';
853 + }
854 +
855 + return esc_url_raw( wp_unslash( $url ) );
856 +}
857 +
754 858 // function to check if there is a need to add the http:// prefix
755 859 function wppb_check_missing_http( $redirectLink ) {
756 860 return preg_match( '#^(?:[a-z\d]+(?:-+[a-z\d]+)*\.)+[a-z]+(?::\d+)?(?:/|$)#i', $redirectLink );
757 861 }
@@ -796,9 +900,9 @@
796 900
797 901 //function to check password strength
798 902 function wppb_check_password_strength(){
799 903 $wppb_generalSettings = get_option( 'wppb_general_settings' );
800 - if( isset( $_POST['wppb_password_strength'] ) && !empty( $wppb_generalSettings['minimum_password_strength'] ) ){
904 + if( isset( $_POST['wppb_password_strength'] ) && sanitize_text_field( $_POST['wppb_password_strength'] ) != '' && !empty( $wppb_generalSettings['minimum_password_strength'] ) ){
801 905 $wppb_password_strength = sanitize_text_field( $_POST['wppb_password_strength'] );
802 906 $password_strength_array = array( 'short' => 0, 'bad' => 1, 'good' => 2, 'strong' => 3 );
803 907 $password_strength_text = array( 'short' => __( 'Very Weak', 'profile-builder' ), 'bad' => __( 'Weak', 'profile-builder' ), 'good' => __( 'Medium', 'profile-builder' ), 'strong' => __( 'Strong', 'profile-builder' ) );
804 908 if( $password_strength_array[$wppb_password_strength] < $password_strength_array[$wppb_generalSettings['minimum_password_strength']] ){
@@ -835,8 +939,9 @@
835 939
836 940 /**
837 941 * Include password strength check scripts on frontend where we have shortcodes present
838 942 */
943 +add_action( 'elementor/frontend/after_enqueue_scripts', 'wppb_enqueue_password_strength_check' );
839 944 add_action( 'wp_footer', 'wppb_enqueue_password_strength_check' );
840 945 function wppb_enqueue_password_strength_check() {
841 946 global $wppb_shortcode_on_front;
842 947 if( $wppb_shortcode_on_front ){
@@ -853,14 +958,16 @@
853 958 $wppb_generalSettings = get_option( 'wppb_general_settings' );
854 959 if( !empty( $wppb_generalSettings['minimum_password_strength'] ) ){
855 960 ?>
856 961 <script type="text/javascript">
857 - function check_pass_strength() {
858 - var pass1 = jQuery('#passw1').val(), pass2 = jQuery('#passw2').val(), strength;
962 + function check_pass_strength(form) {
963 + var pass1 = jQuery(form).find('#passw1').val(),
964 + pass2 = jQuery(form).find('#passw2').val(),
965 + strength;
859 966
860 - jQuery('#pass-strength-result').removeClass('short bad good strong');
861 - if ( ! pass1 ) {
862 - jQuery('#pass-strength-result').html( pwsL10n.empty );
967 + jQuery(form).find('#pass-strength-result').removeClass('short bad good strong');
968 + if (!pass1) {
969 + jQuery(form).find('#pass-strength-result').html(pwsL10n.empty);
863 970 return;
864 971 }
865 972 <?php
866 973 global $wp_version;
@@ -877,33 +984,37 @@
877 984 }
878 985 ?>
879 986 switch ( strength ) {
880 987 case 2:
881 - jQuery('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
882 - jQuery('#wppb_password_strength').val('bad');
988 + jQuery(form).find('#pass-strength-result').addClass('bad').html( pwsL10n.bad );
989 + jQuery(form).find('#wppb_password_strength').val('bad');
883 990 break;
884 991 case 3:
885 - jQuery('#pass-strength-result').addClass('good').html( pwsL10n.good );
886 - jQuery('#wppb_password_strength').val('good');
992 + jQuery(form).find('#pass-strength-result').addClass('good').html( pwsL10n.good );
993 + jQuery(form).find('#wppb_password_strength').val('good');
887 994 break;
888 995 case 4:
889 - jQuery('#pass-strength-result').addClass('strong').html( pwsL10n.strong );
890 - jQuery('#wppb_password_strength').val('strong');
996 + jQuery(form).find('#pass-strength-result').addClass('strong').html( pwsL10n.strong );
997 + jQuery(form).find('#wppb_password_strength').val('strong');
891 998 break;
892 999 case 5:
893 - jQuery('#pass-strength-result').addClass('short').html( pwsL10n.mismatch );
894 - jQuery('#wppb_password_strength').val('short');
1000 + jQuery(form).find('#pass-strength-result').addClass('short').html( pwsL10n.mismatch );
1001 + jQuery(form).find('#wppb_password_strength').val('short');
895 1002 break;
896 1003 default:
897 - jQuery('#pass-strength-result').addClass('short').html( pwsL10n['short'] );
898 - jQuery('#wppb_password_strength').val('short');
1004 + jQuery(form).find('#pass-strength-result').addClass('short').html( pwsL10n['short'] );
1005 + jQuery(form).find('#wppb_password_strength').val('short');
899 1006 }
900 1007 }
901 1008 jQuery( document ).ready( function() {
902 1009 // Binding to trigger checkPasswordStrength
903 - jQuery('#passw1').val('').on( 'keyup', check_pass_strength );
904 - jQuery('#passw2').val('').on( 'keyup', check_pass_strength );
905 - jQuery('#pass-strength-result').show();
1010 + jQuery('.wppb-user-forms').each(function() {
1011 + var form = this;
1012 + jQuery(form).find('#passw1, #passw2').val('').on('keyup change', function() {
1013 + check_pass_strength(form);
1014 + });
1015 + jQuery(form).find('#pass-strength-result').show();
1016 + });
906 1017 });
907 1018 </script>
908 1019 <?php
909 1020 }
@@ -916,9 +1027,9 @@
916 1027 function wppb_password_visibility_toggle_html(){
917 1028 if( apply_filters( 'wppb_show_password_visibility_toggle', false ) ){
918 1029 return '
919 1030 <button type="button" class="wppb-toggle-pw wppb-show-pw hide-if-no-js" data-toggle="0" aria-label="Show password" tabindex="-1">
920 - <img src="'.WPPB_PLUGIN_URL.'/assets/images/eye-outline.svg" width="20px" height="20px" />
1031 + <img src="'.WPPB_PLUGIN_URL.'/assets/images/eye-outline.svg" title="'. esc_html__( 'Show password', 'profile-builder' ) .'" width="20px" height="20px" />
921 1032 </button>';
922 1033 }
923 1034 return '';
924 1035 }
@@ -925,12 +1036,14 @@
925 1036
926 1037 /**
927 1038 * Include toggle password visibility script on frontend where we have shortcodes present
928 1039 */
1040 +add_action( 'elementor/frontend/after_enqueue_scripts', 'wppb_enqueue_password_visibility_toggle' );
929 1041 add_action( 'wp_footer', 'wppb_enqueue_password_visibility_toggle' );
930 1042 function wppb_enqueue_password_visibility_toggle() {
931 1043 global $wppb_shortcode_on_front;
932 - if( $wppb_shortcode_on_front && apply_filters( 'wppb_show_password_visibility_toggle', false ) ){
1044 + static $enqueued = false;
1045 + if( $wppb_shortcode_on_front && apply_filters( 'wppb_show_password_visibility_toggle', false ) && !$enqueued ){
933 1046
934 1047 //load jQuery if needed
935 1048 if( !wp_script_is('jquery', 'done') ){
936 1049 wp_print_scripts('jquery');
@@ -955,32 +1068,32 @@
955 1068 })
956 1069
957 1070 });
958 1071 function wppb_password_visibility_toggle() {
959 - var target_form_id = "#" + jQuery(this).closest('form').attr("id") + " ";
1072 + var button = jQuery( this );
1073 + var container = button.closest( '.wppb-password-field-container' );
1074 + var input = container.find( 'input' ).first();
1075 + var icon = button.find( 'img' );
960 1076
961 - var password_inputs = [ ".login-password input#user_pass", "input#passw1", "input#passw2" ]
1077 + if ( ! input.length ) {
1078 + return;
1079 + }
962 1080
963 - for ( var password_input of password_inputs ){
964 - var input = jQuery( target_form_id + password_input );
965 - var button = jQuery( target_form_id + "button.wppb-toggle-pw" );
966 - var icon = jQuery( target_form_id + "button.wppb-toggle-pw img" );
967 -
968 - if ( input.length ) {
969 - if ("password" === input.attr("type")) {
970 - input.attr("type", "text");
971 - button.toggleClass("wppb-show-pw").toggleClass("wppb-hide-pw");
972 - icon.attr("src", "<?php echo esc_attr( WPPB_PLUGIN_URL ); ?>/assets/images/eye-off-outline.svg");
973 - } else {
974 - input.attr("type", "password");
975 - button.toggleClass("wppb-show-pw").toggleClass("wppb-hide-pw");
976 - icon.attr("src", "<?php echo esc_attr( WPPB_PLUGIN_URL ); ?>/assets/images/eye-outline.svg");
977 - }
978 - }
1081 + if ( "password" === input.attr( "type" ) ) {
1082 + input.attr( "type", "text" );
1083 + button.removeClass( "wppb-show-pw" ).addClass( "wppb-hide-pw" );
1084 + icon.attr( "src", "<?php echo esc_attr( WPPB_PLUGIN_URL ); ?>/assets/images/eye-off-outline.svg" );
1085 + icon.attr( "title", "<?php esc_html_e( 'Hide password', 'profile-builder' ); ?>" );
1086 + } else {
1087 + input.attr( "type", "password" );
1088 + button.removeClass( "wppb-hide-pw" ).addClass( "wppb-show-pw" );
1089 + icon.attr( "src", "<?php echo esc_attr( WPPB_PLUGIN_URL ); ?>/assets/images/eye-outline.svg" );
1090 + icon.attr( "title", "<?php esc_html_e( 'Show password', 'profile-builder' ); ?>" );
979 1091 }
980 1092 }
981 1093 </script>
982 1094 <?php
1095 + $enqueued = true;
983 1096 }
984 1097 }
985 1098
986 1099 /**
@@ -1022,12 +1135,63 @@
1022 1135 return '';
1023 1136 }
1024 1137
1025 1138
1139 +/**
1140 + * Returns the AJAX actions that check the login/checkout credentials before the real form submission is sent.
1141 + *
1142 + * Those requests run the whole authentication stack, so our CAPTCHA check runs too and the token gets spent
1143 + * with the CAPTCHA provider, but they never log the user in - the browser still submits the form afterwards
1144 + * with the very same token. CAPTCHA tokens are single use, so verifying one a second time comes back as a
1145 + * duplicate and the login fails. For these actions we remember the successful verification and reuse it once,
1146 + * when the actual form submission arrives.
1147 + */
1148 +function wppb_get_captcha_prevalidation_actions() {
1149 + return apply_filters( 'wppb_captcha_prevalidation_actions', array(
1150 + 'pms_validate_checkout', // Paid Member Subscriptions checkout validation
1151 + 'wordfence_ls_authenticate', // Wordfence Login Security login pre-flight, used to decide if it needs to ask for a 2FA code
1152 + ) );
1153 +}
1154 +
1155 +/* Whether the current request is one of the CAPTCHA pre-validation AJAX calls above */
1156 +function wppb_is_captcha_prevalidation_request() {
1157 + if ( ! wp_doing_ajax() || empty( $_POST['action'] ) || ! is_string( $_POST['action'] ) ) /* phpcs:ignore WordPress.Security.NonceVerification.Missing */
1158 + return false;
1159 +
1160 + return in_array( sanitize_text_field( $_POST['action'] ), wppb_get_captcha_prevalidation_actions(), true ); /* phpcs:ignore WordPress.Security.NonceVerification.Missing */
1161 +}
1162 +
1163 +/**
1164 + * Drops pre-validated CAPTCHA tokens that were never claimed by a form submission.
1165 + *
1166 + * A pre-validation that is not followed by a submission (wrong password, abandoned login, bots) leaves its
1167 + * entry behind, so without this the option would keep growing on sites where every login is pre-validated.
1168 + */
1169 +function wppb_prune_captcha_prevalidations( $saved ) {
1170 + if ( ! is_array( $saved ) )
1171 + return array();
1172 +
1173 + $lifetime = apply_filters( 'wppb_captcha_prevalidation_lifetime', 15 * MINUTE_IN_SECONDS );
1174 +
1175 + foreach ( $saved as $token => $validated_at ) {
1176 + if ( ! is_int( $validated_at ) || ( time() - $validated_at ) > $lifetime )
1177 + unset( $saved[ $token ] );
1178 + }
1179 +
1180 + return $saved;
1181 +}
1182 +
1026 1183 /* Function for displaying reCAPTCHA error on Login and Recover Password forms */
1027 1184 function wppb_recaptcha_field_error($field_title='') {
1028 - $recaptcha_error = apply_filters('wppb_recaptcha_error' , __('Please enter a (valid) reCAPTCHA value','profile-builder') , $field_title);
1029 1185
1186 + $recaptcha_field = wppb_get_recaptcha_field();
1187 +
1188 + if( $recaptcha_field['recaptcha-type'] === 'v2' ) {
1189 + $recaptcha_error = apply_filters('wppb_recaptcha_error' , __('Please enter a (valid) reCAPTCHA value','profile-builder') , $field_title);
1190 + } else {
1191 + $recaptcha_error = apply_filters('wppb_recaptcha_error' , __('reCaptcha could not be verified. Please try again.','profile-builder') , $field_title);
1192 + }
1193 +
1030 1194 return $recaptcha_error;
1031 1195
1032 1196 }
1033 1197 /* Function for displaying phone field error */
@@ -1360,9 +1524,9 @@
1360 1524 }
1361 1525 }
1362 1526
1363 1527 if( ! empty( $redirect_url ) ) {
1364 - $redirect_url = ( wppb_check_missing_http( $redirect_url ) ? 'http://'. $redirect_url : $redirect_url );
1528 + $redirect_url = ( wppb_check_missing_http( $redirect_url ) ? wppb_add_missing_http( $redirect_url ) : $redirect_url );
1365 1529 }
1366 1530
1367 1531 return $redirect_url;
1368 1532 }
@@ -1367,8 +1531,87 @@
1367 1531 return $redirect_url;
1368 1532 }
1369 1533
1370 1534 /**
1535 + * Bind an autologin nonce to a user ID server-side (one-time use).
1536 + *
1537 + * @param int $user_id User ID to log in.
1538 + * @param string $nonce Autologin nonce.
1539 + */
1540 +function wppb_store_autologin_user( $user_id, $nonce ) {
1541 + $user_id = absint( $user_id );
1542 +
1543 + if ( ! $user_id || empty( $nonce ) ) {
1544 + return;
1545 + }
1546 +
1547 + set_transient( 'wppb_autologin_' . md5( $nonce ), $user_id, 2 * MINUTE_IN_SECONDS );
1548 +}
1549 +
1550 +/**
1551 + * Resolve the user bound to an autologin nonce.
1552 + *
1553 + * @param string $nonce Autologin nonce.
1554 + * @param bool $consume Whether to delete the stored mapping.
1555 + *
1556 + * @return int User ID, or 0 when not found.
1557 + */
1558 +function wppb_get_autologin_user_id( $nonce, $consume = true ) {
1559 + if ( empty( $nonce ) ) {
1560 + return 0;
1561 + }
1562 +
1563 + $key = 'wppb_autologin_' . md5( $nonce );
1564 + $user_id = absint( get_transient( $key ) );
1565 +
1566 + if ( $user_id && $consume ) {
1567 + delete_transient( $key );
1568 + }
1569 +
1570 + return $user_id;
1571 +}
1572 +
1573 +/**
1574 + * Build autologin query args for a user.
1575 + *
1576 + * @param int $user_id User ID to log in.
1577 + *
1578 + * @return array Query args for add_query_arg().
1579 + */
1580 +function wppb_get_autologin_query_args( $user_id ) {
1581 + $user_id = absint( $user_id );
1582 + $nonce = wp_create_nonce( 'autologin-' . $user_id . '-' . (int) ( time() / 60 ) );
1583 +
1584 + wppb_store_autologin_user( $user_id, $nonce );
1585 +
1586 + return array(
1587 + 'autologin' => 'true',
1588 + '_wpnonce' => $nonce,
1589 + );
1590 +}
1591 +
1592 +/**
1593 + * Verify an autologin nonce for the given user ID.
1594 + *
1595 + * @param string $nonce Autologin nonce.
1596 + * @param int $user_id User ID bound to the nonce.
1597 + *
1598 + * @return bool
1599 + */
1600 +function wppb_verify_autologin_nonce( $nonce, $user_id ) {
1601 + $user_id = absint( $user_id );
1602 +
1603 + if ( ! $user_id || empty( $nonce ) ) {
1604 + return false;
1605 + }
1606 +
1607 + $nonce_action = 'autologin-' . $user_id . '-';
1608 +
1609 + return wp_verify_nonce( $nonce, $nonce_action . (int) ( time() / 60 ) )
1610 + || wp_verify_nonce( $nonce, $nonce_action . (int) ( time() / 60 - 1 ) );
1611 +}
1612 +
1613 +/**
1371 1614 * Function that builds the redirect
1372 1615 *
1373 1616 * @param string $redirect_url - redirect URL
1374 1617 * @param int $redirect_delay - redirect delay in seconds
@@ -1384,14 +1627,14 @@
1384 1627
1385 1628 $redirect_message = '';
1386 1629
1387 1630 if( ! empty( $redirect_url ) ) {
1388 - $redirect_url = ( wppb_check_missing_http( $redirect_url ) ? 'http://'. $redirect_url : $redirect_url );
1631 + $redirect_url = ( wppb_check_missing_http( $redirect_url ) ? wppb_add_missing_http( $redirect_url ) : $redirect_url );
1389 1632
1390 1633 if( $redirect_delay == 0 ) {
1391 1634 $redirect_message = '<meta http-equiv="Refresh" content="'. $redirect_delay .';url='. $redirect_url .'" />';
1392 1635 } else {
1393 - $redirect_url_href = apply_filters( 'wppb_redirect_url', '<a href="'. $redirect_url .'">'. __( 'here', 'profile-builder' ) .'</a>', $redirect_url, $redirect_type, $form_args );
1636 + $redirect_url_href = apply_filters( 'wppb_redirect_url', '<a href="'. esc_url( $redirect_url ) .'">'. __( 'here', 'profile-builder' ) .'</a>', $redirect_url, $redirect_type, $form_args );
1394 1637 $redirect_message = apply_filters( 'wppb_redirect_message_before_returning', '<p class="redirect_message">'. sprintf( wp_slash( __( 'You will soon be redirected automatically. If you see this page for more than %1$d seconds, please click %2$s.%3$s', 'profile-builder' ) ), $redirect_delay, $redirect_url_href, '<meta http-equiv="Refresh" content="'. $redirect_delay .';url='. $redirect_url .'" />' ) .'</p>', $redirect_url, $redirect_delay, $redirect_url_href, $redirect_type, $form_args );
1395 1638 }
1396 1639 }
1397 1640
@@ -1458,17 +1701,21 @@
1458 1701 if( $wppb_private_website_settings != 'not_found' ){
1459 1702 if( !empty( $wppb_private_website_settings['private_website'] ) && $wppb_private_website_settings['private_website'] == 'yes' ){
1460 1703 if( !is_user_logged_in() ){
1461 1704
1462 - if(is_404())
1705 + if( is_404() )
1463 1706 return;
1464 1707
1465 - //force wp-login.php if you accidentally get locked out
1708 + // force wp-login.php if you accidentally get locked out
1466 1709 global $pagenow;
1467 - if( $pagenow === 'wp-login.php' && isset( $_GET['wppb_force_wp_login'] ) )
1710 + if( $pagenow === 'wp-login.php' && ( isset( $_GET['wppb_force_wp_login'] ) || ( isset( $_SERVER['HTTP_REFERER'] ) && strpos( esc_url_raw( $_SERVER['HTTP_REFERER'] ), 'wppb_force_wp_login=true' ) !== false ) || ( isset($_REQUEST['redirect_to']) && strpos( sanitize_text_field( $_REQUEST['redirect_to'] ), 'wppb_force_wp_login=true' ) !== false ) ) )
1468 1711 return;
1469 1712
1470 - //go through paths first if they are set
1713 + // bypass requests that enter the password of a password protected post
1714 + if( $pagenow === 'wp-login.php' && isset( $_GET['action'] ) && $_GET['action'] == 'postpass' && isset( $_POST['post_password'] ) )
1715 + return;
1716 +
1717 + // go through paths first if they are set
1471 1718 if( isset( $wppb_private_website_settings['allowed_paths'] ) && !empty( $wppb_private_website_settings['allowed_paths'] ) ){
1472 1719 $allowed_paths = explode( "\r\n", $wppb_private_website_settings['allowed_paths'] );
1473 1720 $parsed_url = wp_parse_url( wppb_curpageurl() );
1474 1721 if( !empty( $parsed_url['path'] ) ) {
@@ -1487,8 +1734,23 @@
1487 1734 }
1488 1735 }
1489 1736 }
1490 1737
1738 + if( isset( $wppb_private_website_settings['allowed_query_strings'] ) && !empty( $wppb_private_website_settings['allowed_query_strings'] ) ){
1739 + $allowed_query_strings = explode( "\r\n", $wppb_private_website_settings['allowed_query_strings'] );
1740 + $parsed_url_parameters = wp_parse_url( wppb_curpageurl() );
1741 +
1742 + if( !empty( $parsed_url_parameters['query'] ) ) {
1743 + parse_str( $parsed_url_parameters['query'], $query_params );
1744 +
1745 + foreach ( $allowed_query_strings as $allowed_query ) {
1746 + if ( array_key_exists( $allowed_query, $query_params ) ) {
1747 + return;
1748 + }
1749 + }
1750 + }
1751 + }
1752 +
1491 1753 if( isset( $wppb_private_website_settings['allowed_pages'] ) )
1492 1754 $allowed_pages = $wppb_private_website_settings['allowed_pages'];
1493 1755 else{
1494 1756 $allowed_pages = array();
@@ -1610,8 +1872,17 @@
1610 1872 if ( !empty( $wppb_private_website_settings['private_website'] ) && $wppb_private_website_settings['private_website'] == 'yes' ) {
1611 1873 if ( !isset( $wppb_private_website_settings[ 'disable_rest_api' ] ) || $wppb_private_website_settings[ 'disable_rest_api' ] !== 'yes' ) {
1612 1874 return $result;
1613 1875 }
1876 +
1877 + // THE EVENTS CALENDAR EXCEPTION
1878 + // They do some rest API calls in the front-end for their event view but due to their usage, they are breaking the authenticated user
1879 + // and WordPress thinks the user is not authenticated (is_user_logged_in() == false)
1880 + // This makes things break for logged in users whe the Private Website + Rest API functionality is enabled
1881 + // We are going to ignore requests that contain their nonces so we can exlude them from our restrictions
1882 + if( isset( $_REQUEST['_tec_view_rest_nonce_primary'] ) || isset( $_REQUEST['_tec_view_rest_nonce_secondary'] ) )
1883 + return $result;
1884 +
1614 1885 if (!is_user_logged_in() && isset( $_SERVER['REQUEST_URI'] ) && $_SERVER['REQUEST_URI'] !== "/wp-json/jwt-auth/v1/token" && $_SERVER['REQUEST_URI'] !== "/wp-json/jwt-auth/v1/token/validate") {
1615 1886 return new WP_Error('rest_not_logged_in', __( 'You are not currently logged in.', 'profile-builder' ), array('status' => 401));
1616 1887 }
1617 1888 }
@@ -1792,9 +2063,9 @@
1792 2063 global $wp_embed;
1793 2064 if(empty($atts['width']) || empty($atts['height'])){
1794 2065 $content = $wp_embed->run_shortcode('[embed]'.$content.'[/embed]');
1795 2066 } else {
1796 - $content = $wp_embed->run_shortcode('[embed width="'.$atts['width'].'" height="'.$atts['height'].'"]'.$content.'[/embed]');
2067 + $content = $wp_embed->run_shortcode('[embed width="'.esc_attr($atts['width']).'" height="'.esc_attr($atts['height']).'"]'.$content.'[/embed]');
1797 2068 }
1798 2069
1799 2070 return $content;
1800 2071 }