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


Generated : Thu Nov 21 08:20:01 2024 Cross-referenced by PHPXref