From a6fa8ab3ea54c052256fb3728d30e9e736fdbde9 Mon Sep 17 00:00:00 2001 From: Nikita Sinelnikov Date: Thu, 15 Jul 2021 13:50:23 +0300 Subject: [PATCH] - fixed sanitizing data on submit field data in wp-admin builder; --- includes/admin/class-admin.php | 376 ++++++++++++++++++++ includes/admin/core/class-admin-builder.php | 8 +- includes/core/class-builtin.php | 62 +++- readme.txt | 1 + 4 files changed, 424 insertions(+), 23 deletions(-) diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index fa204692..537cc9d8 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -46,6 +46,12 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { public $form_meta; + /** + * @var array + */ + public $builder_input; + + /** * @var array */ @@ -507,6 +513,300 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { ) ); + $this->builder_input = apply_filters( + 'um_builder_input_map', + array( + '_in_row' => array( + 'sanitize' => 'key', + ), + '_in_sub_row' => array( + 'sanitize' => 'absint', + ), + '_in_column' => array( + 'sanitize' => 'absint', + ), + '_in_group' => array( + 'sanitize' => 'absint', + ), + '_visibility' => array( + 'sanitize' => 'key', + ), + '_conditional_action' => array( + 'sanitize' => 'key', + ), + '_conditional_action1' => array( + 'sanitize' => 'key', + ), + '_conditional_action2' => array( + 'sanitize' => 'key', + ), + '_conditional_action3' => array( + 'sanitize' => 'key', + ), + '_conditional_action4' => array( + 'sanitize' => 'key', + ), + '_conditional_field' => array( + 'sanitize' => 'text', + ), + '_conditional_field1' => array( + 'sanitize' => 'text', + ), + '_conditional_field2' => array( + 'sanitize' => 'text', + ), + '_conditional_field3' => array( + 'sanitize' => 'text', + ), + '_conditional_field4' => array( + 'sanitize' => 'text', + ), + '_conditional_operator' => array( + 'sanitize' => 'text', + ), + '_conditional_operator1' => array( + 'sanitize' => 'text', + ), + '_conditional_operator2' => array( + 'sanitize' => 'text', + ), + '_conditional_operator3' => array( + 'sanitize' => 'text', + ), + '_conditional_operator4' => array( + 'sanitize' => 'text', + ), + '_conditional_value' => array( + 'sanitize' => 'text', + ), + '_conditional_value1' => array( + 'sanitize' => 'text', + ), + '_conditional_value2' => array( + 'sanitize' => 'text', + ), + '_conditional_value3' => array( + 'sanitize' => 'text', + ), + '_conditional_value4' => array( + 'sanitize' => 'text', + ), + '_validate' => array( + 'sanitize' => 'key', + ), + '_custom_validate' => array( + 'sanitize' => 'text', + ), + '_icon' => array( + 'sanitize' => 'key', + ), + '_css_class' => array( + 'sanitize' => 'text', + ), + '_width' => array( + 'sanitize' => 'absint', + ), + '_divider_text' => array( + 'sanitize' => 'text', + ), + '_padding' => array( + 'sanitize' => 'text', + ), + '_margin' => array( + 'sanitize' => 'text', + ), + '_border' => array( + 'sanitize' => 'text', + ), + '_borderstyle' => array( + 'sanitize' => 'key', + ), + '_borderradius' => array( + 'sanitize' => 'text', + ), + '_bordercolor' => array( + 'sanitize' => 'text', + ), + '_heading' => array( + 'sanitize' => 'bool', + ), + '_heading_text' => array( + 'sanitize' => 'text', + ), + '_background' => array( + 'sanitize' => 'text', + ), + '_heading_background_color' => array( + 'sanitize' => 'text', + ), + '_heading_text_color' => array( + 'sanitize' => 'text', + ), + '_text_color' => array( + 'sanitize' => 'text', + ), + '_icon_color' => array( + 'sanitize' => 'text', + ), + '_color' => array( + 'sanitize' => 'text', + ), + '_url_text' => array( + 'sanitize' => 'text', + ), + '_url_target' => array( + 'sanitize' => 'key', + ), + '_url_rel' => array( + 'sanitize' => 'key', + ), + '_force_good_pass' => array( + 'sanitize' => 'bool', + ), + '_force_confirm_pass' => array( + 'sanitize' => 'bool', + ), + '_style' => array( + 'sanitize' => 'key', + ), + '_intervals' => array( + 'sanitize' => 'absint', + ), + '_format' => array( + 'sanitize' => 'text', + ), + '_format_custom' => array( + 'sanitize' => 'text', + ), + '_pretty_format' => array( + 'sanitize' => 'bool', + ), + '_disabled_weekdays' => array( + 'sanitize' => 'absint', + ), + '_years' => array( + 'sanitize' => 'absint', + ), + '_years_x' => array( + 'sanitize' => 'key', + ), + '_range_start' => array( + 'sanitize' => 'text', + ), + '_range_end' => array( + 'sanitize' => 'text', + ), + '_range' => array( + 'sanitize' => 'key', + ), + '_content' => array( + 'sanitize' => 'textarea', + ), + '_crop' => array( + 'sanitize' => 'int', + ), + '_allowed_types' => array( + 'sanitize' => 'key', + ), + '_upload_text' => array( + 'sanitize' => 'text', + ), + '_upload_help_text' => array( + 'sanitize' => 'text', + ), + '_button_text' => array( + 'sanitize' => 'text', + ), + '_max_size' => array( + 'sanitize' => 'absint', + ), + '_height' => array( + 'sanitize' => 'text', + ), + '_spacing' => array( + 'sanitize' => 'text', + ), + '_is_multi' => array( + 'sanitize' => 'bool', + ), + '_max_selections' => array( + 'sanitize' => 'absint', + ), + '_min_selections' => array( + 'sanitize' => 'absint', + ), + '_max_entries' => array( + 'sanitize' => 'absint', + ), + '_max_words' => array( + 'sanitize' => 'absint', + ), + '_min' => array( + 'sanitize' => 'absint', + ), + '_max' => array( + 'sanitize' => 'absint', + ), + '_min_chars' => array( + 'sanitize' => 'absint', + ), + '_max_chars' => array( + 'sanitize' => 'absint', + ), + '_html' => array( + 'sanitize' => 'bool', + ), + '_options' => array( + 'sanitize' => 'textarea', + ), + '_title' => array( + 'sanitize' => 'text', + ), + '_id' => array( + 'sanitize' => 'text', + ), + '_metakey' => array( + 'sanitize' => 'text', + ), + '_help' => array( + 'sanitize' => 'text', + ), + '_default' => array( + 'sanitize' => 'text', + ), + '_label' => array( + 'sanitize' => 'text', + ), + '_label_confirm_pass' => array( + 'sanitize' => 'text', + ), + '_placeholder' => array( + 'sanitize' => 'text', + ), + '_public' => array( + 'sanitize' => 'text', + ), + '_roles' => array( + 'sanitize' => array( $this, 'sanitize_existed_role' ), + ), + '_required' => array( + 'sanitize' => 'bool', + ), + '_editable' => array( + 'sanitize' => 'bool', + ), + '_number' => array( + 'sanitize' => 'absint', + ), + '_custom_dropdown_options_source' => array( + 'sanitize' => 'text', + ), + '_parent_dropdown_relationship' => array( + 'sanitize' => 'text', + ), + ) + ); + add_action( 'admin_init', array( &$this, 'admin_init' ), 0 ); $prefix = is_network_admin() ? 'network_admin_' : ''; @@ -1016,6 +1316,82 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { } + /** + * Sanitize builder field meta when wp-admin form has been submitted + * + * @todo checking all sanitize types + * + * @param array $data + * + * @return array + */ + public function sanitize_builder_field_meta( $data ) { + $sanitized = array(); + foreach ( $data as $k => $v ) { + if ( ! array_key_exists( $k, $this->builder_input ) ) { + // @todo remove since 2.2.x and leave only continue + $sanitized[ $k ] = $v; + continue; + } + + if ( ! array_key_exists( 'sanitize', $this->builder_input[ $k ] ) ) { + // @todo remove since 2.2.x and leave only continue + $sanitized[ $k ] = $v; + continue; + } + + if ( is_callable( $this->builder_input[ $k ]['sanitize'], true, $callable_name ) ) { + add_filter( 'um_builder_input_sanitize_' . $k, $this->builder_input[ $k ]['sanitize'], 10, 1 ); + } + + switch ( $this->builder_input[ $k ]['sanitize'] ) { + default: + $sanitized[ $k ] = apply_filters( 'um_builder_input_sanitize_' . $k, $data[ $k ] ); + break; + case 'int': + $sanitized[ $k ] = (int) $v; + break; + case 'bool': + $sanitized[ $k ] = (bool) $v; + break; + case 'url': + if ( is_array( $v ) ) { + $sanitized[ $k ] = array_map( 'esc_url_raw', $v ); + } else { + $sanitized[ $k ] = esc_url_raw( $v ); + } + break; + case 'text': + $sanitized[ $k ] = sanitize_text_field( $v ); + break; + case 'textarea': + $sanitized[ $k ] = sanitize_textarea_field( $v ); + break; + case 'key': + if ( is_array( $v ) ) { + $sanitized[ $k ] = array_map( 'sanitize_key', $v ); + } else { + $sanitized[ $k ] = sanitize_key( $v ); + } + break; + case 'absint': + if ( is_array( $v ) ) { + $sanitized[ $k ] = array_map( 'absint', $v ); + } else { + $sanitized[ $k ] = absint( $v ); + } + break; + } + } + + $data = $sanitized; + + $data = apply_filters( 'um_save_builder_input_sanitize', $data ); + + return $data; + } + + /** * Sanitize form meta when wp-admin form has been submitted * diff --git a/includes/admin/core/class-admin-builder.php b/includes/admin/core/class-admin-builder.php index 451bee1c..8221aaa0 100644 --- a/includes/admin/core/class-admin-builder.php +++ b/includes/admin/core/class-admin-builder.php @@ -615,10 +615,10 @@ if ( ! class_exists( 'um\admin\core\Admin_Builder' ) ) { $output['error'] = null; $array = array( - 'field_type' => sanitize_key( $_POST['_type'] ), - 'form_id' => absint( $_POST['post_id'] ), - 'args' => UM()->builtin()->get_core_field_attrs( sanitize_key( $_POST['_type'] ) ), - 'post' => $_POST + 'field_type' => sanitize_key( $_POST['_type'] ), + 'form_id' => absint( $_POST['post_id'] ), + 'args' => UM()->builtin()->get_core_field_attrs( sanitize_key( $_POST['_type'] ) ), + 'post' => UM()->admin()->sanitize_builder_field_meta( $_POST ), ); /** diff --git a/includes/core/class-builtin.php b/includes/core/class-builtin.php index 0445586c..f079113f 100644 --- a/includes/core/class-builtin.php +++ b/includes/core/class-builtin.php @@ -36,9 +36,9 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { * Builtin constructor. */ function __construct() { - add_action( 'init', array(&$this, 'set_core_fields'), 1); - add_action( 'init', array(&$this, 'set_predefined_fields'), 1); - add_action( 'init', array(&$this, 'set_custom_fields'), 1); + add_action( 'init', array( &$this, 'set_core_fields' ), 1 ); + add_action( 'init', array( &$this, 'set_predefined_fields' ), 1 ); + add_action( 'init', array( &$this, 'set_custom_fields' ), 1 ); $this->saved_fields = get_option( 'um_fields' ); } @@ -61,13 +61,15 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { */ function is_dropdown_field( $field, $attrs ) { - if ( isset( $attrs['options'] ) ) + if ( isset( $attrs['options'] ) ) { return true; + } $fields = $this->all_user_fields; - if ( isset( $fields[$field]['options'] ) || ! empty( $fields[$field]['custom_dropdown_options_source'] ) ) + if ( isset( $fields[$field]['options'] ) || ! empty( $fields[$field]['custom_dropdown_options_source'] ) ) { return true; + } return false; } @@ -134,14 +136,25 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { * * @param $key * - * @return int|string|void + * @return int|string */ function unique_field_err( $key ) { - if ( empty( $key ) ) return __('Please provide a meta key','ultimate-member'); - if ( isset( $this->core_fields[ $key ] ) ) return __('Your meta key is a reserved core field and cannot be used','ultimate-member'); - if ( isset( $this->predefined_fields[ $key ] ) ) return __('Your meta key is a predefined reserved key and cannot be used','ultimate-member'); - if ( isset( $this->saved_fields[ $key ] ) ) return __('Your meta key already exists in your fields list','ultimate-member'); - if ( ! UM()->validation()->safe_string( $key ) ) return __('Your meta key contains illegal characters. Please correct it.','ultimate-member'); + if ( empty( $key ) ) { + return __( 'Please provide a meta key', 'ultimate-member' ); + } + if ( isset( $this->core_fields[ $key ] ) ) { + return __( 'Your meta key is a reserved core field and cannot be used', 'ultimate-member' ); + } + if ( isset( $this->predefined_fields[ $key ] ) ) { + return __( 'Your meta key is a predefined reserved key and cannot be used', 'ultimate-member' ); + } + if ( isset( $this->saved_fields[ $key ] ) ) { + return __( 'Your meta key already exists in your fields list', 'ultimate-member' ); + } + if ( ! UM()->validation()->safe_string( $key ) ) { + return __( 'Your meta key contains illegal characters. Please correct it.', 'ultimate-member' ); + } + return 0; } @@ -151,11 +164,16 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { * * @param $date * - * @return int|string|void + * @return int|string */ function date_range_start_err( $date ) { - if ( empty( $date ) ) return __('Please provide a date range beginning','ultimate-member'); - if ( ! UM()->validation()->validate_date( $date ) ) return __('Please enter a valid start date in the date range','ultimate-member'); + if ( empty( $date ) ) { + return __( 'Please provide a date range beginning', 'ultimate-member' ); + } + if ( ! UM()->validation()->validate_date( $date ) ) { + return __( 'Please enter a valid start date in the date range', 'ultimate-member' ); + } + return 0; } @@ -166,12 +184,18 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { * @param $date * @param $start_date * - * @return int|string|void + * @return int|string */ function date_range_end_err( $date, $start_date ) { - if ( empty( $date ) ) return __('Please provide a date range end','ultimate-member'); - if ( ! UM()->validation()->validate_date( $date ) ) return __('Please enter a valid end date in the date range','ultimate-member'); - if ( strtotime( $date ) <= strtotime( $start_date ) ) return __('The end of date range must be greater than the start of date range','ultimate-member'); + if ( empty( $date ) ) { + return __( 'Please provide a date range end', 'ultimate-member' ); + } + if ( ! UM()->validation()->validate_date( $date ) ) { + return __( 'Please enter a valid end date in the date range', 'ultimate-member' ); + } + if ( strtotime( $date ) <= strtotime( $start_date ) ) { + return __( 'The end of date range must be greater than the start of date range', 'ultimate-member' ); + } return 0; } @@ -1888,4 +1912,4 @@ if ( ! class_exists( 'um\core\Builtin' ) ) { } } -} \ No newline at end of file +} diff --git a/readme.txt b/readme.txt index 5c8effa2..3e8deb9a 100644 --- a/readme.txt +++ b/readme.txt @@ -162,6 +162,7 @@ The plugin works with popular caching plugins by automatically excluding Ultimat - Added: Sanitizing handlers to the Ultimate Member > Settings forms' fields - Added: Sanitizing handlers to the Ultimate Member > User Role Add/Edit forms' fields - Added: Sanitizing handlers to the Ultimate Member > Forms forms' fields + - Added: Sanitizing handlers to the Ultimate Member > Forms > Add Field/Edit Field forms' fields - Added: Sanitizing handlers to the Ultimate Member > User Roles forms' fields - Added: Sanitizing handlers to the Restriction Content forms' fields in the posts/pages/menus additional fields - Added: Custom placeholder setting for the Confirm Password field