wp/wp-login.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
    40  */
    40  */
    41 function login_header( $title = 'Log In', $message = '', $wp_error = null ) {
    41 function login_header( $title = 'Log In', $message = '', $wp_error = null ) {
    42 	global $error, $interim_login, $action;
    42 	global $error, $interim_login, $action;
    43 
    43 
    44 	// Don't index any of these forms.
    44 	// Don't index any of these forms.
    45 	add_action( 'login_head', 'wp_sensitive_page_meta' );
    45 	add_filter( 'wp_robots', 'wp_robots_sensitive_page' );
       
    46 	add_action( 'login_head', 'wp_strict_cross_origin_referrer' );
    46 
    47 
    47 	add_action( 'login_head', 'wp_login_viewport_meta' );
    48 	add_action( 'login_head', 'wp_login_viewport_meta' );
    48 
    49 
    49 	if ( ! is_wp_error( $wp_error ) ) {
    50 	if ( ! is_wp_error( $wp_error ) ) {
    50 		$wp_error = new WP_Error();
    51 		$wp_error = new WP_Error();
   279 	global $interim_login;
   280 	global $interim_login;
   280 
   281 
   281 	// Don't allow interim logins to navigate away from the page.
   282 	// Don't allow interim logins to navigate away from the page.
   282 	if ( ! $interim_login ) {
   283 	if ( ! $interim_login ) {
   283 		?>
   284 		?>
   284 		<p id="backtoblog"><a href="<?php echo esc_url( home_url( '/' ) ); ?>">
   285 		<p id="backtoblog">
   285 		<?php
   286 			<?php
   286 
   287 			$html_link = sprintf(
   287 		/* translators: %s: Site title. */
   288 				'<a href="%s">%s</a>',
   288 		printf( _x( '&larr; Back to %s', 'site' ), get_bloginfo( 'title', 'display' ) );
   289 				esc_url( home_url( '/' ) ),
   289 
   290 				sprintf(
   290 		?>
   291 					/* translators: %s: Site title. */
   291 		</a></p>
   292 					_x( '&larr; Go to %s', 'site' ),
       
   293 					get_bloginfo( 'title', 'display' )
       
   294 				)
       
   295 			);
       
   296 			/**
       
   297 			 * Filter the "Go to site" link displayed in the login page footer.
       
   298 			 *
       
   299 			 * @since 5.7.0
       
   300 			 *
       
   301 			 * @param string $link HTML link to the home URL of the current site.
       
   302 			 */
       
   303 			echo apply_filters( 'login_site_html_link', $html_link );
       
   304 			?>
       
   305 		</p>
   292 		<?php
   306 		<?php
   293 
   307 
   294 		the_privacy_policy_link( '<div class="privacy-policy-page-link">', '</div>' );
   308 		the_privacy_policy_link( '<div class="privacy-policy-page-link">', '</div>' );
   295 	}
   309 	}
   296 
   310 
   301 
   315 
   302 	if ( ! empty( $input_id ) ) {
   316 	if ( ! empty( $input_id ) ) {
   303 		?>
   317 		?>
   304 		<script type="text/javascript">
   318 		<script type="text/javascript">
   305 		try{document.getElementById('<?php echo $input_id; ?>').focus();}catch(e){}
   319 		try{document.getElementById('<?php echo $input_id; ?>').focus();}catch(e){}
   306 		if(typeof wpOnload=='function')wpOnload();
   320 		if(typeof wpOnload==='function')wpOnload();
   307 		</script>
   321 		</script>
   308 		<?php
   322 		<?php
   309 	}
   323 	}
   310 
   324 
   311 	/**
   325 	/**
   321 	</html>
   335 	</html>
   322 	<?php
   336 	<?php
   323 }
   337 }
   324 
   338 
   325 /**
   339 /**
   326  * Outputs the Javascript to handle the form shaking.
   340  * Outputs the JavaScript to handle the form shaking on the login page.
   327  *
   341  *
   328  * @since 3.0.0
   342  * @since 3.0.0
   329  */
   343  */
   330 function wp_shake_js() {
   344 function wp_shake_js() {
   331 	?>
   345 	?>
   334 	</script>
   348 	</script>
   335 	<?php
   349 	<?php
   336 }
   350 }
   337 
   351 
   338 /**
   352 /**
   339  * Outputs the viewport meta tag.
   353  * Outputs the viewport meta tag for the login page.
   340  *
   354  *
   341  * @since 3.7.0
   355  * @since 3.7.0
   342  */
   356  */
   343 function wp_login_viewport_meta() {
   357 function wp_login_viewport_meta() {
   344 	?>
   358 	?>
   345 	<meta name="viewport" content="width=device-width" />
   359 	<meta name="viewport" content="width=device-width" />
   346 	<?php
   360 	<?php
   347 }
       
   348 
       
   349 /**
       
   350  * Handles sending password retrieval email to user.
       
   351  *
       
   352  * @since 2.5.0
       
   353  *
       
   354  * @return bool|WP_Error True: when finish. WP_Error on error
       
   355  */
       
   356 function retrieve_password() {
       
   357 	$errors    = new WP_Error();
       
   358 	$user_data = false;
       
   359 
       
   360 	if ( empty( $_POST['user_login'] ) || ! is_string( $_POST['user_login'] ) ) {
       
   361 		$errors->add( 'empty_username', __( '<strong>Error</strong>: Please enter a username or email address.' ) );
       
   362 	} elseif ( strpos( $_POST['user_login'], '@' ) ) {
       
   363 		$user_data = get_user_by( 'email', trim( wp_unslash( $_POST['user_login'] ) ) );
       
   364 		if ( empty( $user_data ) ) {
       
   365 			$errors->add( 'invalid_email', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
       
   366 		}
       
   367 	} else {
       
   368 		$login     = trim( wp_unslash( $_POST['user_login'] ) );
       
   369 		$user_data = get_user_by( 'login', $login );
       
   370 	}
       
   371 
       
   372 	/**
       
   373 	 * Fires before errors are returned from a password reset request.
       
   374 	 *
       
   375 	 * @since 2.1.0
       
   376 	 * @since 4.4.0 Added the `$errors` parameter.
       
   377 	 * @since 5.4.0 Added the `$user_data` parameter.
       
   378 	 *
       
   379 	 * @param WP_Error      $errors    A WP_Error object containing any errors generated
       
   380 	 *                                 by using invalid credentials.
       
   381 	 * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
       
   382 	 */
       
   383 	do_action( 'lostpassword_post', $errors, $user_data );
       
   384 
       
   385 	/**
       
   386 	 * Filters the errors encountered on a password reset request.
       
   387 	 *
       
   388 	 * The filtered WP_Error object may, for example, contain errors for an invalid
       
   389 	 * username or email address. A WP_Error object should always be returned,
       
   390 	 * but may or may not contain errors.
       
   391 	 *
       
   392 	 * If any errors are present in $errors, this will abort the password reset request.
       
   393 	 *
       
   394 	 * @since 5.5.0
       
   395 	 *
       
   396 	 * @param WP_Error      $errors    A WP_Error object containing any errors generated
       
   397 	 *                                 by using invalid credentials.
       
   398 	 * @param WP_User|false $user_data WP_User object if found, false if the user does not exist.
       
   399 	 */
       
   400 	$errors = apply_filters( 'lostpassword_errors', $errors, $user_data );
       
   401 
       
   402 	if ( $errors->has_errors() ) {
       
   403 		return $errors;
       
   404 	}
       
   405 
       
   406 	if ( ! $user_data ) {
       
   407 		$errors->add( 'invalidcombo', __( '<strong>Error</strong>: There is no account with that username or email address.' ) );
       
   408 		return $errors;
       
   409 	}
       
   410 
       
   411 	// Redefining user_login ensures we return the right case in the email.
       
   412 	$user_login = $user_data->user_login;
       
   413 	$user_email = $user_data->user_email;
       
   414 	$key        = get_password_reset_key( $user_data );
       
   415 
       
   416 	if ( is_wp_error( $key ) ) {
       
   417 		return $key;
       
   418 	}
       
   419 
       
   420 	if ( is_multisite() ) {
       
   421 		$site_name = get_network()->site_name;
       
   422 	} else {
       
   423 		/*
       
   424 		 * The blogname option is escaped with esc_html on the way into the database
       
   425 		 * in sanitize_option we want to reverse this for the plain text arena of emails.
       
   426 		 */
       
   427 		$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
       
   428 	}
       
   429 
       
   430 	$message = __( 'Someone has requested a password reset for the following account:' ) . "\r\n\r\n";
       
   431 	/* translators: %s: Site name. */
       
   432 	$message .= sprintf( __( 'Site Name: %s' ), $site_name ) . "\r\n\r\n";
       
   433 	/* translators: %s: User login. */
       
   434 	$message .= sprintf( __( 'Username: %s' ), $user_login ) . "\r\n\r\n";
       
   435 	$message .= __( 'If this was a mistake, just ignore this email and nothing will happen.' ) . "\r\n\r\n";
       
   436 	$message .= __( 'To reset your password, visit the following address:' ) . "\r\n\r\n";
       
   437 	$message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n";
       
   438 
       
   439 	/* translators: Password reset notification email subject. %s: Site title. */
       
   440 	$title = sprintf( __( '[%s] Password Reset' ), $site_name );
       
   441 
       
   442 	/**
       
   443 	 * Filters the subject of the password reset email.
       
   444 	 *
       
   445 	 * @since 2.8.0
       
   446 	 * @since 4.4.0 Added the `$user_login` and `$user_data` parameters.
       
   447 	 *
       
   448 	 * @param string  $title      Default email title.
       
   449 	 * @param string  $user_login The username for the user.
       
   450 	 * @param WP_User $user_data  WP_User object.
       
   451 	 */
       
   452 	$title = apply_filters( 'retrieve_password_title', $title, $user_login, $user_data );
       
   453 
       
   454 	/**
       
   455 	 * Filters the message body of the password reset mail.
       
   456 	 *
       
   457 	 * If the filtered message is empty, the password reset email will not be sent.
       
   458 	 *
       
   459 	 * @since 2.8.0
       
   460 	 * @since 4.1.0 Added `$user_login` and `$user_data` parameters.
       
   461 	 *
       
   462 	 * @param string  $message    Default mail message.
       
   463 	 * @param string  $key        The activation key.
       
   464 	 * @param string  $user_login The username for the user.
       
   465 	 * @param WP_User $user_data  WP_User object.
       
   466 	 */
       
   467 	$message = apply_filters( 'retrieve_password_message', $message, $key, $user_login, $user_data );
       
   468 
       
   469 	if ( $message && ! wp_mail( $user_email, wp_specialchars_decode( $title ), $message ) ) {
       
   470 		$errors->add(
       
   471 			'retrieve_password_email_failure',
       
   472 			sprintf(
       
   473 				/* translators: %s: Documentation URL. */
       
   474 				__( '<strong>Error</strong>: The email could not be sent. Your site may not be correctly configured to send emails. <a href="%s">Get support for resetting your password</a>.' ),
       
   475 				esc_url( __( 'https://wordpress.org/support/article/resetting-your-password/' ) )
       
   476 			)
       
   477 		);
       
   478 		return $errors;
       
   479 	}
       
   480 
       
   481 	return true;
       
   482 }
   361 }
   483 
   362 
   484 //
   363 //
   485 // Main.
   364 // Main.
   486 //
   365 //
   549 
   428 
   550 /**
   429 /**
   551  * Fires before a specified login form action.
   430  * Fires before a specified login form action.
   552  *
   431  *
   553  * The dynamic portion of the hook name, `$action`, refers to the action
   432  * The dynamic portion of the hook name, `$action`, refers to the action
   554  * that brought the visitor to the login form. Actions include 'postpass',
   433  * that brought the visitor to the login form.
   555  * 'logout', 'lostpassword', etc.
   434  *
       
   435  * Possible hook names include:
       
   436  *
       
   437  *  - 'login_form_checkemail'
       
   438  *  - 'login_form_confirm_admin_email'
       
   439  *  - 'login_form_confirmaction'
       
   440  *  - 'login_form_entered_recovery_mode'
       
   441  *  - 'login_form_login'
       
   442  *  - 'login_form_logout'
       
   443  *  - 'login_form_lostpassword'
       
   444  *  - 'login_form_postpass'
       
   445  *  - 'login_form_register'
       
   446  *  - 'login_form_resetpass'
       
   447  *  - 'login_form_retrievepassword'
       
   448  *  - 'login_form_rp'
   556  *
   449  *
   557  * @since 2.8.0
   450  * @since 2.8.0
   558  */
   451  */
   559 do_action( "login_form_{$action}" );
   452 do_action( "login_form_{$action}" );
   560 
   453 
   683 				<?php
   576 				<?php
   684 
   577 
   685 				/* translators: URL to the WordPress help section about admin email. */
   578 				/* translators: URL to the WordPress help section about admin email. */
   686 				$admin_email_help_url = __( 'https://wordpress.org/support/article/settings-general-screen/#email-address' );
   579 				$admin_email_help_url = __( 'https://wordpress.org/support/article/settings-general-screen/#email-address' );
   687 
   580 
   688 				/* translators: accessibility text */
   581 				/* translators: Accessibility text. */
   689 				$accessibility_text = sprintf( '<span class="screen-reader-text"> %s</span>', __( '(opens in a new tab)' ) );
   582 				$accessibility_text = sprintf( '<span class="screen-reader-text"> %s</span>', __( '(opens in a new tab)' ) );
   690 
   583 
   691 				printf(
   584 				printf(
   692 					'<a href="%s" rel="noopener noreferrer" target="_blank">%s%s</a>',
   585 					'<a href="%s" rel="noopener" target="_blank">%s%s</a>',
   693 					esc_url( $admin_email_help_url ),
   586 					esc_url( $admin_email_help_url ),
   694 					__( 'Why is this important?' ),
   587 					__( 'Why is this important?' ),
   695 					$accessibility_text
   588 					$accessibility_text
   696 				);
   589 				);
   697 
   590 
   829 			}
   722 			}
   830 		}
   723 		}
   831 
   724 
   832 		if ( isset( $_GET['error'] ) ) {
   725 		if ( isset( $_GET['error'] ) ) {
   833 			if ( 'invalidkey' === $_GET['error'] ) {
   726 			if ( 'invalidkey' === $_GET['error'] ) {
   834 				$errors->add( 'invalidkey', __( 'Your password reset link appears to be invalid. Please request a new link below.' ) );
   727 				$errors->add( 'invalidkey', __( '<strong>Error</strong>: Your password reset link appears to be invalid. Please request a new link below.' ) );
   835 			} elseif ( 'expiredkey' === $_GET['error'] ) {
   728 			} elseif ( 'expiredkey' === $_GET['error'] ) {
   836 				$errors->add( 'expiredkey', __( 'Your password reset link has expired. Please request a new link below.' ) );
   729 				$errors->add( 'expiredkey', __( '<strong>Error</strong>: Your password reset link has expired. Please request a new link below.' ) );
   837 			}
   730 			}
   838 		}
   731 		}
   839 
   732 
   840 		$lostpassword_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
   733 		$lostpassword_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
   841 		/**
   734 		/**
   912 	case 'resetpass':
   805 	case 'resetpass':
   913 	case 'rp':
   806 	case 'rp':
   914 		list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) );
   807 		list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) );
   915 		$rp_cookie       = 'wp-resetpass-' . COOKIEHASH;
   808 		$rp_cookie       = 'wp-resetpass-' . COOKIEHASH;
   916 
   809 
   917 		if ( isset( $_GET['key'] ) ) {
   810 		if ( isset( $_GET['key'] ) && isset( $_GET['login'] ) ) {
   918 			$value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
   811 			$value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
   919 			setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
   812 			setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
   920 
   813 
   921 			wp_safe_redirect( remove_query_arg( array( 'key', 'login' ) ) );
   814 			wp_safe_redirect( remove_query_arg( array( 'key', 'login' ) ) );
   922 			exit;
   815 			exit;
   947 		}
   840 		}
   948 
   841 
   949 		$errors = new WP_Error();
   842 		$errors = new WP_Error();
   950 
   843 
   951 		if ( isset( $_POST['pass1'] ) && $_POST['pass1'] !== $_POST['pass2'] ) {
   844 		if ( isset( $_POST['pass1'] ) && $_POST['pass1'] !== $_POST['pass2'] ) {
   952 			$errors->add( 'password_reset_mismatch', __( 'The passwords do not match.' ) );
   845 			$errors->add( 'password_reset_mismatch', __( '<strong>Error</strong>: The passwords do not match.' ) );
   953 		}
   846 		}
   954 
   847 
   955 		/**
   848 		/**
   956 		 * Fires before the password reset procedure is validated.
   849 		 * Fires before the password reset procedure is validated.
   957 		 *
   850 		 *
   971 		}
   864 		}
   972 
   865 
   973 		wp_enqueue_script( 'utils' );
   866 		wp_enqueue_script( 'utils' );
   974 		wp_enqueue_script( 'user-profile' );
   867 		wp_enqueue_script( 'user-profile' );
   975 
   868 
   976 		login_header( __( 'Reset Password' ), '<p class="message reset-pass">' . __( 'Enter your new password below.' ) . '</p>', $errors );
   869 		login_header( __( 'Reset Password' ), '<p class="message reset-pass">' . __( 'Enter your new password below or generate one.' ) . '</p>', $errors );
   977 
   870 
   978 		?>
   871 		?>
   979 		<form name="resetpassform" id="resetpassform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=resetpass', 'login_post' ) ); ?>" method="post" autocomplete="off">
   872 		<form name="resetpassform" id="resetpassform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=resetpass', 'login_post' ) ); ?>" method="post" autocomplete="off">
   980 			<input type="hidden" id="user_login" value="<?php echo esc_attr( $rp_login ); ?>" autocomplete="off" />
   873 			<input type="hidden" id="user_login" value="<?php echo esc_attr( $rp_login ); ?>" autocomplete="off" />
   981 
   874 
  1017 			 */
   910 			 */
  1018 			do_action( 'resetpass_form', $user );
   911 			do_action( 'resetpass_form', $user );
  1019 
   912 
  1020 			?>
   913 			?>
  1021 			<input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" />
   914 			<input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" />
  1022 			<p class="submit">
   915 			<p class="submit reset-pass-submit">
  1023 				<input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Reset Password' ); ?>" />
   916 				<button type="button" class="button wp-generate-pw hide-if-no-js" aria-expanded="true"><?php _e( 'Generate Password' ); ?></button>
       
   917 				<input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Save Password' ); ?>" />
  1024 			</p>
   918 			</p>
  1025 		</form>
   919 		</form>
  1026 
   920 
  1027 		<p id="nav">
   921 		<p id="nav">
  1028 			<a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
   922 			<a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
  1364 		} else {
  1258 		} else {
  1365 			// Some parts of this script use the main login form to display a message.
  1259 			// Some parts of this script use the main login form to display a message.
  1366 			if ( isset( $_GET['loggedout'] ) && $_GET['loggedout'] ) {
  1260 			if ( isset( $_GET['loggedout'] ) && $_GET['loggedout'] ) {
  1367 				$errors->add( 'loggedout', __( 'You are now logged out.' ), 'message' );
  1261 				$errors->add( 'loggedout', __( 'You are now logged out.' ), 'message' );
  1368 			} elseif ( isset( $_GET['registration'] ) && 'disabled' === $_GET['registration'] ) {
  1262 			} elseif ( isset( $_GET['registration'] ) && 'disabled' === $_GET['registration'] ) {
  1369 				$errors->add( 'registerdisabled', __( 'User registration is currently not allowed.' ) );
  1263 				$errors->add( 'registerdisabled', __( '<strong>Error</strong>: User registration is currently not allowed.' ) );
  1370 			} elseif ( strpos( $redirect_to, 'about.php?updated' ) ) {
  1264 			} elseif ( strpos( $redirect_to, 'about.php?updated' ) ) {
  1371 				$errors->add( 'updated', __( '<strong>You have successfully updated WordPress!</strong> Please log back in to see what&#8217;s new.' ), 'message' );
  1265 				$errors->add( 'updated', __( '<strong>You have successfully updated WordPress!</strong> Please log back in to see what&#8217;s new.' ), 'message' );
  1372 			} elseif ( WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED === $action ) {
  1266 			} elseif ( WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED === $action ) {
  1373 				$errors->add( 'enter_recovery_mode', __( 'Recovery Mode Initialized. Please log in to continue.' ), 'message' );
  1267 				$errors->add( 'enter_recovery_mode', __( 'Recovery Mode Initialized. Please log in to continue.' ), 'message' );
       
  1268 			} elseif ( isset( $_GET['redirect_to'] ) && false !== strpos( $_GET['redirect_to'], 'wp-admin/authorize-application.php' ) ) {
       
  1269 				$query_component = wp_parse_url( $_GET['redirect_to'], PHP_URL_QUERY );
       
  1270 				parse_str( $query_component, $query );
       
  1271 
       
  1272 				if ( ! empty( $query['app_name'] ) ) {
       
  1273 					/* translators: 1: Website name, 2: Application name. */
       
  1274 					$message = sprintf( 'Please log in to %1$s to authorize %2$s to connect to your account.', get_bloginfo( 'name', 'display' ), '<strong>' . esc_html( $query['app_name'] ) . '</strong>' );
       
  1275 				} else {
       
  1276 					/* translators: %s: Website name. */
       
  1277 					$message = sprintf( 'Please log in to %s to proceed with authorization.', get_bloginfo( 'name', 'display' ) );
       
  1278 				}
       
  1279 
       
  1280 				$errors->add( 'authorize_application', $message, 'message' );
  1374 			}
  1281 			}
  1375 		}
  1282 		}
  1376 
  1283 
  1377 		/**
  1284 		/**
  1378 		 * Filters the login page errors.
  1285 		 * Filters the login page errors.
  1525 				try {
  1432 				try {
  1526 					var i, links = document.getElementsByTagName( 'a' );
  1433 					var i, links = document.getElementsByTagName( 'a' );
  1527 					for ( i in links ) {
  1434 					for ( i in links ) {
  1528 						if ( links[i].href ) {
  1435 						if ( links[i].href ) {
  1529 							links[i].target = '_blank';
  1436 							links[i].target = '_blank';
  1530 							links[i].rel = 'noreferrer noopener';
  1437 							links[i].rel = 'noopener';
  1531 						}
  1438 						}
  1532 					}
  1439 					}
  1533 				} catch( er ) {}
  1440 				} catch( er ) {}
  1534 			}());
  1441 			}());
  1535 			</script>
  1442 			</script>