WordPress.org

Make WordPress Core

Ticket #31039: 31039.patch

File 31039.patch, 11.9 KB (added by jfarthing84, 6 years ago)

Separate retrieve_password() from wp-login.php

  • wp-login.php

     
    261261        <?php
    262262}
    263263
    264 /**
    265  * Handles sending password retrieval email to user.
    266  *
    267  * @global wpdb         $wpdb      WordPress database abstraction object.
    268  * @global PasswordHash $wp_hasher Portable PHP password hashing framework.
    269  *
    270  * @return bool|WP_Error True: when finish. WP_Error on error
    271  */
    272 function retrieve_password() {
    273         global $wpdb, $wp_hasher;
    274 
    275         $errors = new WP_Error();
    276 
    277         if ( empty( $_POST['user_login'] ) ) {
    278                 $errors->add('empty_username', __('<strong>ERROR</strong>: Enter a username or e-mail address.'));
    279         } elseif ( strpos( $_POST['user_login'], '@' ) ) {
    280                 $user_data = get_user_by( 'email', trim( $_POST['user_login'] ) );
    281                 if ( empty( $user_data ) )
    282                         $errors->add('invalid_email', __('<strong>ERROR</strong>: There is no user registered with that email address.'));
    283         } else {
    284                 $login = trim($_POST['user_login']);
    285                 $user_data = get_user_by('login', $login);
    286         }
    287 
    288         /**
    289          * Fires before errors are returned from a password reset request.
    290          *
    291          * @since 2.1.0
    292          */
    293         do_action( 'lostpassword_post' );
    294 
    295         if ( $errors->get_error_code() )
    296                 return $errors;
    297 
    298         if ( !$user_data ) {
    299                 $errors->add('invalidcombo', __('<strong>ERROR</strong>: Invalid username or e-mail.'));
    300                 return $errors;
    301         }
    302 
    303         // Redefining user_login ensures we return the right case in the email.
    304         $user_login = $user_data->user_login;
    305         $user_email = $user_data->user_email;
    306 
    307         /**
    308          * Fires before a new password is retrieved.
    309          *
    310          * @since 1.5.0
    311          * @deprecated 1.5.1 Misspelled. Use 'retrieve_password' hook instead.
    312          *
    313          * @param string $user_login The user login name.
    314          */
    315         do_action( 'retreive_password', $user_login );
    316 
    317         /**
    318          * Fires before a new password is retrieved.
    319          *
    320          * @since 1.5.1
    321          *
    322          * @param string $user_login The user login name.
    323          */
    324         do_action( 'retrieve_password', $user_login );
    325 
    326         /**
    327          * Filter whether to allow a password to be reset.
    328          *
    329          * @since 2.7.0
    330          *
    331          * @param bool true           Whether to allow the password to be reset. Default true.
    332          * @param int  $user_data->ID The ID of the user attempting to reset a password.
    333          */
    334         $allow = apply_filters( 'allow_password_reset', true, $user_data->ID );
    335 
    336         if ( ! $allow ) {
    337                 return new WP_Error( 'no_password_reset', __('Password reset is not allowed for this user') );
    338         } elseif ( is_wp_error( $allow ) ) {
    339                 return $allow;
    340         }
    341 
    342         // Generate something random for a password reset key.
    343         $key = wp_generate_password( 20, false );
    344 
    345         /**
    346          * Fires when a password reset key is generated.
    347          *
    348          * @since 2.5.0
    349          *
    350          * @param string $user_login The username for the user.
    351          * @param string $key        The generated password reset key.
    352          */
    353         do_action( 'retrieve_password_key', $user_login, $key );
    354 
    355         // Now insert the key, hashed, into the DB.
    356         if ( empty( $wp_hasher ) ) {
    357                 require_once ABSPATH . WPINC . '/class-phpass.php';
    358                 $wp_hasher = new PasswordHash( 8, true );
    359         }
    360         $hashed = $wp_hasher->HashPassword( $key );
    361         $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user_login ) );
    362 
    363         $message = __('Someone requested that the password be reset for the following account:') . "\r\n\r\n";
    364         $message .= network_home_url( '/' ) . "\r\n\r\n";
    365         $message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n";
    366         $message .= __('If this was a mistake, just ignore this email and nothing will happen.') . "\r\n\r\n";
    367         $message .= __('To reset your password, visit the following address:') . "\r\n\r\n";
    368         $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user_login), 'login') . ">\r\n";
    369 
    370         if ( is_multisite() )
    371                 $blogname = $GLOBALS['current_site']->site_name;
    372         else
    373                 /*
    374                  * The blogname option is escaped with esc_html on the way into the database
    375                  * in sanitize_option we want to reverse this for the plain text arena of emails.
    376                  */
    377                 $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
    378 
    379         $title = sprintf( __('[%s] Password Reset'), $blogname );
    380 
    381         /**
    382          * Filter the subject of the password reset email.
    383          *
    384          * @since 2.8.0
    385          *
    386          * @param string $title Default email title.
    387          */
    388         $title = apply_filters( 'retrieve_password_title', $title );
    389 
    390         /**
    391          * Filter the message body of the password reset mail.
    392          *
    393          * @since 2.8.0
    394          * @since 4.1.0 Added `$user_login` and `$user_data` parameters.
    395          *
    396          * @param string  $message    Default mail message.
    397          * @param string  $key        The activation key.
    398          * @param string  $user_login The username for the user.
    399          * @param WP_User $user_data  WP_User object.
    400          */
    401         $message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
    402 
    403         if ( $message && !wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) )
    404                 wp_die( __('The e-mail could not be sent.') . "<br />\n" . __('Possible reason: your host may have disabled the mail() function.') );
    405 
    406         return true;
    407 }
    408 
    409264//
    410265// Main
    411266//
     
    494349case 'retrievepassword' :
    495350
    496351        if ( $http_post ) {
    497                 $errors = retrieve_password();
    498                 if ( !is_wp_error($errors) ) {
    499                         $redirect_to = !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : 'wp-login.php?checkemail=confirm';
    500                         wp_safe_redirect( $redirect_to );
    501                         exit();
     352                $errors = new WP_Error();
     353
     354                if ( empty( $_POST['user_login'] ) ) {
     355                        $errors->add( 'empty_username', __( '<strong>ERROR</strong>: Enter a username or e-mail address.' ) );
     356                } elseif ( strpos( $_POST['user_login'], '@' ) ) {
     357                        $user_data = get_user_by( 'email', trim( $_POST['user_login'] ) );
     358                        if ( empty( $user_data ) )
     359                                $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: There is no user registered with that email address.' ) );
     360                } else {
     361                        $user_data = get_user_by( 'login', trim( $_POST['user_login'] ) );
     362                        if ( empty( $user_data ) )
     363                                $errors->add( 'invalidcombo', __( '<strong>ERROR</strong>: Invalid username or e-mail.' ) );
    502364                }
     365
     366                /**
     367                 * Fires before errors are returned from a password reset request.
     368                 *
     369                 * @since 2.1.0
     370                 */
     371                do_action( 'lostpassword_post' );
     372
     373                if ( ! $errors->get_error_code() ) {
     374                        /**
     375                         * Filter whether to allow a password to be reset.
     376                         *
     377                         * @since 2.7.0
     378                         *
     379                         * @param bool true           Whether to allow the password to be reset. Default true.
     380                         * @param int  $user_data->ID The ID of the user attempting to reset a password.
     381                         */
     382                        $allow = apply_filters( 'allow_password_reset', true, $user->ID );
     383
     384                        if ( ! $allow ) {
     385                                $errors->add( 'no_password_reset', __( 'Password reset is not allowed for this user' ) );
     386                        } elseif ( is_wp_error( $allow ) ) {
     387                                $errors = $allow;
     388                        } else {
     389                                $errors = retrieve_password( $user_data );
     390                                if ( ! is_wp_error( $errors ) ) {
     391                                        $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : 'wp-login.php?checkemail=confirm';
     392                                        wp_safe_redirect( $redirect_to );
     393                                        exit();
     394                                }
     395                        }
     396                }
    503397        }
    504398
    505399        if ( isset( $_GET['error'] ) ) {
  • wp-includes/user.php

     
    21232123}
    21242124
    21252125/**
     2126 * Genereate a password reset key for a user.
     2127 *
     2128 * @global wpdb         $wpdb      WordPress database abstraction object.
     2129 * @global PasswordHash $wp_hasher Portable PHP password hashing framework.
     2130 *
     2131 * @param WP_User $user User object
     2132 * @return string|bool The password reset key on success, false on failure.
     2133 */
     2134function generate_password_reset_key( $user ) {
     2135        global $wpdb, $wp_hasher;
     2136
     2137        // Generate something random for a password reset key.
     2138        $key = wp_generate_password( 20, false );
     2139
     2140        /**
     2141         * Fires when a password reset key is generated.
     2142         *
     2143         * @since 2.5.0
     2144         *
     2145         * @param string $user_login The username for the user.
     2146         * @param string $key        The generated password reset key.
     2147         */
     2148        do_action( 'retrieve_password_key', $user->user_login, $key );
     2149
     2150        // Now insert the key, hashed, into the DB.
     2151        if ( empty( $wp_hasher ) ) {
     2152                require_once ABSPATH . WPINC . '/class-phpass.php';
     2153                $wp_hasher = new PasswordHash( 8, true );
     2154        }
     2155        $hashed = $wp_hasher->HashPassword( $key );
     2156        $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
     2157
     2158        return $key;
     2159}
     2160
     2161/**
     2162 * Handles sending password retrieval email to user.
     2163 *
     2164 * @param WP_User $user User object
     2165 */
     2166function retrieve_password( $user ) {
     2167
     2168        /**
     2169         * Fires before a new password is retrieved.
     2170         *
     2171         * @since 1.5.0
     2172         * @deprecated 1.5.1 Misspelled. Use 'retrieve_password' hook instead.
     2173         *
     2174         * @param string $user_login The user login name.
     2175         */
     2176        do_action( 'retreive_password', $user->user_login );
     2177
     2178        /**
     2179         * Fires before a new password is retrieved.
     2180         *
     2181         * @since 1.5.1
     2182         *
     2183         * @param string $user_login The user login name.
     2184         */
     2185        do_action( 'retrieve_password', $user->user_login );
     2186
     2187        // Generate something random for a password reset key.
     2188        $key = generate_password_reset_key( $user );
     2189
     2190        // Send the reset link to the user.
     2191        wp_lost_password_request_notification( $user, $key );
     2192}
     2193
     2194/**
    21262195 * Retrieves a user row based on password reset key and login
    21272196 *
    21282197 * A key is considered 'expired' if it exactly matches the value of the
  • wp-includes/pluggable.php

     
    16001600}
    16011601endif;
    16021602
     1603if ( ! function_exists( 'wp_lost_password_request_notification' ) ) :
     1604/**
     1605 * Email password reset link to a user who has requested it.
     1606 *
     1607 * @param WP_User $user User object
     1608 * @param string  $key  The password reset key in plaintext.
     1609 */
     1610function wp_lost_password_request_notification( $user, $key ) {
     1611
     1612        $message = __( 'Someone requested that the password be reset for the following account:' ) . "\r\n\r\n";
     1613        $message .= network_home_url( '/' ) . "\r\n\r\n";
     1614        $message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
     1615        $message .= __( 'If this was a mistake, just ignore this email and nothing will happen.' ) . "\r\n\r\n";
     1616        $message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
     1617        $message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . ">\r\n";
     1618
     1619        if ( is_multisite() )
     1620                $blogname = $GLOBALS['current_site']->site_name;
     1621        else
     1622                /*
     1623                 * The blogname option is escaped with esc_html on the way into the database
     1624                 * in sanitize_option we want to reverse this for the plain text arena of emails.
     1625                 */
     1626                $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
     1627
     1628        $title = sprintf( __('[%s] Password Reset'), $blogname );
     1629
     1630        /**
     1631         * Filter the subject of the password reset email.
     1632         *
     1633         * @since 2.8.0
     1634         *
     1635         * @param string $title Default email title.
     1636         */
     1637        $title = apply_filters( 'retrieve_password_title', $title );
     1638
     1639        /**
     1640         * Filter the message body of the password reset mail.
     1641         *
     1642         * @since 2.8.0
     1643         * @since 4.1.0 Added `$user_login` and `$user_data` parameters.
     1644         *
     1645         * @param string  $message    Default mail message.
     1646         * @param string  $key        The activation key.
     1647         * @param string  $user_login The username for the user.
     1648         * @param WP_User $user_data  WP_User object.
     1649         */
     1650        $message = apply_filters( 'retrieve_password_message', $message, $user->user_activation_key, $user->user_login, $user );
     1651
     1652        if ( $message && ! wp_mail( $user->user_email, wp_specialchars_decode( $title ), $message ) )
     1653                wp_die( __( 'The e-mail could not be sent.' ) . "<br />\n" . __( 'Possible reason: your host may have disabled the mail() function.' ) );
     1654}
     1655endif;
     1656
    16031657if ( !function_exists('wp_password_change_notification') ) :
    16041658/**
    16051659 * Notify the blog admin of a user changing password, normally via email.