Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/userswp/admin/settings/class-formbuilder.php
+++ b/userswp/admin/settings/class-formbuilder.php
@@ -1818,7 +1818,7 @@
'label' => __( 'Validation Pattern', 'userswp' ) . uwp_help_tip( __( 'Enter regex expression for HTML5 pattern validation.', 'userswp' ) ),
'type' => 'text',
'wrap_class' => uwp_advanced_toggle_class(),
- 'value' => addslashes_gpc( $value ), // Keep slashes
+ 'value' => wp_slash( $value ), // Keep slashes
)
);
--- a/userswp/includes/class-forms.php
+++ b/userswp/includes/class-forms.php
@@ -103,25 +103,24 @@
}
if ( $processed ) {
-
if ( is_wp_error( $errors ) ) {
- echo aui()->alert(
- array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
- 'type' => 'error',
- 'class' => 'text-center',
- 'content' => wp_kses_post( $errors->get_error_message() ),
- )
- );
- } elseif ( $redirect ) {
+ aui()->alert(
+ array(
+ 'type' => 'error',
+ 'content' => wp_kses_post( $errors->get_error_message() )
+ ),
+ true
+ );
+ } else if ( $redirect ) {
wp_safe_redirect( $redirect );
exit();
- } else {
- echo aui()->alert(
- array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
- 'type' => 'success',
- 'class' => 'text-center',
- 'content' => wp_kses_post( $message ),
- )
+ } else {
+ aui()->alert(
+ array(
+ 'type' => 'success',
+ 'content' => wp_kses_post( $message )
+ ),
+ true
);
}
}
@@ -197,6 +196,7 @@
*/
public function process_image_crop( $data = array(), $type = 'avatar', $unlink_prev_img = false ) {
global $wpdb;
+
if ( ! is_user_logged_in() ) {
return false;
}
@@ -205,6 +205,27 @@
return;
}
+ $image_url = ! empty( $data['uwp_crop'] ) ? esc_url( $data['uwp_crop'] ) : '';
+
+ if ( empty( $image_url ) ) {
+ return new WP_Error( 'empty_image', __( 'Upload valid image.', 'userswp' ) );
+ }
+
+ // Ensure we have a valid URL with an allowed meme type.
+ $image_url = $this->normalize_url( $image_url );
+
+ $content_url = str_replace( array( 'https://', 'http://' ) , '', untrailingslashit( WP_CONTENT_URL ) );
+ $_image_url = str_replace( array( 'https://', 'http://' ), '', $image_url );
+ if ( strpos( $_image_url, $content_url ) !== 0 ) {
+ return new WP_Error( 'invalid_image', __( 'Invalid image url.', 'userswp' ) );
+ }
+
+ $filetype = wp_check_filetype( $image_url );
+
+ if ( empty( $filetype['ext'] ) ) {
+ return new WP_Error( 'invalid_image', __( 'Invalid image type.', 'userswp' ) );
+ }
+
// If is current user's profile (profile.php)
if ( is_admin() && defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE ) {
$user_id = get_current_user_id();
@@ -216,19 +237,6 @@
$user_id = get_current_user_id();
}
- // Ensure we have a valid URL with an allowed meme type.
- $image_url = $this->normalize_url( esc_url( $data['uwp_crop'] ) );
- $filetype = wp_check_filetype( $image_url );
-
- $errors = new WP_Error();
- if ( empty( $image_url ) || empty( $filetype['ext'] ) ) {
- $errors->add( 'something_wrong', __( 'Something went wrong. Please contact site admin.', 'userswp' ) );
- }
-
- if ( $errors->has_errors() ) {
- return $errors;
- }
-
// Retrieve current thumbnail.
$current_field = 'avatar' === $type ? 'avatar_thumb' : 'banner_thumb';
$current_thumbnail = $this->normalize_url( uwp_get_usermeta( $user_id, $current_field, '' ) );
@@ -253,11 +261,12 @@
$name = sanitize_file_name( pathinfo( $image_path, PATHINFO_FILENAME ) ); //file name without extension
$thumb_image_name = $name . $thumb_postfix . '.' . $ext;
$thumb_image_location = str_replace( $name . '.' . $ext, $thumb_image_name, $image_path );
+
//Get the new coordinates to crop the image.
- $x = $data['x'];
- $y = $data['y'];
- $w = $data['w'];
- $h = $data['h'];
+ $x = $data['uwpx'];
+ $y = $data['uwpy'];
+ $w = $data['uwpw'];
+ $h = $data['uwph'];
//Scale the image based on cropped width setting
$scale = $full_width / $w;
//$scale = 1; // no scaling
@@ -2249,44 +2258,79 @@
* @since 1.0.0
*/
public function upload_file_remove() {
+ global $wpdb;
+
check_ajax_referer( 'uwp_basic_nonce', 'security' );
- $htmlvar = esc_sql( strip_tags( $_POST['htmlvar'] ) );
+ // Check user logged in.
+ if ( ! is_user_logged_in() ) {
+ $message = aui()->alert( array( 'type' => 'error', 'content' => __( 'Access denied!', 'userswp' ) ) );
+ wp_send_json_error( array( 'message' => $message ) );
+ }
+
$user_id = ! empty( $_POST['uid'] ) ? absint( $_POST['uid'] ) : 0;
+ $htmlvar = ! empty( $_POST['htmlvar'] ) ? sanitize_key( $_POST['htmlvar'] ) : '';
- if ( empty( $user_id ) ) {
- wp_die( -1 );
+ if ( empty( $user_id ) || empty( $htmlvar ) ) {
+ $message = aui()->alert( array( 'type' => 'error', 'content' => __( 'Invalid data!', 'userswp' ) ) );
+ wp_send_json_error( array( 'message' => $message ) );
}
- if ( ! ( is_user_logged_in() && ( $user_id == (int) get_current_user_id() || current_user_can( 'manage_options' ) ) ) ) {
- wp_send_json_error( __( 'Invalid access!', 'userswp' ) );
+ // Validate the user / admin.
+ if ( ! ( $user_id == (int) get_current_user_id() || current_user_can( 'manage_options' ) ) ) {
+ $message = aui()->alert( array( 'type' => 'error', 'content' => __( 'Invalid access!', 'userswp' ) ) );
+ wp_send_json_error( array( 'message' => $message ) );
}
- // Remove file
if ( $htmlvar == 'banner_thumb' ) {
- $file = uwp_get_usermeta( $user_id, 'banner_thumb' );
+ $field_key = 'banner';
$type = 'banner';
- } elseif ( $htmlvar == 'avatar_thumb' ) {
- $file = uwp_get_usermeta( $user_id, 'avatar_thumb' );
+ } else if ( $htmlvar == 'avatar_thumb' ) {
+ $field_key = 'avatar';
$type = 'avatar';
} else {
- $file = '';
+ $field_key = $htmlvar;
$type = '';
}
+ $field = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM " . uwp_get_table_prefix() . "uwp_form_fields WHERE htmlvar_name = %s LIMIT 1", $field_key ) );
+
+ // Check field exists.
+ if ( empty( $field ) ) {
+ $message = aui()->alert( array( 'type' => 'error', 'content' => __( 'Invalid field!', 'userswp' ) ) );
+ wp_send_json_error( array( 'message' => $message ) );
+ }
+
+ // Validate field access.
+ if ( ! empty( $field->for_admin_use ) && ! current_user_can( 'manage_options' ) ) {
+ $message = aui()->alert( array( 'type' => 'error', 'content' => __( 'You are not allowed to perform this action!', 'userswp' ) ) );
+ wp_send_json_error( array( 'message' => $message ) );
+ }
+
+ if ( ! in_array( $field->field_type, array( 'file', 'image' ) ) ) {
+ $message = aui()->alert( array( 'type' => 'error', 'content' => __( 'Invalid field type!', 'userswp' ) ) );
+ wp_send_json_error( array( 'message' => $message ) );
+ }
+
+ $value = uwp_get_usermeta( $user_id, $htmlvar );
+
uwp_update_usermeta( $user_id, $htmlvar, '' );
- if ( $file ) {
+ if ( $value ) {
$uploads = wp_upload_dir();
$upload_path = $uploads['basedir'];
- $unlink_file = untrailingslashit( $upload_path ) . '/' . ltrim( $file, '/' );
+ $unlink_file = untrailingslashit( $upload_path ) . '/' . ltrim( $value, '/' );
if ( is_file( $unlink_file ) && file_exists( $unlink_file ) ) {
@unlink( $unlink_file );
- $unlink_ori_file = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $unlink_file );
- if ( is_file( $unlink_ori_file ) && file_exists( $unlink_ori_file ) ) {
- @unlink( $unlink_ori_file );
+ // For avatar/banner, also remove the original (non-thumb) file.
+ if ( $type ) {
+ $unlink_ori_file = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $unlink_file );
+
+ if ( is_file( $unlink_ori_file ) && file_exists( $unlink_ori_file ) ) {
+ @unlink( $unlink_ori_file );
+ }
}
}
}
@@ -4322,7 +4366,7 @@
if ( empty( $html ) ) {
$design_style = uwp_get_option( 'design_style', 'bootstrap' );
- $bs_form_group = $design_style ? 'form-group m-0' : ''; // country wrapper div added by JS adds marginso we remove ours
+ $bs_form_group = $design_style ? 'form-group m-0' : ''; // country wrapper div added by JS adds margin so we remove ours
$bs_sr_only = $design_style ? 'sr-only' : '';
$bs_form_control = $design_style ? 'form-control' : '';
--- a/userswp/includes/class-userswp.php
+++ b/userswp/includes/class-userswp.php
@@ -571,7 +571,7 @@
// general
add_action( 'init', array( $instance, 'init_notices' ), 1 );
- add_action( 'uwp_loaded', array( $instance, 'handler' ) );
+ add_action( 'init', array( $instance, 'handler' ), 11 );
add_action( 'init', array( $instance, 'privacy_submit_handler' ) );
add_action( 'uwp_template_display_notices', array( $instance, 'display_notices' ), 10, 1 );
add_action( 'wp_ajax_uwp_upload_file_remove', array( $instance, 'upload_file_remove' ) );
--- a/userswp/templates/bootstrap/modal-profile-image-crop.php
+++ b/userswp/templates/bootstrap/modal-profile-image-crop.php
@@ -36,28 +36,28 @@
echo aui()->input(array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'type' => 'hidden',
'id' => esc_html( $type.'-x' ),
- 'name' => 'x',
+ 'name' => 'uwpx',
'value' => '',
'no_wrap' => true,
));
echo aui()->input(array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'type' => 'hidden',
'id' => esc_html( $type.'-y' ),
- 'name' => 'y',
+ 'name' => 'uwpy',
'value' => '',
'no_wrap' => true,
));
echo aui()->input(array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'type' => 'hidden',
'id' => esc_html( $type.'-w' ),
- 'name' => 'w',
+ 'name' => 'uwpw',
'value' => '',
'no_wrap' => true,
));
echo aui()->input(array( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'type' => 'hidden',
'id' => esc_html( $type.'-h' ),
- 'name' => 'h',
+ 'name' => 'uwph',
'value' => '',
'no_wrap' => true,
));
--- a/userswp/templates/bootstrap/profile-header.php
+++ b/userswp/templates/bootstrap/profile-header.php
@@ -23,7 +23,9 @@
return;
}
-if ( ! $uwp_in_user_loop ){ ?>
+if ( ! $uwp_in_user_loop ) {
+do_action( 'uwp_template_display_notices', 'profile' );
+?>
<div class="card shadow-0 border-0 mw-100"><?php }
if ( ! $hide_cover ) {
--- a/userswp/templates/modal-profile-image-crop.php
+++ b/userswp/templates/modal-profile-image-crop.php
@@ -34,10 +34,10 @@
<div class="uwp-<?php echo esc_attr( $type ); ?>-crop-p-wrap">
<div id="<?php echo esc_attr( $type ); ?>-crop-actions">
<form class="uwp-crop-form" method="post">
- <input type="hidden" name="x" value="" id="<?php echo esc_attr( $type ); ?>-x" />
- <input type="hidden" name="y" value="" id="<?php echo esc_attr( $type ); ?>-y" />
- <input type="hidden" name="w" value="" id="<?php echo esc_attr( $type ); ?>-w" />
- <input type="hidden" name="h" value="" id="<?php echo esc_attr( $type ); ?>-h" />
+ <input type="hidden" name="uwpx" value="" id="<?php echo esc_attr( $type ); ?>-x" />
+ <input type="hidden" name="uwpy" value="" id="<?php echo esc_attr( $type ); ?>-y" />
+ <input type="hidden" name="uwpw" value="" id="<?php echo esc_attr( $type ); ?>-w" />
+ <input type="hidden" name="uwph" value="" id="<?php echo esc_attr( $type ); ?>-h" />
<input type="hidden" id="uwp-<?php echo esc_attr( $type ); ?>-crop-image" name="uwp_crop" value="<?php echo esc_attr( $image_url ); ?>" />
<input type="hidden" name="uwp_crop_nonce" value="<?php echo esc_attr( wp_create_nonce( 'uwp_crop_nonce_'.$type ) ); ?>" />
<input type="submit" name="uwp_<?php echo esc_attr( $type ); ?>_crop" value="<?php esc_attr_e('Apply', 'userswp'); ?>" class="button button-primary" id="save_uwp_<?php echo esc_attr( $type ); ?>" />
--- a/userswp/userswp.php
+++ b/userswp/userswp.php
@@ -3,7 +3,7 @@
Plugin Name: UsersWP
Plugin URI: https://userswp.io/
Description: The only lightweight user profile plugin for WordPress. UsersWP features front end user profile, users directory, a registration and a login form.
-Version: 1.2.58
+Version: 1.2.59
Author: AyeCode Ltd
Author URI: https://userswp.io
License: GPL-2.0+
@@ -24,7 +24,7 @@
}
if ( ! defined( 'USERSWP_VERSION' ) ) {
- define( 'USERSWP_VERSION', '1.2.58' );
+ define( 'USERSWP_VERSION', '1.2.59' );
}
if ( ! defined( 'USERSWP_PATH' ) ) {
--- a/userswp/vendor/ayecode/wp-ayecode-ui/ayecode-ui-loader.php
+++ b/userswp/vendor/ayecode/wp-ayecode-ui/ayecode-ui-loader.php
@@ -15,7 +15,7 @@
*/
add_action('after_setup_theme', function () {
global $ayecode_ui_version,$ayecode_ui_file_key;
- $this_version = "0.2.44";
+ $this_version = "0.2.45";
if(empty($ayecode_ui_version) || version_compare($this_version , $ayecode_ui_version, '>')){
$ayecode_ui_version = $this_version ;
$ayecode_ui_file_key = wp_hash( __FILE__ );
--- a/userswp/vendor/ayecode/wp-ayecode-ui/example-plugin.php
+++ b/userswp/vendor/ayecode/wp-ayecode-ui/example-plugin.php
@@ -3,7 +3,7 @@
Plugin Name: AyeCode UI
Plugin URI: https://ayecode.io/
Description: This is an example plugin to test AyeCode UI Quickly.
-Version: 0.2.44
+Version: 0.2.45
Author: AyeCode Ltd
Author URI: https://userswp.io
License: GPL-2.0+
--- a/userswp/vendor/ayecode/wp-ayecode-ui/includes/ayecode-ui-settings.php
+++ b/userswp/vendor/ayecode/wp-ayecode-ui/includes/ayecode-ui-settings.php
@@ -35,7 +35,7 @@
*
* @var string
*/
- public $version = '0.2.44';
+ public $version = '0.2.45';
/**
* Class textdomain.
--- a/userswp/vendor/ayecode/wp-ayecode-ui/includes/inc/bs5-js.php
+++ b/userswp/vendor/ayecode/wp-ayecode-ui/includes/inc/bs5-js.php
@@ -599,10 +599,8 @@
} );
});
-
}
-
/**
* Open a lightbox when an embed item is clicked.
*/
@@ -665,8 +663,6 @@
$carousel += '</ol>';
}
-
-
// items
$i = 0;
$rtl_class = '<?php echo is_rtl() ? 'justify-content-end' : 'justify-content-start'; ?>';
@@ -685,12 +681,17 @@
if (srcset) {
var sources = srcset.split(',')
.map(s => {
- var parts = s.trim().split(' ');
- return {
- width: parseInt(parts[1].replace('w', '')),
- descriptor: parts[1].replace('w', 'px') // Ensuring the descriptor is in pixels
- };
+ // Using regex /s+/ handles multiple spaces between the URL and width
+ var parts = s.trim().split(/s+/).filter(Boolean);
+ if (parts.length >= 2) {
+ return {
+ width: parseInt(parts[1].replace('w', '')),
+ descriptor: parts[1].replace('w', 'px') // Ensuring the descriptor is in pixels
+ };
+ }
+ return null;
})
+ .filter(item => item !== null) // Remove any empty entries
.sort((a, b) => b.width - a.width); // Sort from largest to smallest for proper descending order
// Build the sizes string
@@ -703,10 +704,8 @@
return `(max-width: ${source.width - 1}px) ${array[index - 1].descriptor}`;
}
}).reverse().join(', '); // Reverse to start from smallest to largest for logical order
-
}
-
var img = href ? jQuery(a).find('img').clone().attr('src', href ).attr('sizes', sizes ).removeClass().addClass('mx-auto d-block w-auto rounded').css({'max-height':css_height,'max-width':'98%'}).get(0).outerHTML : jQuery(a).find('img').clone().removeClass().addClass('mx-auto d-block w-auto rounded').css({'max-height':css_height,'max-width':'98%'}).get(0).outerHTML;
$carousel += img;
// captions
@@ -736,11 +735,9 @@
$carousel += '</div></div>';
$i++;
-
});
$carousel += '</div>';
-
// next/prev indicators
if($images.length > 1) {
$carousel += '<a class="carousel-control-prev" href="#aui-embed-slider-modal" role="button" data-bs-slide="prev">';
--- a/userswp/vendor/composer/installed.php
+++ b/userswp/vendor/composer/installed.php
@@ -3,7 +3,7 @@
'name' => 'uswerwp/userswp',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => 'cb6b334724a429ae4a83490a46a5f3480fa82bd4',
+ 'reference' => 'cd9221d17db82a25422efb5dc6eb83ed42811a04',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -20,9 +20,9 @@
'dev_requirement' => false,
),
'ayecode/wp-ayecode-ui' => array(
- 'pretty_version' => '0.2.44',
- 'version' => '0.2.44.0',
- 'reference' => '8a2cb97147c889473e611e8bb240c8b658b87237',
+ 'pretty_version' => '0.2.45',
+ 'version' => '0.2.45.0',
+ 'reference' => 'a68d22a3bc87a85dd12a519dee52366b8a7e4321',
'type' => 'library',
'install_path' => __DIR__ . '/../ayecode/wp-ayecode-ui',
'aliases' => array(),
@@ -79,7 +79,7 @@
'uswerwp/userswp' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
- 'reference' => 'cb6b334724a429ae4a83490a46a5f3480fa82bd4',
+ 'reference' => 'cd9221d17db82a25422efb5dc6eb83ed42811a04',
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),