wp/wp-includes/pluggable.php
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
   249 		// (Re)create it, if it's gone missing.
   249 		// (Re)create it, if it's gone missing.
   250 		if ( ! ( $phpmailer instanceof PHPMailer\PHPMailer\PHPMailer ) ) {
   250 		if ( ! ( $phpmailer instanceof PHPMailer\PHPMailer\PHPMailer ) ) {
   251 			require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
   251 			require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
   252 			require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
   252 			require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
   253 			require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
   253 			require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
   254 			$phpmailer = new PHPMailer\PHPMailer\PHPMailer( true );
   254 			require_once ABSPATH . WPINC . '/class-wp-phpmailer.php';
       
   255 			$phpmailer = new WP_PHPMailer( true );
   255 
   256 
   256 			$phpmailer::$validator = static function ( $email ) {
   257 			$phpmailer::$validator = static function ( $email ) {
   257 				return (bool) is_email( $email );
   258 				return (bool) is_email( $email );
   258 			};
   259 			};
   259 		}
   260 		}
   595 	 * @param string $username User's username or email address.
   596 	 * @param string $username User's username or email address.
   596 	 * @param string $password User's password.
   597 	 * @param string $password User's password.
   597 	 * @return WP_User|WP_Error WP_User object if the credentials are valid,
   598 	 * @return WP_User|WP_Error WP_User object if the credentials are valid,
   598 	 *                          otherwise WP_Error.
   599 	 *                          otherwise WP_Error.
   599 	 */
   600 	 */
   600 	function wp_authenticate( $username, $password ) {
   601 	function wp_authenticate(
       
   602 		$username,
       
   603 		#[\SensitiveParameter]
       
   604 		$password
       
   605 	) {
   601 		$username = sanitize_user( $username );
   606 		$username = sanitize_user( $username );
   602 		$password = trim( $password );
   607 		$password = trim( $password );
   603 
   608 
   604 		/**
   609 		/**
   605 		 * Filters whether a set of user login credentials are valid.
   610 		 * Filters whether a set of user login credentials are valid.
   686 	 *
   691 	 *
   687 	 * @global int $login_grace_period
   692 	 * @global int $login_grace_period
   688 	 *
   693 	 *
   689 	 * @param string $cookie Optional. If used, will validate contents instead of cookie's.
   694 	 * @param string $cookie Optional. If used, will validate contents instead of cookie's.
   690 	 * @param string $scheme Optional. The cookie scheme to use: 'auth', 'secure_auth', or 'logged_in'.
   695 	 * @param string $scheme Optional. The cookie scheme to use: 'auth', 'secure_auth', or 'logged_in'.
       
   696 	 *                       Note: This does *not* default to 'auth' like other cookie functions.
   691 	 * @return int|false User ID if valid cookie, false if invalid.
   697 	 * @return int|false User ID if valid cookie, false if invalid.
   692 	 */
   698 	 */
   693 	function wp_validate_auth_cookie( $cookie = '', $scheme = '' ) {
   699 	function wp_validate_auth_cookie( $cookie = '', $scheme = '' ) {
   694 		$cookie_elements = wp_parse_auth_cookie( $cookie, $scheme );
   700 		$cookie_elements = wp_parse_auth_cookie( $cookie, $scheme );
   695 		if ( ! $cookie_elements ) {
   701 		if ( ! $cookie_elements ) {
   708 
   714 
   709 		$scheme     = $cookie_elements['scheme'];
   715 		$scheme     = $cookie_elements['scheme'];
   710 		$username   = $cookie_elements['username'];
   716 		$username   = $cookie_elements['username'];
   711 		$hmac       = $cookie_elements['hmac'];
   717 		$hmac       = $cookie_elements['hmac'];
   712 		$token      = $cookie_elements['token'];
   718 		$token      = $cookie_elements['token'];
   713 		$expired    = $cookie_elements['expiration'];
       
   714 		$expiration = $cookie_elements['expiration'];
   719 		$expiration = $cookie_elements['expiration'];
       
   720 
       
   721 		$expired = (int) $expiration;
   715 
   722 
   716 		// Allow a grace period for POST and Ajax requests.
   723 		// Allow a grace period for POST and Ajax requests.
   717 		if ( wp_doing_ajax() || 'POST' === $_SERVER['REQUEST_METHOD'] ) {
   724 		if ( wp_doing_ajax() || 'POST' === $_SERVER['REQUEST_METHOD'] ) {
   718 			$expired += HOUR_IN_SECONDS;
   725 			$expired += HOUR_IN_SECONDS;
   719 		}
   726 		}
   760 			 */
   767 			 */
   761 			do_action( 'auth_cookie_bad_username', $cookie_elements );
   768 			do_action( 'auth_cookie_bad_username', $cookie_elements );
   762 			return false;
   769 			return false;
   763 		}
   770 		}
   764 
   771 
   765 		$pass_frag = substr( $user->user_pass, 8, 4 );
   772 		if ( str_starts_with( $user->user_pass, '$P$' ) || str_starts_with( $user->user_pass, '$2y$' ) ) {
       
   773 			// Retain previous behaviour of phpass or vanilla bcrypt hashed passwords.
       
   774 			$pass_frag = substr( $user->user_pass, 8, 4 );
       
   775 		} else {
       
   776 			// Otherwise, use a substring from the end of the hash to avoid dealing with potentially long hash prefixes.
       
   777 			$pass_frag = substr( $user->user_pass, -4 );
       
   778 		}
   766 
   779 
   767 		$key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
   780 		$key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
   768 
   781 
   769 		// If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
   782 		$hash = hash_hmac( 'sha256', $username . '|' . $expiration . '|' . $token, $key );
   770 		$algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
       
   771 		$hash = hash_hmac( $algo, $username . '|' . $expiration . '|' . $token, $key );
       
   772 
   783 
   773 		if ( ! hash_equals( $hash, $hmac ) ) {
   784 		if ( ! hash_equals( $hash, $hmac ) ) {
   774 			/**
   785 			/**
   775 			 * Fires if a bad authentication cookie hash is encountered.
   786 			 * Fires if a bad authentication cookie hash is encountered.
   776 			 *
   787 			 *
   863 		if ( ! $token ) {
   874 		if ( ! $token ) {
   864 			$manager = WP_Session_Tokens::get_instance( $user_id );
   875 			$manager = WP_Session_Tokens::get_instance( $user_id );
   865 			$token   = $manager->create( $expiration );
   876 			$token   = $manager->create( $expiration );
   866 		}
   877 		}
   867 
   878 
   868 		$pass_frag = substr( $user->user_pass, 8, 4 );
   879 		if ( str_starts_with( $user->user_pass, '$P$' ) || str_starts_with( $user->user_pass, '$2y$' ) ) {
       
   880 			// Retain previous behaviour of phpass or vanilla bcrypt hashed passwords.
       
   881 			$pass_frag = substr( $user->user_pass, 8, 4 );
       
   882 		} else {
       
   883 			// Otherwise, use a substring from the end of the hash to avoid dealing with potentially long hash prefixes.
       
   884 			$pass_frag = substr( $user->user_pass, -4 );
       
   885 		}
   869 
   886 
   870 		$key = wp_hash( $user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
   887 		$key = wp_hash( $user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
   871 
   888 
   872 		// If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
   889 		$hash = hash_hmac( 'sha256', $user->user_login . '|' . $expiration . '|' . $token, $key );
   873 		$algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
       
   874 		$hash = hash_hmac( $algo, $user->user_login . '|' . $expiration . '|' . $token, $key );
       
   875 
   890 
   876 		$cookie = $user->user_login . '|' . $expiration . '|' . $token . '|' . $hash;
   891 		$cookie = $user->user_login . '|' . $expiration . '|' . $token . '|' . $hash;
   877 
   892 
   878 		/**
   893 		/**
   879 		 * Filters the authentication cookie.
   894 		 * Filters the authentication cookie.
  1717 			return false;
  1732 			return false;
  1718 		} else {
  1733 		} else {
  1719 			$emails = array_flip( $emails );
  1734 			$emails = array_flip( $emails );
  1720 		}
  1735 		}
  1721 
  1736 
  1722 		$switched_locale = switch_to_locale( get_locale() );
       
  1723 
       
  1724 		$comment_author_domain = '';
  1737 		$comment_author_domain = '';
  1725 		if ( WP_Http::is_ip_address( $comment->comment_author_IP ) ) {
  1738 		if ( WP_Http::is_ip_address( $comment->comment_author_IP ) ) {
  1726 			$comment_author_domain = gethostbyaddr( $comment->comment_author_IP );
  1739 			$comment_author_domain = gethostbyaddr( $comment->comment_author_IP );
  1727 		}
  1740 		}
  1728 
  1741 
  1730 		 * The blogname option is escaped with esc_html() on the way into the database in sanitize_option().
  1743 		 * The blogname option is escaped with esc_html() on the way into the database in sanitize_option().
  1731 		 * We want to reverse this for the plain text arena of emails.
  1744 		 * We want to reverse this for the plain text arena of emails.
  1732 		 */
  1745 		 */
  1733 		$blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
  1746 		$blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
  1734 		$comment_content = wp_specialchars_decode( $comment->comment_content );
  1747 		$comment_content = wp_specialchars_decode( $comment->comment_content );
  1735 
       
  1736 		switch ( $comment->comment_type ) {
       
  1737 			case 'trackback':
       
  1738 				/* translators: %s: Post title. */
       
  1739 				$notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
       
  1740 				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1741 				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1742 				/* translators: %s: Trackback/pingback/comment author URL. */
       
  1743 				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1744 				/* translators: %s: Comment text. */
       
  1745 				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  1746 				$notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
       
  1747 				/* translators: Trackback notification email subject. 1: Site title, 2: Post title. */
       
  1748 				$subject = sprintf( __( '[%1$s] Trackback: "%2$s"' ), $blogname, $post->post_title );
       
  1749 				break;
       
  1750 
       
  1751 			case 'pingback':
       
  1752 				/* translators: %s: Post title. */
       
  1753 				$notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
       
  1754 				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1755 				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1756 				/* translators: %s: Trackback/pingback/comment author URL. */
       
  1757 				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1758 				/* translators: %s: Comment text. */
       
  1759 				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  1760 				$notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
       
  1761 				/* translators: Pingback notification email subject. 1: Site title, 2: Post title. */
       
  1762 				$subject = sprintf( __( '[%1$s] Pingback: "%2$s"' ), $blogname, $post->post_title );
       
  1763 				break;
       
  1764 
       
  1765 			default: // Comments.
       
  1766 				/* translators: %s: Post title. */
       
  1767 				$notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
       
  1768 				/* translators: 1: Comment author's name, 2: Comment author's IP address, 3: Comment author's hostname. */
       
  1769 				$notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1770 				/* translators: %s: Comment author email. */
       
  1771 				$notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
       
  1772 				/* translators: %s: Trackback/pingback/comment author URL. */
       
  1773 				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1774 
       
  1775 				if ( $comment->comment_parent && user_can( $post->post_author, 'edit_comment', $comment->comment_parent ) ) {
       
  1776 					/* translators: Comment moderation. %s: Parent comment edit URL. */
       
  1777 					$notify_message .= sprintf( __( 'In reply to: %s' ), admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) ) . "\r\n";
       
  1778 				}
       
  1779 
       
  1780 				/* translators: %s: Comment text. */
       
  1781 				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  1782 				$notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
       
  1783 				/* translators: Comment notification email subject. 1: Site title, 2: Post title. */
       
  1784 				$subject = sprintf( __( '[%1$s] Comment: "%2$s"' ), $blogname, $post->post_title );
       
  1785 				break;
       
  1786 		}
       
  1787 
       
  1788 		$notify_message .= get_permalink( $comment->comment_post_ID ) . "#comments\r\n\r\n";
       
  1789 		/* translators: %s: Comment URL. */
       
  1790 		$notify_message .= sprintf( __( 'Permalink: %s' ), get_comment_link( $comment ) ) . "\r\n";
       
  1791 
       
  1792 		if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
       
  1793 			if ( EMPTY_TRASH_DAYS ) {
       
  1794 				/* translators: Comment moderation. %s: Comment action URL. */
       
  1795 				$notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
       
  1796 			} else {
       
  1797 				/* translators: Comment moderation. %s: Comment action URL. */
       
  1798 				$notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
       
  1799 			}
       
  1800 			/* translators: Comment moderation. %s: Comment action URL. */
       
  1801 			$notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
       
  1802 		}
       
  1803 
  1748 
  1804 		$wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', wp_parse_url( network_home_url(), PHP_URL_HOST ) );
  1749 		$wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', wp_parse_url( network_home_url(), PHP_URL_HOST ) );
  1805 
  1750 
  1806 		if ( '' === $comment->comment_author ) {
  1751 		if ( '' === $comment->comment_author ) {
  1807 			$from = "From: \"$blogname\" <$wp_email>";
  1752 			$from = "From: \"$blogname\" <$wp_email>";
  1821 		if ( isset( $reply_to ) ) {
  1766 		if ( isset( $reply_to ) ) {
  1822 			$message_headers .= $reply_to . "\n";
  1767 			$message_headers .= $reply_to . "\n";
  1823 		}
  1768 		}
  1824 
  1769 
  1825 		/**
  1770 		/**
  1826 		 * Filters the comment notification email text.
       
  1827 		 *
       
  1828 		 * @since 1.5.2
       
  1829 		 *
       
  1830 		 * @param string $notify_message The comment notification email text.
       
  1831 		 * @param string $comment_id     Comment ID as a numeric string.
       
  1832 		 */
       
  1833 		$notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
       
  1834 
       
  1835 		/**
       
  1836 		 * Filters the comment notification email subject.
       
  1837 		 *
       
  1838 		 * @since 1.5.2
       
  1839 		 *
       
  1840 		 * @param string $subject    The comment notification email subject.
       
  1841 		 * @param string $comment_id Comment ID as a numeric string.
       
  1842 		 */
       
  1843 		$subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
       
  1844 
       
  1845 		/**
       
  1846 		 * Filters the comment notification email headers.
  1771 		 * Filters the comment notification email headers.
  1847 		 *
  1772 		 *
  1848 		 * @since 1.5.2
  1773 		 * @since 1.5.2
  1849 		 *
  1774 		 *
  1850 		 * @param string $message_headers Headers for the comment notification email.
  1775 		 * @param string $message_headers Headers for the comment notification email.
  1851 		 * @param string $comment_id      Comment ID as a numeric string.
  1776 		 * @param string $comment_id      Comment ID as a numeric string.
  1852 		 */
  1777 		 */
  1853 		$message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
  1778 		$message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
  1854 
  1779 
  1855 		foreach ( $emails as $email ) {
  1780 		foreach ( $emails as $email ) {
       
  1781 			$user = get_user_by( 'email', $email );
       
  1782 
       
  1783 			if ( $user ) {
       
  1784 				$switched_locale = switch_to_user_locale( $user->ID );
       
  1785 			} else {
       
  1786 				$switched_locale = switch_to_locale( get_locale() );
       
  1787 			}
       
  1788 
       
  1789 			switch ( $comment->comment_type ) {
       
  1790 				case 'trackback':
       
  1791 					/* translators: %s: Post title. */
       
  1792 					$notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
       
  1793 					/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1794 					$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1795 					/* translators: %s: Trackback/pingback/comment author URL. */
       
  1796 					$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1797 					/* translators: %s: Comment text. */
       
  1798 					$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  1799 					$notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
       
  1800 					/* translators: Trackback notification email subject. 1: Site title, 2: Post title. */
       
  1801 					$subject = sprintf( __( '[%1$s] Trackback: "%2$s"' ), $blogname, $post->post_title );
       
  1802 					break;
       
  1803 
       
  1804 				case 'pingback':
       
  1805 					/* translators: %s: Post title. */
       
  1806 					$notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
       
  1807 					/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1808 					$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1809 					/* translators: %s: Trackback/pingback/comment author URL. */
       
  1810 					$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1811 					/* translators: %s: Comment text. */
       
  1812 					$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  1813 					$notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
       
  1814 					/* translators: Pingback notification email subject. 1: Site title, 2: Post title. */
       
  1815 					$subject = sprintf( __( '[%1$s] Pingback: "%2$s"' ), $blogname, $post->post_title );
       
  1816 					break;
       
  1817 
       
  1818 				default: // Comments.
       
  1819 					/* translators: %s: Post title. */
       
  1820 					$notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
       
  1821 					/* translators: 1: Comment author's name, 2: Comment author's IP address, 3: Comment author's hostname. */
       
  1822 					$notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1823 					/* translators: %s: Comment author email. */
       
  1824 					$notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
       
  1825 					/* translators: %s: Trackback/pingback/comment author URL. */
       
  1826 					$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1827 
       
  1828 					if ( $comment->comment_parent && user_can( $post->post_author, 'edit_comment', $comment->comment_parent ) ) {
       
  1829 						/* translators: Comment moderation. %s: Parent comment edit URL. */
       
  1830 						$notify_message .= sprintf( __( 'In reply to: %s' ), admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) ) . "\r\n";
       
  1831 					}
       
  1832 
       
  1833 					/* translators: %s: Comment text. */
       
  1834 					$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  1835 					$notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
       
  1836 					/* translators: Comment notification email subject. 1: Site title, 2: Post title. */
       
  1837 					$subject = sprintf( __( '[%1$s] Comment: "%2$s"' ), $blogname, $post->post_title );
       
  1838 					break;
       
  1839 			}
       
  1840 
       
  1841 			$notify_message .= get_permalink( $comment->comment_post_ID ) . "#comments\r\n\r\n";
       
  1842 			/* translators: %s: Comment URL. */
       
  1843 			$notify_message .= sprintf( __( 'Permalink: %s' ), get_comment_link( $comment ) ) . "\r\n";
       
  1844 
       
  1845 			if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
       
  1846 				if ( EMPTY_TRASH_DAYS ) {
       
  1847 					/* translators: Comment moderation. %s: Comment action URL. */
       
  1848 					$notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
       
  1849 				} else {
       
  1850 					/* translators: Comment moderation. %s: Comment action URL. */
       
  1851 					$notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
       
  1852 				}
       
  1853 				/* translators: Comment moderation. %s: Comment action URL. */
       
  1854 				$notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
       
  1855 			}
       
  1856 
       
  1857 			/**
       
  1858 			 * Filters the comment notification email text.
       
  1859 			 *
       
  1860 			 * @since 1.5.2
       
  1861 			 *
       
  1862 			 * @param string $notify_message The comment notification email text.
       
  1863 			 * @param string $comment_id     Comment ID as a numeric string.
       
  1864 			 */
       
  1865 			$notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
       
  1866 
       
  1867 			/**
       
  1868 			 * Filters the comment notification email subject.
       
  1869 			 *
       
  1870 			 * @since 1.5.2
       
  1871 			 *
       
  1872 			 * @param string $subject    The comment notification email subject.
       
  1873 			 * @param string $comment_id Comment ID as a numeric string.
       
  1874 			 */
       
  1875 			$subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
       
  1876 
  1856 			wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
  1877 			wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
  1857 		}
  1878 
  1858 
  1879 			if ( $switched_locale ) {
  1859 		if ( $switched_locale ) {
  1880 				restore_previous_locale();
  1860 			restore_previous_locale();
  1881 			}
  1861 		}
  1882 		}
  1862 
  1883 
  1863 		return true;
  1884 		return true;
  1864 	}
  1885 	}
  1865 endif;
  1886 endif;
  1906 			if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
  1927 			if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
  1907 				$emails[] = $user->user_email;
  1928 				$emails[] = $user->user_email;
  1908 			}
  1929 			}
  1909 		}
  1930 		}
  1910 
  1931 
  1911 		$switched_locale = switch_to_locale( get_locale() );
       
  1912 
       
  1913 		$comment_author_domain = '';
  1932 		$comment_author_domain = '';
  1914 		if ( WP_Http::is_ip_address( $comment->comment_author_IP ) ) {
  1933 		if ( WP_Http::is_ip_address( $comment->comment_author_IP ) ) {
  1915 			$comment_author_domain = gethostbyaddr( $comment->comment_author_IP );
  1934 			$comment_author_domain = gethostbyaddr( $comment->comment_author_IP );
  1916 		}
  1935 		}
  1917 
  1936 
  1922 		 * We want to reverse this for the plain text arena of emails.
  1941 		 * We want to reverse this for the plain text arena of emails.
  1923 		 */
  1942 		 */
  1924 		$blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
  1943 		$blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
  1925 		$comment_content = wp_specialchars_decode( $comment->comment_content );
  1944 		$comment_content = wp_specialchars_decode( $comment->comment_content );
  1926 
  1945 
  1927 		switch ( $comment->comment_type ) {
       
  1928 			case 'trackback':
       
  1929 				/* translators: %s: Post title. */
       
  1930 				$notify_message  = sprintf( __( 'A new trackback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
       
  1931 				$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
       
  1932 				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1933 				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1934 				/* translators: %s: Trackback/pingback/comment author URL. */
       
  1935 				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1936 				$notify_message .= __( 'Trackback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
       
  1937 				break;
       
  1938 
       
  1939 			case 'pingback':
       
  1940 				/* translators: %s: Post title. */
       
  1941 				$notify_message  = sprintf( __( 'A new pingback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
       
  1942 				$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
       
  1943 				/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1944 				$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1945 				/* translators: %s: Trackback/pingback/comment author URL. */
       
  1946 				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1947 				$notify_message .= __( 'Pingback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
       
  1948 				break;
       
  1949 
       
  1950 			default: // Comments.
       
  1951 				/* translators: %s: Post title. */
       
  1952 				$notify_message  = sprintf( __( 'A new comment on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
       
  1953 				$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
       
  1954 				/* translators: 1: Comment author's name, 2: Comment author's IP address, 3: Comment author's hostname. */
       
  1955 				$notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1956 				/* translators: %s: Comment author email. */
       
  1957 				$notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
       
  1958 				/* translators: %s: Trackback/pingback/comment author URL. */
       
  1959 				$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1960 
       
  1961 				if ( $comment->comment_parent ) {
       
  1962 					/* translators: Comment moderation. %s: Parent comment edit URL. */
       
  1963 					$notify_message .= sprintf( __( 'In reply to: %s' ), admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) ) . "\r\n";
       
  1964 				}
       
  1965 
       
  1966 				/* translators: %s: Comment text. */
       
  1967 				$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  1968 				break;
       
  1969 		}
       
  1970 
       
  1971 		/* translators: Comment moderation. %s: Comment action URL. */
       
  1972 		$notify_message .= sprintf( __( 'Approve it: %s' ), admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  1973 
       
  1974 		if ( EMPTY_TRASH_DAYS ) {
       
  1975 			/* translators: Comment moderation. %s: Comment action URL. */
       
  1976 			$notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  1977 		} else {
       
  1978 			/* translators: Comment moderation. %s: Comment action URL. */
       
  1979 			$notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  1980 		}
       
  1981 
       
  1982 		/* translators: Comment moderation. %s: Comment action URL. */
       
  1983 		$notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  1984 
       
  1985 		$notify_message .= sprintf(
       
  1986 			/* translators: Comment moderation. %s: Number of comments awaiting approval. */
       
  1987 			_n(
       
  1988 				'Currently %s comment is waiting for approval. Please visit the moderation panel:',
       
  1989 				'Currently %s comments are waiting for approval. Please visit the moderation panel:',
       
  1990 				$comments_waiting
       
  1991 			),
       
  1992 			number_format_i18n( $comments_waiting )
       
  1993 		) . "\r\n";
       
  1994 		$notify_message .= admin_url( 'edit-comments.php?comment_status=moderated#wpbody-content' ) . "\r\n";
       
  1995 
       
  1996 		/* translators: Comment moderation notification email subject. 1: Site title, 2: Post title. */
       
  1997 		$subject         = sprintf( __( '[%1$s] Please moderate: "%2$s"' ), $blogname, $post->post_title );
       
  1998 		$message_headers = '';
  1946 		$message_headers = '';
  1999 
  1947 
  2000 		/**
  1948 		/**
  2001 		 * Filters the list of recipients for comment moderation emails.
  1949 		 * Filters the list of recipients for comment moderation emails.
  2002 		 *
  1950 		 *
  2006 		 * @param int      $comment_id Comment ID.
  1954 		 * @param int      $comment_id Comment ID.
  2007 		 */
  1955 		 */
  2008 		$emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
  1956 		$emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
  2009 
  1957 
  2010 		/**
  1958 		/**
  2011 		 * Filters the comment moderation email text.
       
  2012 		 *
       
  2013 		 * @since 1.5.2
       
  2014 		 *
       
  2015 		 * @param string $notify_message Text of the comment moderation email.
       
  2016 		 * @param int    $comment_id     Comment ID.
       
  2017 		 */
       
  2018 		$notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
       
  2019 
       
  2020 		/**
       
  2021 		 * Filters the comment moderation email subject.
       
  2022 		 *
       
  2023 		 * @since 1.5.2
       
  2024 		 *
       
  2025 		 * @param string $subject    Subject of the comment moderation email.
       
  2026 		 * @param int    $comment_id Comment ID.
       
  2027 		 */
       
  2028 		$subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
       
  2029 
       
  2030 		/**
       
  2031 		 * Filters the comment moderation email headers.
  1959 		 * Filters the comment moderation email headers.
  2032 		 *
  1960 		 *
  2033 		 * @since 2.8.0
  1961 		 * @since 2.8.0
  2034 		 *
  1962 		 *
  2035 		 * @param string $message_headers Headers for the comment moderation email.
  1963 		 * @param string $message_headers Headers for the comment moderation email.
  2036 		 * @param int    $comment_id      Comment ID.
  1964 		 * @param int    $comment_id      Comment ID.
  2037 		 */
  1965 		 */
  2038 		$message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
  1966 		$message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
  2039 
  1967 
  2040 		foreach ( $emails as $email ) {
  1968 		foreach ( $emails as $email ) {
       
  1969 			$user = get_user_by( 'email', $email );
       
  1970 
       
  1971 			if ( $user ) {
       
  1972 				$switched_locale = switch_to_user_locale( $user->ID );
       
  1973 			} else {
       
  1974 				$switched_locale = switch_to_locale( get_locale() );
       
  1975 			}
       
  1976 
       
  1977 			switch ( $comment->comment_type ) {
       
  1978 				case 'trackback':
       
  1979 					/* translators: %s: Post title. */
       
  1980 					$notify_message  = sprintf( __( 'A new trackback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
       
  1981 					$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
       
  1982 					/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1983 					$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1984 					/* translators: %s: Trackback/pingback/comment author URL. */
       
  1985 					$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1986 					$notify_message .= __( 'Trackback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
       
  1987 					break;
       
  1988 
       
  1989 				case 'pingback':
       
  1990 					/* translators: %s: Post title. */
       
  1991 					$notify_message  = sprintf( __( 'A new pingback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
       
  1992 					$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
       
  1993 					/* translators: 1: Trackback/pingback website name, 2: Website IP address, 3: Website hostname. */
       
  1994 					$notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  1995 					/* translators: %s: Trackback/pingback/comment author URL. */
       
  1996 					$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  1997 					$notify_message .= __( 'Pingback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
       
  1998 					break;
       
  1999 
       
  2000 				default: // Comments.
       
  2001 					/* translators: %s: Post title. */
       
  2002 					$notify_message  = sprintf( __( 'A new comment on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
       
  2003 					$notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
       
  2004 					/* translators: 1: Comment author's name, 2: Comment author's IP address, 3: Comment author's hostname. */
       
  2005 					$notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
       
  2006 					/* translators: %s: Comment author email. */
       
  2007 					$notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
       
  2008 					/* translators: %s: Trackback/pingback/comment author URL. */
       
  2009 					$notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
       
  2010 
       
  2011 					if ( $comment->comment_parent ) {
       
  2012 						/* translators: Comment moderation. %s: Parent comment edit URL. */
       
  2013 						$notify_message .= sprintf( __( 'In reply to: %s' ), admin_url( "comment.php?action=editcomment&c={$comment->comment_parent}#wpbody-content" ) ) . "\r\n";
       
  2014 					}
       
  2015 
       
  2016 					/* translators: %s: Comment text. */
       
  2017 					$notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
       
  2018 					break;
       
  2019 			}
       
  2020 
       
  2021 			/* translators: Comment moderation. %s: Comment action URL. */
       
  2022 			$notify_message .= sprintf( __( 'Approve it: %s' ), admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  2023 
       
  2024 			if ( EMPTY_TRASH_DAYS ) {
       
  2025 				/* translators: Comment moderation. %s: Comment action URL. */
       
  2026 				$notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  2027 			} else {
       
  2028 				/* translators: Comment moderation. %s: Comment action URL. */
       
  2029 				$notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  2030 			}
       
  2031 
       
  2032 			/* translators: Comment moderation. %s: Comment action URL. */
       
  2033 			$notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ) . "\r\n";
       
  2034 
       
  2035 			$notify_message .= sprintf(
       
  2036 				/* translators: Comment moderation. %s: Number of comments awaiting approval. */
       
  2037 				_n(
       
  2038 					'Currently %s comment is waiting for approval. Please visit the moderation panel:',
       
  2039 					'Currently %s comments are waiting for approval. Please visit the moderation panel:',
       
  2040 					$comments_waiting
       
  2041 				),
       
  2042 				number_format_i18n( $comments_waiting )
       
  2043 			) . "\r\n";
       
  2044 			$notify_message .= admin_url( 'edit-comments.php?comment_status=moderated#wpbody-content' ) . "\r\n";
       
  2045 
       
  2046 			/* translators: Comment moderation notification email subject. 1: Site title, 2: Post title. */
       
  2047 			$subject = sprintf( __( '[%1$s] Please moderate: "%2$s"' ), $blogname, $post->post_title );
       
  2048 
       
  2049 			/**
       
  2050 			 * Filters the comment moderation email text.
       
  2051 			 *
       
  2052 			 * @since 1.5.2
       
  2053 			 *
       
  2054 			 * @param string $notify_message Text of the comment moderation email.
       
  2055 			 * @param int    $comment_id     Comment ID.
       
  2056 			 */
       
  2057 			$notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
       
  2058 
       
  2059 			/**
       
  2060 			 * Filters the comment moderation email subject.
       
  2061 			 *
       
  2062 			 * @since 1.5.2
       
  2063 			 *
       
  2064 			 * @param string $subject    Subject of the comment moderation email.
       
  2065 			 * @param int    $comment_id Comment ID.
       
  2066 			 */
       
  2067 			$subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
       
  2068 
  2041 			wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
  2069 			wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
  2042 		}
  2070 
  2043 
  2071 			if ( $switched_locale ) {
  2044 		if ( $switched_locale ) {
  2072 				restore_previous_locale();
  2045 			restore_previous_locale();
  2073 			}
  2046 		}
  2074 		}
  2047 
  2075 
  2048 		return true;
  2076 		return true;
  2049 	}
  2077 	}
  2050 endif;
  2078 endif;
  2061 		/*
  2089 		/*
  2062 		 * Send a copy of password change notification to the admin,
  2090 		 * Send a copy of password change notification to the admin,
  2063 		 * but check to see if it's the admin whose password we're changing, and skip this.
  2091 		 * but check to see if it's the admin whose password we're changing, and skip this.
  2064 		 */
  2092 		 */
  2065 		if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
  2093 		if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
       
  2094 
       
  2095 			$admin_user = get_user_by( 'email', get_option( 'admin_email' ) );
       
  2096 
       
  2097 			if ( $admin_user ) {
       
  2098 				$switched_locale = switch_to_user_locale( $admin_user->ID );
       
  2099 			} else {
       
  2100 				$switched_locale = switch_to_locale( get_locale() );
       
  2101 			}
       
  2102 
  2066 			/* translators: %s: User name. */
  2103 			/* translators: %s: User name. */
  2067 			$message = sprintf( __( 'Password changed for user: %s' ), $user->user_login ) . "\r\n";
  2104 			$message = sprintf( __( 'Password changed for user: %s' ), $user->user_login ) . "\r\n";
  2068 			/*
  2105 			/*
  2069 			 * The blogname option is escaped with esc_html() on the way into the database in sanitize_option().
  2106 			 * The blogname option is escaped with esc_html() on the way into the database in sanitize_option().
  2070 			 * We want to reverse this for the plain text arena of emails.
  2107 			 * We want to reverse this for the plain text arena of emails.
  2101 				$wp_password_change_notification_email['to'],
  2138 				$wp_password_change_notification_email['to'],
  2102 				wp_specialchars_decode( sprintf( $wp_password_change_notification_email['subject'], $blogname ) ),
  2139 				wp_specialchars_decode( sprintf( $wp_password_change_notification_email['subject'], $blogname ) ),
  2103 				$wp_password_change_notification_email['message'],
  2140 				$wp_password_change_notification_email['message'],
  2104 				$wp_password_change_notification_email['headers']
  2141 				$wp_password_change_notification_email['headers']
  2105 			);
  2142 			);
       
  2143 
       
  2144 			if ( $switched_locale ) {
       
  2145 				restore_previous_locale();
       
  2146 			}
  2106 		}
  2147 		}
  2107 	}
  2148 	}
  2108 endif;
  2149 endif;
  2109 
  2150 
  2110 if ( ! function_exists( 'wp_new_user_notification' ) ) :
  2151 if ( ! function_exists( 'wp_new_user_notification' ) ) :
  2150 		 * @param WP_User $user User object for new user.
  2191 		 * @param WP_User $user User object for new user.
  2151 		 */
  2192 		 */
  2152 		$send_notification_to_admin = apply_filters( 'wp_send_new_user_notification_to_admin', true, $user );
  2193 		$send_notification_to_admin = apply_filters( 'wp_send_new_user_notification_to_admin', true, $user );
  2153 
  2194 
  2154 		if ( 'user' !== $notify && true === $send_notification_to_admin ) {
  2195 		if ( 'user' !== $notify && true === $send_notification_to_admin ) {
  2155 			$switched_locale = switch_to_locale( get_locale() );
  2196 
       
  2197 			$admin_user = get_user_by( 'email', get_option( 'admin_email' ) );
       
  2198 
       
  2199 			if ( $admin_user ) {
       
  2200 				$switched_locale = switch_to_user_locale( $admin_user->ID );
       
  2201 			} else {
       
  2202 				$switched_locale = switch_to_locale( get_locale() );
       
  2203 			}
  2156 
  2204 
  2157 			/* translators: %s: Site title. */
  2205 			/* translators: %s: Site title. */
  2158 			$message = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
  2206 			$message = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
  2159 			/* translators: %s: User login. */
  2207 			/* translators: %s: User login. */
  2160 			$message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
  2208 			$message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
  2222 		$switched_locale = switch_to_user_locale( $user_id );
  2270 		$switched_locale = switch_to_user_locale( $user_id );
  2223 
  2271 
  2224 		/* translators: %s: User login. */
  2272 		/* translators: %s: User login. */
  2225 		$message  = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
  2273 		$message  = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
  2226 		$message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n";
  2274 		$message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n";
  2227 		$message .= network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . "\r\n\r\n";
  2275 
       
  2276 		/*
       
  2277 		 * Since some user login names end in a period, this could produce ambiguous URLs that
       
  2278 		 * end in a period. To avoid the ambiguity, ensure that the login is not the last query
       
  2279 		 * arg in the URL. If moving it to the end, a trailing period will need to be escaped.
       
  2280 		 *
       
  2281 		 * @see https://core.trac.wordpress.org/tickets/42957
       
  2282 		 */
       
  2283 		$message .= network_site_url( 'wp-login.php?login=' . rawurlencode( $user->user_login ) . "&key=$key&action=rp", 'login' ) . "\r\n\r\n";
  2228 
  2284 
  2229 		$message .= wp_login_url() . "\r\n";
  2285 		$message .= wp_login_url() . "\r\n";
  2230 
  2286 
  2231 		$wp_new_user_notification_email = array(
  2287 		$wp_new_user_notification_email = array(
  2232 			'to'      => $user->user_email,
  2288 			'to'      => $user->user_email,
  2298 
  2354 
  2299 if ( ! function_exists( 'wp_verify_nonce' ) ) :
  2355 if ( ! function_exists( 'wp_verify_nonce' ) ) :
  2300 	/**
  2356 	/**
  2301 	 * Verifies that a correct security nonce was used with time limit.
  2357 	 * Verifies that a correct security nonce was used with time limit.
  2302 	 *
  2358 	 *
  2303 	 * A nonce is valid for 24 hours (by default).
  2359 	 * A nonce is valid for between 12 and 24 hours (by default).
  2304 	 *
  2360 	 *
  2305 	 * @since 2.0.3
  2361 	 * @since 2.0.3
  2306 	 *
  2362 	 *
  2307 	 * @param string     $nonce  Nonce value that was used for verification, usually via a form field.
  2363 	 * @param string     $nonce  Nonce value that was used for verification, usually via a form field.
  2308 	 * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
  2364 	 * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
  2436 			return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
  2492 			return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
  2437 		}
  2493 		}
  2438 
  2494 
  2439 		static $duplicated_keys;
  2495 		static $duplicated_keys;
  2440 		if ( null === $duplicated_keys ) {
  2496 		if ( null === $duplicated_keys ) {
  2441 			$duplicated_keys = array(
  2497 			$duplicated_keys = array();
  2442 				'put your unique phrase here' => true,
       
  2443 			);
       
  2444 
       
  2445 			/*
       
  2446 			 * translators: This string should only be translated if wp-config-sample.php is localized.
       
  2447 			 * You can check the localized release package or
       
  2448 			 * https://i18n.svn.wordpress.org/<locale code>/branches/<wp version>/dist/wp-config-sample.php
       
  2449 			 */
       
  2450 			$duplicated_keys[ __( 'put your unique phrase here' ) ] = true;
       
  2451 
  2498 
  2452 			foreach ( array( 'AUTH', 'SECURE_AUTH', 'LOGGED_IN', 'NONCE', 'SECRET' ) as $first ) {
  2499 			foreach ( array( 'AUTH', 'SECURE_AUTH', 'LOGGED_IN', 'NONCE', 'SECRET' ) as $first ) {
  2453 				foreach ( array( 'KEY', 'SALT' ) as $second ) {
  2500 				foreach ( array( 'KEY', 'SALT' ) as $second ) {
  2454 					if ( ! defined( "{$first}_{$second}" ) ) {
  2501 					if ( ! defined( "{$first}_{$second}" ) ) {
  2455 						continue;
  2502 						continue;
  2456 					}
  2503 					}
  2457 					$value                     = constant( "{$first}_{$second}" );
  2504 					$value                     = constant( "{$first}_{$second}" );
  2458 					$duplicated_keys[ $value ] = isset( $duplicated_keys[ $value ] );
  2505 					$duplicated_keys[ $value ] = isset( $duplicated_keys[ $value ] );
  2459 				}
  2506 				}
  2460 			}
  2507 			}
       
  2508 
       
  2509 			$duplicated_keys['put your unique phrase here'] = true;
       
  2510 
       
  2511 			/*
       
  2512 			 * translators: This string should only be translated if wp-config-sample.php is localized.
       
  2513 			 * You can check the localized release package or
       
  2514 			 * https://i18n.svn.wordpress.org/<locale code>/branches/<wp version>/dist/wp-config-sample.php
       
  2515 			 */
       
  2516 			$duplicated_keys[ __( 'put your unique phrase here' ) ] = true;
       
  2517 		}
       
  2518 
       
  2519 		/*
       
  2520 		 * Determine which options to prime.
       
  2521 		 *
       
  2522 		 * If the salt keys are undefined, use a duplicate value or the
       
  2523 		 * default `put your unique phrase here` value the salt will be
       
  2524 		 * generated via `wp_generate_password()` and stored as a site
       
  2525 		 * option. These options will be primed to avoid repeated
       
  2526 		 * database requests for undefined salts.
       
  2527 		 */
       
  2528 		$options_to_prime = array();
       
  2529 		foreach ( array( 'auth', 'secure_auth', 'logged_in', 'nonce' ) as $key ) {
       
  2530 			foreach ( array( 'key', 'salt' ) as $second ) {
       
  2531 				$const = strtoupper( "{$key}_{$second}" );
       
  2532 				if ( ! defined( $const ) || true === $duplicated_keys[ constant( $const ) ] ) {
       
  2533 					$options_to_prime[] = "{$key}_{$second}";
       
  2534 				}
       
  2535 			}
       
  2536 		}
       
  2537 
       
  2538 		if ( ! empty( $options_to_prime ) ) {
       
  2539 			/*
       
  2540 			 * Also prime `secret_key` used for undefined salting schemes.
       
  2541 			 *
       
  2542 			 * If the scheme is unknown, the default value for `secret_key` will be
       
  2543 			 * used too for the salt. This should rarely happen, so the option is only
       
  2544 			 * primed if other salts are undefined.
       
  2545 			 *
       
  2546 			 * At this point of execution it is known that a database call will be made
       
  2547 			 * to prime salts, so the `secret_key` option can be primed regardless of the
       
  2548 			 * constants status.
       
  2549 			 */
       
  2550 			$options_to_prime[] = 'secret_key';
       
  2551 			wp_prime_site_option_caches( $options_to_prime );
  2461 		}
  2552 		}
  2462 
  2553 
  2463 		$values = array(
  2554 		$values = array(
  2464 			'key'  => '',
  2555 			'key'  => '',
  2465 			'salt' => '',
  2556 			'salt' => '',
  2502 	}
  2593 	}
  2503 endif;
  2594 endif;
  2504 
  2595 
  2505 if ( ! function_exists( 'wp_hash' ) ) :
  2596 if ( ! function_exists( 'wp_hash' ) ) :
  2506 	/**
  2597 	/**
  2507 	 * Gets hash of given string.
  2598 	 * Gets the hash of the given string.
       
  2599 	 *
       
  2600 	 * The default algorithm is md5 but can be changed to any algorithm supported by
       
  2601 	 * `hash_hmac()`. Use the `hash_hmac_algos()` function to check the supported
       
  2602 	 * algorithms.
  2508 	 *
  2603 	 *
  2509 	 * @since 2.0.3
  2604 	 * @since 2.0.3
       
  2605 	 * @since 6.8.0 The `$algo` parameter was added.
       
  2606 	 *
       
  2607 	 * @throws InvalidArgumentException if the hashing algorithm is not supported.
  2510 	 *
  2608 	 *
  2511 	 * @param string $data   Plain text to hash.
  2609 	 * @param string $data   Plain text to hash.
  2512 	 * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce).
  2610 	 * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce).
       
  2611 	 * @param string $algo   Hashing algorithm to use. Default: 'md5'.
  2513 	 * @return string Hash of $data.
  2612 	 * @return string Hash of $data.
  2514 	 */
  2613 	 */
  2515 	function wp_hash( $data, $scheme = 'auth' ) {
  2614 	function wp_hash( $data, $scheme = 'auth', $algo = 'md5' ) {
  2516 		$salt = wp_salt( $scheme );
  2615 		$salt = wp_salt( $scheme );
  2517 
  2616 
  2518 		return hash_hmac( 'md5', $data, $salt );
  2617 		// Ensure the algorithm is supported by the hash_hmac function.
       
  2618 		if ( ! in_array( $algo, hash_hmac_algos(), true ) ) {
       
  2619 			throw new InvalidArgumentException(
       
  2620 				sprintf(
       
  2621 					/* translators: 1: Name of a cryptographic hash algorithm. 2: List of supported algorithms. */
       
  2622 					__( 'Unsupported hashing algorithm: %1$s. Supported algorithms are: %2$s' ),
       
  2623 					$algo,
       
  2624 					implode( ', ', hash_hmac_algos() )
       
  2625 				)
       
  2626 			);
       
  2627 		}
       
  2628 
       
  2629 		return hash_hmac( $algo, $data, $salt );
  2519 	}
  2630 	}
  2520 endif;
  2631 endif;
  2521 
  2632 
  2522 if ( ! function_exists( 'wp_hash_password' ) ) :
  2633 if ( ! function_exists( 'wp_hash_password' ) ) :
  2523 	/**
  2634 	/**
  2524 	 * Creates a hash (encrypt) of a plain text password.
  2635 	 * Creates a hash of a plain text password.
  2525 	 *
  2636 	 *
  2526 	 * For integration with other applications, this function can be overwritten to
  2637 	 * For integration with other applications, this function can be overwritten to
  2527 	 * instead use the other package password checking algorithm.
  2638 	 * instead use the other package password hashing algorithm.
  2528 	 *
  2639 	 *
  2529 	 * @since 2.5.0
  2640 	 * @since 2.5.0
  2530 	 *
  2641 	 * @since 6.8.0 The password is now hashed using bcrypt by default instead of phpass.
  2531 	 * @global PasswordHash $wp_hasher PHPass object.
  2642 	 *
       
  2643 	 * @global PasswordHash $wp_hasher phpass object.
  2532 	 *
  2644 	 *
  2533 	 * @param string $password Plain text user password to hash.
  2645 	 * @param string $password Plain text user password to hash.
  2534 	 * @return string The hash string of the password.
  2646 	 * @return string The hash string of the password.
  2535 	 */
  2647 	 */
  2536 	function wp_hash_password( $password ) {
  2648 	function wp_hash_password(
       
  2649 		#[\SensitiveParameter]
       
  2650 		$password
       
  2651 	) {
  2537 		global $wp_hasher;
  2652 		global $wp_hasher;
  2538 
  2653 
  2539 		if ( empty( $wp_hasher ) ) {
  2654 		if ( ! empty( $wp_hasher ) ) {
       
  2655 			return $wp_hasher->HashPassword( trim( $password ) );
       
  2656 		}
       
  2657 
       
  2658 		if ( strlen( $password ) > 4096 ) {
       
  2659 			return '*';
       
  2660 		}
       
  2661 
       
  2662 		/**
       
  2663 		 * Filters the hashing algorithm to use in the password_hash() and password_needs_rehash() functions.
       
  2664 		 *
       
  2665 		 * The default is the value of the `PASSWORD_BCRYPT` constant which means bcrypt is used.
       
  2666 		 *
       
  2667 		 * **Important:** The only password hashing algorithm that is guaranteed to be available across PHP
       
  2668 		 * installations is bcrypt. If you use any other algorithm you must make sure that it is available on
       
  2669 		 * the server. The `password_algos()` function can be used to check which hashing algorithms are available.
       
  2670 		 *
       
  2671 		 * The hashing options can be controlled via the {@see 'wp_hash_password_options'} filter.
       
  2672 		 *
       
  2673 		 * Other available constants include:
       
  2674 		 *
       
  2675 		 * - `PASSWORD_ARGON2I`
       
  2676 		 * - `PASSWORD_ARGON2ID`
       
  2677 		 * - `PASSWORD_DEFAULT`
       
  2678 		 *
       
  2679 		 * @since 6.8.0
       
  2680 		 *
       
  2681 		 * @param string $algorithm The hashing algorithm. Default is the value of the `PASSWORD_BCRYPT` constant.
       
  2682 		 */
       
  2683 		$algorithm = apply_filters( 'wp_hash_password_algorithm', PASSWORD_BCRYPT );
       
  2684 
       
  2685 		/**
       
  2686 		 * Filters the options passed to the password_hash() and password_needs_rehash() functions.
       
  2687 		 *
       
  2688 		 * The default hashing algorithm is bcrypt, but this can be changed via the {@see 'wp_hash_password_algorithm'}
       
  2689 		 * filter. You must ensure that the options are appropriate for the algorithm in use.
       
  2690 		 *
       
  2691 		 * @since 6.8.0
       
  2692 		 *
       
  2693 		 * @param array $options    Array of options to pass to the password hashing functions.
       
  2694 		 *                          By default this is an empty array which means the default
       
  2695 		 *                          options will be used.
       
  2696 		 * @param string $algorithm The hashing algorithm in use.
       
  2697 		 */
       
  2698 		$options = apply_filters( 'wp_hash_password_options', array(), $algorithm );
       
  2699 
       
  2700 		// Algorithms other than bcrypt don't need to use pre-hashing.
       
  2701 		if ( PASSWORD_BCRYPT !== $algorithm ) {
       
  2702 			return password_hash( $password, $algorithm, $options );
       
  2703 		}
       
  2704 
       
  2705 		// Use SHA-384 to retain entropy from a password that's longer than 72 bytes, and a `wp-sha384` key for domain separation.
       
  2706 		$password_to_hash = base64_encode( hash_hmac( 'sha384', trim( $password ), 'wp-sha384', true ) );
       
  2707 
       
  2708 		// Add a prefix to facilitate distinguishing vanilla bcrypt hashes.
       
  2709 		return '$wp' . password_hash( $password_to_hash, $algorithm, $options );
       
  2710 	}
       
  2711 endif;
       
  2712 
       
  2713 if ( ! function_exists( 'wp_check_password' ) ) :
       
  2714 	/**
       
  2715 	 * Checks a plaintext password against a hashed password.
       
  2716 	 *
       
  2717 	 * Note that this function may be used to check a value that is not a user password.
       
  2718 	 * A plugin may use this function to check a password of a different type, and there
       
  2719 	 * may not always be a user ID associated with the password.
       
  2720 	 *
       
  2721 	 * For integration with other applications, this function can be overwritten to
       
  2722 	 * instead use the other package password hashing algorithm.
       
  2723 	 *
       
  2724 	 * @since 2.5.0
       
  2725 	 * @since 6.8.0 Passwords in WordPress are now hashed with bcrypt by default. A
       
  2726 	 *              password that wasn't hashed with bcrypt will be checked with phpass.
       
  2727 	 *
       
  2728 	 * @global PasswordHash $wp_hasher phpass object. Used as a fallback for verifying
       
  2729 	 *                                 passwords that were hashed with phpass.
       
  2730 	 *
       
  2731 	 * @param string     $password Plaintext password.
       
  2732 	 * @param string     $hash     Hash of the password to check against.
       
  2733 	 * @param string|int $user_id  Optional. ID of a user associated with the password.
       
  2734 	 * @return bool False, if the $password does not match the hashed password.
       
  2735 	 */
       
  2736 	function wp_check_password(
       
  2737 		#[\SensitiveParameter]
       
  2738 		$password,
       
  2739 		$hash,
       
  2740 		$user_id = ''
       
  2741 	) {
       
  2742 		global $wp_hasher;
       
  2743 
       
  2744 		if ( strlen( $hash ) <= 32 ) {
       
  2745 			// Check the hash using md5 regardless of the current hashing mechanism.
       
  2746 			$check = hash_equals( $hash, md5( $password ) );
       
  2747 		} elseif ( ! empty( $wp_hasher ) ) {
       
  2748 			// Check the password using the overridden hasher.
       
  2749 			$check = $wp_hasher->CheckPassword( $password, $hash );
       
  2750 		} elseif ( strlen( $password ) > 4096 ) {
       
  2751 			// Passwords longer than 4096 characters are not supported.
       
  2752 			$check = false;
       
  2753 		} elseif ( str_starts_with( $hash, '$wp' ) ) {
       
  2754 			// Check the password using the current prefixed hash.
       
  2755 			$password_to_verify = base64_encode( hash_hmac( 'sha384', $password, 'wp-sha384', true ) );
       
  2756 			$check              = password_verify( $password_to_verify, substr( $hash, 3 ) );
       
  2757 		} elseif ( str_starts_with( $hash, '$P$' ) ) {
       
  2758 			// Check the password using phpass.
  2540 			require_once ABSPATH . WPINC . '/class-phpass.php';
  2759 			require_once ABSPATH . WPINC . '/class-phpass.php';
  2541 			// By default, use the portable hash from phpass.
  2760 			$check = ( new PasswordHash( 8, true ) )->CheckPassword( $password, $hash );
  2542 			$wp_hasher = new PasswordHash( 8, true );
  2761 		} else {
  2543 		}
  2762 			// Check the password using compat support for any non-prefixed hash.
  2544 
  2763 			$check = password_verify( $password, $hash );
  2545 		return $wp_hasher->HashPassword( trim( $password ) );
  2764 		}
  2546 	}
  2765 
  2547 endif;
  2766 		/**
  2548 
  2767 		 * Filters whether the plaintext password matches the hashed password.
  2549 if ( ! function_exists( 'wp_check_password' ) ) :
  2768 		 *
  2550 	/**
  2769 		 * @since 2.5.0
  2551 	 * Checks the plaintext password against the encrypted Password.
  2770 		 * @since 6.8.0 Passwords are now hashed with bcrypt by default.
  2552 	 *
  2771 		 *              Old passwords may still be hashed with phpass or md5.
  2553 	 * Maintains compatibility between old version and the new cookie authentication
  2772 		 *
  2554 	 * protocol using PHPass library. The $hash parameter is the encrypted password
  2773 		 * @param bool       $check    Whether the passwords match.
  2555 	 * and the function compares the plain text password when encrypted similarly
  2774 		 * @param string     $password The plaintext password.
  2556 	 * against the already encrypted password to see if they match.
  2775 		 * @param string     $hash     The hashed password.
  2557 	 *
  2776 		 * @param string|int $user_id  Optional ID of a user associated with the password.
  2558 	 * For integration with other applications, this function can be overwritten to
  2777 		 *                             Can be empty.
  2559 	 * instead use the other package password checking algorithm.
  2778 		 */
  2560 	 *
  2779 		return apply_filters( 'check_password', $check, $password, $hash, $user_id );
  2561 	 * @since 2.5.0
  2780 	}
  2562 	 *
  2781 endif;
  2563 	 * @global PasswordHash $wp_hasher PHPass object used for checking the password
  2782 
  2564 	 *                                 against the $hash + $password.
  2783 if ( ! function_exists( 'wp_password_needs_rehash' ) ) :
  2565 	 * @uses PasswordHash::CheckPassword
  2784 	/**
  2566 	 *
  2785 	 * Checks whether a password hash needs to be rehashed.
  2567 	 * @param string     $password Plaintext user's password.
  2786 	 *
  2568 	 * @param string     $hash     Hash of the user's password to check against.
  2787 	 * Passwords are hashed with bcrypt using the default cost. A password hashed in a prior version
  2569 	 * @param string|int $user_id  Optional. User ID.
  2788 	 * of WordPress may still be hashed with phpass and will need to be rehashed. If the default cost
  2570 	 * @return bool False, if the $password does not match the hashed password.
  2789 	 * or algorithm is changed in PHP or WordPress then a password hashed in a previous version will
  2571 	 */
  2790 	 * need to be rehashed.
  2572 	function wp_check_password( $password, $hash, $user_id = '' ) {
  2791 	 *
       
  2792 	 * Note that, just like wp_check_password(), this function may be used to check a value that is
       
  2793 	 * not a user password. A plugin may use this function to check a password of a different type,
       
  2794 	 * and there may not always be a user ID associated with the password.
       
  2795 	 *
       
  2796 	 * @since 6.8.0
       
  2797 	 *
       
  2798 	 * @global PasswordHash $wp_hasher phpass object.
       
  2799 	 *
       
  2800 	 * @param string     $hash    Hash of a password to check.
       
  2801 	 * @param string|int $user_id Optional. ID of a user associated with the password.
       
  2802 	 * @return bool Whether the hash needs to be rehashed.
       
  2803 	 */
       
  2804 	function wp_password_needs_rehash( $hash, $user_id = '' ) {
  2573 		global $wp_hasher;
  2805 		global $wp_hasher;
  2574 
  2806 
  2575 		// If the hash is still md5...
  2807 		if ( ! empty( $wp_hasher ) ) {
  2576 		if ( strlen( $hash ) <= 32 ) {
  2808 			return false;
  2577 			$check = hash_equals( $hash, md5( $password ) );
  2809 		}
  2578 			if ( $check && $user_id ) {
       
  2579 				// Rehash using new hash.
       
  2580 				wp_set_password( $password, $user_id );
       
  2581 				$hash = wp_hash_password( $password );
       
  2582 			}
       
  2583 
       
  2584 			/**
       
  2585 			 * Filters whether the plaintext password matches the encrypted password.
       
  2586 			 *
       
  2587 			 * @since 2.5.0
       
  2588 			 *
       
  2589 			 * @param bool       $check    Whether the passwords match.
       
  2590 			 * @param string     $password The plaintext password.
       
  2591 			 * @param string     $hash     The hashed password.
       
  2592 			 * @param string|int $user_id  User ID. Can be empty.
       
  2593 			 */
       
  2594 			return apply_filters( 'check_password', $check, $password, $hash, $user_id );
       
  2595 		}
       
  2596 
       
  2597 		/*
       
  2598 		 * If the stored hash is longer than an MD5,
       
  2599 		 * presume the new style phpass portable hash.
       
  2600 		 */
       
  2601 		if ( empty( $wp_hasher ) ) {
       
  2602 			require_once ABSPATH . WPINC . '/class-phpass.php';
       
  2603 			// By default, use the portable hash from phpass.
       
  2604 			$wp_hasher = new PasswordHash( 8, true );
       
  2605 		}
       
  2606 
       
  2607 		$check = $wp_hasher->CheckPassword( $password, $hash );
       
  2608 
  2810 
  2609 		/** This filter is documented in wp-includes/pluggable.php */
  2811 		/** This filter is documented in wp-includes/pluggable.php */
  2610 		return apply_filters( 'check_password', $check, $password, $hash, $user_id );
  2812 		$algorithm = apply_filters( 'wp_hash_password_algorithm', PASSWORD_BCRYPT );
       
  2813 
       
  2814 		/** This filter is documented in wp-includes/pluggable.php */
       
  2815 		$options = apply_filters( 'wp_hash_password_options', array(), $algorithm );
       
  2816 
       
  2817 		$prefixed = str_starts_with( $hash, '$wp' );
       
  2818 
       
  2819 		if ( ( PASSWORD_BCRYPT === $algorithm ) && ! $prefixed ) {
       
  2820 			// If bcrypt is in use and the hash is not prefixed then it needs to be rehashed.
       
  2821 			$needs_rehash = true;
       
  2822 		} else {
       
  2823 			// Otherwise check the hash minus its prefix if necessary.
       
  2824 			$hash_to_check = $prefixed ? substr( $hash, 3 ) : $hash;
       
  2825 			$needs_rehash  = password_needs_rehash( $hash_to_check, $algorithm, $options );
       
  2826 		}
       
  2827 
       
  2828 		/**
       
  2829 		 * Filters whether the password hash needs to be rehashed.
       
  2830 		 *
       
  2831 		 * @since 6.8.0
       
  2832 		 *
       
  2833 		 * @param bool       $needs_rehash Whether the password hash needs to be rehashed.
       
  2834 		 * @param string     $hash         The password hash.
       
  2835 		 * @param string|int $user_id      Optional. ID of a user associated with the password.
       
  2836 		 */
       
  2837 		return apply_filters( 'password_needs_rehash', $needs_rehash, $hash, $user_id );
  2611 	}
  2838 	}
  2612 endif;
  2839 endif;
  2613 
  2840 
  2614 if ( ! function_exists( 'wp_generate_password' ) ) :
  2841 if ( ! function_exists( 'wp_generate_password' ) ) :
  2615 	/**
  2842 	/**
  2747 	}
  2974 	}
  2748 endif;
  2975 endif;
  2749 
  2976 
  2750 if ( ! function_exists( 'wp_set_password' ) ) :
  2977 if ( ! function_exists( 'wp_set_password' ) ) :
  2751 	/**
  2978 	/**
  2752 	 * Updates the user's password with a new encrypted one.
  2979 	 * Updates the user's password with a new hashed one.
  2753 	 *
  2980 	 *
  2754 	 * For integration with other applications, this function can be overwritten to
  2981 	 * For integration with other applications, this function can be overwritten to
  2755 	 * instead use the other package password checking algorithm.
  2982 	 * instead use the other package password checking algorithm.
  2756 	 *
  2983 	 *
  2757 	 * Please note: This function should be used sparingly and is really only meant for single-time
  2984 	 * Please note: This function should be used sparingly and is really only meant for single-time
  2758 	 * application. Leveraging this improperly in a plugin or theme could result in an endless loop
  2985 	 * application. Leveraging this improperly in a plugin or theme could result in an endless loop
  2759 	 * of password resets if precautions are not taken to ensure it does not execute on every page load.
  2986 	 * of password resets if precautions are not taken to ensure it does not execute on every page load.
  2760 	 *
  2987 	 *
  2761 	 * @since 2.5.0
  2988 	 * @since 2.5.0
       
  2989 	 * @since 6.8.0 The password is now hashed using bcrypt by default instead of phpass.
  2762 	 *
  2990 	 *
  2763 	 * @global wpdb $wpdb WordPress database abstraction object.
  2991 	 * @global wpdb $wpdb WordPress database abstraction object.
  2764 	 *
  2992 	 *
  2765 	 * @param string $password The plaintext new user password.
  2993 	 * @param string $password The plaintext new user password.
  2766 	 * @param int    $user_id  User ID.
  2994 	 * @param int    $user_id  User ID.
  2767 	 */
  2995 	 */
  2768 	function wp_set_password( $password, $user_id ) {
  2996 	function wp_set_password(
       
  2997 		#[\SensitiveParameter]
       
  2998 		$password,
       
  2999 		$user_id
       
  3000 	) {
  2769 		global $wpdb;
  3001 		global $wpdb;
       
  3002 
       
  3003 		$old_user_data = get_userdata( $user_id );
  2770 
  3004 
  2771 		$hash = wp_hash_password( $password );
  3005 		$hash = wp_hash_password( $password );
  2772 		$wpdb->update(
  3006 		$wpdb->update(
  2773 			$wpdb->users,
  3007 			$wpdb->users,
  2774 			array(
  3008 			array(
  2782 
  3016 
  2783 		/**
  3017 		/**
  2784 		 * Fires after the user password is set.
  3018 		 * Fires after the user password is set.
  2785 		 *
  3019 		 *
  2786 		 * @since 6.2.0
  3020 		 * @since 6.2.0
  2787 		 *
  3021 		 * @since 6.7.0 The `$old_user_data` parameter was added.
  2788 		 * @param string $password The plaintext password just set.
  3022 		 *
  2789 		 * @param int    $user_id  The ID of the user whose password was just set.
  3023 		 * @param string  $password      The plaintext password just set.
  2790 		 */
  3024 		 * @param int     $user_id       The ID of the user whose password was just set.
  2791 		do_action( 'wp_set_password', $password, $user_id );
  3025 		 * @param WP_User $old_user_data Object containing user's data prior to update.
       
  3026 		 */
       
  3027 		do_action( 'wp_set_password', $password, $user_id, $old_user_data );
  2792 	}
  3028 	}
  2793 endif;
  3029 endif;
  2794 
  3030 
  2795 if ( ! function_exists( 'get_avatar' ) ) :
  3031 if ( ! function_exists( 'get_avatar' ) ) :
  2796 	/**
  3032 	/**