Merge branch 'development/2.9.x' into fix/CVE-2025-13220

This commit is contained in:
Mykyta Synelnikov
2025-12-16 17:13:37 +02:00
committed by GitHub
22 changed files with 337 additions and 86 deletions
+2
View File
@@ -5,6 +5,8 @@
* Bugfixes:
- Fixed: CVE-2025-13220.
- Fixed: CVE-2025-13217.
- Fixed: CVE-2025-14081.
= 2.11.0 December 02, 2025 =
+6
View File
@@ -284,6 +284,12 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
'_um_mode' => array(
'sanitize' => 'key',
),
'_um_privacy' => array(
'sanitize' => 'absint',
),
'_um_privacy_roles' => array(
'sanitize' => array( $this, 'sanitize_existed_role' ),
),
'_um_view_types' => array(
'sanitize' => array( $this, 'sanitize_md_view_types' ),
),
+7
View File
@@ -209,6 +209,13 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
$scanner_content .= '</span>';
$secure_fields = array(
array(
'id' => 'ajax_nopriv_rate_limit',
'type' => 'checkbox',
'label' => __( 'Rate Limit', 'ultimate-member' ),
'checkbox_label' => __( 'Enable Rate Limiting', 'ultimate-member' ),
'description' => __( 'This prevents brute-force enumeration attempts in guest AJAX requests.', 'ultimate-member' ),
),
array(
'id' => 'banned_capabilities',
'type' => 'multi_checkbox',
+2 -1
View File
@@ -728,7 +728,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
* @param $object
* @param $box
*/
function load_metabox_directory( $object, $box ) {
public function load_metabox_directory( $object, $box ) {
$box['id'] = str_replace( 'um-admin-form-', '', $box['id'] );
preg_match('#\{.*?\}#s', $box['id'], $matches );
@@ -857,6 +857,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
public function add_metabox_directory() {
add_meta_box( 'submitdiv', __( 'Publish', 'ultimate-member' ), array( &$this, 'custom_submitdiv' ), 'um_directory', 'side', 'high' );
add_meta_box( 'um-admin-form-general', __( 'General Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
add_meta_box( 'um-admin-form-privacy', __( 'Privacy Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
add_meta_box( 'um-admin-form-sorting', __( 'Sorting', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
add_meta_box( 'um-admin-form-profile', __( 'Profile Card', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
add_meta_box( 'um-admin-form-search', __( 'Search Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
@@ -1032,6 +1032,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) {
'display_login_form_notice' => array(
'sanitize' => 'bool',
),
'ajax_nopriv_rate_limit' => array(
'sanitize' => 'bool',
),
'banned_capabilities' => array(
'sanitize' => array( UM()->admin(), 'sanitize_wp_capabilities_assoc' ),
),
@@ -0,0 +1,48 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$fields = array(
array(
'id' => '_um_privacy',
'type' => 'select',
'label' => __( 'Who can see this member directory', 'ultimate-member' ),
'description' => __( 'Select which users can view this member directory. Minimum recommended visibility is `Members only`. Please pay attention that visible for guests (anyone) member directory can have sensitive information.', 'ultimate-member' ),
'options' => array(
0 => __( 'Anyone', 'ultimate-member' ),
1 => __( 'Guests only', 'ultimate-member' ),
2 => __( 'Members only', 'ultimate-member' ),
3 => __( 'Only specific roles', 'ultimate-member' ),
),
'value' => UM()->query()->get_meta_value( '_um_privacy', null, 2 ),
),
array(
'id' => '_um_privacy_roles',
'type' => 'select',
'multi' => true,
'label' => __( 'Allowed roles', 'ultimate-member' ),
'description' => __( 'Select the the user roles allowed to view this member directory.', 'ultimate-member' ),
'options' => UM()->roles()->get_roles(),
'placeholder' => __( 'Choose user roles...', 'ultimate-member' ),
'conditional' => array( '_um_privacy', '=', '3' ),
'value' => UM()->query()->get_meta_value( '_um_privacy_roles', null, 'na' ),
),
);
$fields = apply_filters( 'um_admin_extend_directory_options_privacy', $fields );
?>
<div class="um-admin-metabox">
<?php
UM()->admin_forms(
array(
'class' => 'um-member-directory-privacy um-half-column',
'prefix_id' => 'um_metadata',
'fields' => $fields,
)
)->render_form();
?>
<div class="clear"></div>
</div>
+3
View File
@@ -141,6 +141,8 @@ if ( ! class_exists( 'um\Config' ) ) {
'_um_core' => 'members',
'_um_template' => 'members',
'_um_mode' => 'directory',
'_um_privacy' => 2,
'_um_privacy_roles' => array(),
'_um_view_types' => array( 'grid' ),
'_um_default_view' => 'grid',
'_um_roles' => array(),
@@ -729,6 +731,7 @@ if ( ! class_exists( 'um\Config' ) ) {
'lock_register_forms' => false,
'display_login_form_notice' => false,
'secure_ban_admins_accounts' => false,
'ajax_nopriv_rate_limit' => true,
'banned_capabilities' => array( 'manage_options', 'promote_users', 'level_10' ),
'secure_notify_admins_banned_accounts' => false,
'secure_notify_admins_banned_accounts__interval' => 'instant',
+31
View File
@@ -47,6 +47,37 @@ if ( ! class_exists( 'UM_Functions' ) ) {
}
}
/**
* Check if the user rate limit has been reached based on the provided context
*
* @param string $context The context for which the rate limit check is being performed
* @param int|null $requests_num Number requests per minute. Default 10.
*
* @return bool True if the rate limit has been reached, false otherwise
*/
public function is_rate_limited( $context, $requests_num = 10 ) {
if ( is_user_logged_in() ) {
return false;
}
if ( ! UM()->options()->get( 'ajax_nopriv_rate_limit' ) ) {
return false;
}
$transient_name = 'um_ajax_nopriv_rate_limit_' . md5( $context . '_' . $_SERVER['REMOTE_ADDR'] );
$rate_limit = get_transient( $transient_name );
$requests_num = apply_filters( 'um_ajax_rate_limit_requests_num', $requests_num, $context ); // 10 requests per minute per IP
if ( false === $rate_limit ) {
set_transient( $transient_name, 1, MINUTE_IN_SECONDS );
} elseif ( $rate_limit < $requests_num ) {
set_transient( $transient_name, $rate_limit + 1, MINUTE_IN_SECONDS );
} else {
return true;
}
return false;
}
/**
* What type of request is this?
-1
View File
@@ -1375,7 +1375,6 @@ if ( ! class_exists( 'UM' ) ) {
require_once 'core/um-actions-form.php';
require_once 'core/um-actions-access.php';
require_once 'core/um-actions-wpadmin.php';
require_once 'core/um-actions-ajax.php';
require_once 'core/um-actions-login.php';
require_once 'core/um-actions-register.php';
require_once 'core/um-actions-profile.php';
+7 -3
View File
@@ -473,23 +473,27 @@ if ( ! class_exists( 'um\core\Account' ) ) {
return $url;
}
/**
* @param $fields
* @param $shortcode_args
* @return mixed
*/
function filter_fields_by_attrs( $fields, $shortcode_args ) {
private function filter_fields_by_attrs( $fields, $shortcode_args ) {
foreach ( $fields as $k => $field ) {
if ( isset( $shortcode_args[ $field['metakey'] ] ) && 0 == $shortcode_args[ $field['metakey'] ] ) {
unset( $fields[ $k ] );
continue;
}
// required user permission 'required_perm' - it's field attribute predefined in the field data in code.
if ( isset( $data['required_perm'] ) && ! UM()->roles()->um_user_can( $data['required_perm'] ) ) {
unset( $fields[ $k ] );
}
}
return $fields;
}
/**
* Init displayed fields for security check
*
+17
View File
@@ -266,6 +266,10 @@ if ( ! class_exists( 'um\core\Files' ) ) {
public function ajax_remove_file() {
UM()->check_ajax_nonce();
if ( UM()->is_rate_limited( 'remove_file' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
if ( empty( $_POST['src'] ) ) {
wp_send_json_error( __( 'Wrong path', 'ultimate-member' ) );
}
@@ -314,6 +318,11 @@ if ( ! class_exists( 'um\core\Files' ) ) {
*/
public function ajax_resize_image() {
UM()->check_ajax_nonce();
if ( UM()->is_rate_limited( 'resize_image' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
// phpcs:disable WordPress.Security.NonceVerification -- verified by the `check_ajax_nonce()`
if ( ! isset( $_REQUEST['src'], $_REQUEST['coord'], $_REQUEST['key'] ) ) {
wp_send_json_error( esc_js( __( 'Invalid parameters', 'ultimate-member' ) ) );
@@ -447,6 +456,10 @@ if ( ! class_exists( 'um\core\Files' ) ) {
* @throws Exception
*/
public function ajax_image_upload() {
if ( UM()->is_rate_limited( 'upload_image' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
$ret['error'] = null;
$ret = array();
@@ -645,6 +658,10 @@ if ( ! class_exists( 'um\core\Files' ) ) {
* @throws Exception
*/
public function ajax_file_upload() {
if ( UM()->is_rate_limited( 'upload_file' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
$ret['error'] = null;
$ret = array();
+4
View File
@@ -116,6 +116,10 @@ if ( ! class_exists( 'um\core\Form' ) ) {
public function ajax_select_options() {
UM()->check_ajax_nonce();
if ( UM()->is_rate_limited( 'select_options' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
// phpcs:disable WordPress.Security.NonceVerification
$arr_options = array();
@@ -595,6 +595,10 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
public function ajax_get_members() {
UM()->check_ajax_nonce();
if ( UM()->is_rate_limited( 'member_directory' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
global $wpdb;
$blog_id = get_current_blog_id();
@@ -609,6 +613,10 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
}
// phpcs:enable WordPress.Security.NonceVerification -- verified via `UM()->check_ajax_nonce();`.
if ( ! $this->can_view_directory( $directory_id ) ) {
wp_send_json_error( __( 'You cannot see this member directory', 'ultimate-member' ) );
}
$directory_data = UM()->query()->post_data( $directory_id );
// Predefined result for user without capabilities to see other members.
+165 -15
View File
@@ -2,6 +2,7 @@
namespace um\core;
use Exception;
use WP_Post;
use WP_User_Query;
if ( ! defined( 'ABSPATH' ) ) {
@@ -123,11 +124,79 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
public function __construct() {
add_filter( 'init', array( &$this, 'init_variables' ) );
add_action( 'wp_insert_post', array( &$this, 'set_token' ), 10, 3 );
add_action( 'template_redirect', array( &$this, 'access_members' ), 555 );
}
/**
* Set member directory token as soon as it's created.
*
* @param int $post_ID
* @param WP_Post $post
* @param bool $update
*
* @return void
*/
public function set_token( $post_ID, $post, $update ) {
if ( 'um_directory' === $post->post_type && ! $update ) {
$this->set_directory_hash( $post_ID );
}
}
/**
* Check if the user can view the member directory.
*
* @param int $directory_id
* @param int|null $user_id
*
* @return bool
*/
public function can_view_directory( $directory_id, $user_id = null ) {
if ( is_null( $user_id ) && is_user_logged_in() ) {
$user_id = get_current_user_id();
}
$can_view = false;
$privacy = get_post_meta( $directory_id, '_um_privacy', true );
if ( '' === $privacy ) {
$can_view = true;
} else {
$privacy = absint( $privacy );
switch ( $privacy ) {
case 0:
$can_view = true;
break;
case 1:
if ( ! is_user_logged_in() ) {
$can_view = true;
}
break;
case 2:
if ( is_user_logged_in() ) {
$can_view = true;
}
break;
case 3:
if ( is_user_logged_in() ) {
$privacy_roles = get_post_meta( $directory_id, '_um_privacy_roles', true );
$privacy_roles = ! empty( $privacy_roles ) && is_array( $privacy_roles ) ? $privacy_roles : array();
$current_user_roles = um_user( 'roles' );
if ( ! empty( $current_user_roles ) && count( array_intersect( $current_user_roles, $privacy_roles ) ) > 0 ) {
$can_view = true;
}
}
break;
}
}
return apply_filters( 'um_directory_user_can_view', $can_view, $directory_id, $user_id );
}
/**
* Get the WordPress core searching fields in wp_users query.
*
* @since 2.6.10
* @version 2.10.2
* @param array|null $qv WP_User_Query variables.
@@ -202,29 +271,104 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
*
* @return bool|int
*/
function get_directory_by_hash( $hash ) {
public function get_directory_by_hash( $hash ) {
global $wpdb;
$directory_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE SUBSTRING( MD5( ID ), 11, 5 ) = %s", $hash ) );
$directory_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT post_id
FROM {$wpdb->postmeta}
WHERE meta_key = '_um_directory_token' AND
meta_value = %s
LIMIT 1",
$hash
)
);
if ( empty( $directory_id ) ) {
return false;
// Fallback, use old value.
$directory_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT ID
FROM {$wpdb->posts}
WHERE SUBSTRING( MD5( ID ), 11, 5 ) = %s",
$hash
)
);
if ( empty( $directory_id ) ) {
return false;
}
}
return (int) $directory_id;
}
/**
* Generate a secure random token for each directory
*
* @param int $id
*
* @return false|string
*/
public function set_directory_hash( $id ) {
$unique_hash = wp_generate_password( 5, false );
$result = update_post_meta( $id, '_um_directory_token', $unique_hash );
if ( false === $result ) {
return false;
}
return $unique_hash;
}
/**
* @param $id
*
* @return bool|string
*/
function get_directory_hash( $id ) {
$hash = substr( md5( $id ), 10, 5 );
public function get_directory_hash( $id ) {
$hash = get_post_meta( $id, '_um_directory_token', true );
if ( '' === $hash ) {
// Set the hash if empty.
$hash = $this->set_directory_hash( $id );
}
if ( empty( $hash ) ) {
// Fallback, use old value.
$hash = substr( md5( $id ), 10, 5 );
}
return $hash;
}
/**
* Generate a secure random token for each user card
*
* @param int $id
*
* @return false|string
*/
public function set_user_hash( $id ) {
$unique_hash = wp_generate_password( 5, false );
$result = update_user_meta( $id, '_um_card_anchor_token', $unique_hash );
if ( false === $result ) {
return false;
}
return $unique_hash;
}
/**
* @param $id
*
* @return bool|string
*/
public function get_user_hash( $id ) {
$hash = get_user_meta( $id, '_um_card_anchor_token', true );
if ( '' === $hash ) {
// Set the hash if empty.
$hash = $this->set_user_hash( $id );
}
if ( empty( $hash ) ) {
// Fallback, use old value.
$hash = substr( md5( $id ), 10, 5 );
}
return $hash;
}
/**
* Get view Type template
@@ -673,7 +817,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
*/
$attrs = apply_filters( 'um_search_fields', $attrs, $field_key, $directory_data['form_id'] );
$unique_hash = substr( md5( $directory_data['form_id'] ), 10, 5 );
$unique_hash = $this->get_directory_hash( $directory_data['form_id'] );
ob_start();
@@ -2545,16 +2689,15 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$hook_after_user_name = ob_get_clean();
$data_array = array(
'card_anchor' => esc_html( substr( md5( $user_id ), 10, 5 ) ),
'id' => absint( $user_id ),
'role' => esc_html( um_user( 'role' ) ),
'account_status' => esc_html( UM()->common()->users()->get_status( $user_id ) ),
'account_status_name' => esc_html( UM()->common()->users()->get_status( $user_id, 'formatted' ) ),
'card_anchor' => esc_html( $this->get_user_hash( $user_id ) ),
'role' => is_user_logged_in() ? esc_html( um_user( 'role' ) ) : 'undefined', // make the role hidden for the nopriv requests.
'account_status' => is_user_logged_in() ? esc_html( UM()->common()->users()->get_status( $user_id ) ) : 'undefined', // make the status hidden for the nopriv requests.
'account_status_name' => is_user_logged_in() ? esc_html( UM()->common()->users()->get_status( $user_id, 'formatted' ) ) : __( 'Undefined', 'ultimate-member' ), // make the status hidden for the nopriv requests.
'cover_photo' => wp_kses( um_user( 'cover_photo', $this->cover_size ), UM()->get_allowed_html( 'templates' ) ),
'display_name' => esc_html( um_user( 'display_name' ) ),
'profile_url' => esc_url( um_user_profile_url() ),
'can_edit' => (bool) $can_edit,
'edit_profile_url' => esc_url( um_edit_profile_url() ),
'edit_profile_url' => $can_edit ? esc_url( um_edit_profile_url() ) : '',
'avatar' => wp_kses( get_avatar( $user_id, $this->avatar_size ), UM()->get_allowed_html( 'templates' ) ),
'display_name_html' => wp_kses( um_user( 'display_name', 'html' ), UM()->get_allowed_html( 'templates' ) ),
'dropdown_actions' => $dropdown_actions,
@@ -2788,13 +2931,16 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
}
}
/**
* Main Query function for getting members via AJAX
*/
function ajax_get_members() {
public function ajax_get_members() {
UM()->check_ajax_nonce();
if ( UM()->is_rate_limited( 'member_directory' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
global $wpdb;
if ( empty( $_POST['directory_id'] ) ) {
@@ -2807,6 +2953,10 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
wp_send_json_error( __( 'Wrong member directory data', 'ultimate-member' ) );
}
if ( ! $this->can_view_directory( $directory_id ) ) {
wp_send_json_error( __( 'You cannot see this member directory', 'ultimate-member' ) );
}
$directory_data = UM()->query()->post_data( $directory_id );
//predefined result for user without capabilities to see other members
+3
View File
@@ -775,6 +775,9 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
}
if ( 'directory' === $args['mode'] ) {
if ( ! UM()->member_directory()->can_view_directory( $this->form_id ) ) {
return ''; // Checking for privacy settings of the member directory
}
wp_enqueue_script( 'um_members' );
wp_enqueue_style( 'um_members' );
}
+8
View File
@@ -105,6 +105,10 @@ if ( ! class_exists( 'um\core\User_posts' ) ) {
function load_posts() {
UM()->check_ajax_nonce();
if ( UM()->is_rate_limited( 'paginate_posts' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
$author = ! empty( $_POST['author'] ) ? absint( $_POST['author'] ) : get_current_user_id();
$page = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 0;
@@ -153,6 +157,10 @@ if ( ! class_exists( 'um\core\User_posts' ) ) {
function load_comments() {
UM()->check_ajax_nonce();
if ( UM()->is_rate_limited( 'paginate_comments' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
$user_id = ! empty( $_POST['user_id'] ) ? absint( $_POST['user_id'] ) : get_current_user_id();
$page = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 0;
-49
View File
@@ -1,49 +0,0 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Run check if username exists
* @uses action hooks: wp_ajax_nopriv_ultimatemember_check_username_exists, wp_ajax_ultimatemember_check_username_exists
* @return boolean
*/
function ultimatemember_check_username_exists() {
UM()->check_ajax_nonce();
$username = isset( $_REQUEST['username'] ) ? sanitize_user( $_REQUEST['username'] ) : '';
$exists = username_exists( $username );
/**
* UM hook
*
* @type filter
* @title um_validate_username_exists
* @description Change username exists validation
* @input_vars
* [{"var":"$exists","type":"bool","desc":"Exists?"},
* {"var":"$username","type":"string","desc":"Username"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_validate_username_exists', 'function_name', 10, 2 ); ?>
* @example
* <?php
* add_filter( 'um_validate_username_exists', 'my_validate_username_exists', 10, 2 );
* function my_account_pre_updating_profile( $exists, $username ) {
* // your code here
* return $exists;
* }
* ?>
*/
$exists = apply_filters( 'um_validate_username_exists', $exists, $username );
if ( $exists ) {
echo 1;
} else {
echo 0;
}
die();
}
add_action('wp_ajax_nopriv_ultimatemember_check_username_exists', 'ultimatemember_check_username_exists');
add_action('wp_ajax_ultimatemember_check_username_exists', 'ultimatemember_check_username_exists');
+6 -5
View File
@@ -76,15 +76,15 @@ function um_profile_field_filter_hook__youtube_video( $value, $data ) {
}
$value = ( strstr( $value, 'http' ) || strstr( $value, '://' ) ) ? um_youtube_id_from_url( $value ) : $value;
if ( false !== $value ) {
$value = 'https://www.youtube.com/embed/' . $value;
$value = '<div class="um-youtube">'
. '<iframe width="600" height="450" src="https://www.youtube.com/embed/' . $value . '" frameborder="0" allowfullscreen></iframe>'
. '<iframe width="600" height="450" src="' . esc_url( $value ) . '" frameborder="0" allowfullscreen></iframe>'
. '</div>';
}
return $value;
}
add_filter( 'um_profile_field_filter_hook__youtube_video', 'um_profile_field_filter_hook__youtube_video', 99, 2 );
/**
* Outputs a spotify iframe
*
@@ -127,8 +127,9 @@ function um_profile_field_filter_hook__vimeo_video( $value, $data ) {
}
$value = ! is_numeric( $value ) ? (int) substr( parse_url( $value, PHP_URL_PATH ), 1 ) : $value;
$value = 'https://player.vimeo.com/video/' . $value;
$value = '<div class="um-vimeo">
<iframe src="https://player.vimeo.com/video/' . $value . '" width="600" height="450" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<iframe src="' . esc_url( $value ) . '" width="600" height="450" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
</div>';
return $value;
}
@@ -199,14 +200,14 @@ function um_profile_field_filter_hook__googlemap( $value, $data ) {
if ( ! $value ) {
return '';
}
$value = 'https://maps.google.it/maps?q=' . urlencode( $value ) . '&output=embed';
$value = '<div class="um-googlemap">
<iframe width="600" height="450" frameborder="0" style="border:0" src="https://maps.google.it/maps?q=' . urlencode( $value ) . '&output=embed"></iframe>
<iframe width="600" height="450" frameborder="0" style="border:0" src="' . esc_url( $value ) . '"></iframe>
</div>';
return $value;
}
add_filter( 'um_profile_field_filter_hook__googlemap', 'um_profile_field_filter_hook__googlemap', 99, 2 );
/**
* User's registration date
*
+3
View File
@@ -172,6 +172,9 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI
**Bugfixes**
* Fixed: CVE-2025-13220.
* Fixed: CVE-2025-13217.
* Fixed: CVE-2025-14081.
* Fixed: CVE-2025-12492.
= 2.11.0 2025-12-02 =
+3 -3
View File
@@ -6,7 +6,7 @@
*
* Page: "Members"
*
* @version 2.6.1
* @version 2.11.1
*
* @var array $args
* @var bool $cover_photos
@@ -23,8 +23,8 @@ if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$unique_hash = substr( md5( $args['form_id'] ), 10, 5 ); ?>
$unique_hash = UM()->member_directory()->get_directory_hash( $args['form_id'] );
?>
<script type="text/template" id="tmpl-um-member-grid-<?php echo esc_attr( $unique_hash ) ?>">
<div class="um-members um-members-grid">
<div class="um-gutter-sizer"></div>
+6 -4
View File
@@ -6,7 +6,7 @@
*
* Page: "Members"
*
* @version 2.6.1
* @version 2.11.1
*
* @var array $args
* @var bool $cover_photos
@@ -19,10 +19,12 @@
* @var array $reveal_fields
* @var string $no_users
*/
if ( ! defined( 'ABSPATH' ) ) exit;
$unique_hash = substr( md5( $args['form_id'] ), 10, 5 ); ?>
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
$unique_hash = UM()->member_directory()->get_directory_hash( $args['form_id'] );
?>
<script type="text/template" id="tmpl-um-member-list-<?php echo esc_attr( $unique_hash ) ?>">
<div class="um-members um-members-list">
+5 -5
View File
@@ -6,7 +6,7 @@
*
* Page: "Members"
*
* @version 2.6.8
* @version 2.11.1
*
* @var array $args
*/
@@ -23,7 +23,7 @@ foreach ( UM()->config()->core_directory_meta['members'] as $k => $v ) {
$def_args[ $key ] = $v;
}
$unique_hash = substr( md5( $args['form_id'] ), 10, 5 );
$unique_hash = UM()->member_directory()->get_directory_hash( $args['form_id'] );
$args = array_merge( $def_args, $args );
@@ -237,8 +237,8 @@ if ( ( ( $search && $show_search ) || ( $filters && $show_filters && count( $sea
$postid = ! empty( $post->ID ) ? $post->ID : '';
?>
<div class="um <?php echo esc_attr( $this->get_class( $mode ) ); ?> um-<?php echo esc_attr( substr( md5( $form_id ), 10, 5 ) ); ?>"
data-hash="<?php echo esc_attr( substr( md5( $form_id ), 10, 5 ) ) ?>" data-base-post="<?php echo esc_attr( $postid ) ?>"
<div class="um <?php echo esc_attr( $this->get_class( $mode ) ); ?> um-<?php echo esc_attr( $unique_hash ); ?>"
data-hash="<?php echo esc_attr( $unique_hash ) ?>" data-base-post="<?php echo esc_attr( $postid ) ?>"
data-must-search="<?php echo esc_attr( $must_search ); ?>" data-searched="<?php echo $not_searched ? '0' : '1'; ?>"
data-view_type="<?php echo esc_attr( $current_view ) ?>" data-page="<?php echo esc_attr( $current_page ) ?>"
data-sorting="<?php echo esc_attr( $sort_from_url ) ?>">
@@ -313,7 +313,7 @@ $postid = ! empty( $post->ID ) ? $post->ID : '';
<?php $items = array();
foreach ( $sorting_options as $value => $title ) {
$items[] = '<a href="javascript:void(0);" data-directory-hash="' . esc_attr( substr( md5( $form_id ), 10, 5 ) ) . '" class="um-sortyng-by-' . esc_attr( $value ) . '" data-value="' . esc_attr( $value ) . '" data-selected="' . ( ( $sort_from_url == $value ) ? '1' : '0' ) . '" data-default="' . ( ( $default_sorting == $value ) ? '1' : '0' ) . '">' . $title . '</a>'; ?>
$items[] = '<a href="javascript:void(0);" data-directory-hash="' . esc_attr( $unique_hash ) . '" class="um-sortyng-by-' . esc_attr( $value ) . '" data-value="' . esc_attr( $value ) . '" data-selected="' . ( ( $sort_from_url == $value ) ? '1' : '0' ) . '" data-default="' . ( ( $default_sorting == $value ) ? '1' : '0' ) . '">' . $title . '</a>'; ?>
<?php }
UM()->member_directory()->dropdown_menu( '.um-member-directory-sorting-a', 'click', $items ); ?>