PluginProbe
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP / 1.2.77
UsersWP – Front-end login form, User Registration, User Profile & Members Directory plugin for WP v1.2.77
1.2.77 1.2.76 1.2.75 1.2.74 1.2.73 1.2.72 1.2.71 1.2.70 1.2.69 1.2.68 1.2.67 1.2.66 1.2.65 1.2.64 1.2.63 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 All 177 releases
← All changes | includes/class-forms.php +64 -13 1.2.73 → 1.2.77 View file →
@@ -219,8 +219,16 @@
219 219 if ( strpos( $_image_url, $content_url ) !== 0 ) {
220 220 return new WP_Error( 'invalid_image', __( 'Invalid image url.', 'userswp' ) );
221 221 }
222 222
223 + // Only allow cropping the image the current user just uploaded (normalized like $image_url).
224 + $pending_key = '_uwp_pending_' . $type . '_upload';
225 + $pending_url = get_user_meta( get_current_user_id(), $pending_key, true );
226 + $pending_url = $pending_url ? str_replace( array( 'https://', 'http://' ), '', $this->normalize_url( esc_url( $pending_url ) ) ) : '';
227 + if ( empty( $pending_url ) || $pending_url !== $_image_url ) {
228 + return new WP_Error( 'crop_session_expired', __( 'Your image upload could not be verified. Please upload the image again.', 'userswp' ) );
229 + }
230 +
223 231 $filetype = wp_check_filetype( $image_url );
224 232
225 233 if ( empty( $filetype['ext'] ) ) {
226 234 return new WP_Error( 'invalid_image', __( 'Invalid image type.', 'userswp' ) );
@@ -281,8 +289,15 @@
281 289 wp_die( esc_html__( 'Something went wrong. Please contact site admin.', 'userswp' ), 403 );
282 290 }
283 291
284 292 $cropped = uwp_resizeThumbnailImage( $thumb_image_location, $image_path, $x, $y, $w, $h, $scale );
293 +
294 + // Resize returns a path even on failure; bail before touching meta or files so the crop can be retried.
295 + clearstatcache( true, $thumb_image_location );
296 + if ( ! is_file( $thumb_image_location ) ) {
297 + return new WP_Error( 'crop_failed', __( 'Could not crop the image. Please try again.', 'userswp' ) );
298 + }
299 +
285 300 $cropped = str_replace( $upload_path, $upload_url, $cropped );
286 301
287 302 // Remove previous avatar/banner
288 303 $unlink_img = '';
@@ -297,13 +312,34 @@
297 312 } else {
298 313 uwp_update_usermeta( $user_id, 'banner_thumb', $cropped );
299 314 }
300 315
301 - if ( $unlink_img && $unlink_img != $thumb_image_location && is_file( $unlink_img ) && file_exists( $unlink_img ) ) {
302 - @unlink( $unlink_img );
303 - $unlink_ori_img = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $unlink_img );
304 - if ( is_file( $unlink_ori_img ) && file_exists( $unlink_ori_img ) ) {
305 - @unlink( $unlink_ori_img );
316 + $original_key = '_uwp_' . $type . '_original';
317 + $prev_original = get_user_meta( $user_id, $original_key, true );
318 +
319 + delete_user_meta( get_current_user_id(), $pending_key );
320 + $relative_original = ltrim( wp_normalize_path( str_replace( wp_normalize_path( untrailingslashit( $upload_path ) ), '', wp_normalize_path( $image_path ) ) ), '/' );
321 + update_user_meta( $user_id, $original_key, $relative_original );
322 +
323 + // Enforce containment inside uploads before deleting, matching upload_file_remove().
324 + $real_upload_path = realpath( $upload_path );
325 + $real_unlink_img = $unlink_img ? realpath( $unlink_img ) : false;
326 +
327 + if ( $real_upload_path && $real_unlink_img && realpath( $thumb_image_location ) !== $real_unlink_img
328 + && false !== strpos( basename( $real_unlink_img ), $thumb_postfix . '.' )
329 + && 0 === strpos( $real_unlink_img, $real_upload_path . DIRECTORY_SEPARATOR )
330 + && is_file( $real_unlink_img ) ) {
331 + wp_delete_file( $real_unlink_img );
332 +
333 + // Delete the previous source only if it is the exact file this user cropped.
334 + $unlink_ori_img = str_replace( $thumb_postfix . '.', '.', $real_unlink_img );
335 + $real_unlink_ori_img = realpath( $unlink_ori_img );
336 + $expected_original = $prev_original ? realpath( untrailingslashit( $upload_path ) . '/' . $prev_original ) : false;
337 + if ( $expected_original && $real_unlink_ori_img && $expected_original === $real_unlink_ori_img
338 + && realpath( $image_path ) !== $real_unlink_ori_img
339 + && 0 === strpos( $real_unlink_ori_img, $real_upload_path . DIRECTORY_SEPARATOR )
340 + && is_file( $real_unlink_ori_img ) ) {
341 + wp_delete_file( $real_unlink_ori_img );
306 342 }
307 343 }
308 344 }
309 345
@@ -390,8 +426,13 @@
390 426 } else {
391 427 // Do nothing
392 428 }
393 429
430 + if ( in_array( $type, array( 'avatar', 'banner' ), true ) ) {
431 + delete_user_meta( $user_id, '_uwp_' . $type . '_original' );
432 + delete_user_meta( get_current_user_id(), '_uwp_pending_' . $type . '_upload' );
433 + }
434 +
394 435 if ( is_admin() ) {
395 436 if ( $user_id == get_current_user_id() ) {
396 437 $redirect_url = admin_url( 'profile.php' );
397 438 } else {
@@ -1654,9 +1695,9 @@
1654 1695
1655 1696 $code = isset( $_POST['authcode'] ) ? sanitize_text_field( wp_unslash( $_POST['authcode'] ) ) : '';
1656 1697
1657 1698 if ( empty( $code ) || true !== \WordfenceLS\Controller_TOTP::shared()->validate_2fa( $user, $code ) ) {
1658 - do_action( 'wp_login_failed', $user->user_login );
1699 + do_action( 'wp_login_failed', $user->user_login, new WP_Error( 'invalid_2fa_code', __( 'Invalid verification code.', 'userswp' ) ) );
1659 1700
1660 1701 $message = aui()->alert(
1661 1702 array(
1662 1703 'type' => 'error',
@@ -1743,9 +1784,9 @@
1743 1784 $error = $e->getMessage();
1744 1785 }
1745 1786
1746 1787 if ( $error ) {
1747 - do_action( 'wp_login_failed', $user->user_login );
1788 + do_action( 'wp_login_failed', $user->user_login, new WP_Error( 'invalid_2fa', $error ) );
1748 1789
1749 1790 $message = aui()->alert(
1750 1791 array(
1751 1792 'type' => 'error',
@@ -1762,9 +1803,9 @@
1762 1803 }
1763 1804
1764 1805 // Validate TOTP.
1765 1806 if ( 'totp' === $provider && true !== $this->validate_wp2fa_totp_authentication( $user ) ) {
1766 - do_action( 'wp_login_failed', $user->user_login );
1807 + do_action( 'wp_login_failed', $user->user_login, new WP_Error( 'invalid_2fa_code', __( 'Invalid verification code.', 'userswp' ) ) );
1767 1808
1768 1809 $message = aui()->alert(
1769 1810 array(
1770 1811 'type' => 'error',
@@ -1776,9 +1817,9 @@
1776 1817 }
1777 1818
1778 1819 // Validate Email.
1779 1820 if ( 'email' === $provider && true !== $this->validate_wp2fa_email_authentication( $user ) ) {
1780 - do_action( 'wp_login_failed', $user->user_login );
1821 + do_action( 'wp_login_failed', $user->user_login, new WP_Error( 'invalid_2fa_code', __( 'Invalid verification code.', 'userswp' ) ) );
1781 1822
1782 1823 if ( isset( $_REQUEST['wp-2fa-email-code-resend'] ) && 1 == $_REQUEST['wp-2fa-email-code-resend'] ) {
1783 1824 $message = aui()->alert(
1784 1825 array(
@@ -1801,9 +1842,9 @@
1801 1842 }
1802 1843
1803 1844 // Backup Codes.
1804 1845 if ( 'backup_codes' === $provider && true !== $this->validate_wp2fa_backup_codes( $user ) ) {
1805 - do_action( 'wp_login_failed', $user->user_login );
1846 + do_action( 'wp_login_failed', $user->user_login, new WP_Error( 'invalid_2fa_code', __( 'Invalid verification code.', 'userswp' ) ) );
1806 1847
1807 1848 $message = aui()->alert(
1808 1849 array(
1809 1850 'type' => 'error',
@@ -2637,19 +2678,29 @@
2637 2678 if ( $real_upload_path && $real_unlink_file && is_file( $real_unlink_file )
2638 2679 && strpos( $real_unlink_file, $real_upload_path . DIRECTORY_SEPARATOR ) === 0 ) {
2639 2680 wp_delete_file( $real_unlink_file );
2640 2681
2641 - // For avatar/banner, also remove the original (non-thumb) file.
2682 + // For avatar/banner, also remove the original (non-thumb) file, only if it is the exact file this user cropped.
2642 2683 if ( $type ) {
2643 - $unlink_ori_file = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $real_unlink_file );
2684 + $unlink_ori_file = str_replace( '_uwp_' . $type . '_thumb' . '.', '.', $real_unlink_file );
2644 2685 $real_unlink_ori_file = realpath( $unlink_ori_file );
2686 + $prev_original = get_user_meta( $user_id, '_uwp_' . $type . '_original', true );
2687 + $expected_original = $prev_original ? realpath( untrailingslashit( $upload_path ) . '/' . $prev_original ) : false;
2645 2688
2646 - if ( $real_unlink_ori_file && is_file( $real_unlink_ori_file )
2689 + if ( $expected_original && $real_unlink_ori_file && $expected_original === $real_unlink_ori_file
2690 + && $real_unlink_ori_file !== $real_unlink_file
2691 + && is_file( $real_unlink_ori_file )
2647 2692 && strpos( $real_unlink_ori_file, $real_upload_path . DIRECTORY_SEPARATOR ) === 0 ) {
2648 2693 wp_delete_file( $real_unlink_ori_file );
2649 2694 }
2650 2695 }
2651 2696 }
2697 + }
2698 +
2699 + // Clear crop bookkeeping meta (pending upload is stored against the uploader).
2700 + if ( $type ) {
2701 + delete_user_meta( $user_id, '_uwp_' . $type . '_original' );
2702 + delete_user_meta( get_current_user_id(), '_uwp_pending_' . $type . '_upload' );
2652 2703 }
2653 2704
2654 2705 wp_send_json_success();
2655 2706