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( '← 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( '← 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 |
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 |
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; |
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’s new.' ), 'message' ); |
1265 $errors->add( 'updated', __( '<strong>You have successfully updated WordPress!</strong> Please log back in to see what’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. |