[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/ -> wp-login.php (source)

   1  <?php
   2  /**
   3   * WordPress User Page
   4   *
   5   * Handles authentication, registering, resetting passwords, forgot password,
   6   * and other user handling.
   7   *
   8   * @package WordPress
   9   */
  10  
  11  /** Make sure that the WordPress bootstrap has run before continuing. */
  12  require  __DIR__ . '/wp-load.php';
  13  
  14  // Redirect to HTTPS login if forced to use SSL.
  15  if ( force_ssl_admin() && ! is_ssl() ) {
  16      if ( str_starts_with( $_SERVER['REQUEST_URI'], 'http' ) ) {
  17          wp_safe_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
  18          exit;
  19      } else {
  20          wp_safe_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
  21          exit;
  22      }
  23  }
  24  
  25  /**
  26   * Outputs the login page header.
  27   *
  28   * @since 2.1.0
  29   *
  30   * @global string      $error         Login error message set by deprecated pluggable wp_login() function
  31   *                                    or plugins replacing it.
  32   * @global bool|string $interim_login Whether interim login modal is being displayed. String 'success'
  33   *                                    upon successful login.
  34   * @global string      $action        The action that brought the visitor to the login page.
  35   *
  36   * @param string   $title    Optional. WordPress login Page title to display in the `<title>` element.
  37   *                           Default 'Log In'.
  38   * @param string   $message  Optional. Message to display in header. Default empty.
  39   * @param WP_Error $wp_error Optional. The error to pass. Default is a WP_Error instance.
  40   */
  41  function login_header( $title = 'Log In', $message = '', $wp_error = null ) {
  42      global $error, $interim_login, $action;
  43  
  44      // Don't index any of these forms.
  45      add_filter( 'wp_robots', 'wp_robots_sensitive_page' );
  46      add_action( 'login_head', 'wp_strict_cross_origin_referrer' );
  47  
  48      add_action( 'login_head', 'wp_login_viewport_meta' );
  49  
  50      if ( ! is_wp_error( $wp_error ) ) {
  51          $wp_error = new WP_Error();
  52      }
  53  
  54      // Shake it!
  55      $shake_error_codes = array( 'empty_password', 'empty_email', 'invalid_email', 'invalidcombo', 'empty_username', 'invalid_username', 'incorrect_password', 'retrieve_password_email_failure' );
  56      /**
  57       * Filters the error codes array for shaking the login form.
  58       *
  59       * @since 3.0.0
  60       *
  61       * @param string[] $shake_error_codes Error codes that shake the login form.
  62       */
  63      $shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );
  64  
  65      if ( $shake_error_codes && $wp_error->has_errors() && in_array( $wp_error->get_error_code(), $shake_error_codes, true ) ) {
  66          add_action( 'login_footer', 'wp_shake_js', 12 );
  67      }
  68  
  69      $login_title = get_bloginfo( 'name', 'display' );
  70  
  71      /* translators: Login screen title. 1: Login screen name, 2: Network or site name. */
  72      $login_title = sprintf( __( '%1$s &lsaquo; %2$s &#8212; WordPress' ), $title, $login_title );
  73  
  74      if ( wp_is_recovery_mode() ) {
  75          /* translators: %s: Login screen title. */
  76          $login_title = sprintf( __( 'Recovery Mode &#8212; %s' ), $login_title );
  77      }
  78  
  79      /**
  80       * Filters the title tag content for login page.
  81       *
  82       * @since 4.9.0
  83       *
  84       * @param string $login_title The page title, with extra context added.
  85       * @param string $title       The original page title.
  86       */
  87      $login_title = apply_filters( 'login_title', $login_title, $title );
  88  
  89      ?><!DOCTYPE html>
  90      <html <?php language_attributes(); ?>>
  91      <head>
  92      <meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php bloginfo( 'charset' ); ?>" />
  93      <title><?php echo $login_title; ?></title>
  94      <?php
  95  
  96      wp_enqueue_style( 'login' );
  97  
  98      /*
  99       * Remove all stored post data on logging out.
 100       * This could be added by add_action('login_head'...) like wp_shake_js(),
 101       * but maybe better if it's not removable by plugins.
 102       */
 103      if ( 'loggedout' === $wp_error->get_error_code() ) {
 104          ob_start();
 105          ?>
 106          <script>if("sessionStorage" in window){try{for(var key in sessionStorage){if(key.indexOf("wp-autosave-")!=-1){sessionStorage.removeItem(key)}}}catch(e){}};</script>
 107          <?php
 108          wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
 109      }
 110  
 111      /**
 112       * Enqueues scripts and styles for the login page.
 113       *
 114       * @since 3.1.0
 115       */
 116      do_action( 'login_enqueue_scripts' );
 117  
 118      /**
 119       * Fires in the login page header after scripts are enqueued.
 120       *
 121       * @since 2.1.0
 122       */
 123      do_action( 'login_head' );
 124  
 125      $login_header_url = __( 'https://wordpress.org/' );
 126  
 127      /**
 128       * Filters link URL of the header logo above login form.
 129       *
 130       * @since 2.1.0
 131       *
 132       * @param string $login_header_url Login header logo URL.
 133       */
 134      $login_header_url = apply_filters( 'login_headerurl', $login_header_url );
 135  
 136      $login_header_title = '';
 137  
 138      /**
 139       * Filters the title attribute of the header logo above login form.
 140       *
 141       * @since 2.1.0
 142       * @deprecated 5.2.0 Use {@see 'login_headertext'} instead.
 143       *
 144       * @param string $login_header_title Login header logo title attribute.
 145       */
 146      $login_header_title = apply_filters_deprecated(
 147          'login_headertitle',
 148          array( $login_header_title ),
 149          '5.2.0',
 150          'login_headertext',
 151          __( 'Usage of the title attribute on the login logo is not recommended for accessibility reasons. Use the link text instead.' )
 152      );
 153  
 154      $login_header_text = empty( $login_header_title ) ? __( 'Powered by WordPress' ) : $login_header_title;
 155  
 156      /**
 157       * Filters the link text of the header logo above the login form.
 158       *
 159       * @since 5.2.0
 160       *
 161       * @param string $login_header_text The login header logo link text.
 162       */
 163      $login_header_text = apply_filters( 'login_headertext', $login_header_text );
 164  
 165      $classes = array( 'login-action-' . $action, 'wp-core-ui' );
 166  
 167      if ( is_rtl() ) {
 168          $classes[] = 'rtl';
 169      }
 170  
 171      if ( $interim_login ) {
 172          $classes[] = 'interim-login';
 173  
 174          ?>
 175          <style type="text/css">html{background-color: transparent;}</style>
 176          <?php
 177  
 178          if ( 'success' === $interim_login ) {
 179              $classes[] = 'interim-login-success';
 180          }
 181      }
 182  
 183      $classes[] = ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_locale() ) ) );
 184  
 185      /**
 186       * Filters the login page body classes.
 187       *
 188       * @since 3.5.0
 189       *
 190       * @param string[] $classes An array of body classes.
 191       * @param string   $action  The action that brought the visitor to the login page.
 192       */
 193      $classes = apply_filters( 'login_body_class', $classes, $action );
 194  
 195      ?>
 196      </head>
 197      <body class="login no-js <?php echo esc_attr( implode( ' ', $classes ) ); ?>">
 198      <?php
 199      wp_print_inline_script_tag( "document.body.className = document.body.className.replace('no-js','js');" );
 200      ?>
 201  
 202      <?php
 203      /**
 204       * Fires in the login page header after the body tag is opened.
 205       *
 206       * @since 4.6.0
 207       */
 208      do_action( 'login_header' );
 209  
 210      ?>
 211      <div id="login">
 212          <h1><a href="<?php echo esc_url( $login_header_url ); ?>"><?php echo $login_header_text; ?></a></h1>
 213      <?php
 214      /**
 215       * Filters the message to display above the login form.
 216       *
 217       * @since 2.1.0
 218       *
 219       * @param string $message Login message text.
 220       */
 221      $message = apply_filters( 'login_message', $message );
 222  
 223      if ( ! empty( $message ) ) {
 224          echo $message . "\n";
 225      }
 226  
 227      // In case a plugin uses $error rather than the $wp_errors object.
 228      if ( ! empty( $error ) ) {
 229          $wp_error->add( 'error', $error );
 230          unset( $error );
 231      }
 232  
 233      if ( $wp_error->has_errors() ) {
 234          $error_list = array();
 235          $messages   = '';
 236  
 237          foreach ( $wp_error->get_error_codes() as $code ) {
 238              $severity = $wp_error->get_error_data( $code );
 239              foreach ( $wp_error->get_error_messages( $code ) as $error_message ) {
 240                  if ( 'message' === $severity ) {
 241                      $messages .= '<p>' . $error_message . '</p>';
 242                  } else {
 243                      $error_list[] = $error_message;
 244                  }
 245              }
 246          }
 247  
 248          if ( ! empty( $error_list ) ) {
 249              $errors = '';
 250  
 251              if ( count( $error_list ) > 1 ) {
 252                  $errors .= '<ul class="login-error-list">';
 253  
 254                  foreach ( $error_list as $item ) {
 255                      $errors .= '<li>' . $item . '</li>';
 256                  }
 257  
 258                  $errors .= '</ul>';
 259              } else {
 260                  $errors .= '<p>' . $error_list[0] . '</p>';
 261              }
 262  
 263              /**
 264               * Filters the error messages displayed above the login form.
 265               *
 266               * @since 2.1.0
 267               *
 268               * @param string $errors Login error messages.
 269               */
 270              $errors = apply_filters( 'login_errors', $errors );
 271  
 272              wp_admin_notice(
 273                  $errors,
 274                  array(
 275                      'type'           => 'error',
 276                      'id'             => 'login_error',
 277                      'paragraph_wrap' => false,
 278                  )
 279              );
 280          }
 281  
 282          if ( ! empty( $messages ) ) {
 283              /**
 284               * Filters instructional messages displayed above the login form.
 285               *
 286               * @since 2.5.0
 287               *
 288               * @param string $messages Login messages.
 289               */
 290              $messages = apply_filters( 'login_messages', $messages );
 291  
 292              wp_admin_notice(
 293                  $messages,
 294                  array(
 295                      'type'               => 'info',
 296                      'id'                 => 'login-message',
 297                      'additional_classes' => array( 'message' ),
 298                      'paragraph_wrap'     => false,
 299                  )
 300              );
 301          }
 302      }
 303  } // End of login_header().
 304  
 305  /**
 306   * Outputs the footer for the login page.
 307   *
 308   * @since 3.1.0
 309   *
 310   * @global bool|string $interim_login Whether interim login modal is being displayed. String 'success'
 311   *                                    upon successful login.
 312   *
 313   * @param string $input_id Which input to auto-focus.
 314   */
 315  function login_footer( $input_id = '' ) {
 316      global $interim_login;
 317  
 318      // Don't allow interim logins to navigate away from the page.
 319      if ( ! $interim_login ) {
 320          ?>
 321          <p id="backtoblog">
 322              <?php
 323              $html_link = sprintf(
 324                  '<a href="%s">%s</a>',
 325                  esc_url( home_url( '/' ) ),
 326                  sprintf(
 327                      /* translators: %s: Site title. */
 328                      _x( '&larr; Go to %s', 'site' ),
 329                      get_bloginfo( 'title', 'display' )
 330                  )
 331              );
 332              /**
 333               * Filters the "Go to site" link displayed in the login page footer.
 334               *
 335               * @since 5.7.0
 336               *
 337               * @param string $link HTML link to the home URL of the current site.
 338               */
 339              echo apply_filters( 'login_site_html_link', $html_link );
 340              ?>
 341          </p>
 342          <?php
 343  
 344          the_privacy_policy_link( '<div class="privacy-policy-page-link">', '</div>' );
 345      }
 346  
 347      ?>
 348      </div><?php // End of <div id="login">. ?>
 349  
 350      <?php
 351      if (
 352          ! $interim_login &&
 353          /**
 354           * Filters whether to display the Language selector on the login screen.
 355           *
 356           * @since 5.9.0
 357           *
 358           * @param bool $display Whether to display the Language selector on the login screen.
 359           */
 360          apply_filters( 'login_display_language_dropdown', true )
 361      ) {
 362          $languages = get_available_languages();
 363  
 364          if ( ! empty( $languages ) ) {
 365              ?>
 366              <div class="language-switcher">
 367                  <form id="language-switcher" method="get">
 368  
 369                      <label for="language-switcher-locales">
 370                          <span class="dashicons dashicons-translation" aria-hidden="true"></span>
 371                          <span class="screen-reader-text">
 372                              <?php
 373                              /* translators: Hidden accessibility text. */
 374                              _e( 'Language' );
 375                              ?>
 376                          </span>
 377                      </label>
 378  
 379                      <?php
 380                      $args = array(
 381                          'id'                          => 'language-switcher-locales',
 382                          'name'                        => 'wp_lang',
 383                          'selected'                    => determine_locale(),
 384                          'show_available_translations' => false,
 385                          'explicit_option_en_us'       => true,
 386                          'languages'                   => $languages,
 387                      );
 388  
 389                      /**
 390                       * Filters default arguments for the Languages select input on the login screen.
 391                       *
 392                       * The arguments get passed to the wp_dropdown_languages() function.
 393                       *
 394                       * @since 5.9.0
 395                       *
 396                       * @param array $args Arguments for the Languages select input on the login screen.
 397                       */
 398                      wp_dropdown_languages( apply_filters( 'login_language_dropdown_args', $args ) );
 399                      ?>
 400  
 401                      <?php if ( $interim_login ) { ?>
 402                          <input type="hidden" name="interim-login" value="1" />
 403                      <?php } ?>
 404  
 405                      <?php if ( isset( $_GET['redirect_to'] ) && '' !== $_GET['redirect_to'] ) { ?>
 406                          <input type="hidden" name="redirect_to" value="<?php echo sanitize_url( $_GET['redirect_to'] ); ?>" />
 407                      <?php } ?>
 408  
 409                      <?php if ( isset( $_GET['action'] ) && '' !== $_GET['action'] ) { ?>
 410                          <input type="hidden" name="action" value="<?php echo esc_attr( $_GET['action'] ); ?>" />
 411                      <?php } ?>
 412  
 413                          <input type="submit" class="button" value="<?php esc_attr_e( 'Change' ); ?>">
 414  
 415                      </form>
 416                  </div>
 417          <?php } ?>
 418      <?php } ?>
 419      <?php
 420  
 421      if ( ! empty( $input_id ) ) {
 422          ob_start();
 423          ?>
 424          <script>
 425          try{document.getElementById('<?php echo $input_id; ?>').focus();}catch(e){}
 426          if(typeof wpOnload==='function')wpOnload();
 427          </script>
 428          <?php
 429          wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
 430      }
 431  
 432      /**
 433       * Fires in the login page footer.
 434       *
 435       * @since 3.1.0
 436       */
 437      do_action( 'login_footer' );
 438  
 439      ?>
 440      </body>
 441      </html>
 442      <?php
 443  }
 444  
 445  /**
 446   * Outputs the JavaScript to handle the form shaking on the login page.
 447   *
 448   * @since 3.0.0
 449   */
 450  function wp_shake_js() {
 451      wp_print_inline_script_tag( "document.querySelector('form').classList.add('shake');" );
 452  }
 453  
 454  /**
 455   * Outputs the viewport meta tag for the login page.
 456   *
 457   * @since 3.7.0
 458   */
 459  function wp_login_viewport_meta() {
 460      ?>
 461      <meta name="viewport" content="width=device-width" />
 462      <?php
 463  }
 464  
 465  /*
 466   * Main part.
 467   *
 468   * Check the request and redirect or display a form based on the current action.
 469   */
 470  
 471  $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : 'login';
 472  $errors = new WP_Error();
 473  
 474  if ( isset( $_GET['key'] ) ) {
 475      $action = 'resetpass';
 476  }
 477  
 478  if ( isset( $_GET['checkemail'] ) ) {
 479      $action = 'checkemail';
 480  }
 481  
 482  $default_actions = array(
 483      'confirm_admin_email',
 484      'postpass',
 485      'logout',
 486      'lostpassword',
 487      'retrievepassword',
 488      'resetpass',
 489      'rp',
 490      'register',
 491      'checkemail',
 492      'confirmaction',
 493      'login',
 494      WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED,
 495  );
 496  
 497  // Validate action so as to default to the login screen.
 498  if ( ! in_array( $action, $default_actions, true ) && false === has_filter( 'login_form_' . $action ) ) {
 499      $action = 'login';
 500  }
 501  
 502  nocache_headers();
 503  
 504  header( 'Content-Type: ' . get_bloginfo( 'html_type' ) . '; charset=' . get_bloginfo( 'charset' ) );
 505  
 506  if ( defined( 'RELOCATE' ) && RELOCATE ) { // Move flag is set.
 507      if ( isset( $_SERVER['PATH_INFO'] ) && ( $_SERVER['PATH_INFO'] !== $_SERVER['PHP_SELF'] ) ) {
 508          $_SERVER['PHP_SELF'] = str_replace( $_SERVER['PATH_INFO'], '', $_SERVER['PHP_SELF'] );
 509      }
 510  
 511      $url = dirname( set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'] ) );
 512  
 513      if ( get_option( 'siteurl' ) !== $url ) {
 514          update_option( 'siteurl', $url );
 515      }
 516  }
 517  
 518  // Set a cookie now to see if they are supported by the browser.
 519  $secure = ( 'https' === parse_url( wp_login_url(), PHP_URL_SCHEME ) );
 520  setcookie( TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN, $secure );
 521  
 522  if ( SITECOOKIEPATH !== COOKIEPATH ) {
 523      setcookie( TEST_COOKIE, 'WP Cookie check', 0, SITECOOKIEPATH, COOKIE_DOMAIN, $secure );
 524  }
 525  
 526  if ( isset( $_GET['wp_lang'] ) ) {
 527      setcookie( 'wp_lang', sanitize_text_field( $_GET['wp_lang'] ), 0, COOKIEPATH, COOKIE_DOMAIN, $secure );
 528  }
 529  
 530  /**
 531   * Fires when the login form is initialized.
 532   *
 533   * @since 3.2.0
 534   */
 535  do_action( 'login_init' );
 536  
 537  /**
 538   * Fires before a specified login form action.
 539   *
 540   * The dynamic portion of the hook name, `$action`, refers to the action
 541   * that brought the visitor to the login form.
 542   *
 543   * Possible hook names include:
 544   *
 545   *  - `login_form_checkemail`
 546   *  - `login_form_confirm_admin_email`
 547   *  - `login_form_confirmaction`
 548   *  - `login_form_entered_recovery_mode`
 549   *  - `login_form_login`
 550   *  - `login_form_logout`
 551   *  - `login_form_lostpassword`
 552   *  - `login_form_postpass`
 553   *  - `login_form_register`
 554   *  - `login_form_resetpass`
 555   *  - `login_form_retrievepassword`
 556   *  - `login_form_rp`
 557   *
 558   * @since 2.8.0
 559   */
 560  do_action( "login_form_{$action}" );
 561  
 562  $http_post     = ( 'POST' === $_SERVER['REQUEST_METHOD'] );
 563  $interim_login = isset( $_REQUEST['interim-login'] );
 564  
 565  /**
 566   * Filters the separator used between login form navigation links.
 567   *
 568   * @since 4.9.0
 569   *
 570   * @param string $login_link_separator The separator used between login form navigation links.
 571   */
 572  $login_link_separator = apply_filters( 'login_link_separator', ' | ' );
 573  
 574  switch ( $action ) {
 575  
 576      case 'confirm_admin_email':
 577          /*
 578           * Note that `is_user_logged_in()` will return false immediately after logging in
 579           * as the current user is not set, see wp-includes/pluggable.php.
 580           * However this action runs on a redirect after logging in.
 581           */
 582          if ( ! is_user_logged_in() ) {
 583              wp_safe_redirect( wp_login_url() );
 584              exit;
 585          }
 586  
 587          if ( ! empty( $_REQUEST['redirect_to'] ) ) {
 588              $redirect_to = $_REQUEST['redirect_to'];
 589          } else {
 590              $redirect_to = admin_url();
 591          }
 592  
 593          if ( current_user_can( 'manage_options' ) ) {
 594              $admin_email = get_option( 'admin_email' );
 595          } else {
 596              wp_safe_redirect( $redirect_to );
 597              exit;
 598          }
 599  
 600          /**
 601           * Filters the interval for dismissing the admin email confirmation screen.
 602           *
 603           * If `0` (zero) is returned, the "Remind me later" link will not be displayed.
 604           *
 605           * @since 5.3.1
 606           *
 607           * @param int $interval Interval time (in seconds). Default is 3 days.
 608           */
 609          $remind_interval = (int) apply_filters( 'admin_email_remind_interval', 3 * DAY_IN_SECONDS );
 610  
 611          if ( ! empty( $_GET['remind_me_later'] ) ) {
 612              if ( ! wp_verify_nonce( $_GET['remind_me_later'], 'remind_me_later_nonce' ) ) {
 613                  wp_safe_redirect( wp_login_url() );
 614                  exit;
 615              }
 616  
 617              if ( $remind_interval > 0 ) {
 618                  update_option( 'admin_email_lifespan', time() + $remind_interval );
 619              }
 620  
 621              $redirect_to = add_query_arg( 'admin_email_remind_later', 1, $redirect_to );
 622              wp_safe_redirect( $redirect_to );
 623              exit;
 624          }
 625  
 626          if ( ! empty( $_POST['correct-admin-email'] ) ) {
 627              if ( ! check_admin_referer( 'confirm_admin_email', 'confirm_admin_email_nonce' ) ) {
 628                  wp_safe_redirect( wp_login_url() );
 629                  exit;
 630              }
 631  
 632              /**
 633               * Filters the interval for redirecting the user to the admin email confirmation screen.
 634               *
 635               * If `0` (zero) is returned, the user will not be redirected.
 636               *
 637               * @since 5.3.0
 638               *
 639               * @param int $interval Interval time (in seconds). Default is 6 months.
 640               */
 641              $admin_email_check_interval = (int) apply_filters( 'admin_email_check_interval', 6 * MONTH_IN_SECONDS );
 642  
 643              if ( $admin_email_check_interval > 0 ) {
 644                  update_option( 'admin_email_lifespan', time() + $admin_email_check_interval );
 645              }
 646  
 647              wp_safe_redirect( $redirect_to );
 648              exit;
 649          }
 650  
 651          login_header( __( 'Confirm your administration email' ), '', $errors );
 652  
 653          /**
 654           * Fires before the admin email confirm form.
 655           *
 656           * @since 5.3.0
 657           *
 658           * @param WP_Error $errors A `WP_Error` object containing any errors generated by using invalid
 659           *                         credentials. Note that the error object may not contain any errors.
 660           */
 661          do_action( 'admin_email_confirm', $errors );
 662  
 663          ?>
 664  
 665          <form class="admin-email-confirm-form" name="admin-email-confirm-form" action="<?php echo esc_url( site_url( 'wp-login.php?action=confirm_admin_email', 'login_post' ) ); ?>" method="post">
 666              <?php
 667              /**
 668               * Fires inside the admin-email-confirm-form form tags, before the hidden fields.
 669               *
 670               * @since 5.3.0
 671               */
 672              do_action( 'admin_email_confirm_form' );
 673  
 674              wp_nonce_field( 'confirm_admin_email', 'confirm_admin_email_nonce' );
 675  
 676              ?>
 677              <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
 678  
 679              <h1 class="admin-email__heading">
 680                  <?php _e( 'Administration email verification' ); ?>
 681              </h1>
 682              <p class="admin-email__details">
 683                  <?php _e( 'Please verify that the <strong>administration email</strong> for this website is still correct.' ); ?>
 684                  <?php
 685  
 686                  /* translators: URL to the WordPress help section about admin email. */
 687                  $admin_email_help_url = __( 'https://wordpress.org/documentation/article/settings-general-screen/#email-address' );
 688  
 689                  $accessibility_text = sprintf(
 690                      '<span class="screen-reader-text"> %s</span>',
 691                      /* translators: Hidden accessibility text. */
 692                      __( '(opens in a new tab)' )
 693                  );
 694  
 695                  printf(
 696                      '<a href="%s" rel="noopener" target="_blank">%s%s</a>',
 697                      esc_url( $admin_email_help_url ),
 698                      __( 'Why is this important?' ),
 699                      $accessibility_text
 700                  );
 701  
 702                  ?>
 703              </p>
 704              <p class="admin-email__details">
 705                  <?php
 706  
 707                  printf(
 708                      /* translators: %s: Admin email address. */
 709                      __( 'Current administration email: %s' ),
 710                      '<strong>' . esc_html( $admin_email ) . '</strong>'
 711                  );
 712  
 713                  ?>
 714              </p>
 715              <p class="admin-email__details">
 716                  <?php _e( 'This email may be different from your personal email address.' ); ?>
 717              </p>
 718  
 719              <div class="admin-email__actions">
 720                  <div class="admin-email__actions-primary">
 721                      <?php
 722  
 723                      $change_link = admin_url( 'options-general.php' );
 724                      $change_link = add_query_arg( 'highlight', 'confirm_admin_email', $change_link );
 725  
 726                      ?>
 727                      <a class="button button-large" href="<?php echo esc_url( $change_link ); ?>"><?php _e( 'Update' ); ?></a>
 728                      <input type="submit" name="correct-admin-email" id="correct-admin-email" class="button button-primary button-large" value="<?php esc_attr_e( 'The email is correct' ); ?>" />
 729                  </div>
 730                  <?php if ( $remind_interval > 0 ) : ?>
 731                      <div class="admin-email__actions-secondary">
 732                          <?php
 733  
 734                          $remind_me_link = wp_login_url( $redirect_to );
 735                          $remind_me_link = add_query_arg(
 736                              array(
 737                                  'action'          => 'confirm_admin_email',
 738                                  'remind_me_later' => wp_create_nonce( 'remind_me_later_nonce' ),
 739                              ),
 740                              $remind_me_link
 741                          );
 742  
 743                          ?>
 744                          <a href="<?php echo esc_url( $remind_me_link ); ?>"><?php _e( 'Remind me later' ); ?></a>
 745                      </div>
 746                  <?php endif; ?>
 747              </div>
 748          </form>
 749  
 750          <?php
 751  
 752          login_footer();
 753          break;
 754  
 755      case 'postpass':
 756          if ( ! array_key_exists( 'post_password', $_POST ) ) {
 757              wp_safe_redirect( wp_get_referer() );
 758              exit;
 759          }
 760  
 761          require_once  ABSPATH . WPINC . '/class-phpass.php';
 762          $hasher = new PasswordHash( 8, true );
 763  
 764          /**
 765           * Filters the life span of the post password cookie.
 766           *
 767           * By default, the cookie expires 10 days from creation. To turn this
 768           * into a session cookie, return 0.
 769           *
 770           * @since 3.7.0
 771           *
 772           * @param int $expires The expiry time, as passed to setcookie().
 773           */
 774          $expire  = apply_filters( 'post_password_expires', time() + 10 * DAY_IN_SECONDS );
 775          $referer = wp_get_referer();
 776  
 777          if ( $referer ) {
 778              $secure = ( 'https' === parse_url( $referer, PHP_URL_SCHEME ) );
 779          } else {
 780              $secure = false;
 781          }
 782  
 783          setcookie( 'wp-postpass_' . COOKIEHASH, $hasher->HashPassword( wp_unslash( $_POST['post_password'] ) ), $expire, COOKIEPATH, COOKIE_DOMAIN, $secure );
 784  
 785          wp_safe_redirect( wp_get_referer() );
 786          exit;
 787  
 788      case 'logout':
 789          check_admin_referer( 'log-out' );
 790  
 791          $user = wp_get_current_user();
 792  
 793          wp_logout();
 794  
 795          if ( ! empty( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ) {
 796              $redirect_to           = $_REQUEST['redirect_to'];
 797              $requested_redirect_to = $redirect_to;
 798          } else {
 799              $redirect_to = add_query_arg(
 800                  array(
 801                      'loggedout' => 'true',
 802                      'wp_lang'   => get_user_locale( $user ),
 803                  ),
 804                  wp_login_url()
 805              );
 806  
 807              $requested_redirect_to = '';
 808          }
 809  
 810          /**
 811           * Filters the log out redirect URL.
 812           *
 813           * @since 4.2.0
 814           *
 815           * @param string  $redirect_to           The redirect destination URL.
 816           * @param string  $requested_redirect_to The requested redirect destination URL passed as a parameter.
 817           * @param WP_User $user                  The WP_User object for the user that's logging out.
 818           */
 819          $redirect_to = apply_filters( 'logout_redirect', $redirect_to, $requested_redirect_to, $user );
 820  
 821          wp_safe_redirect( $redirect_to );
 822          exit;
 823  
 824      case 'lostpassword':
 825      case 'retrievepassword':
 826          if ( $http_post ) {
 827              $errors = retrieve_password();
 828  
 829              if ( ! is_wp_error( $errors ) ) {
 830                  $redirect_to = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : 'wp-login.php?checkemail=confirm';
 831                  wp_safe_redirect( $redirect_to );
 832                  exit;
 833              }
 834          }
 835  
 836          if ( isset( $_GET['error'] ) ) {
 837              if ( 'invalidkey' === $_GET['error'] ) {
 838                  $errors->add( 'invalidkey', __( '<strong>Error:</strong> Your password reset link appears to be invalid. Please request a new link below.' ) );
 839              } elseif ( 'expiredkey' === $_GET['error'] ) {
 840                  $errors->add( 'expiredkey', __( '<strong>Error:</strong> Your password reset link has expired. Please request a new link below.' ) );
 841              }
 842          }
 843  
 844          $lostpassword_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
 845          /**
 846           * Filters the URL redirected to after submitting the lostpassword/retrievepassword form.
 847           *
 848           * @since 3.0.0
 849           *
 850           * @param string $lostpassword_redirect The redirect destination URL.
 851           */
 852          $redirect_to = apply_filters( 'lostpassword_redirect', $lostpassword_redirect );
 853  
 854          /**
 855           * Fires before the lost password form.
 856           *
 857           * @since 1.5.1
 858           * @since 5.1.0 Added the `$errors` parameter.
 859           *
 860           * @param WP_Error $errors A `WP_Error` object containing any errors generated by using invalid
 861           *                         credentials. Note that the error object may not contain any errors.
 862           */
 863          do_action( 'lost_password', $errors );
 864  
 865          login_header(
 866              __( 'Lost Password' ),
 867              wp_get_admin_notice(
 868                  __( 'Please enter your username or email address. You will receive an email message with instructions on how to reset your password.' ),
 869                  array(
 870                      'type'               => 'info',
 871                      'additional_classes' => array( 'message' ),
 872                  )
 873              ),
 874              $errors
 875          );
 876  
 877          $user_login = '';
 878  
 879          if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) {
 880              $user_login = wp_unslash( $_POST['user_login'] );
 881          }
 882  
 883          ?>
 884  
 885          <form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post">
 886              <p>
 887                  <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label>
 888                  <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" autocomplete="username" required="required" />
 889              </p>
 890              <?php
 891  
 892              /**
 893               * Fires inside the lostpassword form tags, before the hidden fields.
 894               *
 895               * @since 2.1.0
 896               */
 897              do_action( 'lostpassword_form' );
 898  
 899              ?>
 900              <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
 901              <p class="submit">
 902                  <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Get New Password' ); ?>" />
 903              </p>
 904          </form>
 905  
 906          <p id="nav">
 907              <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
 908              <?php
 909  
 910              if ( get_option( 'users_can_register' ) ) {
 911                  $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
 912  
 913                  echo esc_html( $login_link_separator );
 914  
 915                  /** This filter is documented in wp-includes/general-template.php */
 916                  echo apply_filters( 'register', $registration_url );
 917              }
 918  
 919              ?>
 920          </p>
 921          <?php
 922  
 923          login_footer( 'user_login' );
 924          break;
 925  
 926      case 'resetpass':
 927      case 'rp':
 928          list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) );
 929          $rp_cookie       = 'wp-resetpass-' . COOKIEHASH;
 930  
 931          if ( isset( $_GET['key'] ) && isset( $_GET['login'] ) ) {
 932              $value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['key'] ) );
 933              setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
 934  
 935              wp_safe_redirect( remove_query_arg( array( 'key', 'login' ) ) );
 936              exit;
 937          }
 938  
 939          if ( isset( $_COOKIE[ $rp_cookie ] ) && 0 < strpos( $_COOKIE[ $rp_cookie ], ':' ) ) {
 940              list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ $rp_cookie ] ), 2 );
 941  
 942              $user = check_password_reset_key( $rp_key, $rp_login );
 943  
 944              if ( isset( $_POST['pass1'] ) && ! hash_equals( $rp_key, $_POST['rp_key'] ) ) {
 945                  $user = false;
 946              }
 947          } else {
 948              $user = false;
 949          }
 950  
 951          if ( ! $user || is_wp_error( $user ) ) {
 952              setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
 953  
 954              if ( $user && $user->get_error_code() === 'expired_key' ) {
 955                  wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=expiredkey' ) );
 956              } else {
 957                  wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=invalidkey' ) );
 958              }
 959  
 960              exit;
 961          }
 962  
 963          $errors = new WP_Error();
 964  
 965          // Check if password is one or all empty spaces.
 966          if ( ! empty( $_POST['pass1'] ) ) {
 967              $_POST['pass1'] = trim( $_POST['pass1'] );
 968  
 969              if ( empty( $_POST['pass1'] ) ) {
 970                  $errors->add( 'password_reset_empty_space', __( 'The password cannot be a space or all spaces.' ) );
 971              }
 972          }
 973  
 974          // Check if password fields do not match.
 975          if ( ! empty( $_POST['pass1'] ) && trim( $_POST['pass2'] ) !== $_POST['pass1'] ) {
 976              $errors->add( 'password_reset_mismatch', __( '<strong>Error:</strong> The passwords do not match.' ) );
 977          }
 978  
 979          /**
 980           * Fires before the password reset procedure is validated.
 981           *
 982           * @since 3.5.0
 983           *
 984           * @param WP_Error         $errors WP Error object.
 985           * @param WP_User|WP_Error $user   WP_User object if the login and reset key match. WP_Error object otherwise.
 986           */
 987          do_action( 'validate_password_reset', $errors, $user );
 988  
 989          if ( ( ! $errors->has_errors() ) && isset( $_POST['pass1'] ) && ! empty( $_POST['pass1'] ) ) {
 990              reset_password( $user, $_POST['pass1'] );
 991              setcookie( $rp_cookie, ' ', time() - YEAR_IN_SECONDS, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
 992              login_header(
 993                  __( 'Password Reset' ),
 994                  wp_get_admin_notice(
 995                      __( 'Your password has been reset.' ) . ' <a href="' . esc_url( wp_login_url() ) . '">' . __( 'Log in' ) . '</a>',
 996                      array(
 997                          'type'               => 'info',
 998                          'additional_classes' => array( 'message', 'reset-pass' ),
 999                      )
1000                  )
1001              );
1002              login_footer();
1003              exit;
1004          }
1005  
1006          wp_enqueue_script( 'utils' );
1007          wp_enqueue_script( 'user-profile' );
1008  
1009          login_header(
1010              __( 'Reset Password' ),
1011              wp_get_admin_notice(
1012                  __( 'Enter your new password below or generate one.' ),
1013                  array(
1014                      'type'               => 'info',
1015                      'additional_classes' => array( 'message', 'reset-pass' ),
1016                  )
1017              ),
1018              $errors
1019          );
1020  
1021          ?>
1022          <form name="resetpassform" id="resetpassform" action="<?php echo esc_url( network_site_url( 'wp-login.php?action=resetpass', 'login_post' ) ); ?>" method="post" autocomplete="off">
1023              <input type="hidden" id="user_login" value="<?php echo esc_attr( $rp_login ); ?>" autocomplete="off" />
1024  
1025              <div class="user-pass1-wrap">
1026                  <p>
1027                      <label for="pass1"><?php _e( 'New password' ); ?></label>
1028                  </p>
1029  
1030                  <div class="wp-pwd">
1031                      <input type="password" name="pass1" id="pass1" class="input password-input" size="24" value="" autocomplete="new-password" spellcheck="false" data-reveal="1" data-pw="<?php echo esc_attr( wp_generate_password( 16 ) ); ?>" aria-describedby="pass-strength-result" />
1032  
1033                      <button type="button" class="button button-secondary wp-hide-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Hide password' ); ?>">
1034                          <span class="dashicons dashicons-hidden" aria-hidden="true"></span>
1035                      </button>
1036                      <div id="pass-strength-result" class="hide-if-no-js" aria-live="polite"><?php _e( 'Strength indicator' ); ?></div>
1037                  </div>
1038                  <div class="pw-weak">
1039                      <input type="checkbox" name="pw_weak" id="pw-weak" class="pw-checkbox" />
1040                      <label for="pw-weak"><?php _e( 'Confirm use of weak password' ); ?></label>
1041                  </div>
1042              </div>
1043  
1044              <p class="user-pass2-wrap">
1045                  <label for="pass2"><?php _e( 'Confirm new password' ); ?></label>
1046                  <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="new-password" spellcheck="false" />
1047              </p>
1048  
1049              <p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p>
1050  
1051              <?php
1052  
1053              /**
1054               * Fires following the 'Strength indicator' meter in the user password reset form.
1055               *
1056               * @since 3.9.0
1057               *
1058               * @param WP_User $user User object of the user whose password is being reset.
1059               */
1060              do_action( 'resetpass_form', $user );
1061  
1062              ?>
1063              <input type="hidden" name="rp_key" value="<?php echo esc_attr( $rp_key ); ?>" />
1064              <p class="submit reset-pass-submit">
1065                  <button type="button" class="button wp-generate-pw hide-if-no-js skip-aria-expanded"><?php _e( 'Generate Password' ); ?></button>
1066                  <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Save Password' ); ?>" />
1067              </p>
1068          </form>
1069  
1070          <p id="nav">
1071              <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
1072              <?php
1073  
1074              if ( get_option( 'users_can_register' ) ) {
1075                  $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
1076  
1077                  echo esc_html( $login_link_separator );
1078  
1079                  /** This filter is documented in wp-includes/general-template.php */
1080                  echo apply_filters( 'register', $registration_url );
1081              }
1082  
1083              ?>
1084          </p>
1085          <?php
1086  
1087          login_footer( 'pass1' );
1088          break;
1089  
1090      case 'register':
1091          if ( is_multisite() ) {
1092              /**
1093               * Filters the Multisite sign up URL.
1094               *
1095               * @since 3.0.0
1096               *
1097               * @param string $sign_up_url The sign up URL.
1098               */
1099              wp_redirect( apply_filters( 'wp_signup_location', network_site_url( 'wp-signup.php' ) ) );
1100              exit;
1101          }
1102  
1103          if ( ! get_option( 'users_can_register' ) ) {
1104              wp_redirect( site_url( 'wp-login.php?registration=disabled' ) );
1105              exit;
1106          }
1107  
1108          $user_login = '';
1109          $user_email = '';
1110  
1111          if ( $http_post ) {
1112              if ( isset( $_POST['user_login'] ) && is_string( $_POST['user_login'] ) ) {
1113                  $user_login = wp_unslash( $_POST['user_login'] );
1114              }
1115  
1116              if ( isset( $_POST['user_email'] ) && is_string( $_POST['user_email'] ) ) {
1117                  $user_email = wp_unslash( $_POST['user_email'] );
1118              }
1119  
1120              $errors = register_new_user( $user_login, $user_email );
1121  
1122              if ( ! is_wp_error( $errors ) ) {
1123                  $redirect_to = ! empty( $_POST['redirect_to'] ) ? $_POST['redirect_to'] : 'wp-login.php?checkemail=registered';
1124                  wp_safe_redirect( $redirect_to );
1125                  exit;
1126              }
1127          }
1128  
1129          $registration_redirect = ! empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
1130  
1131          /**
1132           * Filters the registration redirect URL.
1133           *
1134           * @since 3.0.0
1135           * @since 5.9.0 Added the `$errors` parameter.
1136           *
1137           * @param string       $registration_redirect The redirect destination URL.
1138           * @param int|WP_Error $errors                User id if registration was successful,
1139           *                                            WP_Error object otherwise.
1140           */
1141          $redirect_to = apply_filters( 'registration_redirect', $registration_redirect, $errors );
1142  
1143          login_header(
1144              __( 'Registration Form' ),
1145              wp_get_admin_notice(
1146                  __( 'Register For This Site' ),
1147                  array(
1148                      'type'               => 'info',
1149                      'additional_classes' => array( 'message', 'register' ),
1150                  )
1151              ),
1152              $errors
1153          );
1154  
1155          ?>
1156          <form name="registerform" id="registerform" action="<?php echo esc_url( site_url( 'wp-login.php?action=register', 'login_post' ) ); ?>" method="post" novalidate="novalidate">
1157              <p>
1158                  <label for="user_login"><?php _e( 'Username' ); ?></label>
1159                  <input type="text" name="user_login" id="user_login" class="input" value="<?php echo esc_attr( wp_unslash( $user_login ) ); ?>" size="20" autocapitalize="off" autocomplete="username" required="required" />
1160              </p>
1161              <p>
1162                  <label for="user_email"><?php _e( 'Email' ); ?></label>
1163                  <input type="email" name="user_email" id="user_email" class="input" value="<?php echo esc_attr( wp_unslash( $user_email ) ); ?>" size="25" autocomplete="email" required="required" />
1164              </p>
1165              <?php
1166  
1167              /**
1168               * Fires following the 'Email' field in the user registration form.
1169               *
1170               * @since 2.1.0
1171               */
1172              do_action( 'register_form' );
1173  
1174              ?>
1175              <p id="reg_passmail">
1176                  <?php _e( 'Registration confirmation will be emailed to you.' ); ?>
1177              </p>
1178              <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
1179              <p class="submit">
1180                  <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Register' ); ?>" />
1181              </p>
1182          </form>
1183  
1184          <p id="nav">
1185              <a class="wp-login-log-in" href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log in' ); ?></a>
1186              <?php
1187  
1188              echo esc_html( $login_link_separator );
1189  
1190              $html_link = sprintf( '<a class="wp-login-lost-password" href="%s">%s</a>', esc_url( wp_lostpassword_url() ), __( 'Lost your password?' ) );
1191  
1192              /** This filter is documented in wp-login.php */
1193              echo apply_filters( 'lost_password_html_link', $html_link );
1194  
1195              ?>
1196          </p>
1197          <?php
1198  
1199          login_footer( 'user_login' );
1200          break;
1201  
1202      case 'checkemail':
1203          $redirect_to = admin_url();
1204          $errors      = new WP_Error();
1205  
1206          if ( 'confirm' === $_GET['checkemail'] ) {
1207              $errors->add(
1208                  'confirm',
1209                  sprintf(
1210                      /* translators: %s: Link to the login page. */
1211                      __( 'Check your email for the confirmation link, then visit the <a href="%s">login page</a>.' ),
1212                      wp_login_url()
1213                  ),
1214                  'message'
1215              );
1216          } elseif ( 'registered' === $_GET['checkemail'] ) {
1217              $errors->add(
1218                  'registered',
1219                  sprintf(
1220                      /* translators: %s: Link to the login page. */
1221                      __( 'Registration complete. Please check your email, then visit the <a href="%s">login page</a>.' ),
1222                      wp_login_url()
1223                  ),
1224                  'message'
1225              );
1226          }
1227  
1228          /** This action is documented in wp-login.php */
1229          $errors = apply_filters( 'wp_login_errors', $errors, $redirect_to );
1230  
1231          login_header( __( 'Check your email' ), '', $errors );
1232          login_footer();
1233          break;
1234  
1235      case 'confirmaction':
1236          if ( ! isset( $_GET['request_id'] ) ) {
1237              wp_die( __( 'Missing request ID.' ) );
1238          }
1239  
1240          if ( ! isset( $_GET['confirm_key'] ) ) {
1241              wp_die( __( 'Missing confirm key.' ) );
1242          }
1243  
1244          $request_id = (int) $_GET['request_id'];
1245          $key        = sanitize_text_field( wp_unslash( $_GET['confirm_key'] ) );
1246          $result     = wp_validate_user_request_key( $request_id, $key );
1247  
1248          if ( is_wp_error( $result ) ) {
1249              wp_die( $result );
1250          }
1251  
1252          /**
1253           * Fires an action hook when the account action has been confirmed by the user.
1254           *
1255           * Using this you can assume the user has agreed to perform the action by
1256           * clicking on the link in the confirmation email.
1257           *
1258           * After firing this action hook the page will redirect to wp-login a callback
1259           * redirects or exits first.
1260           *
1261           * @since 4.9.6
1262           *
1263           * @param int $request_id Request ID.
1264           */
1265          do_action( 'user_request_action_confirmed', $request_id );
1266  
1267          $message = _wp_privacy_account_request_confirmed_message( $request_id );
1268  
1269          login_header( __( 'User action confirmed.' ), $message );
1270          login_footer();
1271          exit;
1272  
1273      case 'login':
1274      default:
1275          $secure_cookie   = '';
1276          $customize_login = isset( $_REQUEST['customize-login'] );
1277  
1278          if ( $customize_login ) {
1279              wp_enqueue_script( 'customize-base' );
1280          }
1281  
1282          // If the user wants SSL but the session is not SSL, force a secure cookie.
1283          if ( ! empty( $_POST['log'] ) && ! force_ssl_admin() ) {
1284              $user_name = sanitize_user( wp_unslash( $_POST['log'] ) );
1285              $user      = get_user_by( 'login', $user_name );
1286  
1287              if ( ! $user && strpos( $user_name, '@' ) ) {
1288                  $user = get_user_by( 'email', $user_name );
1289              }
1290  
1291              if ( $user ) {
1292                  if ( get_user_option( 'use_ssl', $user->ID ) ) {
1293                      $secure_cookie = true;
1294                      force_ssl_admin( true );
1295                  }
1296              }
1297          }
1298  
1299          if ( isset( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ) {
1300              $redirect_to = $_REQUEST['redirect_to'];
1301              // Redirect to HTTPS if user wants SSL.
1302              if ( $secure_cookie && str_contains( $redirect_to, 'wp-admin' ) ) {
1303                  $redirect_to = preg_replace( '|^http://|', 'https://', $redirect_to );
1304              }
1305          } else {
1306              $redirect_to = admin_url();
1307          }
1308  
1309          $reauth = empty( $_REQUEST['reauth'] ) ? false : true;
1310  
1311          $user = wp_signon( array(), $secure_cookie );
1312  
1313          if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) ) {
1314              if ( headers_sent() ) {
1315                  $user = new WP_Error(
1316                      'test_cookie',
1317                      sprintf(
1318                          /* translators: 1: Browser cookie documentation URL, 2: Support forums URL. */
1319                          __( '<strong>Error:</strong> Cookies are blocked due to unexpected output. For help, please see <a href="%1$s">this documentation</a> or try the <a href="%2$s">support forums</a>.' ),
1320                          __( 'https://developer.wordpress.org/advanced-administration/wordpress/cookies/' ),
1321                          __( 'https://wordpress.org/support/forums/' )
1322                      )
1323                  );
1324              } elseif ( isset( $_POST['testcookie'] ) && empty( $_COOKIE[ TEST_COOKIE ] ) ) {
1325                  // If cookies are disabled, the user can't log in even with a valid username and password.
1326                  $user = new WP_Error(
1327                      'test_cookie',
1328                      sprintf(
1329                          /* translators: %s: Browser cookie documentation URL. */
1330                          __( '<strong>Error:</strong> Cookies are blocked or not supported by your browser. You must <a href="%s">enable cookies</a> to use WordPress.' ),
1331                          __( 'https://developer.wordpress.org/advanced-administration/wordpress/cookies/#enable-cookies-in-your-browser' )
1332                      )
1333                  );
1334              }
1335          }
1336  
1337          $requested_redirect_to = isset( $_REQUEST['redirect_to'] ) && is_string( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
1338  
1339          /**
1340           * Filters the login redirect URL.
1341           *
1342           * @since 3.0.0
1343           *
1344           * @param string           $redirect_to           The redirect destination URL.
1345           * @param string           $requested_redirect_to The requested redirect destination URL passed as a parameter.
1346           * @param WP_User|WP_Error $user                  WP_User object if login was successful, WP_Error object otherwise.
1347           */
1348          $redirect_to = apply_filters( 'login_redirect', $redirect_to, $requested_redirect_to, $user );
1349  
1350          if ( ! is_wp_error( $user ) && ! $reauth ) {
1351              if ( $interim_login ) {
1352                  $message       = '<p class="message">' . __( 'You have logged in successfully.' ) . '</p>';
1353                  $interim_login = 'success';
1354                  login_header( '', $message );
1355  
1356                  ?>
1357                  </div>
1358                  <?php
1359  
1360                  /** This action is documented in wp-login.php */
1361                  do_action( 'login_footer' );
1362  
1363                  if ( $customize_login ) {
1364                      ob_start();
1365                      ?>
1366                      <script>setTimeout( function(){ new wp.customize.Messenger({ url: '<?php echo wp_customize_url(); ?>', channel: 'login' }).send('login') }, 1000 );</script>
1367                      <?php
1368                      wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
1369                  }
1370  
1371                  ?>
1372                  </body></html>
1373                  <?php
1374  
1375                  exit;
1376              }
1377  
1378              // Check if it is time to add a redirect to the admin email confirmation screen.
1379              if ( $user instanceof WP_User && $user->exists() && $user->has_cap( 'manage_options' ) ) {
1380                  $admin_email_lifespan = (int) get_option( 'admin_email_lifespan' );
1381  
1382                  /*
1383                   * If `0` (or anything "falsey" as it is cast to int) is returned, the user will not be redirected
1384                   * to the admin email confirmation screen.
1385                   */
1386                  /** This filter is documented in wp-login.php */
1387                  $admin_email_check_interval = (int) apply_filters( 'admin_email_check_interval', 6 * MONTH_IN_SECONDS );
1388  
1389                  if ( $admin_email_check_interval > 0 && time() > $admin_email_lifespan ) {
1390                      $redirect_to = add_query_arg(
1391                          array(
1392                              'action'  => 'confirm_admin_email',
1393                              'wp_lang' => get_user_locale( $user ),
1394                          ),
1395                          wp_login_url( $redirect_to )
1396                      );
1397                  }
1398              }
1399  
1400              if ( ( empty( $redirect_to ) || 'wp-admin/' === $redirect_to || admin_url() === $redirect_to ) ) {
1401                  // If the user doesn't belong to a blog, send them to user admin. If the user can't edit posts, send them to their profile.
1402                  if ( is_multisite() && ! get_active_blog_for_user( $user->ID ) && ! is_super_admin( $user->ID ) ) {
1403                      $redirect_to = user_admin_url();
1404                  } elseif ( is_multisite() && ! $user->has_cap( 'read' ) ) {
1405                      $redirect_to = get_dashboard_url( $user->ID );
1406                  } elseif ( ! $user->has_cap( 'edit_posts' ) ) {
1407                      $redirect_to = $user->has_cap( 'read' ) ? admin_url( 'profile.php' ) : home_url();
1408                  }
1409  
1410                  wp_redirect( $redirect_to );
1411                  exit;
1412              }
1413  
1414              wp_safe_redirect( $redirect_to );
1415              exit;
1416          }
1417  
1418          $errors = $user;
1419          // Clear errors if loggedout is set.
1420          if ( ! empty( $_GET['loggedout'] ) || $reauth ) {
1421              $errors = new WP_Error();
1422          }
1423  
1424          if ( empty( $_POST ) && $errors->get_error_codes() === array( 'empty_username', 'empty_password' ) ) {
1425              $errors = new WP_Error( '', '' );
1426          }
1427  
1428          if ( $interim_login ) {
1429              if ( ! $errors->has_errors() ) {
1430                  $errors->add( 'expired', __( 'Your session has expired. Please log in to continue where you left off.' ), 'message' );
1431              }
1432          } else {
1433              // Some parts of this script use the main login form to display a message.
1434              if ( isset( $_GET['loggedout'] ) && $_GET['loggedout'] ) {
1435                  $errors->add( 'loggedout', __( 'You are now logged out.' ), 'message' );
1436              } elseif ( isset( $_GET['registration'] ) && 'disabled' === $_GET['registration'] ) {
1437                  $errors->add( 'registerdisabled', __( '<strong>Error:</strong> User registration is currently not allowed.' ) );
1438              } elseif ( str_contains( $redirect_to, 'about.php?updated' ) ) {
1439                  $errors->add( 'updated', __( '<strong>You have successfully updated WordPress!</strong> Please log back in to see what&#8217;s new.' ), 'message' );
1440              } elseif ( WP_Recovery_Mode_Link_Service::LOGIN_ACTION_ENTERED === $action ) {
1441                  $errors->add( 'enter_recovery_mode', __( 'Recovery Mode Initialized. Please log in to continue.' ), 'message' );
1442              } elseif ( isset( $_GET['redirect_to'] ) && is_string( $_GET['redirect_to'] )
1443                  && str_contains( $_GET['redirect_to'], 'wp-admin/authorize-application.php' )
1444              ) {
1445                  $query_component = wp_parse_url( $_GET['redirect_to'], PHP_URL_QUERY );
1446                  $query           = array();
1447                  if ( $query_component ) {
1448                      parse_str( $query_component, $query );
1449                  }
1450  
1451                  if ( ! empty( $query['app_name'] ) ) {
1452                      /* translators: 1: Website name, 2: Application name. */
1453                      $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>' );
1454                  } else {
1455                      /* translators: %s: Website name. */
1456                      $message = sprintf( 'Please log in to %s to proceed with authorization.', get_bloginfo( 'name', 'display' ) );
1457                  }
1458  
1459                  $errors->add( 'authorize_application', $message, 'message' );
1460              }
1461          }
1462  
1463          /**
1464           * Filters the login page errors.
1465           *
1466           * @since 3.6.0
1467           *
1468           * @param WP_Error $errors      WP Error object.
1469           * @param string   $redirect_to Redirect destination URL.
1470           */
1471          $errors = apply_filters( 'wp_login_errors', $errors, $redirect_to );
1472  
1473          // Clear any stale cookies.
1474          if ( $reauth ) {
1475              wp_clear_auth_cookie();
1476          }
1477  
1478          login_header( __( 'Log In' ), '', $errors );
1479  
1480          if ( isset( $_POST['log'] ) ) {
1481              $user_login = ( 'incorrect_password' === $errors->get_error_code() || 'empty_password' === $errors->get_error_code() ) ? esc_attr( wp_unslash( $_POST['log'] ) ) : '';
1482          }
1483  
1484          $rememberme = ! empty( $_POST['rememberme'] );
1485  
1486          $aria_describedby = '';
1487          $has_errors       = $errors->has_errors();
1488  
1489          if ( $has_errors ) {
1490              $aria_describedby = ' aria-describedby="login_error"';
1491          }
1492  
1493          if ( $has_errors && 'message' === $errors->get_error_data() ) {
1494              $aria_describedby = ' aria-describedby="login-message"';
1495          }
1496  
1497          wp_enqueue_script( 'user-profile' );
1498          ?>
1499  
1500          <form name="loginform" id="loginform" action="<?php echo esc_url( site_url( 'wp-login.php', 'login_post' ) ); ?>" method="post">
1501              <p>
1502                  <label for="user_login"><?php _e( 'Username or Email Address' ); ?></label>
1503                  <input type="text" name="log" id="user_login"<?php echo $aria_describedby; ?> class="input" value="<?php echo esc_attr( $user_login ); ?>" size="20" autocapitalize="off" autocomplete="username" required="required" />
1504              </p>
1505  
1506              <div class="user-pass-wrap">
1507                  <label for="user_pass"><?php _e( 'Password' ); ?></label>
1508                  <div class="wp-pwd">
1509                      <input type="password" name="pwd" id="user_pass"<?php echo $aria_describedby; ?> class="input password-input" value="" size="20" autocomplete="current-password" spellcheck="false" required="required" />
1510                      <button type="button" class="button button-secondary wp-hide-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Show password' ); ?>">
1511                          <span class="dashicons dashicons-visibility" aria-hidden="true"></span>
1512                      </button>
1513                  </div>
1514              </div>
1515              <?php
1516  
1517              /**
1518               * Fires following the 'Password' field in the login form.
1519               *
1520               * @since 2.1.0
1521               */
1522              do_action( 'login_form' );
1523  
1524              ?>
1525              <p class="forgetmenot"><input name="rememberme" type="checkbox" id="rememberme" value="forever" <?php checked( $rememberme ); ?> /> <label for="rememberme"><?php esc_html_e( 'Remember Me' ); ?></label></p>
1526              <p class="submit">
1527                  <input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="<?php esc_attr_e( 'Log In' ); ?>" />
1528                  <?php
1529  
1530                  if ( $interim_login ) {
1531                      ?>
1532                      <input type="hidden" name="interim-login" value="1" />
1533                      <?php
1534                  } else {
1535                      ?>
1536                      <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $redirect_to ); ?>" />
1537                      <?php
1538                  }
1539  
1540                  if ( $customize_login ) {
1541                      ?>
1542                      <input type="hidden" name="customize-login" value="1" />
1543                      <?php
1544                  }
1545  
1546                  ?>
1547                  <input type="hidden" name="testcookie" value="1" />
1548              </p>
1549          </form>
1550  
1551          <?php
1552  
1553          if ( ! $interim_login ) {
1554              ?>
1555              <p id="nav">
1556                  <?php
1557  
1558                  if ( get_option( 'users_can_register' ) ) {
1559                      $registration_url = sprintf( '<a class="wp-login-register" href="%s">%s</a>', esc_url( wp_registration_url() ), __( 'Register' ) );
1560  
1561                      /** This filter is documented in wp-includes/general-template.php */
1562                      echo apply_filters( 'register', $registration_url );
1563  
1564                      echo esc_html( $login_link_separator );
1565                  }
1566  
1567                  $html_link = sprintf( '<a class="wp-login-lost-password" href="%s">%s</a>', esc_url( wp_lostpassword_url() ), __( 'Lost your password?' ) );
1568  
1569                  /**
1570                   * Filters the link that allows the user to reset the lost password.
1571                   *
1572                   * @since 6.1.0
1573                   *
1574                   * @param string $html_link HTML link to the lost password form.
1575                   */
1576                  echo apply_filters( 'lost_password_html_link', $html_link );
1577  
1578                  ?>
1579              </p>
1580              <?php
1581          }
1582  
1583          $login_script  = 'function wp_attempt_focus() {';
1584          $login_script .= 'setTimeout( function() {';
1585          $login_script .= 'try {';
1586  
1587          if ( $user_login ) {
1588              $login_script .= 'd = document.getElementById( "user_pass" ); d.value = "";';
1589          } else {
1590              $login_script .= 'd = document.getElementById( "user_login" );';
1591  
1592              if ( $errors->get_error_code() === 'invalid_username' ) {
1593                  $login_script .= 'd.value = "";';
1594              }
1595          }
1596  
1597          $login_script .= 'd.focus(); d.select();';
1598          $login_script .= '} catch( er ) {}';
1599          $login_script .= '}, 200);';
1600          $login_script .= "}\n"; // End of wp_attempt_focus().
1601  
1602          /**
1603           * Filters whether to print the call to `wp_attempt_focus()` on the login screen.
1604           *
1605           * @since 4.8.0
1606           *
1607           * @param bool $print Whether to print the function call. Default true.
1608           */
1609          if ( apply_filters( 'enable_login_autofocus', true ) && ! $error ) {
1610              $login_script .= "wp_attempt_focus();\n";
1611          }
1612  
1613          // Run `wpOnload()` if defined.
1614          $login_script .= "if ( typeof wpOnload === 'function' ) { wpOnload() }";
1615  
1616          wp_print_inline_script_tag( $login_script );
1617  
1618          if ( $interim_login ) {
1619              ob_start();
1620              ?>
1621              <script>
1622              ( function() {
1623                  try {
1624                      var i, links = document.getElementsByTagName( 'a' );
1625                      for ( i in links ) {
1626                          if ( links[i].href ) {
1627                              links[i].target = '_blank';
1628                              links[i].rel = 'noopener';
1629                          }
1630                      }
1631                  } catch( er ) {}
1632              }());
1633              </script>
1634              <?php
1635              wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
1636          }
1637  
1638          login_footer();
1639          break;
1640  } // End action switch.


Generated : Sat Apr 27 08:20:02 2024 Cross-referenced by PHPXref