Function
Handle the 'resetpass' action.
tml_password_reset_handler( )
Source
function tml_password_reset_handler() {
// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- mirrors wp-login.php's own resetpass-form processing, which is secured by the rp_key/rp_login cookie/hash rather than a nonce.
list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) );
$rp_cookie = 'wp-resetpass-' . COOKIEHASH;
if ( isset( $_GET['key'] ) && isset( $_GET['login'] ) ) {
$value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
wp_safe_redirect( remove_query_arg( array( 'key', 'login' ) ) );
exit;
}
if ( isset( $_COOKIE[ $rp_cookie ] ) && 0 < strpos( $_COOKIE[ $rp_cookie ], ':' ) ) {
list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 );
$user = check_password_reset_key( $rp_key, $rp_login );
if ( isset( $_POST['pass1'] ) && ! hash_equals( $rp_key, $_POST['rp_key'] ) ) {
$user = false;
}
} else {
$user = false;
}
if ( ! $user || is_wp_error( $user ) ) {
setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
// phpcs:disable WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- matches wp-login.php's own use of plain wp_redirect() here; target is always a hardcoded site_url() string, never raw user input.
if ( $user && $user->get_error_code() === 'expired_key' ) {
wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=expiredkey' ) );
} else {
wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=invalidkey' ) );
}
// phpcs:enable WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
exit;
}
$errors = new WP_Error();
// phpcs:disable WordPress.WP.I18n.MissingArgDomain -- these messages intentionally reuse WP core's translated wp-login.php strings verbatim, not TML-specific strings.
// Check if password is one or all empty spaces.
if ( ! empty( $_POST['pass1'] ) ) {
$_POST['pass1'] = trim( $_POST['pass1'] );
if ( empty( $_POST['pass1'] ) ) {
$errors->add( 'password_reset_empty_space', __( 'The password cannot be a space or all spaces.' ) );
}
}
// Check if password fields do not match.
if ( ! empty( $_POST['pass1'] ) && trim( $_POST['pass2'] ) !== $_POST['pass1'] ) {
$errors->add( 'password_reset_mismatch', __( '<strong>Error:</strong> The passwords do not match.' ) );
}
// phpcs:enable WordPress.WP.I18n.MissingArgDomain
/** This action is documented in wp-login.php */
do_action( 'validate_password_reset', $errors, $user );
if ( ( ! $errors->has_errors() ) && isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) {
reset_password( $user, $_POST['pass1'] );
setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
// phpcs:disable WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- target is always a hardcoded site_url() string, never raw user input.
wp_redirect( site_url( 'wp-login.php?resetpass=complete' ) );
// phpcs:enable WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
exit;
} else {
tml_set_errors( $errors );
}
// phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
}
Uses
Changelog
| Version | Description |
|---|---|
| 7.0 | Introduced. |