From 0fc2d131ee2d41aa1baf9b5caa013be97e55b46b Mon Sep 17 00:00:00 2001 From: Nikita Sinelnikov Date: Tue, 29 Jun 2021 21:15:48 +0300 Subject: [PATCH] - fixed sanitizing functions; --- includes/admin/class-admin.php | 200 +++---- includes/admin/core/class-admin-settings.php | 14 +- includes/core/class-form.php | 528 +++++++++++-------- includes/core/class-member-directory.php | 11 +- 4 files changed, 413 insertions(+), 340 deletions(-) diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index 8a290e75..cb4e2bf6 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -345,10 +345,10 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { 'sanitize' => 'bool', ), '_um_search_filters' => array( - 'sanitize' => array( $this, 'sanitize_md_default_filters' ), + 'sanitize' => array( $this, 'sanitize_filter_fields' ), ), '_um_sortby' => array( - 'sanitize' => array( $this, 'sanitize_sort_by_fields' ), + 'sanitize' => 'text', ), '_um_sortby_custom' => array( 'sanitize' => 'text', @@ -393,7 +393,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { 'sanitize' => 'bool', ), '_um_register_role' => array( - 'sanitize' => array( $this, 'sanitize_existed_role' ), + 'sanitize' => 'key', ), '_um_register_template' => array( 'sanitize' => 'text', @@ -538,58 +538,37 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { */ public function sanitize_md_sorting_fields( $value ) { $filter_fields = array_merge( UM()->member_directory()->sort_fields, array( 'other' => __( 'Other (Custom Field)', 'ultimate-member' ) ) ); + $filter_fields = array_keys( $filter_fields ); if ( '' !== $value ) { $value = array_filter( $value, function( $v, $k ) use ( $filter_fields ) { - return in_array( sanitize_text_field( $v ), $filter_fields, true ); + if ( 'other_data' === $k ) { + return true; + } else { + return in_array( sanitize_text_field( $v ), $filter_fields, true ); + } }, ARRAY_FILTER_USE_BOTH ); - } - return $value; - } + $value = array_map( + function( $item ) { + if ( is_array( $item ) ) { + if ( isset( $item['meta_key'] ) ) { + $item['meta_key'] = sanitize_text_field( $item['meta_key'] ); + } + if ( isset( $item['label'] ) ) { + $item['label'] = sanitize_text_field( $item['label'] ); + } - - /** - * @param array|string $value - * - * @return array|string - */ - public function sanitize_sort_by_fields( $value ) { - $sorting_fields = UM()->member_directory()->default_sorting; - - if ( '' !== $value ) { - $value = array_filter( - $value, - function( $v, $k ) use ( $sorting_fields ) { - return in_array( sanitize_text_field( $v ), $sorting_fields, true ); + return $item; + } else { + return sanitize_text_field( $item ); + } }, - ARRAY_FILTER_USE_BOTH - ); - } - - return $value; - } - - - /** - * @param array|string $value - * - * @return array|string - */ - public function sanitize_md_default_filters( $value ) { - $filter_fields = UM()->member_directory()->filter_fields; - - if ( '' !== $value ) { - $value = array_filter( - $value, - function( $v, $k ) use ( $filter_fields ) { - return in_array( sanitize_text_field( $v ), $filter_fields, true ); - }, - ARRAY_FILTER_USE_BOTH + $value ); } @@ -603,7 +582,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { * @return array|string */ public function sanitize_filter_fields( $value ) { - $filter_fields = UM()->member_directory()->filter_fields; + $filter_fields = array_keys( UM()->member_directory()->filter_fields ); if ( '' !== $value ) { $value = array_filter( @@ -613,6 +592,8 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { }, ARRAY_FILTER_USE_BOTH ); + + $value = array_map( 'sanitize_text_field', $value ); } return $value; @@ -625,10 +606,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { * @return array|string */ public function sanitize_user_field( $value ) { - $user_fields = array(); - foreach ( UM()->builtin()->all_user_fields() as $key => $arr ) { - $user_fields[ $key ] = isset( $arr['title'] ) ? $arr['title'] : ''; - } + $user_fields = array_keys( UM()->builtin()->all_user_fields() ); if ( '' !== $value ) { $value = array_filter( @@ -638,6 +616,38 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { }, ARRAY_FILTER_USE_BOTH ); + + $value = array_map( 'sanitize_text_field', $value ); + } + + return $value; + } + + + /** + * @param array|string $value + * + * @return array|string + */ + public function sanitize_md_view_types( $value ) { + $view_types = array_map( + function ( $item ) { + return $item['title']; + }, + UM()->member_directory()->view_types + ); + $view_types = array_keys( $view_types ); + + if ( '' !== $value ) { + $value = array_filter( + $value, + function( $v, $k ) use ( $view_types ) { + return in_array( sanitize_key( $k ), $view_types, true ) && 1 === (int) $v; + }, + ARRAY_FILTER_USE_BOTH + ); + + $value = array_map( 'sanitize_key', $value ); } return $value; @@ -653,13 +663,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { $sizes = UM()->files()->get_profile_photo_size( 'photo_thumb_sizes' ); if ( '' !== $value ) { - $value = array_filter( - $value, - function( $v, $k ) use ( $sizes ) { - return in_array( sanitize_text_field( $v ), $sizes, true ); - }, - ARRAY_FILTER_USE_BOTH - ); + $value = in_array( absint( $value ), $sizes, true ) ? absint( $value ) : ''; } return $value; @@ -671,23 +675,11 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { * * @return array|string */ - public function sanitize_md_view_types( $value ) { - $view_types = array_map( - function( $item ) { - return $item['title']; - }, - UM()->member_directory()->view_types - ); - + public function sanitize_cover_photosize( $value ) { + $sizes = UM()->files()->get_profile_photo_size( 'cover_thumb_sizes' ); if ( '' !== $value ) { - $value = array_filter( - $value, - function( $v, $k ) use ( $view_types ) { - return in_array( sanitize_key( $k ), $view_types, true ) && 1 === (int) $v; - }, - ARRAY_FILTER_USE_BOTH - ); + $value = in_array( absint( $value ), $sizes, true ) ? absint( $value ) : ''; } return $value; @@ -710,6 +702,8 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { }, ARRAY_FILTER_USE_BOTH ); + + $value = array_map( 'sanitize_key', $value ); } return $value; @@ -732,6 +726,8 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { }, ARRAY_FILTER_USE_BOTH ); + + $value = array_map( 'sanitize_key', $value ); } return $value; @@ -747,13 +743,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { $all_privacy = array_keys( UM()->profile()->tabs_privacy() ); if ( '' !== $value ) { - $value = array_filter( - $value, - function( $v, $k ) use ( $all_privacy ) { - return in_array( $v, $all_privacy, true ); - }, - ARRAY_FILTER_USE_BOTH - ); + $value = in_array( absint( $value ), $all_privacy, true ) ? absint( $value ) : ''; } return $value; @@ -783,6 +773,8 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { /** + * Sanitize role meta fields when wp-admin form has been submitted + * * @param array $data * * @return array @@ -841,6 +833,8 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { /** + * Sanitize post restriction meta fields when wp-admin form has been submitted + * * @param array $data * * @return array @@ -892,6 +886,8 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { /** + * Sanitize term restriction meta fields when wp-admin form has been submitted + * * @param array $data * * @return array @@ -943,6 +939,10 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { /** + * Sanitize member directory meta when wp-admin form has been submitted + * + * @todo checking all sanitize types + * * @param array $data * * @return array @@ -997,6 +997,10 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { /** + * Sanitize form meta when wp-admin form has been submitted + * + * @todo checking all sanitize types + * * @param array $data * * @return array @@ -1051,6 +1055,10 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { /** + * Sanitize options when wp-admin form has been submitted + * + * @todo checking all sanitize types + * * @param array $data * * @return array @@ -1076,31 +1084,34 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { switch ( UM()->admin_settings()->settings_map[ $k ]['sanitize'] ) { default: - $sanitized[ $k ] = apply_filters( 'um_settings_sanitize_' . $k, $data[ $k ] ); + $sanitized[ $k ] = apply_filters( 'um_settings_sanitize_' . $k, $v ); break; case 'int': $sanitized[ $k ] = (int) $v; break; case 'absint': - $sanitized[ $k ] = absint( $v ); - break; - case 'absints_array': - $sanitized[ $k ] = array_map( 'absint', $v ); + if ( is_array( $v ) ) { + $sanitized[ $k ] = array_map( 'absint', $v ); + } else { + $sanitized[ $k ] = absint( $v ); + } break; case 'key': - $sanitized[ $k ] = sanitize_key( $v ); - break; - case 'keys_array': - $sanitized[ $k ] = array_map( 'sanitize_key', $v ); + if ( is_array( $v ) ) { + $sanitized[ $k ] = array_map( 'sanitize_key', $v ); + } else { + $sanitized[ $k ] = sanitize_key( $v ); + } break; case 'bool': $sanitized[ $k ] = (bool) $v; break; case 'url': - $sanitized[ $k ] = esc_url_raw( $v ); - break; - case 'urls_array': - $sanitized[ $k ] = array_map( 'esc_url_raw', $v ); + if ( is_array( $v ) ) { + $sanitized[ $k ] = array_map( 'esc_url_raw', $v ); + } else { + $sanitized[ $k ] = esc_url_raw( $v ); + } break; case 'wp_kses': $sanitized[ $k ] = wp_kses_post( $v ); @@ -1108,13 +1119,6 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { case 'textarea': $sanitized[ $k ] = sanitize_textarea_field( $v ); break; - case 'sanitize_array_key': - if ( ! array_key_exists( 'default', UM()->admin_settings()->settings_map[ $k ] ) || ! array_key_exists( 'array', UM()->admin_settings()->settings_map[ $k ] ) ) { - continue 2; - } - - $sanitized[ $k ] = ! in_array( sanitize_key( $v ), UM()->admin_settings()->settings_map[ $k ]['array'], true ) ? UM()->admin_settings()->settings_map[ $k ]['default'] : sanitize_key( $v ); - break; } } diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php index e0b9685b..85a35fc7 100644 --- a/includes/admin/core/class-admin-settings.php +++ b/includes/admin/core/class-admin-settings.php @@ -523,7 +523,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { 'sanitize' => 'url', ), 'access_exclude_uris' => array( - 'sanitize' => 'urls_array', + 'sanitize' => 'url', ), 'home_page_accessible' => array( 'sanitize' => 'bool', @@ -605,10 +605,10 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { $settings_map, array( 'restricted_access_post_metabox' => array( - 'sanitize' => 'keys_array', + 'sanitize' => 'key', ), 'restricted_access_taxonomy_metabox' => array( - 'sanitize' => 'keys_array', + 'sanitize' => 'key', ), ) ); @@ -715,10 +715,10 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { 'sanitize' => 'absint', ), 'photo_thumb_sizes' => array( - 'sanitize' => 'absints_array', + 'sanitize' => 'absint', ), 'cover_thumb_sizes' => array( - 'sanitize' => 'absints_array', + 'sanitize' => 'absint', ), 'image_orientation_by_exif' => array( 'sanitize' => 'bool', @@ -793,7 +793,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { 'sanitize' => 'bool', ), 'profile_coversize' => array( - 'sanitize' => array( UM()->admin(), 'sanitize_photosize' ), + 'sanitize' => array( UM()->admin(), 'sanitize_cover_photosize' ), ), 'profile_cover_ratio' => array( 'sanitize' => 'text', @@ -850,7 +850,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) { 'sanitize' => 'url', ), 'register_role' => array( - 'sanitize' => array( UM()->admin(), 'sanitize_existed_role' ), + 'sanitize' => 'key', ), 'login_template' => array( 'sanitize' => 'text', diff --git a/includes/core/class-form.php b/includes/core/class-form.php index 61a510d1..ffb0f2ef 100644 --- a/includes/core/class-form.php +++ b/includes/core/class-form.php @@ -104,32 +104,34 @@ if ( ! class_exists( 'um\core\Form' ) ) { /** * */ - function ajax_select_options() { + public function ajax_select_options() { UM()->check_ajax_nonce(); - $arr_options = array(); + $arr_options = array(); $arr_options['status'] = 'success'; - $arr_options['post'] = $_POST; + $arr_options['post'] = $_POST; - UM()->fields()->set_id = absint( $_POST['form_id'] ); + UM()->fields()->set_id = absint( $_POST['form_id'] ); UM()->fields()->set_mode = 'profile'; - $form_fields = UM()->fields()->get_fields(); - $arr_options['fields'] = $form_fields; + $form_fields = UM()->fields()->get_fields(); + $arr_options['fields'] = $form_fields; - if ( isset( $arr_options['post']['members_directory'] ) && $arr_options['post']['members_directory'] == 'yes' ) { + if ( isset( $arr_options['post']['members_directory'] ) && 'yes' === $arr_options['post']['members_directory'] ) { $ajax_source_func = $_POST['child_callback']; if ( function_exists( $ajax_source_func ) ) { $arr_options['items'] = call_user_func( $ajax_source_func, $arr_options['field']['parent_dropdown_relationship'] ); global $wpdb; - $values_array = $wpdb->get_col( $wpdb->prepare( - "SELECT DISTINCT meta_value - FROM $wpdb->usermeta - WHERE meta_key = %s AND - meta_value != ''", - $arr_options['post']['child_name'] - ) ); + $values_array = $wpdb->get_col( + $wpdb->prepare( + "SELECT DISTINCT meta_value + FROM $wpdb->usermeta + WHERE meta_key = %s AND + meta_value != ''", + $arr_options['post']['child_name'] + ) + ); if ( ! empty( $values_array ) ) { $arr_options['items'] = array_intersect( $arr_options['items'], $values_array ); @@ -161,8 +163,8 @@ if ( ! class_exists( 'um\core\Form' ) ) { * } * ?> */ - $debug = apply_filters('um_ajax_select_options__debug_mode', false ); - if( $debug ){ + $debug = apply_filters( 'um_ajax_select_options__debug_mode', false ); + if ( $debug ) { $arr_options['debug'] = array( $_POST, $form_fields, @@ -176,19 +178,17 @@ if ( ! class_exists( 'um\core\Form' ) ) { // If the requested callback function is added in the form or added in the field option, execute it with call_user_func. if ( isset( $form_fields[ $_POST['child_name'] ]['custom_dropdown_options_source'] ) && ! empty( $form_fields[ $_POST['child_name'] ]['custom_dropdown_options_source'] ) && - $form_fields[ $_POST['child_name'] ]['custom_dropdown_options_source'] == $ajax_source_func ) { + $form_fields[ $_POST['child_name'] ]['custom_dropdown_options_source'] === $ajax_source_func ) { $arr_options['field'] = $form_fields[ $_POST['child_name'] ]; if ( function_exists( $ajax_source_func ) ) { $arr_options['items'] = call_user_func( $ajax_source_func, $arr_options['field']['parent_dropdown_relationship'] ); } - } else { - $arr_options['status'] = 'error'; + $arr_options['status'] = 'error'; $arr_options['message'] = __( 'This is not possible for security reasons.', 'ultimate-member' ); } - } wp_send_json( $arr_options ); @@ -200,10 +200,10 @@ if ( ! class_exists( 'um\core\Form' ) ) { * Count the form errors. * @return integer */ - function count_errors() { + public function count_errors() { $errors = $this->errors; - if( $errors && is_array( $errors ) ) { + if ( $errors && is_array( $errors ) ) { return count( $errors ); } @@ -213,11 +213,12 @@ if ( ! class_exists( 'um\core\Form' ) ) { /** * Appends field errors + * * @param string $key * @param string $error */ - function add_error( $key, $error ) { - if ( ! isset( $this->errors[ $key ] ) ){ + public function add_error( $key, $error ) { + if ( ! isset( $this->errors[ $key ] ) ) { /** * UM hook * @@ -240,8 +241,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { * } * ?> */ - $error = apply_filters( 'um_submit_form_error', $error, $key ); - $this->errors[ $key ] = $error; + $this->errors[ $key ] = apply_filters( 'um_submit_form_error', $error, $key ); } } @@ -250,8 +250,8 @@ if ( ! class_exists( 'um\core\Form' ) ) { * @param string $key * @param string $notice */ - function add_notice( $key, $notice ) { - if ( ! isset( $this->notices[ $key ] ) ){ + public function add_notice( $key, $notice ) { + if ( ! isset( $this->notices[ $key ] ) ) { /** * UM hook * @@ -274,30 +274,32 @@ if ( ! class_exists( 'um\core\Form' ) ) { * } * ?> */ - $notice = apply_filters( 'um_submit_form_notice', $notice, $key ); - $this->notices[ $key ] = $notice; + $this->notices[ $key ] = apply_filters( 'um_submit_form_notice', $notice, $key ); } } /** * If a form has errors + * * @param string $key * @return boolean */ - function has_error( $key ) { + public function has_error( $key ) { if ( isset( $this->errors[ $key ] ) ) { return true; } return false; } + /** * If a form has notices/info + * * @param string $key * @return boolean */ - function has_notice( $key ) { + public function has_notice( $key ) { if ( isset( $this->notices[ $key ] ) ) { return true; } @@ -308,7 +310,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { /** * Declare all fields */ - function field_declare() { + public function field_declare() { if ( isset( UM()->builtin()->custom_fields ) ) { $this->all_fields = UM()->builtin()->custom_fields; } else { @@ -320,23 +322,29 @@ if ( ! class_exists( 'um\core\Form' ) ) { /** * Validate form on submit */ - function form_init() { + public function form_init() { if ( isset( $_SERVER['REQUEST_METHOD'] ) ) { - $http_post = ( 'POST' == $_SERVER['REQUEST_METHOD'] ); + $http_post = ( 'POST' === $_SERVER['REQUEST_METHOD'] ); } else { $http_post = 'POST'; } if ( $http_post && ! is_admin() && isset( $_POST['form_id'] ) && is_numeric( $_POST['form_id'] ) ) { + $this->form_id = absint( $_POST['form_id'] ); + $this->form_status = get_post_status( $this->form_id ); + + + if ( 'publish' !== $this->form_status ) { + return; + } + /** * UM hook * * @type action * @title um_before_submit_form_post * @description Before submit form - * @input_vars - * [{"var":"$post","type":"int","desc":"Post data"}] * @change_log * ["Since: 2.0"] * @usage add_action( 'um_before_submit_form_post', 'function_name', 10, 1 ); @@ -348,184 +356,176 @@ if ( ! class_exists( 'um\core\Form' ) ) { * } * ?> */ - do_action( 'um_before_submit_form_post', $_POST ); + do_action( 'um_before_submit_form_post' ); - $this->form_id = absint( $_POST['form_id'] ); - $this->form_status = get_post_status( $this->form_id ); - - - if ( $this->form_status == 'publish' ) { - /* save entire form as global */ - /** - * UM hook - * - * @type filter - * @title um_submit_post_form - * @description Change submitted data on form submit - * @input_vars - * [{"var":"$data","type":"array","desc":"Submitted data"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $this->post_form = apply_filters( 'um_submit_post_form', $_POST ); - - if ( isset( $this->post_form[ UM()->honeypot ] ) && $this->post_form[ UM()->honeypot ] != '' ) { - wp_die( __( 'Hello, spam bot!', 'ultimate-member' ) ); - } - - $this->post_form = $this->beautify( $this->post_form ); - $this->post_form['submitted'] = $this->post_form; - - $this->form_data = UM()->query()->post_data( $this->form_id ); - - $this->post_form = array_merge( $this->form_data, $this->post_form ); - - // Remove role from post_form at first if role ! empty and there aren't custom fields with role name - if ( ! empty( $_POST['role'] ) ) { - if ( ! isset( $this->form_data['custom_fields'] ) || ! strstr( $this->form_data['custom_fields'], 'role_' ) ) { - unset( $this->post_form['role'] ); - unset( $this->post_form['submitted']['role'] ); - } - } - - // Secure sanitize of the submitted data - if ( ! empty( $this->post_form ) ) { - $this->post_form = array_diff_key( $this->post_form, array_flip( UM()->user()->banned_keys ) ); - } - if ( ! empty( $this->post_form['submitted'] ) ) { - $this->post_form['submitted'] = array_diff_key( $this->post_form['submitted'], array_flip( UM()->user()->banned_keys ) ); - } - - // set default role from settings on registration form - if ( isset( $this->post_form['mode'] ) && $this->post_form['mode'] == 'register' ) { - - $role = $this->assigned_role( $this->form_id ); - $this->post_form['role'] = $role; - - } - - if ( isset( $this->form_data['custom_fields'] ) && strstr( $this->form_data['custom_fields'], 'role_' ) ) { // Secure selected role - - if ( ! empty( $_POST['role'] ) ) { - - $custom_field_roles = $this->custom_field_roles( $this->form_data['custom_fields'] ); - - if ( ! empty( $custom_field_roles ) ) { - if ( is_array( $_POST['role'] ) ) { - $role = current( $_POST['role'] ); - $role = sanitize_key( $role ); - } else { - $role = sanitize_key( $_POST['role'] ); - } - - global $wp_roles; - $role_keys = array_map( function( $item ) { - return 'um_' . $item; - }, get_option( 'um_roles', array() ) ); - $exclude_roles = array_diff( array_keys( $wp_roles->roles ), array_merge( $role_keys, array( 'subscriber' ) ) ); - - if ( ! empty( $role ) && - ( ! in_array( $role, $custom_field_roles, true ) || in_array( $role, $exclude_roles ) ) ) { - wp_die( __( 'This is not possible for security reasons.', 'ultimate-member' ) ); - } - - $this->post_form['role'] = $role; - $this->post_form['submitted']['role'] = $role; - } else { - unset( $this->post_form['role'] ); - unset( $this->post_form['submitted']['role'] ); - - // set default role for registration form if custom field hasn't proper value - if ( isset( $this->post_form['mode'] ) && $this->post_form['mode'] == 'register' ) { - $role = $this->assigned_role( $this->form_id ); - $this->post_form['role'] = $role; - } - } - } - - } - - /** - * UM hook - * - * @type filter - * @title um_submit_form_data - * @description Change submitted data on form submit - * @input_vars - * [{"var":"$data","type":"array","desc":"Submitted data"}, - * {"var":"$mode","type":"string","desc":"Form mode"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $this->post_form = apply_filters( 'um_submit_form_data', $this->post_form, $this->post_form['mode'] ); - - /* Continue based on form mode - pre-validation */ - - /** - * UM hook - * - * @type action - * @title um_submit_form_errors_hook - * @description Action on submit form - * @input_vars - * [{"var":"$post","type":"int","desc":"Post data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook', 'function_name', 10, 1 ); - * @example - * - */ - do_action( 'um_submit_form_errors_hook', $this->post_form ); - /** - * UM hook - * - * @type action - * @title um_submit_form_{$mode} - * @description Action on submit form - * @input_vars - * [{"var":"$post","type":"int","desc":"Post data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_{$mode}', 'function_name', 10, 1 ); - * @example - * - */ - do_action( "um_submit_form_{$this->post_form['mode']}", $this->post_form ); + /* save entire form as global */ + /** + * UM hook + * + * @type filter + * @title um_submit_post_form + * @description Change submitted data on form submit + * @input_vars + * [{"var":"$data","type":"array","desc":"Submitted data"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $this->post_form = apply_filters( 'um_submit_post_form', $_POST ); + if ( isset( $this->post_form[ UM()->honeypot ] ) && '' !== $this->post_form[ UM()->honeypot ] ) { + wp_die( esc_html__( 'Hello, spam bot!', 'ultimate-member' ) ); } - } + $this->post_form = $this->beautify( $this->post_form ); + $this->post_form = $this->sanitize( $this->post_form ); + $this->post_form['submitted'] = $this->post_form; + $this->form_data = UM()->query()->post_data( $this->form_id ); + + $this->post_form = array_merge( $this->form_data, $this->post_form ); + + // Remove role from post_form at first if role ! empty and there aren't custom fields with role name + if ( ! empty( $_POST['role'] ) ) { + if ( ! isset( $this->form_data['custom_fields'] ) || ! strstr( $this->form_data['custom_fields'], 'role_' ) ) { + unset( $this->post_form['role'] ); + unset( $this->post_form['submitted']['role'] ); + } + } + + // Secure sanitize of the submitted data + if ( ! empty( $this->post_form ) ) { + $this->post_form = array_diff_key( $this->post_form, array_flip( UM()->user()->banned_keys ) ); + } + if ( ! empty( $this->post_form['submitted'] ) ) { + $this->post_form['submitted'] = array_diff_key( $this->post_form['submitted'], array_flip( UM()->user()->banned_keys ) ); + } + + // set default role from settings on registration form + if ( isset( $this->post_form['mode'] ) && 'register' === $this->post_form['mode'] ) { + $role = $this->assigned_role( $this->form_id ); + $this->post_form['role'] = $role; + } + + if ( isset( $this->form_data['custom_fields'] ) && strstr( $this->form_data['custom_fields'], 'role_' ) ) { // Secure selected role + + if ( ! empty( $_POST['role'] ) ) { + $custom_field_roles = $this->custom_field_roles( $this->form_data['custom_fields'] ); + + if ( ! empty( $custom_field_roles ) ) { + if ( is_array( $_POST['role'] ) ) { + $role = current( $_POST['role'] ); + $role = sanitize_key( $role ); + } else { + $role = sanitize_key( $_POST['role'] ); + } + + global $wp_roles; + $role_keys = array_map( + function( $item ) { + return 'um_' . $item; + }, + get_option( 'um_roles', array() ) + ); + $exclude_roles = array_diff( array_keys( $wp_roles->roles ), array_merge( $role_keys, array( 'subscriber' ) ) ); + + if ( ! empty( $role ) && + ( ! in_array( $role, $custom_field_roles, true ) || in_array( $role, $exclude_roles, true ) ) ) { + wp_die( esc_html__( 'This is not possible for security reasons.', 'ultimate-member' ) ); + } + + $this->post_form['role'] = $role; + $this->post_form['submitted']['role'] = $role; + } else { + unset( $this->post_form['role'] ); + unset( $this->post_form['submitted']['role'] ); + + // set default role for registration form if custom field hasn't proper value + if ( isset( $this->post_form['mode'] ) && 'register' === $this->post_form['mode'] ) { + $role = $this->assigned_role( $this->form_id ); + $this->post_form['role'] = $role; + } + } + } + } + + /** + * UM hook + * + * @type filter + * @title um_submit_form_data + * @description Change submitted data on form submit + * @input_vars + * [{"var":"$data","type":"array","desc":"Submitted data"}, + * {"var":"$mode","type":"string","desc":"Form mode"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $this->post_form = apply_filters( 'um_submit_form_data', $this->post_form, $this->post_form['mode'] ); + + /* Continue based on form mode - pre-validation */ + + /** + * UM hook + * + * @type action + * @title um_submit_form_errors_hook + * @description Action on submit form + * @input_vars + * [{"var":"$post","type":"int","desc":"Post data"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_submit_form_errors_hook', 'function_name', 10, 1 ); + * @example + * + */ + do_action( 'um_submit_form_errors_hook', $this->post_form ); + /** + * UM hook + * + * @type action + * @title um_submit_form_{$mode} + * @description Action on submit form + * @input_vars + * [{"var":"$post","type":"int","desc":"Post data"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_submit_form_{$mode}', 'function_name', 10, 1 ); + * @example + * + */ + do_action( "um_submit_form_{$this->post_form['mode']}", $this->post_form ); + + } } @@ -533,24 +533,82 @@ if ( ! class_exists( 'um\core\Form' ) ) { * Beautify form data * * @param array $form + * * @return array $form */ - function beautify( $form ) { - + public function beautify( $form ) { if ( isset( $form['form_id'] ) ) { - $this->form_suffix = '-' . $form['form_id']; - - $this->processing = $form['form_id']; + $this->processing = $form['form_id']; foreach ( $form as $key => $value ) { if ( strstr( $key, $this->form_suffix ) ) { - $a_key = str_replace( $this->form_suffix, '', $key ); + $a_key = str_replace( $this->form_suffix, '', $key ); $form[ $a_key ] = $value; unset( $form[ $key ] ); } } + } + return $form; + } + + + /** + * Beautify form data + * + * @param array $form + * + * @return array $form + */ + public function sanitize( $form ) { + if ( isset( $form['form_id'] ) ) { + if ( isset( $this->form_data['custom_fields'] ) ) { + $custom_fields = maybe_unserialize( $this->form_data['custom_fields'] ); + + if ( is_array( $custom_fields ) ) { + foreach ( $custom_fields as $k => $field ) { + if ( isset( $field['type'] ) ) { + if ( isset( $form[ $k ] ) ) { + + switch ( $field['type'] ) { + default: + $form[ $k ] = apply_filters( 'um_sanitize_form_field', $form[ $k ], $field ); + break; + case 'number': + $form[ $k ] = (int) $form[ $k ]; + break; + case 'textarea': + $form[ $k ] = sanitize_textarea_field( $form[ $k ] ); + break; + case 'url': + $form[ $k ] = esc_url_raw( $form[ $k ] ); + break; + case 'text': + case 'select': + case 'password': + case 'image': + case 'file': + case 'date': + case 'time': + case 'rating': + case 'googlemap': + case 'youtube_video': + case 'vimeo_video': + case 'soundcloud_track': + $form[ $k ] = sanitize_text_field( $form[ $k ] ); + break; + case 'multiselect': + case 'radio': + case 'checkbox': + $form[ $k ] = array_map( 'sanitize_text_field', $form[ $k ] ); + break; + } + } + } + } + } + } } return $form; @@ -563,17 +621,17 @@ if ( ! class_exists( 'um\core\Form' ) ) { * @param integer $post_id * @return string $output */ - function display_form_type( $mode, $post_id ){ + public function display_form_type( $mode, $post_id ) { $output = null; - switch( $mode ){ + switch ( $mode ) { case 'login': - $output = 'Login'; + $output = __( 'Login', 'ultimate-member' ); break; case 'profile': - $output = 'Profile'; + $output = __( 'Profile', 'ultimate-member' ); break; case 'register': - $output = 'Register'; + $output = __( 'Register', 'ultimate-member' ); break; } return $output; @@ -585,7 +643,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { * @param integer $post_id * @return string $role */ - function assigned_role( $post_id ) { + public function assigned_role( $post_id ) { $global_role = get_option( 'default_role' ); // WP Global settings @@ -617,7 +675,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { * @param integer $post_id * @return string */ - function form_type( $post_id ) { + public function form_type( $post_id ) { $mode = get_post_meta( $post_id, '_um_mode', true ); return $mode; } @@ -625,10 +683,11 @@ if ( ! class_exists( 'um\core\Form' ) ) { /** * Get custom field roles + * * @param string $custom_fields serialized * @return bool|array roles */ - function custom_field_roles( $custom_fields ) { + public function custom_field_roles( $custom_fields ) { $fields = maybe_unserialize( $custom_fields ); if ( ! is_array( $fields ) ) { @@ -637,21 +696,27 @@ if ( ! class_exists( 'um\core\Form' ) ) { // role field global $wp_roles; - $role_keys = array_map( function( $item ) { - return 'um_' . $item; - }, get_option( 'um_roles', array() ) ); + $role_keys = array_map( + function( $item ) { + return 'um_' . $item; + }, + get_option( 'um_roles', array() ) + ); $exclude_roles = array_diff( array_keys( $wp_roles->roles ), array_merge( $role_keys, array( 'subscriber' ) ) ); $roles = UM()->roles()->get_roles( false, $exclude_roles ); - $roles = array_map( function( $item ) { - return html_entity_decode( $item, ENT_QUOTES ); - }, $roles ); + $roles = array_map( + function( $item ) { + return html_entity_decode( $item, ENT_QUOTES ); + }, + $roles + ); foreach ( $fields as $field_key => $field_settings ) { if ( strstr( $field_key, 'role_' ) && is_array( $field_settings['options'] ) ) { - if ( isset( $this->post_form['mode'] ) && $this->post_form['mode'] == 'profile' && + if ( isset( $this->post_form['mode'] ) && 'profile' === $this->post_form['mode'] && isset( $field_settings['editable'] ) && $field_settings['editable'] == 0 ) { continue; } @@ -672,7 +737,6 @@ if ( ! class_exists( 'um\core\Form' ) ) { // getting roles only from the first role fields return array_keys( $intersected_options ); } - } return false; diff --git a/includes/core/class-member-directory.php b/includes/core/class-member-directory.php index 529a9fa5..108f9e0f 100644 --- a/includes/core/class-member-directory.php +++ b/includes/core/class-member-directory.php @@ -217,11 +217,14 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { if ( ! empty( $filter_type ) ) { if ( 'slider' === $filter_type ) { if ( ! empty( $_POST[ $k ] ) ) { - $temp_value[ $k ] = $_POST[ $k ]; + $temp_value[ $k ] = (int) $_POST[ $k ]; } } elseif ( 'timepicker' === $filter_type || 'datepicker' === $filter_type ) { if ( ! empty( $_POST[ $k . '_from' ] ) && ! empty( $_POST[ $k . '_to' ] ) ) { - $temp_value[ $k ] = array( $_POST[ $k . '_from' ], $_POST[ $k . '_to' ] ); + $temp_value[ $k ] = array( + sanitize_text_field( $_POST[ $k . '_from' ] ), + sanitize_text_field( $_POST[ $k . '_to' ] ), + ); } } elseif ( 'select' === $filter_type ) { if ( ! empty( $_POST[ $k ] ) ) { @@ -230,10 +233,12 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { } else { $temp_value[ $k ] = array( trim( $_POST[ $k ] ) ); } + + $temp_value[ $k ] = array_map( 'sanitize_text_field', $temp_value[ $k ] ); } } else { if ( ! empty( $_POST[ $k ] ) ) { - $temp_value[ $k ] = trim( $_POST[ $k ] ); + $temp_value[ $k ] = trim( sanitize_text_field( $_POST[ $k ] ) ); } } }