WordPress.org

Make WordPress Core

Ticket #43443: update.43443.diff

File update.43443.diff, 13.8 KB (added by mikejolley, 4 years ago)

Update for 43443

  • wp-includes/user.php

    diff --git wp-includes/user.php wp-includes/user.php
    index def16fa272..0c7825f329 100644
    function new_user_email_admin_notice() { 
    28152815 *
    28162816 * @since 5.0.0
    28172817 *
    2818  * @param string $action_name        Name of the action that is being confirmed.
    2819  * @param string $action_description User facing description of the action they will be confirming.
    2820  * @param string $email              User email address. This can be the address of a registered or non-registered user. Defaults to logged in user email address.
    2821  *
    2822  * @return WP_ERROR|bool Will return true/false based on the success of sending the email, or a WP_Error object.
     2818 * @param string $email              User email address. This can be the address of a registered or non-registered user. Defaults to logged in user email address.
     2819 * @param string $action_name        Name of the action that is being confirmed. Defaults to 'confirm_email'.
     2820 * @param string $action_description User facing description of the action they will be confirming. Defaults to "confirm your email address".
     2821 * @return WP_Error|bool Will return true/false based on the success of sending the email, or a WP_Error object.
    28232822 */
    2824 function send_confirm_account_action_email( $action_name, $action_description = '', $email = '' ) {
     2823function wp_send_account_verification_key( $email = '', $action_name = '', $action_description = '' ) {
     2824        if ( ! function_exists( 'wp_get_current_user' ) ) {
     2825                return new WP_Error( 'invalid', __( 'This function cannot be used before init.' ) );
     2826        }
     2827
    28252828        $action_name        = sanitize_key( $action_name );
    28262829        $action_description = wp_kses_post( $action_description );
    28272830
    28282831        if ( empty( $action_name ) ) {
    2829                 return new WP_Error( 'invalid_action', __( 'Invalid action' ) );
     2832                $action_name = 'confirm_email';
     2833        }
     2834
     2835        if ( empty( $action_description ) ) {
     2836                $action_description = __( 'Confirm your email address.' );
    28302837        }
    28312838
    28322839        if ( empty( $email ) ) {
    function send_confirm_account_action_email( $action_name, $action_description = 
    28462853                $user = get_user_by( 'email', $email );
    28472854        }
    28482855
    2849         // We could be dealing with a registered user account, or a visitor.
    2850         $is_registered_user = $user && ! is_wp_error( $user );
    2851         $uid                = $is_registered_user ? $user->ID : hash( 'sha256', $email );
    2852         $confirm_key        = get_confirm_account_action_key( $action_name, $email );
     2856        $confirm_key = wp_get_account_verification_key( $email, $action_name );
    28532857
    28542858        if ( is_wp_error( $confirm_key ) ) {
    28552859                return $confirm_key;
    28562860        }
    28572861
    2858         // Prepare the email content.
    2859         if ( ! $action_description ) {
    2860                 $action_description = $action_name;
     2862        // We could be dealing with a registered user account, or a visitor.
     2863        $is_registered_user = $user && ! is_wp_error( $user );
     2864
     2865        if ( $is_registered_user ) {
     2866                $uid = $user->ID;
     2867        } else {
     2868                $uid = function_exists( 'hash' ) ? hash( 'sha256', $email ) : sha1( $email );
    28612869        }
    28622870
    28632871        /* translators: Do not translate DESCRIPTION, CONFIRM_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
    28642872        $email_text = __(
    28652873                'Howdy,
    28662874
    2867 An account linked to your email address has requested to perform
    2868 the following action:
     2875An account linked to your email address has requested to:
    28692876
    28702877     ###DESCRIPTION###
    28712878
    2872 To confirm this action, please click on the following link:
     2879To do this, please click on the following link:
    28732880###CONFIRM_URL###
    28742881
    28752882You can safely ignore and delete this email if you do not want to
    All at ###SITENAME### 
    28872894                'email'       => $email,
    28882895                'description' => $action_description,
    28892896                'confirm_url' => add_query_arg( array(
    2890                         'action'         => 'emailconfirm',
     2897                        'action'         => 'verifyaccount',
    28912898                        'confirm_action' => $action_name,
    28922899                        'uid'            => $uid,
    28932900                        'confirm_key'    => $confirm_key,
    All at ###SITENAME### 
    29072914         * ###SITENAME###           The name of the site.
    29082915         * ###SITEURL###            The URL to the site.
    29092916         *
     2917         * @since 5.0.0
     2918         *
    29102919         * @param string $email_text     Text in the email.
    29112920         * @param array  $email_data {
    29122921         *     Data relating to the account action email.
    All at ###SITENAME### 
    29192928         *     @type string $siteurl     The site URL sending the mail.
    29202929         * }
    29212930         */
    2922         $content = apply_filters( 'confirm_account_action_email_content', $email_text, $email_data );
     2931        $content = apply_filters( 'account_verification_email_content', $email_text, $email_data );
    29232932
    29242933        $content = str_replace( '###DESCRIPTION###', $email_data['description'], $content );
    29252934        $content = str_replace( '###CONFIRM_URL###', esc_url_raw( $email_data['confirm_url'] ), $content );
    All at ###SITENAME### 
    29282937        $content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content );
    29292938
    29302939        /* translators: %s Site name. */
    2931         return wp_mail( $email_data['email'], sprintf( __( '[%s] Confirm Account Action' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ), $content );
     2940        return wp_mail( $email_data['email'], sprintf( __( '[%s] Confirm Action' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ), $content );
    29322941}
    29332942
    29342943/**
    All at ###SITENAME### 
    29362945 *
    29372946 * @since 5.0.0
    29382947 *
    2939  * @param string $action_name Name of the action this key is being generated for.
    29402948 * @param string $email       User email address. This can be the address of a registered or non-registered user.
    2941  *
     2949 * @param string $action_name Name of the action this key is being generated for.
    29422950 * @return string|WP_Error Confirmation key on success. WP_Error on error.
    29432951 */
    2944 function get_confirm_account_action_key( $action_name, $email ) {
     2952function wp_get_account_verification_key( $email, $action_name ) {
    29452953        global $wp_hasher;
    29462954
    29472955        if ( ! is_email( $email ) ) {
    function get_confirm_account_action_key( $action_name, $email ) { 
    29692977        $hashed_key = $wp_hasher->HashPassword( $key );
    29702978
    29712979        if ( $is_registered_user ) {
    2972                 $key_saved = (bool) update_user_meta( $user->ID, '_account_action_' . $action_name, implode( ':', array( time(), $hashed_key ) ) );
     2980                $key_saved = (bool) update_user_meta( $user->ID, '_verify_' . $action_name, implode( ':', array( time(), $hashed_key ) ) );
    29732981        } else {
    2974                 $key_saved = (bool) update_site_option( '_account_action_' . hash( 'sha256', $email ) . '_' . $action_name, implode( ':', array( time(), $hashed_key, $email ) ) );
     2982                $uid       = function_exists( 'hash' ) ? hash( 'sha256', $email ) : sha1( $email );
     2983                $key_saved = (bool) update_site_option( '_verify_' . $uid . '_' . $action_name, implode( ':', array( time(), $hashed_key, $email ) ) );
    29752984        }
    29762985
    29772986        if ( false === $key_saved ) {
    2978                 return new WP_Error( 'no_confirm_account_action_key_update', __( 'Could not save confirm account action key to database.' ) );
     2987                return new WP_Error( 'no_account_verification_key_update', __( 'Could not save confirm account action key to database.' ) );
    29792988        }
    29802989
    29812990        return $key;
    function get_confirm_account_action_key( $action_name, $email ) { 
    29862995 *
    29872996 * @since 5.0.0
    29882997 *
    2989  * @param string $action_name Name of the action this key is being generated for.
    29902998 * @param string $key         Key to confirm.
    29912999 * @param string $uid         Email hash or user ID.
    2992  *
     3000 * @param string $action_name Name of the action this key is being generated for.
    29933001 * @return array|WP_Error WP_Error on failure, action name and user email address on success.
    29943002 */
    2995 function check_confirm_account_action_key( $action_name, $key, $uid ) {
     3003function wp_check_account_verification_key( $key, $uid, $action_name ) {
    29963004        global $wp_hasher;
    29973005
    2998         if ( ! empty( $action_name ) && ! empty( $key ) && ! empty( $uid ) ) {
    2999                 $user = false;
     3006        if ( empty( $action_name ) || empty( $key ) || empty( $uid ) ) {
     3007                return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
     3008        }
    30003009
    3001                 if ( is_numeric( $uid ) ) {
    3002                         $user = get_user_by( 'id', absint( $uid ) );
    3003                 }
     3010        $user = false;
    30043011
    3005                 // We could be dealing with a registered user account, or a visitor.
    3006                 $is_registered_user = $user && ! is_wp_error( $user );
    3007                 $key_request_time = '';
    3008                 $saved_key        = '';
    3009                 $email            = '';
     3012        if ( is_numeric( $uid ) ) {
     3013                $user = get_user_by( 'id', absint( $uid ) );
     3014        }
    30103015
    3011                 if ( empty( $wp_hasher ) ) {
    3012                         require_once ABSPATH . WPINC . '/class-phpass.php';
    3013                         $wp_hasher = new PasswordHash( 8, true );
    3014                 }
     3016        // We could be dealing with a registered user account, or a visitor.
     3017        $is_registered_user = $user && ! is_wp_error( $user );
     3018        $key_request_time = '';
     3019        $saved_key        = '';
     3020        $email            = '';
    30153021
    3016                 // Get the saved key from the database.
    3017                 if ( $is_registered_user ) {
    3018                         $confirm_action_data = get_user_meta( $user->ID, '_account_action_' . $action_name, true );
    3019                         $email               = $user->user_email;
     3022        if ( empty( $wp_hasher ) ) {
     3023                require_once ABSPATH . WPINC . '/class-phpass.php';
     3024                $wp_hasher = new PasswordHash( 8, true );
     3025        }
    30203026
    3021                         if ( false !== strpos( $confirm_action_data, ':' ) ) {
    3022                                 list( $key_request_time, $saved_key ) = explode( ':', $confirm_action_data, 2 );
    3023                         }
    3024                 } else {
    3025                         $confirm_action_data = get_site_option( '_account_action_' . $uid . '_' . $action_name, '' );
     3027        // Get the saved key from the database.
     3028        if ( $is_registered_user ) {
     3029                $confirm_action_data = get_user_meta( $user->ID, '_verify_' . $action_name, true );
     3030                $email               = $user->user_email;
    30263031
    3027                         if ( false !== strpos( $confirm_action_data, ':' ) ) {
    3028                                 list( $key_request_time, $saved_key, $email ) = explode( ':', $confirm_action_data, 3 );
    3029                         }
     3032                if ( false !== strpos( $confirm_action_data, ':' ) ) {
     3033                        list( $key_request_time, $saved_key ) = explode( ':', $confirm_action_data, 2 );
    30303034                }
     3035        } else {
     3036                $confirm_action_data = get_site_option( '_verify_' . $uid . '_' . $action_name, '' );
    30313037
    3032                 if ( ! $saved_key ) {
    3033                         return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
     3038                if ( false !== strpos( $confirm_action_data, ':' ) ) {
     3039                        list( $key_request_time, $saved_key, $email ) = explode( ':', $confirm_action_data, 3 );
    30343040                }
     3041        }
    30353042
    3036                 /**
    3037                  * Filters the expiration time of confirm keys.
    3038                  *
    3039                  * @param int $expiration The expiration time in seconds.
    3040                  */
    3041                 $expiration_duration = apply_filters( 'account_action_expiration', DAY_IN_SECONDS );
    3042                 $expiration_time     = $key_request_time + $expiration_duration;
    3043 
    3044                 if ( $wp_hasher->CheckPassword( $key, $saved_key ) ) {
    3045                         if ( $expiration_time && time() < $expiration_time ) {
    3046                                 $return = array(
    3047                                         'action' => $action_name,
    3048                                         'email'  => $email,
    3049                                 );
    3050                         } else {
    3051                                 $return = new WP_Error( 'expired_key', __( 'The confirmation email has expired.' ) );
    3052                         }
     3043        if ( ! $saved_key ) {
     3044                return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
     3045        }
    30533046
    3054                         // Clean up stored keys.
    3055                         if ( $is_registered_user ) {
    3056                                 delete_user_meta( $user->ID, '_account_action_' . $action_name );
    3057                         } else {
    3058                                 delete_site_option( '_account_action_' . $uid . '_' . $action_name );
    3059                         }
     3047        /**
     3048         * Filters the expiration time of confirm keys.
     3049         *
     3050         * @since 5.0.0
     3051         *
     3052         * @param int $expiration The expiration time in seconds.
     3053         */
     3054        $expiration_duration = apply_filters( 'account_verification_expiration', DAY_IN_SECONDS );
     3055        $expiration_time     = $key_request_time + $expiration_duration;
    30603056
    3061                         return $return;
    3062                 }
     3057        if ( ! $wp_hasher->CheckPassword( $key, $saved_key ) ) {
     3058                return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
    30633059        }
    30643060
    3065         return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
    3066 }
     3061        if ( $expiration_time && time() < $expiration_time ) {
     3062                $return = array(
     3063                        'action' => $action_name,
     3064                        'email'  => $email,
     3065                );
     3066        } else {
     3067                $return = new WP_Error( 'expired_key', __( 'The confirmation email has expired.' ) );
     3068        }
     3069
     3070        // Clean up stored keys.
     3071        if ( $is_registered_user ) {
     3072                delete_user_meta( $user->ID, '_verify_' . $action_name );
     3073        } else {
     3074                delete_site_option( '_verify_' . $uid . '_' . $action_name );
     3075        }
     3076
     3077        return $return;
     3078}
     3079 No newline at end of file
  • wp-login.php

    diff --git wp-login.php wp-login.php
    index 349f232443..815b44fbad 100644
    if ( isset( $_GET['key'] ) ) { 
    427427}
    428428
    429429// validate action so as to default to the login screen
    430 if ( ! in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login', 'emailconfirm' ), true ) && false === has_filter( 'login_form_' . $action ) ) {
     430if ( ! in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login', 'verifyaccount' ), true ) && false === has_filter( 'login_form_' . $action ) ) {
    431431        $action = 'login';
    432432}
    433433
    switch ( $action ) { 
    858858
    859859                break;
    860860
    861         case 'emailconfirm' :
     861        case 'verifyaccount' :
    862862                if ( isset( $_GET['confirm_action'], $_GET['confirm_key'], $_GET['uid'] ) ) {
    863                         $action_name = sanitize_key( wp_unslash( $_GET['confirm_action'] ) );
    864863                        $key         = sanitize_text_field( wp_unslash( $_GET['confirm_key'] ) );
    865864                        $uid         = sanitize_text_field( wp_unslash( $_GET['uid'] ) );
    866                         $result      = check_confirm_account_action_key( $action_name, $key, $uid );
     865                        $action_name = sanitize_key( wp_unslash( $_GET['confirm_action'] ) );
     866                        $result      = wp_check_account_verification_key( $key, $uid, $action_name );
    867867                } else {
    868868                        $result = new WP_Error( 'invalid_key', __( 'Invalid key' ) );
    869869                }
    switch ( $action ) { 
    874874                         *
    875875                         * After running this action hook the page will die.
    876876                         *
     877                         * @since 5.0.0
     878                         *
    877879                         * @param WP_Error $result Error object.
    878880                         */
    879881                        do_action( 'account_action_failed', $result );
    switch ( $action ) { 
    887889                 * Using this you can assume the user has agreed to perform the action by
    888890                 * clicking on the link in the confirmation email.
    889891                 *
    890                  * After firing this action hook the page will redirect to wp-login a callback 
     892                 * After firing this action hook the page will redirect to wp-login a callback
    891893                 * redirects or exits first.
    892894                 *
     895                 * @since 5.0.0
     896                 *
    893897                 * @param array $result {
    894898                 *     Data about the action which was confirmed.
    895899                 *