From e14f165e735ef6cb5c6c117f2f928d72faef992a Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Mon, 24 Jul 2023 22:30:33 +0300 Subject: [PATCH] - fixed issue with lack of the nonces in the um_adm_action handler; - fixed #1263; --- includes/admin/class-admin.php | 186 ++++++++------------ includes/admin/core/class-admin-columns.php | 3 +- includes/admin/core/class-admin-notices.php | 19 +- includes/core/um-actions-profile.php | 28 ++- 4 files changed, 107 insertions(+), 129 deletions(-) diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index 1200d2d8..c2293a52 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -61,21 +61,18 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { public function __construct() { parent::__construct(); - $this->templates_path = um_path . 'includes/admin/templates/'; + $this->templates_path = UM_PATH . 'includes/admin/templates/'; add_action( 'admin_init', array( &$this, 'admin_init' ), 0 ); $prefix = is_network_admin() ? 'network_admin_' : ''; - add_filter( "{$prefix}plugin_action_links_" . um_plugin, array( &$this, 'plugin_links' ) ); + add_filter( "{$prefix}plugin_action_links_" . UM_PLUGIN, array( &$this, 'plugin_links' ) ); add_action( 'um_admin_do_action__user_cache', array( &$this, 'user_cache' ) ); add_action( 'um_admin_do_action__user_status_cache', array( &$this, 'user_status_cache' ) ); add_action( 'um_admin_do_action__purge_temp', array( &$this, 'purge_temp' ) ); add_action( 'um_admin_do_action__manual_upgrades_request', array( &$this, 'manual_upgrades_request' ) ); add_action( 'um_admin_do_action__duplicate_form', array( &$this, 'duplicate_form' ) ); - add_action( 'um_admin_do_action__um_hide_locale_notice', array( &$this, 'um_hide_notice' ) ); - add_action( 'um_admin_do_action__um_can_register_notice', array( &$this, 'um_hide_notice' ) ); - add_action( 'um_admin_do_action__um_hide_exif_notice', array( &$this, 'um_hide_notice' ) ); add_action( 'um_admin_do_action__user_action', array( &$this, 'user_action' ) ); add_action( 'um_admin_do_action__check_templates_version', array( &$this, 'check_templates_version' ) ); @@ -1606,22 +1603,17 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { return $classes; } - /** * */ public function manual_upgrades_request() { - if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { - die(); - } - $last_request = get_option( 'um_last_manual_upgrades_request', false ); if ( empty( $last_request ) || time() > $last_request + DAY_IN_SECONDS ) { if ( is_multisite() ) { $blogs_ids = get_sites(); - foreach( $blogs_ids as $b ) { + foreach ( $blogs_ids as $b ) { switch_to_blog( $b->blog_id ); wp_clean_update_cache(); @@ -1638,22 +1630,30 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { update_option( 'um_last_manual_upgrades_request', time() ); } - $url = add_query_arg( array( 'page' => 'ultimatemember', 'update' => 'um_got_updates' ), admin_url( 'admin.php' ) ); + $url = add_query_arg( + array( + 'page' => 'ultimatemember', + 'update' => 'um_got_updates', + ), + admin_url( 'admin.php' ) + ); } else { - $url = add_query_arg( array( 'page' => 'ultimatemember', 'update' => 'um_often_updates' ), admin_url( 'admin.php' ) ); + $url = add_query_arg( + array( + 'page' => 'ultimatemember', + 'update' => 'um_often_updates', + ), + admin_url( 'admin.php' ) + ); } - exit( wp_redirect( $url ) ); + wp_safe_redirect( $url ); + exit; } - /** - * Core pages installation + * Core pages installation. */ - function install_core_pages() { - if ( ! is_admin() ) { - die(); - } - + public function install_core_pages() { UM()->setup()->install_default_pages(); //check empty pages in settings @@ -1664,7 +1664,7 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { foreach ( $pages as $slug => $page_id ) { $page = get_post( $page_id ); - if ( ! isset( $page->ID ) && in_array( $slug, array_keys( UM()->config()->core_pages ) ) ) { + if ( ! isset( $page->ID ) && array_key_exists( $slug, UM()->config()->core_pages ) ) { $empty_pages[] = $slug; } } @@ -1672,27 +1672,22 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { //if there aren't empty pages - then hide pages notice if ( empty( $empty_pages ) ) { - $hidden_notices = get_option( 'um_hidden_admin_notices', array() ); + $hidden_notices = get_option( 'um_hidden_admin_notices', array() ); $hidden_notices[] = 'wrong_pages'; update_option( 'um_hidden_admin_notices', $hidden_notices ); } $url = add_query_arg( array( 'page' => 'um_options' ), admin_url( 'admin.php' ) ); - exit( wp_redirect( $url ) ); + wp_safe_redirect( $url ); + exit; } - /** - * Clear all users cache - * - * @param $action + * Clear all users cache. */ - function user_cache( $action ) { + public function user_cache() { global $wpdb; - if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { - die(); - } $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'um_cache_userdata_%'" ); @@ -1703,21 +1698,14 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { ), admin_url( 'admin.php' ) ); - wp_redirect( $url ); + wp_safe_redirect( $url ); exit; } - /** - * Clear all users statuses count cache - * - * @param $action + * Clear all users statuses count cache. */ - function user_status_cache( $action ) { - if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { - die(); - } - + public function user_status_cache() { $statuses = array( 'approved', 'awaiting_admin_review', @@ -1741,43 +1729,37 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { ), admin_url( 'admin.php' ) ); - wp_redirect( $url ); + wp_safe_redirect( $url ); exit; } - /** - * Purge temp uploads dir - * @param $action + * Purge temp uploads dir. */ - function purge_temp( $action ) { - if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { - die(); - } - + public function purge_temp() { UM()->files()->remove_dir( UM()->files()->upload_temp ); - $url = add_query_arg( array( 'page' => 'ultimatemember', 'update' => 'um_purged_temp' ), admin_url( 'admin.php' ) ); - exit( wp_redirect( $url ) ); + $url = add_query_arg( + array( + 'page' => 'ultimatemember', + 'update' => 'um_purged_temp', + ), + admin_url( 'admin.php' ) + ); + wp_safe_redirect( $url ); + exit; } - /** * Duplicate form - * - * @param $action */ - public function duplicate_form( $action ) { - if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { - die(); - } - - if ( empty( $_REQUEST['post_id'] ) || empty( $_REQUEST['nonce'] ) || ! wp_verify_nonce( $_REQUEST['nonce'], "um-duplicate_form{$_REQUEST['post_id']}" ) ) { - die(); + public function duplicate_form() { + if ( empty( $_REQUEST['post_id'] ) || empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], "um-duplicate_form{$_REQUEST['post_id']}" ) ) { + die( esc_html__( 'Security check', 'ultimate-member' ) ); } if ( ! is_numeric( $_REQUEST['post_id'] ) ) { - die(); + die( esc_html__( 'Wrong ID', 'ultimate-member' ) ); } $post_id = absint( $_REQUEST['post_id'] ); @@ -1817,26 +1799,10 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { } /** - * Action to hide notices in admin - * - * @param $action + * Various user actions. */ - function um_hide_notice( $action ) { - if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) { - die(); - } - - update_option( $action, 1 ); - exit( wp_redirect( remove_query_arg( 'um_adm_action' ) ) ); - } - - /** - * Various user actions - * - * @param $action - */ - function user_action( $action ) { - if ( ! is_admin() || ! current_user_can( 'edit_users' ) ) { + public function user_action() { + if ( ! current_user_can( 'edit_users' ) ) { die(); } if ( ! isset( $_REQUEST['sub'] ) ) { @@ -1891,17 +1857,14 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { um_reset_user(); - wp_redirect( add_query_arg( 'update', 'um_user_updated', admin_url( '?page=ultimatemember' ) ) ); + wp_safe_redirect( add_query_arg( 'update', 'um_user_updated', admin_url( '?page=ultimatemember' ) ) ); exit; - } /** - * Manual check templates versions - * - * @param $action + * Manual check templates versions. */ - public function check_templates_version( $action ) { + public function check_templates_version() { $templates = UM()->admin_settings()->get_override_templates( true ); $out_date = false; @@ -1928,13 +1891,13 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { } /** - * Add any custom links to plugin page + * Add any custom links to plugin page. * * @param array $links * * @return array */ - function plugin_links( $links ) { + public function plugin_links( $links ) { $more_links[] = '' . esc_html__( 'Docs', 'ultimate-member' ) . ''; $more_links[] = '' . esc_html__( 'Settings', 'ultimate-member' ) . ''; @@ -1951,8 +1914,17 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { if ( ! empty( $_REQUEST['um_adm_action'] ) && is_admin() && current_user_can( 'manage_options' ) ) { $action = sanitize_key( $_REQUEST['um_adm_action'] ); - if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], $action ) ) { - wp_die( esc_attr__( 'Security Check', 'ultimate-member' ) ); + $individual_nonce_actions = array( + 'user_action', + 'duplicate_form', + ); + $individual_nonce_actions = apply_filters( 'um_adm_action_individual_nonce_actions', $individual_nonce_actions ); + + // Some actions have their own nonce. Verify individually. + if ( ! in_array( $action, $individual_nonce_actions, true ) ) { + if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], $action ) ) { + wp_die( esc_attr__( 'Security Check', 'ultimate-member' ) ); + } } /** @@ -1998,7 +1970,6 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { } } - /** * Updated post messages * @@ -2006,31 +1977,30 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { * * @return array */ - function post_updated_messages( $messages ) { + public function post_updated_messages( $messages ) { global $post_ID; $post_type = get_post_type( $post_ID ); - if ( $post_type == 'um_form' ) { + if ( 'um_form' === $post_type ) { $messages['um_form'] = array( - 0 => '', - 1 => __( 'Form updated.', 'ultimate-member' ), - 2 => __( 'Custom field updated.', 'ultimate-member' ), - 3 => __( 'Custom field deleted.', 'ultimate-member' ), - 4 => __( 'Form updated.', 'ultimate-member' ), - 5 => isset( $_GET['revision'] ) ? __( 'Form restored to revision.', 'ultimate-member' ) : false, - 6 => __( 'Form created.', 'ultimate-member' ), - 7 => __( 'Form saved.', 'ultimate-member' ), - 8 => __( 'Form submitted.', 'ultimate-member' ), - 9 => __( 'Form scheduled.', 'ultimate-member' ), - 10 => __( 'Form draft updated.', 'ultimate-member' ), + 0 => '', + 1 => __( 'Form updated.', 'ultimate-member' ), + 2 => __( 'Custom field updated.', 'ultimate-member' ), + 3 => __( 'Custom field deleted.', 'ultimate-member' ), + 4 => __( 'Form updated.', 'ultimate-member' ), + 5 => isset( $_GET['revision'] ) ? __( 'Form restored to revision.', 'ultimate-member' ) : false, + 6 => __( 'Form created.', 'ultimate-member' ), + 7 => __( 'Form saved.', 'ultimate-member' ), + 8 => __( 'Form submitted.', 'ultimate-member' ), + 9 => __( 'Form scheduled.', 'ultimate-member' ), + 10 => __( 'Form draft updated.', 'ultimate-member' ), ); } return $messages; } - /** * Gettext filters * diff --git a/includes/admin/core/class-admin-columns.php b/includes/admin/core/class-admin-columns.php index 1607220d..317b0b36 100644 --- a/includes/admin/core/class-admin-columns.php +++ b/includes/admin/core/class-admin-columns.php @@ -117,8 +117,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Columns' ) ) { 'post_type' => 'um_form', 'um_adm_action' => 'duplicate_form', 'post_id' => $id, - 'nonce' => wp_create_nonce( "um-duplicate_form{$id}" ), - '_wpnonce' => wp_create_nonce( 'duplicate_form' ), + '_wpnonce' => wp_create_nonce( "um-duplicate_form{$id}" ), ), admin_url( 'edit.php' ) ); diff --git a/includes/admin/core/class-admin-notices.php b/includes/admin/core/class-admin-notices.php index 75af3e22..72dd29eb 100644 --- a/includes/admin/core/class-admin-notices.php +++ b/includes/admin/core/class-admin-notices.php @@ -451,28 +451,19 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { } } - /** * EXIF library notice */ public function exif_extension_notice() { - $hide_exif_notice = get_option( 'um_hide_exif_notice' ); - - if ( ! extension_loaded( 'exif' ) && ! $hide_exif_notice ) { - $url = add_query_arg( - array( - 'um_adm_action' => 'um_hide_exif_notice', - '_wpnonce' => wp_create_nonce( 'um_hide_exif_notice' ), - ) - ); + if ( ! extension_loaded( 'exif' ) ) { $this->add_notice( 'exif_disabled', array( - 'class' => 'updated', + 'class' => 'updated', // translators: %s: query args. - 'message' => '

' . sprintf( __( 'Exif is not enabled on your server. Mobile photo uploads will not be rotated correctly until you enable the exif extension. Hide this notice', 'ultimate-member' ), $url ) . '

', - ), - 10 + 'message' => '

' . esc_html__( 'Exif is not enabled on your server. Mobile photo uploads will not be rotated correctly until you enable the exif extension.', 'ultimate-member' ) . '

', + 'dismissible' => true, + ) ); } } diff --git a/includes/core/um-actions-profile.php b/includes/core/um-actions-profile.php index 60d3081a..8c5730ad 100644 --- a/includes/core/um-actions-profile.php +++ b/includes/core/um-actions-profile.php @@ -235,6 +235,14 @@ function um_user_edit_profile( $args, $form_data ) { continue; } + if ( is_array( $array ) ) { + $origin_data = UM()->fields()->get_field( $key ); + if ( is_array( $origin_data ) ) { + // Merge data passed with original field data. + $array = array_merge( $origin_data, $array ); + } + } + // required option? 'required_opt' - it's field attribute predefined in the field data in code // @todo can be unnecessary. it's used in 1 place (user account). if ( isset( $array['required_opt'] ) ) { @@ -283,8 +291,7 @@ function um_user_edit_profile( $args, $form_data ) { */ $has_custom_source = apply_filters( "um_has_dropdown_options_source__{$key}", false ); if ( isset( $array['options'] ) && in_array( $array['type'], array( 'select', 'multiselect' ), true ) ) { - - $options = array(); + $options = $array['options']; if ( ! empty( $array['custom_dropdown_options_source'] ) && function_exists( $array['custom_dropdown_options_source'] ) && ! $has_custom_source ) { if ( ! UM()->fields()->is_source_blacklisted( $array['custom_dropdown_options_source'] ) ) { $callback_result = call_user_func( $array['custom_dropdown_options_source'], $array['options'] ); @@ -293,7 +300,6 @@ function um_user_edit_profile( $args, $form_data ) { } } } - $array['options'] = apply_filters( "um_custom_dropdown_options__{$key}", $options ); } @@ -318,8 +324,20 @@ function um_user_edit_profile( $args, $form_data ) { //the user cannot set invalid value in the hidden input at the page if ( in_array( $array['type'], array( 'multiselect', 'checkbox', 'radio' ), true ) ) { if ( ! empty( $args['submitted'][ $key ] ) && ! empty( $array['options'] ) ) { - $args['submitted'][ $key ] = array_map( 'stripslashes', array_map( 'trim', $args['submitted'][ $key ] ) ); - $args['submitted'][ $key ] = array_intersect( $args['submitted'][ $key ], array_map( 'trim', $array['options'] ) ); + if ( is_array( $args['submitted'][ $key ] ) ) { + $args['submitted'][ $key ] = array_map( 'stripslashes', array_map( 'trim', $args['submitted'][ $key ] ) ); + if ( is_array( $array['options'] ) ) { + $args['submitted'][ $key ] = array_intersect( $args['submitted'][ $key ], array_map( 'trim', $array['options'] ) ); + } else { + $args['submitted'][ $key ] = array_intersect( $args['submitted'][ $key ], array( trim( $array['options'] ) ) ); + } + } else { + if ( is_array( $array['options'] ) ) { + $args['submitted'][ $key ] = array_intersect( array( stripslashes( trim( $args['submitted'][ $key ] ) ) ), array_map( 'trim', $array['options'] ) ); + } else { + $args['submitted'][ $key ] = array_intersect( array( stripslashes( trim( $args['submitted'][ $key ] ) ) ), array( trim( $array['options'] ) ) ); + } + } } // update empty user meta