Make WordPress Core


Ignore:
Timestamp:
11/30/2017 11:09:33 PM (9 years ago)
Author:
pento
Message:

Code is Poetry.
WordPress' code just... wasn't.
This is now dealt with.

Props jrf, pento, netweb, GaryJ, jdgrimes, westonruter, Greg Sherwood from PHPCS, and everyone who's ever contributed to WPCS and PHPCS.
Fixes #41057.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/pluggable.php

    r42206 r42343  
    77 */
    88
    9 if ( !function_exists('wp_set_current_user') ) :
    10 /**
    11  * Changes the current user by ID or name.
    12  *
    13  * Set $id to null and specify a name if you do not know a user's ID.
    14  *
    15  * Some WordPress functionality is based on the current user and not based on
    16  * the signed in user. Therefore, it opens the ability to edit and perform
    17  * actions on users who aren't signed in.
    18  *
    19  * @since 2.0.3
    20  * @global WP_User $current_user The current user object which holds the user data.
    21  *
    22  * @param int    $id   User ID
    23  * @param string $name User's username
    24  * @return WP_User Current user User object
    25  */
    26 function wp_set_current_user($id, $name = '') {
    27         global $current_user;
    28 
    29         // If `$id` matches the user who's already current, there's nothing to do.
    30         if ( isset( $current_user )
     9if ( ! function_exists( 'wp_set_current_user' ) ) :
     10        /**
     11        * Changes the current user by ID or name.
     12        *
     13        * Set $id to null and specify a name if you do not know a user's ID.
     14        *
     15        * Some WordPress functionality is based on the current user and not based on
     16        * the signed in user. Therefore, it opens the ability to edit and perform
     17        * actions on users who aren't signed in.
     18        *
     19        * @since 2.0.3
     20        * @global WP_User $current_user The current user object which holds the user data.
     21        *
     22        * @param int    $id   User ID
     23        * @param string $name User's username
     24        * @return WP_User Current user User object
     25        */
     26        function wp_set_current_user( $id, $name = '' ) {
     27                global $current_user;
     28
     29                // If `$id` matches the user who's already current, there's nothing to do.
     30                if ( isset( $current_user )
    3131                && ( $current_user instanceof WP_User )
    3232                && ( $id == $current_user->ID )
    3333                && ( null !== $id )
    34         ) {
     34                ) {
     35                        return $current_user;
     36                }
     37
     38                $current_user = new WP_User( $id, $name );
     39
     40                setup_userdata( $current_user->ID );
     41
     42                /**
     43                 * Fires after the current user is set.
     44                 *
     45                 * @since 2.0.1
     46                 */
     47                do_action( 'set_current_user' );
     48
    3549                return $current_user;
    3650        }
    37 
    38         $current_user = new WP_User( $id, $name );
    39 
    40         setup_userdata( $current_user->ID );
    41 
    42         /**
    43          * Fires after the current user is set.
    44          *
    45          * @since 2.0.1
    46          */
    47         do_action( 'set_current_user' );
    48 
    49         return $current_user;
    50 }
    51 endif;
    52 
    53 if ( !function_exists('wp_get_current_user') ) :
    54 /**
    55  * Retrieve the current user object.
    56  *
    57  * Will set the current user, if the current user is not set. The current user
    58  * will be set to the logged-in person. If no user is logged-in, then it will
    59  * set the current user to 0, which is invalid and won't have any permissions.
    60  *
    61  * @since 2.0.3
    62  *
    63  * @see _wp_get_current_user()
    64  * @global WP_User $current_user Checks if the current user is set.
    65  *
    66  * @return WP_User Current WP_User instance.
    67  */
    68 function wp_get_current_user() {
    69         return _wp_get_current_user();
    70 }
    71 endif;
    72 
    73 if ( !function_exists('get_userdata') ) :
    74 /**
    75  * Retrieve user info by user ID.
    76  *
    77  * @since 0.71
    78  *
    79  * @param int $user_id User ID
    80  * @return WP_User|false WP_User object on success, false on failure.
    81  */
    82 function get_userdata( $user_id ) {
    83         return get_user_by( 'id', $user_id );
    84 }
    85 endif;
    86 
    87 if ( !function_exists('get_user_by') ) :
    88 /**
    89  * Retrieve user info by a given field
    90  *
    91  * @since 2.8.0
    92  * @since 4.4.0 Added 'ID' as an alias of 'id' for the `$field` parameter.
    93  *
    94  * @param string     $field The field to retrieve the user with. id | ID | slug | email | login.
    95  * @param int|string $value A value for $field. A user ID, slug, email address, or login name.
    96  * @return WP_User|false WP_User object on success, false on failure.
    97  */
    98 function get_user_by( $field, $value ) {
    99         $userdata = WP_User::get_data_by( $field, $value );
    100 
    101         if ( !$userdata )
    102                 return false;
    103 
    104         $user = new WP_User;
    105         $user->init( $userdata );
    106 
    107         return $user;
    108 }
    109 endif;
    110 
    111 if ( !function_exists('cache_users') ) :
    112 /**
    113  * Retrieve info for user lists to prevent multiple queries by get_userdata()
    114  *
    115  * @since 3.0.0
    116  *
    117  * @global wpdb $wpdb WordPress database abstraction object.
    118  *
    119  * @param array $user_ids User ID numbers list
    120  */
    121 function cache_users( $user_ids ) {
    122         global $wpdb;
    123 
    124         $clean = _get_non_cached_ids( $user_ids, 'users' );
    125 
    126         if ( empty( $clean ) )
    127                 return;
    128 
    129         $list = implode( ',', $clean );
    130 
    131         $users = $wpdb->get_results( "SELECT * FROM $wpdb->users WHERE ID IN ($list)" );
    132 
    133         $ids = array();
    134         foreach ( $users as $user ) {
    135                 update_user_caches( $user );
    136                 $ids[] = $user->ID;
    137         }
    138         update_meta_cache( 'user', $ids );
    139 }
    140 endif;
    141 
    142 if ( !function_exists( 'wp_mail' ) ) :
    143 /**
    144  * Send mail, similar to PHP's mail
    145  *
    146  * A true return value does not automatically mean that the user received the
    147  * email successfully. It just only means that the method used was able to
    148  * process the request without any errors.
    149  *
    150  * Using the two 'wp_mail_from' and 'wp_mail_from_name' hooks allow from
    151  * creating a from address like 'Name <email@address.com>' when both are set. If
    152  * just 'wp_mail_from' is set, then just the email address will be used with no
    153  * name.
    154  *
    155  * The default content type is 'text/plain' which does not allow using HTML.
    156  * However, you can set the content type of the email by using the
    157  * {@see 'wp_mail_content_type'} filter.
    158  *
    159  * The default charset is based on the charset used on the blog. The charset can
    160  * be set using the {@see 'wp_mail_charset'} filter.
    161  *
    162  * @since 1.2.1
    163  *
    164  * @global PHPMailer $phpmailer
    165  *
    166  * @param string|array $to          Array or comma-separated list of email addresses to send message.
    167  * @param string       $subject     Email subject
    168  * @param string       $message     Message contents
    169  * @param string|array $headers     Optional. Additional headers.
    170  * @param string|array $attachments Optional. Files to attach.
    171  * @return bool Whether the email contents were sent successfully.
    172  */
    173 function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
    174         // Compact the input, apply the filters, and extract them back out
    175 
    176         /**
    177          * Filters the wp_mail() arguments.
    178          *
    179          * @since 2.2.0
    180          *
    181          * @param array $args A compacted array of wp_mail() arguments, including the "to" email,
    182          *                    subject, message, headers, and attachments values.
    183          */
    184         $atts = apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) );
    185 
    186         if ( isset( $atts['to'] ) ) {
    187                 $to = $atts['to'];
    188         }
    189 
    190         if ( !is_array( $to ) ) {
    191                 $to = explode( ',', $to );
    192         }
    193 
    194         if ( isset( $atts['subject'] ) ) {
    195                 $subject = $atts['subject'];
    196         }
    197 
    198         if ( isset( $atts['message'] ) ) {
    199                 $message = $atts['message'];
    200         }
    201 
    202         if ( isset( $atts['headers'] ) ) {
    203                 $headers = $atts['headers'];
    204         }
    205 
    206         if ( isset( $atts['attachments'] ) ) {
    207                 $attachments = $atts['attachments'];
    208         }
    209 
    210         if ( ! is_array( $attachments ) ) {
    211                 $attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
    212         }
    213         global $phpmailer;
    214 
    215         // (Re)create it, if it's gone missing
    216         if ( ! ( $phpmailer instanceof PHPMailer ) ) {
    217                 require_once ABSPATH . WPINC . '/class-phpmailer.php';
    218                 require_once ABSPATH . WPINC . '/class-smtp.php';
    219                 $phpmailer = new PHPMailer( true );
    220         }
    221 
    222         // Headers
    223         $cc = $bcc = $reply_to = array();
    224 
    225         if ( empty( $headers ) ) {
    226                 $headers = array();
    227         } else {
    228                 if ( !is_array( $headers ) ) {
    229                         // Explode the headers out, so this function can take both
    230                         // string headers and an array of headers.
    231                         $tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );
     51endif;
     52
     53if ( ! function_exists( 'wp_get_current_user' ) ) :
     54        /**
     55         * Retrieve the current user object.
     56         *
     57         * Will set the current user, if the current user is not set. The current user
     58         * will be set to the logged-in person. If no user is logged-in, then it will
     59         * set the current user to 0, which is invalid and won't have any permissions.
     60         *
     61         * @since 2.0.3
     62         *
     63         * @see _wp_get_current_user()
     64         * @global WP_User $current_user Checks if the current user is set.
     65         *
     66         * @return WP_User Current WP_User instance.
     67         */
     68        function wp_get_current_user() {
     69                return _wp_get_current_user();
     70        }
     71endif;
     72
     73if ( ! function_exists( 'get_userdata' ) ) :
     74        /**
     75         * Retrieve user info by user ID.
     76         *
     77         * @since 0.71
     78         *
     79         * @param int $user_id User ID
     80         * @return WP_User|false WP_User object on success, false on failure.
     81         */
     82        function get_userdata( $user_id ) {
     83                return get_user_by( 'id', $user_id );
     84        }
     85endif;
     86
     87if ( ! function_exists( 'get_user_by' ) ) :
     88        /**
     89         * Retrieve user info by a given field
     90         *
     91         * @since 2.8.0
     92         * @since 4.4.0 Added 'ID' as an alias of 'id' for the `$field` parameter.
     93         *
     94         * @param string     $field The field to retrieve the user with. id | ID | slug | email | login.
     95         * @param int|string $value A value for $field. A user ID, slug, email address, or login name.
     96         * @return WP_User|false WP_User object on success, false on failure.
     97         */
     98        function get_user_by( $field, $value ) {
     99                $userdata = WP_User::get_data_by( $field, $value );
     100
     101                if ( ! $userdata ) {
     102                        return false;
     103                }
     104
     105                $user = new WP_User;
     106                $user->init( $userdata );
     107
     108                return $user;
     109        }
     110endif;
     111
     112if ( ! function_exists( 'cache_users' ) ) :
     113        /**
     114         * Retrieve info for user lists to prevent multiple queries by get_userdata()
     115         *
     116         * @since 3.0.0
     117         *
     118         * @global wpdb $wpdb WordPress database abstraction object.
     119         *
     120         * @param array $user_ids User ID numbers list
     121         */
     122        function cache_users( $user_ids ) {
     123                global $wpdb;
     124
     125                $clean = _get_non_cached_ids( $user_ids, 'users' );
     126
     127                if ( empty( $clean ) ) {
     128                        return;
     129                }
     130
     131                $list = implode( ',', $clean );
     132
     133                $users = $wpdb->get_results( "SELECT * FROM $wpdb->users WHERE ID IN ($list)" );
     134
     135                $ids = array();
     136                foreach ( $users as $user ) {
     137                        update_user_caches( $user );
     138                        $ids[] = $user->ID;
     139                }
     140                update_meta_cache( 'user', $ids );
     141        }
     142endif;
     143
     144if ( ! function_exists( 'wp_mail' ) ) :
     145        /**
     146         * Send mail, similar to PHP's mail
     147         *
     148         * A true return value does not automatically mean that the user received the
     149         * email successfully. It just only means that the method used was able to
     150         * process the request without any errors.
     151         *
     152         * Using the two 'wp_mail_from' and 'wp_mail_from_name' hooks allow from
     153         * creating a from address like 'Name <email@address.com>' when both are set. If
     154         * just 'wp_mail_from' is set, then just the email address will be used with no
     155         * name.
     156         *
     157         * The default content type is 'text/plain' which does not allow using HTML.
     158         * However, you can set the content type of the email by using the
     159         * {@see 'wp_mail_content_type'} filter.
     160         *
     161         * The default charset is based on the charset used on the blog. The charset can
     162         * be set using the {@see 'wp_mail_charset'} filter.
     163         *
     164         * @since 1.2.1
     165         *
     166         * @global PHPMailer $phpmailer
     167         *
     168         * @param string|array $to          Array or comma-separated list of email addresses to send message.
     169         * @param string       $subject     Email subject
     170         * @param string       $message     Message contents
     171         * @param string|array $headers     Optional. Additional headers.
     172         * @param string|array $attachments Optional. Files to attach.
     173         * @return bool Whether the email contents were sent successfully.
     174         */
     175        function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
     176                // Compact the input, apply the filters, and extract them back out
     177
     178                /**
     179                 * Filters the wp_mail() arguments.
     180                 *
     181                 * @since 2.2.0
     182                 *
     183                 * @param array $args A compacted array of wp_mail() arguments, including the "to" email,
     184                 *                    subject, message, headers, and attachments values.
     185                 */
     186                $atts = apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) );
     187
     188                if ( isset( $atts['to'] ) ) {
     189                        $to = $atts['to'];
     190                }
     191
     192                if ( ! is_array( $to ) ) {
     193                        $to = explode( ',', $to );
     194                }
     195
     196                if ( isset( $atts['subject'] ) ) {
     197                        $subject = $atts['subject'];
     198                }
     199
     200                if ( isset( $atts['message'] ) ) {
     201                        $message = $atts['message'];
     202                }
     203
     204                if ( isset( $atts['headers'] ) ) {
     205                        $headers = $atts['headers'];
     206                }
     207
     208                if ( isset( $atts['attachments'] ) ) {
     209                        $attachments = $atts['attachments'];
     210                }
     211
     212                if ( ! is_array( $attachments ) ) {
     213                        $attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
     214                }
     215                global $phpmailer;
     216
     217                // (Re)create it, if it's gone missing
     218                if ( ! ( $phpmailer instanceof PHPMailer ) ) {
     219                        require_once ABSPATH . WPINC . '/class-phpmailer.php';
     220                        require_once ABSPATH . WPINC . '/class-smtp.php';
     221                        $phpmailer = new PHPMailer( true );
     222                }
     223
     224                // Headers
     225                $cc = $bcc = $reply_to = array();
     226
     227                if ( empty( $headers ) ) {
     228                        $headers = array();
    232229                } else {
    233                         $tempheaders = $headers;
    234                 }
    235                 $headers = array();
    236 
    237                 // If it's actually got contents
    238                 if ( !empty( $tempheaders ) ) {
    239                         // Iterate through the raw headers
    240                         foreach ( (array) $tempheaders as $header ) {
    241                                 if ( strpos($header, ':') === false ) {
    242                                         if ( false !== stripos( $header, 'boundary=' ) ) {
    243                                                 $parts = preg_split('/boundary=/i', trim( $header ) );
    244                                                 $boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );
     230                        if ( ! is_array( $headers ) ) {
     231                                // Explode the headers out, so this function can take both
     232                                // string headers and an array of headers.
     233                                $tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );
     234                        } else {
     235                                $tempheaders = $headers;
     236                        }
     237                        $headers = array();
     238
     239                        // If it's actually got contents
     240                        if ( ! empty( $tempheaders ) ) {
     241                                // Iterate through the raw headers
     242                                foreach ( (array) $tempheaders as $header ) {
     243                                        if ( strpos( $header, ':' ) === false ) {
     244                                                if ( false !== stripos( $header, 'boundary=' ) ) {
     245                                                        $parts    = preg_split( '/boundary=/i', trim( $header ) );
     246                                                        $boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );
     247                                                }
     248                                                continue;
    245249                                        }
     250                                        // Explode them out
     251                                        list( $name, $content ) = explode( ':', trim( $header ), 2 );
     252
     253                                        // Cleanup crew
     254                                        $name    = trim( $name );
     255                                        $content = trim( $content );
     256
     257                                        switch ( strtolower( $name ) ) {
     258                                                // Mainly for legacy -- process a From: header if it's there
     259                                                case 'from':
     260                                                        $bracket_pos = strpos( $content, '<' );
     261                                                        if ( $bracket_pos !== false ) {
     262                                                                // Text before the bracketed email is the "From" name.
     263                                                                if ( $bracket_pos > 0 ) {
     264                                                                        $from_name = substr( $content, 0, $bracket_pos - 1 );
     265                                                                        $from_name = str_replace( '"', '', $from_name );
     266                                                                        $from_name = trim( $from_name );
     267                                                                }
     268
     269                                                                $from_email = substr( $content, $bracket_pos + 1 );
     270                                                                $from_email = str_replace( '>', '', $from_email );
     271                                                                $from_email = trim( $from_email );
     272
     273                                                                // Avoid setting an empty $from_email.
     274                                                        } elseif ( '' !== trim( $content ) ) {
     275                                                                $from_email = trim( $content );
     276                                                        }
     277                                                        break;
     278                                                case 'content-type':
     279                                                        if ( strpos( $content, ';' ) !== false ) {
     280                                                                list( $type, $charset_content ) = explode( ';', $content );
     281                                                                $content_type                   = trim( $type );
     282                                                                if ( false !== stripos( $charset_content, 'charset=' ) ) {
     283                                                                        $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset_content ) );
     284                                                                } elseif ( false !== stripos( $charset_content, 'boundary=' ) ) {
     285                                                                        $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset_content ) );
     286                                                                        $charset  = '';
     287                                                                }
     288
     289                                                                // Avoid setting an empty $content_type.
     290                                                        } elseif ( '' !== trim( $content ) ) {
     291                                                                $content_type = trim( $content );
     292                                                        }
     293                                                        break;
     294                                                case 'cc':
     295                                                        $cc = array_merge( (array) $cc, explode( ',', $content ) );
     296                                                        break;
     297                                                case 'bcc':
     298                                                        $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
     299                                                        break;
     300                                                case 'reply-to':
     301                                                        $reply_to = array_merge( (array) $reply_to, explode( ',', $content ) );
     302                                                        break;
     303                                                default:
     304                                                        // Add it to our grand headers array
     305                                                        $headers[ trim( $name ) ] = trim( $content );
     306                                                        break;
     307                                        }
     308                                }
     309                        }
     310                }
     311
     312                // Empty out the values that may be set
     313                $phpmailer->clearAllRecipients();
     314                $phpmailer->clearAttachments();
     315                $phpmailer->clearCustomHeaders();
     316                $phpmailer->clearReplyTos();
     317
     318                // From email and name
     319                // If we don't have a name from the input headers
     320                if ( ! isset( $from_name ) ) {
     321                        $from_name = 'WordPress';
     322                }
     323
     324                /* If we don't have an email from the input headers default to wordpress@$sitename
     325                 * Some hosts will block outgoing mail from this address if it doesn't exist but
     326                 * there's no easy alternative. Defaulting to admin_email might appear to be another
     327                 * option but some hosts may refuse to relay mail from an unknown domain. See
     328                 * https://core.trac.wordpress.org/ticket/5007.
     329                 */
     330
     331                if ( ! isset( $from_email ) ) {
     332                        // Get the site domain and get rid of www.
     333                        $sitename = strtolower( $_SERVER['SERVER_NAME'] );
     334                        if ( substr( $sitename, 0, 4 ) == 'www.' ) {
     335                                $sitename = substr( $sitename, 4 );
     336                        }
     337
     338                        $from_email = 'wordpress@' . $sitename;
     339                }
     340
     341                /**
     342                 * Filters the email address to send from.
     343                 *
     344                 * @since 2.2.0
     345                 *
     346                 * @param string $from_email Email address to send from.
     347                 */
     348                $from_email = apply_filters( 'wp_mail_from', $from_email );
     349
     350                /**
     351                 * Filters the name to associate with the "from" email address.
     352                 *
     353                 * @since 2.3.0
     354                 *
     355                 * @param string $from_name Name associated with the "from" email address.
     356                 */
     357                $from_name = apply_filters( 'wp_mail_from_name', $from_name );
     358
     359                try {
     360                        $phpmailer->setFrom( $from_email, $from_name, false );
     361                } catch ( phpmailerException $e ) {
     362                        $mail_error_data                             = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
     363                        $mail_error_data['phpmailer_exception_code'] = $e->getCode();
     364
     365                        /** This filter is documented in wp-includes/pluggable.php */
     366                        do_action( 'wp_mail_failed', new WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_error_data ) );
     367
     368                        return false;
     369                }
     370
     371                // Set mail's subject and body
     372                $phpmailer->Subject = $subject;
     373                $phpmailer->Body    = $message;
     374
     375                // Set destination addresses, using appropriate methods for handling addresses
     376                $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
     377
     378                foreach ( $address_headers as $address_header => $addresses ) {
     379                        if ( empty( $addresses ) ) {
     380                                continue;
     381                        }
     382
     383                        foreach ( (array) $addresses as $address ) {
     384                                try {
     385                                        // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
     386                                        $recipient_name = '';
     387
     388                                        if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) {
     389                                                if ( count( $matches ) == 3 ) {
     390                                                        $recipient_name = $matches[1];
     391                                                        $address        = $matches[2];
     392                                                }
     393                                        }
     394
     395                                        switch ( $address_header ) {
     396                                                case 'to':
     397                                                        $phpmailer->addAddress( $address, $recipient_name );
     398                                                        break;
     399                                                case 'cc':
     400                                                        $phpmailer->addCc( $address, $recipient_name );
     401                                                        break;
     402                                                case 'bcc':
     403                                                        $phpmailer->addBcc( $address, $recipient_name );
     404                                                        break;
     405                                                case 'reply_to':
     406                                                        $phpmailer->addReplyTo( $address, $recipient_name );
     407                                                        break;
     408                                        }
     409                                } catch ( phpmailerException $e ) {
    246410                                        continue;
    247411                                }
    248                                 // Explode them out
    249                                 list( $name, $content ) = explode( ':', trim( $header ), 2 );
    250 
    251                                 // Cleanup crew
    252                                 $name    = trim( $name    );
    253                                 $content = trim( $content );
    254 
    255                                 switch ( strtolower( $name ) ) {
    256                                         // Mainly for legacy -- process a From: header if it's there
    257                                         case 'from':
    258                                                 $bracket_pos = strpos( $content, '<' );
    259                                                 if ( $bracket_pos !== false ) {
    260                                                         // Text before the bracketed email is the "From" name.
    261                                                         if ( $bracket_pos > 0 ) {
    262                                                                 $from_name = substr( $content, 0, $bracket_pos - 1 );
    263                                                                 $from_name = str_replace( '"', '', $from_name );
    264                                                                 $from_name = trim( $from_name );
    265                                                         }
    266 
    267                                                         $from_email = substr( $content, $bracket_pos + 1 );
    268                                                         $from_email = str_replace( '>', '', $from_email );
    269                                                         $from_email = trim( $from_email );
    270 
    271                                                 // Avoid setting an empty $from_email.
    272                                                 } elseif ( '' !== trim( $content ) ) {
    273                                                         $from_email = trim( $content );
    274                                                 }
    275                                                 break;
    276                                         case 'content-type':
    277                                                 if ( strpos( $content, ';' ) !== false ) {
    278                                                         list( $type, $charset_content ) = explode( ';', $content );
    279                                                         $content_type = trim( $type );
    280                                                         if ( false !== stripos( $charset_content, 'charset=' ) ) {
    281                                                                 $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset_content ) );
    282                                                         } elseif ( false !== stripos( $charset_content, 'boundary=' ) ) {
    283                                                                 $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset_content ) );
    284                                                                 $charset = '';
    285                                                         }
    286 
    287                                                 // Avoid setting an empty $content_type.
    288                                                 } elseif ( '' !== trim( $content ) ) {
    289                                                         $content_type = trim( $content );
    290                                                 }
    291                                                 break;
    292                                         case 'cc':
    293                                                 $cc = array_merge( (array) $cc, explode( ',', $content ) );
    294                                                 break;
    295                                         case 'bcc':
    296                                                 $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
    297                                                 break;
    298                                         case 'reply-to':
    299                                                 $reply_to = array_merge( (array) $reply_to, explode( ',', $content ) );
    300                                                 break;
    301                                         default:
    302                                                 // Add it to our grand headers array
    303                                                 $headers[trim( $name )] = trim( $content );
    304                                                 break;
     412                        }
     413                }
     414
     415                // Set to use PHP's mail()
     416                $phpmailer->isMail();
     417
     418                // Set Content-Type and charset
     419                // If we don't have a content-type from the input headers
     420                if ( ! isset( $content_type ) ) {
     421                        $content_type = 'text/plain';
     422                }
     423
     424                /**
     425                 * Filters the wp_mail() content type.
     426                 *
     427                 * @since 2.3.0
     428                 *
     429                 * @param string $content_type Default wp_mail() content type.
     430                 */
     431                $content_type = apply_filters( 'wp_mail_content_type', $content_type );
     432
     433                $phpmailer->ContentType = $content_type;
     434
     435                // Set whether it's plaintext, depending on $content_type
     436                if ( 'text/html' == $content_type ) {
     437                        $phpmailer->isHTML( true );
     438                }
     439
     440                // If we don't have a charset from the input headers
     441                if ( ! isset( $charset ) ) {
     442                        $charset = get_bloginfo( 'charset' );
     443                }
     444
     445                // Set the content-type and charset
     446
     447                /**
     448                 * Filters the default wp_mail() charset.
     449                 *
     450                 * @since 2.3.0
     451                 *
     452                 * @param string $charset Default email charset.
     453                 */
     454                $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
     455
     456                // Set custom headers
     457                if ( ! empty( $headers ) ) {
     458                        foreach ( (array) $headers as $name => $content ) {
     459                                $phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
     460                        }
     461
     462                        if ( false !== stripos( $content_type, 'multipart' ) && ! empty( $boundary ) ) {
     463                                $phpmailer->addCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
     464                        }
     465                }
     466
     467                if ( ! empty( $attachments ) ) {
     468                        foreach ( $attachments as $attachment ) {
     469                                try {
     470                                        $phpmailer->addAttachment( $attachment );
     471                                } catch ( phpmailerException $e ) {
     472                                        continue;
    305473                                }
    306474                        }
    307475                }
    308         }
    309 
    310         // Empty out the values that may be set
    311         $phpmailer->clearAllRecipients();
    312         $phpmailer->clearAttachments();
    313         $phpmailer->clearCustomHeaders();
    314         $phpmailer->clearReplyTos();
    315 
    316         // From email and name
    317         // If we don't have a name from the input headers
    318         if ( !isset( $from_name ) )
    319                 $from_name = 'WordPress';
    320 
    321         /* If we don't have an email from the input headers default to wordpress@$sitename
    322          * Some hosts will block outgoing mail from this address if it doesn't exist but
    323          * there's no easy alternative. Defaulting to admin_email might appear to be another
    324          * option but some hosts may refuse to relay mail from an unknown domain. See
    325          * https://core.trac.wordpress.org/ticket/5007.
    326          */
    327 
    328         if ( !isset( $from_email ) ) {
    329                 // Get the site domain and get rid of www.
    330                 $sitename = strtolower( $_SERVER['SERVER_NAME'] );
    331                 if ( substr( $sitename, 0, 4 ) == 'www.' ) {
    332                         $sitename = substr( $sitename, 4 );
    333                 }
    334 
    335                 $from_email = 'wordpress@' . $sitename;
    336         }
    337 
    338         /**
    339          * Filters the email address to send from.
    340          *
    341          * @since 2.2.0
    342          *
    343          * @param string $from_email Email address to send from.
    344          */
    345         $from_email = apply_filters( 'wp_mail_from', $from_email );
    346 
    347         /**
    348          * Filters the name to associate with the "from" email address.
    349          *
    350          * @since 2.3.0
    351          *
    352          * @param string $from_name Name associated with the "from" email address.
    353          */
    354         $from_name = apply_filters( 'wp_mail_from_name', $from_name );
    355 
    356         try {
    357                 $phpmailer->setFrom( $from_email, $from_name, false );
    358         } catch ( phpmailerException $e ) {
    359                 $mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
    360                 $mail_error_data['phpmailer_exception_code'] = $e->getCode();
    361 
    362                 /** This filter is documented in wp-includes/pluggable.php */
    363                 do_action( 'wp_mail_failed', new WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_error_data ) );
    364 
    365                 return false;
    366         }
    367 
    368         // Set mail's subject and body
    369         $phpmailer->Subject = $subject;
    370         $phpmailer->Body    = $message;
    371 
    372         // Set destination addresses, using appropriate methods for handling addresses
    373         $address_headers = compact( 'to', 'cc', 'bcc', 'reply_to' );
    374 
    375         foreach ( $address_headers as $address_header => $addresses ) {
    376                 if ( empty( $addresses ) ) {
    377                         continue;
    378                 }
    379 
    380                 foreach ( (array) $addresses as $address ) {
    381                         try {
    382                                 // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
    383                                 $recipient_name = '';
    384 
    385                                 if ( preg_match( '/(.*)<(.+)>/', $address, $matches ) ) {
    386                                         if ( count( $matches ) == 3 ) {
    387                                                 $recipient_name = $matches[1];
    388                                                 $address        = $matches[2];
    389                                         }
    390                                 }
    391 
    392                                 switch ( $address_header ) {
    393                                         case 'to':
    394                                                 $phpmailer->addAddress( $address, $recipient_name );
    395                                                 break;
    396                                         case 'cc':
    397                                                 $phpmailer->addCc( $address, $recipient_name );
    398                                                 break;
    399                                         case 'bcc':
    400                                                 $phpmailer->addBcc( $address, $recipient_name );
    401                                                 break;
    402                                         case 'reply_to':
    403                                                 $phpmailer->addReplyTo( $address, $recipient_name );
    404                                                 break;
    405                                 }
    406                         } catch ( phpmailerException $e ) {
    407                                 continue;
    408                         }
    409                 }
    410         }
    411 
    412         // Set to use PHP's mail()
    413         $phpmailer->isMail();
    414 
    415         // Set Content-Type and charset
    416         // If we don't have a content-type from the input headers
    417         if ( !isset( $content_type ) )
    418                 $content_type = 'text/plain';
    419 
    420         /**
    421          * Filters the wp_mail() content type.
    422          *
    423          * @since 2.3.0
    424          *
    425          * @param string $content_type Default wp_mail() content type.
    426          */
    427         $content_type = apply_filters( 'wp_mail_content_type', $content_type );
    428 
    429         $phpmailer->ContentType = $content_type;
    430 
    431         // Set whether it's plaintext, depending on $content_type
    432         if ( 'text/html' == $content_type )
    433                 $phpmailer->isHTML( true );
    434 
    435         // If we don't have a charset from the input headers
    436         if ( !isset( $charset ) )
    437                 $charset = get_bloginfo( 'charset' );
    438 
    439         // Set the content-type and charset
    440 
    441         /**
    442          * Filters the default wp_mail() charset.
    443          *
    444          * @since 2.3.0
    445          *
    446          * @param string $charset Default email charset.
    447          */
    448         $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
    449 
    450         // Set custom headers
    451         if ( !empty( $headers ) ) {
    452                 foreach ( (array) $headers as $name => $content ) {
    453                         $phpmailer->addCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
    454                 }
    455 
    456                 if ( false !== stripos( $content_type, 'multipart' ) && ! empty($boundary) )
    457                         $phpmailer->addCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
    458         }
    459 
    460         if ( !empty( $attachments ) ) {
    461                 foreach ( $attachments as $attachment ) {
    462                         try {
    463                                 $phpmailer->addAttachment($attachment);
    464                         } catch ( phpmailerException $e ) {
    465                                 continue;
    466                         }
    467                 }
    468         }
    469 
    470         /**
    471          * Fires after PHPMailer is initialized.
    472          *
    473          * @since 2.2.0
    474          *
    475          * @param PHPMailer $phpmailer The PHPMailer instance (passed by reference).
    476          */
    477         do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
    478 
    479         // Send!
    480         try {
    481                 return $phpmailer->send();
    482         } catch ( phpmailerException $e ) {
    483 
    484                 $mail_error_data = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
    485                 $mail_error_data['phpmailer_exception_code'] = $e->getCode();
    486 
    487                 /**
    488                  * Fires after a phpmailerException is caught.
    489                  *
    490                  * @since 4.4.0
    491                  *
    492                  * @param WP_Error $error A WP_Error object with the phpmailerException message, and an array
    493                  *                        containing the mail recipient, subject, message, headers, and attachments.
    494                  */
    495                 do_action( 'wp_mail_failed', new WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_error_data ) );
    496 
    497                 return false;
    498         }
    499 }
    500 endif;
    501 
    502 if ( !function_exists('wp_authenticate') ) :
    503 /**
    504  * Authenticate a user, confirming the login credentials are valid.
    505  *
    506  * @since 2.5.0
    507  * @since 4.5.0 `$username` now accepts an email address.
    508  *
    509  * @param string $username User's username or email address.
    510  * @param string $password User's password.
    511  * @return WP_User|WP_Error WP_User object if the credentials are valid,
    512  *                          otherwise WP_Error.
    513  */
    514 function wp_authenticate($username, $password) {
    515         $username = sanitize_user($username);
    516         $password = trim($password);
    517 
    518         /**
    519          * Filters whether a set of user login credentials are valid.
    520          *
    521          * A WP_User object is returned if the credentials authenticate a user.
    522          * WP_Error or null otherwise.
    523          *
    524          * @since 2.8.0
     476
     477                /**
     478                 * Fires after PHPMailer is initialized.
     479                 *
     480                 * @since 2.2.0
     481                 *
     482                 * @param PHPMailer $phpmailer The PHPMailer instance (passed by reference).
     483                 */
     484                do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
     485
     486                // Send!
     487                try {
     488                        return $phpmailer->send();
     489                } catch ( phpmailerException $e ) {
     490
     491                        $mail_error_data                             = compact( 'to', 'subject', 'message', 'headers', 'attachments' );
     492                        $mail_error_data['phpmailer_exception_code'] = $e->getCode();
     493
     494                        /**
     495                         * Fires after a phpmailerException is caught.
     496                         *
     497                         * @since 4.4.0
     498                         *
     499                         * @param WP_Error $error A WP_Error object with the phpmailerException message, and an array
     500                         *                        containing the mail recipient, subject, message, headers, and attachments.
     501                         */
     502                        do_action( 'wp_mail_failed', new WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_error_data ) );
     503
     504                        return false;
     505                }
     506        }
     507endif;
     508
     509if ( ! function_exists( 'wp_authenticate' ) ) :
     510        /**
     511         * Authenticate a user, confirming the login credentials are valid.
     512         *
     513         * @since 2.5.0
    525514         * @since 4.5.0 `$username` now accepts an email address.
    526515         *
    527          * @param null|WP_User|WP_Error $user     WP_User if the user is authenticated.
    528          *                                        WP_Error or null otherwise.
    529          * @param string                $username Username or email address.
    530          * @param string                $password User password
    531          */
    532         $user = apply_filters( 'authenticate', null, $username, $password );
    533 
    534         if ( $user == null ) {
    535                 // TODO what should the error message be? (Or would these even happen?)
    536                 // Only needed if all authentication handlers fail to return anything.
    537                 $user = new WP_Error( 'authentication_failed', __( '<strong>ERROR</strong>: Invalid username, email address or incorrect password.' ) );
    538         }
    539 
    540         $ignore_codes = array('empty_username', 'empty_password');
    541 
    542         if (is_wp_error($user) && !in_array($user->get_error_code(), $ignore_codes) ) {
    543                 /**
    544                  * Fires after a user login has failed.
    545                  *
    546                  * @since 2.5.0
    547                  * @since 4.5.0 The value of `$username` can now be an email address.
    548                  *
    549                  * @param string $username Username or email address.
    550                  */
    551                 do_action( 'wp_login_failed', $username );
    552         }
    553 
    554         return $user;
    555 }
    556 endif;
    557 
    558 if ( !function_exists('wp_logout') ) :
    559 /**
    560  * Log the current user out.
    561  *
    562  * @since 2.5.0
    563  */
    564 function wp_logout() {
    565         wp_destroy_current_session();
    566         wp_clear_auth_cookie();
    567 
    568         /**
    569          * Fires after a user is logged-out.
    570          *
    571          * @since 1.5.0
    572          */
    573         do_action( 'wp_logout' );
    574 }
    575 endif;
    576 
    577 if ( !function_exists('wp_validate_auth_cookie') ) :
    578 /**
    579  * Validates authentication cookie.
    580  *
    581  * The checks include making sure that the authentication cookie is set and
    582  * pulling in the contents (if $cookie is not used).
    583  *
    584  * Makes sure the cookie is not expired. Verifies the hash in cookie is what is
    585  * should be and compares the two.
    586  *
    587  * @since 2.5.0
    588  *
    589  * @global int $login_grace_period
    590  *
    591  * @param string $cookie Optional. If used, will validate contents instead of cookie's
    592  * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
    593  * @return false|int False if invalid cookie, User ID if valid.
    594  */
    595 function wp_validate_auth_cookie($cookie = '', $scheme = '') {
    596         if ( ! $cookie_elements = wp_parse_auth_cookie($cookie, $scheme) ) {
    597                 /**
    598                  * Fires if an authentication cookie is malformed.
     516         * @param string $username User's username or email address.
     517         * @param string $password User's password.
     518         * @return WP_User|WP_Error WP_User object if the credentials are valid,
     519         *                          otherwise WP_Error.
     520         */
     521        function wp_authenticate( $username, $password ) {
     522                $username = sanitize_user( $username );
     523                $password = trim( $password );
     524
     525                /**
     526                 * Filters whether a set of user login credentials are valid.
     527                 *
     528                 * A WP_User object is returned if the credentials authenticate a user.
     529                 * WP_Error or null otherwise.
     530                 *
     531                 * @since 2.8.0
     532                 * @since 4.5.0 `$username` now accepts an email address.
     533                 *
     534                 * @param null|WP_User|WP_Error $user     WP_User if the user is authenticated.
     535                 *                                        WP_Error or null otherwise.
     536                 * @param string                $username Username or email address.
     537                 * @param string                $password User password
     538                 */
     539                $user = apply_filters( 'authenticate', null, $username, $password );
     540
     541                if ( $user == null ) {
     542                        // TODO what should the error message be? (Or would these even happen?)
     543                        // Only needed if all authentication handlers fail to return anything.
     544                        $user = new WP_Error( 'authentication_failed', __( '<strong>ERROR</strong>: Invalid username, email address or incorrect password.' ) );
     545                }
     546
     547                $ignore_codes = array( 'empty_username', 'empty_password' );
     548
     549                if ( is_wp_error( $user ) && ! in_array( $user->get_error_code(), $ignore_codes ) ) {
     550                        /**
     551                         * Fires after a user login has failed.
     552                         *
     553                         * @since 2.5.0
     554                         * @since 4.5.0 The value of `$username` can now be an email address.
     555                         *
     556                         * @param string $username Username or email address.
     557                         */
     558                        do_action( 'wp_login_failed', $username );
     559                }
     560
     561                return $user;
     562        }
     563endif;
     564
     565if ( ! function_exists( 'wp_logout' ) ) :
     566        /**
     567         * Log the current user out.
     568         *
     569         * @since 2.5.0
     570         */
     571        function wp_logout() {
     572                wp_destroy_current_session();
     573                wp_clear_auth_cookie();
     574
     575                /**
     576                 * Fires after a user is logged-out.
     577                 *
     578                 * @since 1.5.0
     579                 */
     580                do_action( 'wp_logout' );
     581        }
     582endif;
     583
     584if ( ! function_exists( 'wp_validate_auth_cookie' ) ) :
     585        /**
     586         * Validates authentication cookie.
     587         *
     588         * The checks include making sure that the authentication cookie is set and
     589         * pulling in the contents (if $cookie is not used).
     590         *
     591         * Makes sure the cookie is not expired. Verifies the hash in cookie is what is
     592         * should be and compares the two.
     593         *
     594         * @since 2.5.0
     595         *
     596         * @global int $login_grace_period
     597         *
     598         * @param string $cookie Optional. If used, will validate contents instead of cookie's
     599         * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
     600         * @return false|int False if invalid cookie, User ID if valid.
     601         */
     602        function wp_validate_auth_cookie( $cookie = '', $scheme = '' ) {
     603                if ( ! $cookie_elements = wp_parse_auth_cookie( $cookie, $scheme ) ) {
     604                        /**
     605                         * Fires if an authentication cookie is malformed.
     606                         *
     607                         * @since 2.7.0
     608                         *
     609                         * @param string $cookie Malformed auth cookie.
     610                         * @param string $scheme Authentication scheme. Values include 'auth', 'secure_auth',
     611                         *                       or 'logged_in'.
     612                         */
     613                        do_action( 'auth_cookie_malformed', $cookie, $scheme );
     614                        return false;
     615                }
     616
     617                $scheme   = $cookie_elements['scheme'];
     618                $username = $cookie_elements['username'];
     619                $hmac     = $cookie_elements['hmac'];
     620                $token    = $cookie_elements['token'];
     621                $expired  = $expiration = $cookie_elements['expiration'];
     622
     623                // Allow a grace period for POST and Ajax requests
     624                if ( wp_doing_ajax() || 'POST' == $_SERVER['REQUEST_METHOD'] ) {
     625                        $expired += HOUR_IN_SECONDS;
     626                }
     627
     628                // Quick check to see if an honest cookie has expired
     629                if ( $expired < time() ) {
     630                        /**
     631                         * Fires once an authentication cookie has expired.
     632                         *
     633                         * @since 2.7.0
     634                         *
     635                         * @param array $cookie_elements An array of data for the authentication cookie.
     636                         */
     637                        do_action( 'auth_cookie_expired', $cookie_elements );
     638                        return false;
     639                }
     640
     641                $user = get_user_by( 'login', $username );
     642                if ( ! $user ) {
     643                        /**
     644                         * Fires if a bad username is entered in the user authentication process.
     645                         *
     646                         * @since 2.7.0
     647                         *
     648                         * @param array $cookie_elements An array of data for the authentication cookie.
     649                         */
     650                        do_action( 'auth_cookie_bad_username', $cookie_elements );
     651                        return false;
     652                }
     653
     654                $pass_frag = substr( $user->user_pass, 8, 4 );
     655
     656                $key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
     657
     658                // If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
     659                $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
     660                $hash = hash_hmac( $algo, $username . '|' . $expiration . '|' . $token, $key );
     661
     662                if ( ! hash_equals( $hash, $hmac ) ) {
     663                        /**
     664                         * Fires if a bad authentication cookie hash is encountered.
     665                         *
     666                         * @since 2.7.0
     667                         *
     668                         * @param array $cookie_elements An array of data for the authentication cookie.
     669                         */
     670                        do_action( 'auth_cookie_bad_hash', $cookie_elements );
     671                        return false;
     672                }
     673
     674                $manager = WP_Session_Tokens::get_instance( $user->ID );
     675                if ( ! $manager->verify( $token ) ) {
     676                        do_action( 'auth_cookie_bad_session_token', $cookie_elements );
     677                        return false;
     678                }
     679
     680                // Ajax/POST grace period set above
     681                if ( $expiration < time() ) {
     682                        $GLOBALS['login_grace_period'] = 1;
     683                }
     684
     685                /**
     686                 * Fires once an authentication cookie has been validated.
    599687                 *
    600688                 * @since 2.7.0
    601689                 *
    602                  * @param string $cookie Malformed auth cookie.
    603                  * @param string $scheme Authentication scheme. Values include 'auth', 'secure_auth',
    604                  *                       or 'logged_in'.
    605                  */
    606                 do_action( 'auth_cookie_malformed', $cookie, $scheme );
    607                 return false;
    608         }
    609 
    610         $scheme = $cookie_elements['scheme'];
    611         $username = $cookie_elements['username'];
    612         $hmac = $cookie_elements['hmac'];
    613         $token = $cookie_elements['token'];
    614         $expired = $expiration = $cookie_elements['expiration'];
    615 
    616         // Allow a grace period for POST and Ajax requests
    617         if ( wp_doing_ajax() || 'POST' == $_SERVER['REQUEST_METHOD'] ) {
    618                 $expired += HOUR_IN_SECONDS;
    619         }
    620 
    621         // Quick check to see if an honest cookie has expired
    622         if ( $expired < time() ) {
    623                 /**
    624                  * Fires once an authentication cookie has expired.
    625                  *
    626                  * @since 2.7.0
    627                  *
    628                  * @param array $cookie_elements An array of data for the authentication cookie.
    629                  */
    630                 do_action( 'auth_cookie_expired', $cookie_elements );
    631                 return false;
    632         }
    633 
    634         $user = get_user_by('login', $username);
    635         if ( ! $user ) {
    636                 /**
    637                  * Fires if a bad username is entered in the user authentication process.
    638                  *
    639                  * @since 2.7.0
    640                  *
    641                  * @param array $cookie_elements An array of data for the authentication cookie.
    642                  */
    643                 do_action( 'auth_cookie_bad_username', $cookie_elements );
    644                 return false;
    645         }
    646 
    647         $pass_frag = substr($user->user_pass, 8, 4);
    648 
    649         $key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
    650 
    651         // If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
    652         $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
    653         $hash = hash_hmac( $algo, $username . '|' . $expiration . '|' . $token, $key );
    654 
    655         if ( ! hash_equals( $hash, $hmac ) ) {
    656                 /**
    657                  * Fires if a bad authentication cookie hash is encountered.
    658                  *
    659                  * @since 2.7.0
    660                  *
    661                  * @param array $cookie_elements An array of data for the authentication cookie.
    662                  */
    663                 do_action( 'auth_cookie_bad_hash', $cookie_elements );
    664                 return false;
    665         }
    666 
    667         $manager = WP_Session_Tokens::get_instance( $user->ID );
    668         if ( ! $manager->verify( $token ) ) {
    669                 do_action( 'auth_cookie_bad_session_token', $cookie_elements );
    670                 return false;
    671         }
    672 
    673         // Ajax/POST grace period set above
    674         if ( $expiration < time() ) {
    675                 $GLOBALS['login_grace_period'] = 1;
    676         }
    677 
    678         /**
    679          * Fires once an authentication cookie has been validated.
    680          *
    681          * @since 2.7.0
    682          *
    683          * @param array   $cookie_elements An array of data for the authentication cookie.
    684          * @param WP_User $user            User object.
    685          */
    686         do_action( 'auth_cookie_valid', $cookie_elements, $user );
    687 
    688         return $user->ID;
    689 }
    690 endif;
    691 
    692 if ( !function_exists('wp_generate_auth_cookie') ) :
    693 /**
    694  * Generate authentication cookie contents.
    695  *
    696  * @since 2.5.0
    697  * @since 4.0.0 The `$token` parameter was added.
    698  *
    699  * @param int    $user_id    User ID
    700  * @param int    $expiration The time the cookie expires as a UNIX timestamp.
    701  * @param string $scheme     Optional. The cookie scheme to use: auth, secure_auth, or logged_in
    702  * @param string $token      User's session token to use for this cookie
    703  * @return string Authentication cookie contents. Empty string if user does not exist.
    704  */
    705 function wp_generate_auth_cookie( $user_id, $expiration, $scheme = 'auth', $token = '' ) {
    706         $user = get_userdata($user_id);
    707         if ( ! $user ) {
    708                 return '';
    709         }
    710 
    711         if ( ! $token ) {
    712                 $manager = WP_Session_Tokens::get_instance( $user_id );
    713                 $token = $manager->create( $expiration );
    714         }
    715 
    716         $pass_frag = substr($user->user_pass, 8, 4);
    717 
    718         $key = wp_hash( $user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
    719 
    720         // If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
    721         $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
    722         $hash = hash_hmac( $algo, $user->user_login . '|' . $expiration . '|' . $token, $key );
    723 
    724         $cookie = $user->user_login . '|' . $expiration . '|' . $token . '|' . $hash;
    725 
    726         /**
    727          * Filters the authentication cookie.
     690                 * @param array   $cookie_elements An array of data for the authentication cookie.
     691                 * @param WP_User $user            User object.
     692                 */
     693                do_action( 'auth_cookie_valid', $cookie_elements, $user );
     694
     695                return $user->ID;
     696        }
     697endif;
     698
     699if ( ! function_exists( 'wp_generate_auth_cookie' ) ) :
     700        /**
     701         * Generate authentication cookie contents.
    728702         *
    729703         * @since 2.5.0
    730704         * @since 4.0.0 The `$token` parameter was added.
    731705         *
    732          * @param string $cookie     Authentication cookie.
    733          * @param int    $user_id    User ID.
     706         * @param int    $user_id    User ID
    734707         * @param int    $expiration The time the cookie expires as a UNIX timestamp.
    735          * @param string $scheme     Cookie scheme used. Accepts 'auth', 'secure_auth', or 'logged_in'.
    736          * @param string $token      User's session token used.
    737          */
    738         return apply_filters( 'auth_cookie', $cookie, $user_id, $expiration, $scheme, $token );
    739 }
    740 endif;
    741 
    742 if ( !function_exists('wp_parse_auth_cookie') ) :
    743 /**
    744  * Parse a cookie into its components
    745  *
    746  * @since 2.7.0
    747  *
    748  * @param string $cookie
    749  * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
    750  * @return array|false Authentication cookie components
    751  */
    752 function wp_parse_auth_cookie($cookie = '', $scheme = '') {
    753         if ( empty($cookie) ) {
    754                 switch ($scheme){
    755                         case 'auth':
    756                                 $cookie_name = AUTH_COOKIE;
    757                                 break;
    758                         case 'secure_auth':
    759                                 $cookie_name = SECURE_AUTH_COOKIE;
    760                                 break;
    761                         case "logged_in":
    762                                 $cookie_name = LOGGED_IN_COOKIE;
    763                                 break;
    764                         default:
    765                                 if ( is_ssl() ) {
     708         * @param string $scheme     Optional. The cookie scheme to use: auth, secure_auth, or logged_in
     709         * @param string $token      User's session token to use for this cookie
     710         * @return string Authentication cookie contents. Empty string if user does not exist.
     711         */
     712        function wp_generate_auth_cookie( $user_id, $expiration, $scheme = 'auth', $token = '' ) {
     713                $user = get_userdata( $user_id );
     714                if ( ! $user ) {
     715                        return '';
     716                }
     717
     718                if ( ! $token ) {
     719                        $manager = WP_Session_Tokens::get_instance( $user_id );
     720                        $token   = $manager->create( $expiration );
     721                }
     722
     723                $pass_frag = substr( $user->user_pass, 8, 4 );
     724
     725                $key = wp_hash( $user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme );
     726
     727                // If ext/hash is not present, compat.php's hash_hmac() does not support sha256.
     728                $algo = function_exists( 'hash' ) ? 'sha256' : 'sha1';
     729                $hash = hash_hmac( $algo, $user->user_login . '|' . $expiration . '|' . $token, $key );
     730
     731                $cookie = $user->user_login . '|' . $expiration . '|' . $token . '|' . $hash;
     732
     733                /**
     734                 * Filters the authentication cookie.
     735                 *
     736                 * @since 2.5.0
     737                 * @since 4.0.0 The `$token` parameter was added.
     738                 *
     739                 * @param string $cookie     Authentication cookie.
     740                 * @param int    $user_id    User ID.
     741                 * @param int    $expiration The time the cookie expires as a UNIX timestamp.
     742                 * @param string $scheme     Cookie scheme used. Accepts 'auth', 'secure_auth', or 'logged_in'.
     743                 * @param string $token      User's session token used.
     744                 */
     745                return apply_filters( 'auth_cookie', $cookie, $user_id, $expiration, $scheme, $token );
     746        }
     747endif;
     748
     749if ( ! function_exists( 'wp_parse_auth_cookie' ) ) :
     750        /**
     751         * Parse a cookie into its components
     752         *
     753         * @since 2.7.0
     754         *
     755         * @param string $cookie
     756         * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
     757         * @return array|false Authentication cookie components
     758         */
     759        function wp_parse_auth_cookie( $cookie = '', $scheme = '' ) {
     760                if ( empty( $cookie ) ) {
     761                        switch ( $scheme ) {
     762                                case 'auth':
     763                                        $cookie_name = AUTH_COOKIE;
     764                                        break;
     765                                case 'secure_auth':
    766766                                        $cookie_name = SECURE_AUTH_COOKIE;
    767                                         $scheme = 'secure_auth';
    768                                 } else {
    769                                         $cookie_name = AUTH_COOKIE;
    770                                         $scheme = 'auth';
    771                                 }
    772             }
    773 
    774                 if ( empty($_COOKIE[$cookie_name]) )
     767                                        break;
     768                                case 'logged_in':
     769                                        $cookie_name = LOGGED_IN_COOKIE;
     770                                        break;
     771                                default:
     772                                        if ( is_ssl() ) {
     773                                                $cookie_name = SECURE_AUTH_COOKIE;
     774                                                $scheme      = 'secure_auth';
     775                                        } else {
     776                                                $cookie_name = AUTH_COOKIE;
     777                                                $scheme      = 'auth';
     778                                        }
     779                        }
     780
     781                        if ( empty( $_COOKIE[ $cookie_name ] ) ) {
     782                                return false;
     783                        }
     784                        $cookie = $_COOKIE[ $cookie_name ];
     785                }
     786
     787                $cookie_elements = explode( '|', $cookie );
     788                if ( count( $cookie_elements ) !== 4 ) {
    775789                        return false;
    776                 $cookie = $_COOKIE[$cookie_name];
    777         }
    778 
    779         $cookie_elements = explode('|', $cookie);
    780         if ( count( $cookie_elements ) !== 4 ) {
    781                 return false;
    782         }
    783 
    784         list( $username, $expiration, $token, $hmac ) = $cookie_elements;
    785 
    786         return compact( 'username', 'expiration', 'token', 'hmac', 'scheme' );
    787 }
    788 endif;
    789 
    790 if ( !function_exists('wp_set_auth_cookie') ) :
    791 /**
    792  * Log in a user by setting authentication cookies.
    793  *
    794  * The $remember parameter increases the time that the cookie will be kept. The
    795  * default the cookie is kept without remembering is two days. When $remember is
    796  * set, the cookies will be kept for 14 days or two weeks.
    797  *
    798  * @since 2.5.0
    799  * @since 4.3.0 Added the `$token` parameter.
    800  *
    801  * @param int    $user_id  User ID
    802  * @param bool   $remember Whether to remember the user
    803  * @param mixed  $secure   Whether the admin cookies should only be sent over HTTPS.
    804  *                         Default is_ssl().
    805  * @param string $token    Optional. User's session token to use for this cookie.
    806  */
    807 function wp_set_auth_cookie( $user_id, $remember = false, $secure = '', $token = '' ) {
    808         if ( $remember ) {
    809                 /**
    810                  * Filters the duration of the authentication cookie expiration period.
    811                  *
    812                  * @since 2.8.0
    813                  *
    814                  * @param int  $length   Duration of the expiration period in seconds.
    815                  * @param int  $user_id  User ID.
    816                  * @param bool $remember Whether to remember the user login. Default false.
    817                  */
    818                 $expiration = time() + apply_filters( 'auth_cookie_expiration', 14 * DAY_IN_SECONDS, $user_id, $remember );
    819 
    820                 /*
    821                  * Ensure the browser will continue to send the cookie after the expiration time is reached.
    822                  * Needed for the login grace period in wp_validate_auth_cookie().
    823                  */
    824                 $expire = $expiration + ( 12 * HOUR_IN_SECONDS );
    825         } else {
     790                }
     791
     792                list( $username, $expiration, $token, $hmac ) = $cookie_elements;
     793
     794                return compact( 'username', 'expiration', 'token', 'hmac', 'scheme' );
     795        }
     796endif;
     797
     798if ( ! function_exists( 'wp_set_auth_cookie' ) ) :
     799        /**
     800         * Log in a user by setting authentication cookies.
     801         *
     802         * The $remember parameter increases the time that the cookie will be kept. The
     803         * default the cookie is kept without remembering is two days. When $remember is
     804         * set, the cookies will be kept for 14 days or two weeks.
     805         *
     806         * @since 2.5.0
     807         * @since 4.3.0 Added the `$token` parameter.
     808         *
     809         * @param int    $user_id  User ID
     810         * @param bool   $remember Whether to remember the user
     811         * @param mixed  $secure   Whether the admin cookies should only be sent over HTTPS.
     812         *                         Default is_ssl().
     813         * @param string $token    Optional. User's session token to use for this cookie.
     814         */
     815        function wp_set_auth_cookie( $user_id, $remember = false, $secure = '', $token = '' ) {
     816                if ( $remember ) {
     817                        /**
     818                         * Filters the duration of the authentication cookie expiration period.
     819                         *
     820                         * @since 2.8.0
     821                         *
     822                         * @param int  $length   Duration of the expiration period in seconds.
     823                         * @param int  $user_id  User ID.
     824                         * @param bool $remember Whether to remember the user login. Default false.
     825                         */
     826                        $expiration = time() + apply_filters( 'auth_cookie_expiration', 14 * DAY_IN_SECONDS, $user_id, $remember );
     827
     828                        /*
     829                         * Ensure the browser will continue to send the cookie after the expiration time is reached.
     830                         * Needed for the login grace period in wp_validate_auth_cookie().
     831                         */
     832                        $expire = $expiration + ( 12 * HOUR_IN_SECONDS );
     833                } else {
     834                        /** This filter is documented in wp-includes/pluggable.php */
     835                        $expiration = time() + apply_filters( 'auth_cookie_expiration', 2 * DAY_IN_SECONDS, $user_id, $remember );
     836                        $expire     = 0;
     837                }
     838
     839                if ( '' === $secure ) {
     840                        $secure = is_ssl();
     841                }
     842
     843                // Front-end cookie is secure when the auth cookie is secure and the site's home URL is forced HTTPS.
     844                $secure_logged_in_cookie = $secure && 'https' === parse_url( get_option( 'home' ), PHP_URL_SCHEME );
     845
     846                /**
     847                 * Filters whether the connection is secure.
     848                 *
     849                 * @since 3.1.0
     850                 *
     851                 * @param bool $secure  Whether the connection is secure.
     852                 * @param int  $user_id User ID.
     853                 */
     854                $secure = apply_filters( 'secure_auth_cookie', $secure, $user_id );
     855
     856                /**
     857                 * Filters whether to use a secure cookie when logged-in.
     858                 *
     859                 * @since 3.1.0
     860                 *
     861                 * @param bool $secure_logged_in_cookie Whether to use a secure cookie when logged-in.
     862                 * @param int  $user_id                 User ID.
     863                 * @param bool $secure                  Whether the connection is secure.
     864                 */
     865                $secure_logged_in_cookie = apply_filters( 'secure_logged_in_cookie', $secure_logged_in_cookie, $user_id, $secure );
     866
     867                if ( $secure ) {
     868                        $auth_cookie_name = SECURE_AUTH_COOKIE;
     869                        $scheme           = 'secure_auth';
     870                } else {
     871                        $auth_cookie_name = AUTH_COOKIE;
     872                        $scheme           = 'auth';
     873                }
     874
     875                if ( '' === $token ) {
     876                        $manager = WP_Session_Tokens::get_instance( $user_id );
     877                        $token   = $manager->create( $expiration );
     878                }
     879
     880                $auth_cookie      = wp_generate_auth_cookie( $user_id, $expiration, $scheme, $token );
     881                $logged_in_cookie = wp_generate_auth_cookie( $user_id, $expiration, 'logged_in', $token );
     882
     883                /**
     884                 * Fires immediately before the authentication cookie is set.
     885                 *
     886                 * @since 2.5.0
     887                 * @since 4.9.0 The `$token` parameter was added.
     888                 *
     889                 * @param string $auth_cookie Authentication cookie.
     890                 * @param int    $expire      The time the login grace period expires as a UNIX timestamp.
     891                 *                            Default is 12 hours past the cookie's expiration time.
     892                 * @param int    $expiration  The time when the authentication cookie expires as a UNIX timestamp.
     893                 *                            Default is 14 days from now.
     894                 * @param int    $user_id     User ID.
     895                 * @param string $scheme      Authentication scheme. Values include 'auth', 'secure_auth', or 'logged_in'.
     896                 * @param string $token       User's session token to use for this cookie.
     897                 */
     898                do_action( 'set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme, $token );
     899
     900                /**
     901                 * Fires immediately before the logged-in authentication cookie is set.
     902                 *
     903                 * @since 2.6.0
     904                 * @since 4.9.0 The `$token` parameter was added.
     905                 *
     906                 * @param string $logged_in_cookie The logged-in cookie.
     907                 * @param int    $expire           The time the login grace period expires as a UNIX timestamp.
     908                 *                                 Default is 12 hours past the cookie's expiration time.
     909                 * @param int    $expiration       The time when the logged-in authentication cookie expires as a UNIX timestamp.
     910                 *                                 Default is 14 days from now.
     911                 * @param int    $user_id          User ID.
     912                 * @param string $scheme           Authentication scheme. Default 'logged_in'.
     913                 * @param string $token            User's session token to use for this cookie.
     914                 */
     915                do_action( 'set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in', $token );
     916
     917                /**
     918                 * Allows preventing auth cookies from actually being sent to the client.
     919                 *
     920                 * @since 4.7.4
     921                 *
     922                 * @param bool $send Whether to send auth cookies to the client.
     923                 */
     924                if ( ! apply_filters( 'send_auth_cookies', true ) ) {
     925                        return;
     926                }
     927
     928                setcookie( $auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, true );
     929                setcookie( $auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true );
     930                setcookie( LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true );
     931                if ( COOKIEPATH != SITECOOKIEPATH ) {
     932                        setcookie( LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true );
     933                }
     934        }
     935endif;
     936
     937if ( ! function_exists( 'wp_clear_auth_cookie' ) ) :
     938        /**
     939         * Removes all of the cookies associated with authentication.
     940         *
     941         * @since 2.5.0
     942         */
     943        function wp_clear_auth_cookie() {
     944                /**
     945                 * Fires just before the authentication cookies are cleared.
     946                 *
     947                 * @since 2.7.0
     948                 */
     949                do_action( 'clear_auth_cookie' );
     950
    826951                /** This filter is documented in wp-includes/pluggable.php */
    827                 $expiration = time() + apply_filters( 'auth_cookie_expiration', 2 * DAY_IN_SECONDS, $user_id, $remember );
    828                 $expire = 0;
    829         }
    830 
    831         if ( '' === $secure ) {
    832                 $secure = is_ssl();
    833         }
    834 
    835         // Front-end cookie is secure when the auth cookie is secure and the site's home URL is forced HTTPS.
    836         $secure_logged_in_cookie = $secure && 'https' === parse_url( get_option( 'home' ), PHP_URL_SCHEME );
    837 
    838         /**
    839          * Filters whether the connection is secure.
    840          *
    841          * @since 3.1.0
    842          *
    843          * @param bool $secure  Whether the connection is secure.
    844          * @param int  $user_id User ID.
    845          */
    846         $secure = apply_filters( 'secure_auth_cookie', $secure, $user_id );
    847 
    848         /**
    849          * Filters whether to use a secure cookie when logged-in.
    850          *
    851          * @since 3.1.0
    852          *
    853          * @param bool $secure_logged_in_cookie Whether to use a secure cookie when logged-in.
    854          * @param int  $user_id                 User ID.
    855          * @param bool $secure                  Whether the connection is secure.
    856          */
    857         $secure_logged_in_cookie = apply_filters( 'secure_logged_in_cookie', $secure_logged_in_cookie, $user_id, $secure );
    858 
    859         if ( $secure ) {
    860                 $auth_cookie_name = SECURE_AUTH_COOKIE;
    861                 $scheme = 'secure_auth';
    862         } else {
    863                 $auth_cookie_name = AUTH_COOKIE;
    864                 $scheme = 'auth';
    865         }
    866 
    867         if ( '' === $token ) {
    868                 $manager = WP_Session_Tokens::get_instance( $user_id );
    869                 $token   = $manager->create( $expiration );
    870         }
    871 
    872         $auth_cookie = wp_generate_auth_cookie( $user_id, $expiration, $scheme, $token );
    873         $logged_in_cookie = wp_generate_auth_cookie( $user_id, $expiration, 'logged_in', $token );
    874 
    875         /**
    876          * Fires immediately before the authentication cookie is set.
    877          *
    878          * @since 2.5.0
    879          * @since 4.9.0 The `$token` parameter was added.
    880          *
    881          * @param string $auth_cookie Authentication cookie.
    882          * @param int    $expire      The time the login grace period expires as a UNIX timestamp.
    883          *                            Default is 12 hours past the cookie's expiration time.
    884          * @param int    $expiration  The time when the authentication cookie expires as a UNIX timestamp.
    885          *                            Default is 14 days from now.
    886          * @param int    $user_id     User ID.
    887          * @param string $scheme      Authentication scheme. Values include 'auth', 'secure_auth', or 'logged_in'.
    888          * @param string $token       User's session token to use for this cookie.
    889          */
    890         do_action( 'set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme, $token );
    891 
    892         /**
    893          * Fires immediately before the logged-in authentication cookie is set.
    894          *
    895          * @since 2.6.0
    896          * @since 4.9.0 The `$token` parameter was added.
    897          *
    898          * @param string $logged_in_cookie The logged-in cookie.
    899          * @param int    $expire           The time the login grace period expires as a UNIX timestamp.
    900          *                                 Default is 12 hours past the cookie's expiration time.
    901          * @param int    $expiration       The time when the logged-in authentication cookie expires as a UNIX timestamp.
    902          *                                 Default is 14 days from now.
    903          * @param int    $user_id          User ID.
    904          * @param string $scheme           Authentication scheme. Default 'logged_in'.
    905          * @param string $token            User's session token to use for this cookie.
    906          */
    907         do_action( 'set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in', $token );
    908 
    909         /**
    910          * Allows preventing auth cookies from actually being sent to the client.
    911          *
    912          * @since 4.7.4
    913          *
    914          * @param bool $send Whether to send auth cookies to the client.
    915          */
    916         if ( ! apply_filters( 'send_auth_cookies', true ) ) {
    917                 return;
    918         }
    919 
    920         setcookie($auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);
    921         setcookie($auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);
    922         setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);
    923         if ( COOKIEPATH != SITECOOKIEPATH )
    924                 setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);
    925 }
    926 endif;
    927 
    928 if ( !function_exists('wp_clear_auth_cookie') ) :
    929 /**
    930  * Removes all of the cookies associated with authentication.
    931  *
    932  * @since 2.5.0
    933  */
    934 function wp_clear_auth_cookie() {
    935         /**
    936          * Fires just before the authentication cookies are cleared.
    937          *
    938          * @since 2.7.0
    939          */
    940         do_action( 'clear_auth_cookie' );
    941 
    942         /** This filter is documented in wp-includes/pluggable.php */
    943         if ( ! apply_filters( 'send_auth_cookies', true ) ) {
    944                 return;
    945         }
    946 
    947         // Auth cookies
    948         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, ADMIN_COOKIE_PATH,   COOKIE_DOMAIN );
    949         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, ADMIN_COOKIE_PATH,   COOKIE_DOMAIN );
    950         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN );
    951         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN );
    952         setcookie( LOGGED_IN_COOKIE,   ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,          COOKIE_DOMAIN );
    953         setcookie( LOGGED_IN_COOKIE,   ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH,      COOKIE_DOMAIN );
    954 
    955         // Settings cookies
    956         setcookie( 'wp-settings-' . get_current_user_id(),      ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
    957         setcookie( 'wp-settings-time-' . get_current_user_id(), ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
    958 
    959         // Old cookies
    960         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
    961         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
    962         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
    963         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
    964 
    965         // Even older cookies
    966         setcookie( USER_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
    967         setcookie( PASS_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
    968         setcookie( USER_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
    969         setcookie( PASS_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
    970 }
    971 endif;
    972 
    973 if ( !function_exists('is_user_logged_in') ) :
    974 /**
    975  * Checks if the current visitor is a logged in user.
    976  *
    977  * @since 2.0.0
    978  *
    979  * @return bool True if user is logged in, false if not logged in.
    980  */
    981 function is_user_logged_in() {
    982         $user = wp_get_current_user();
    983 
    984         return $user->exists();
    985 }
    986 endif;
    987 
    988 if ( !function_exists('auth_redirect') ) :
    989 /**
    990  * Checks if a user is logged in, if not it redirects them to the login page.
    991  *
    992  * @since 1.5.0
    993  */
    994 function auth_redirect() {
    995         // Checks if a user is logged in, if not redirects them to the login page
    996 
    997         $secure = ( is_ssl() || force_ssl_admin() );
    998 
    999         /**
    1000          * Filters whether to use a secure authentication redirect.
    1001          *
    1002          * @since 3.1.0
    1003          *
    1004          * @param bool $secure Whether to use a secure authentication redirect. Default false.
    1005          */
    1006         $secure = apply_filters( 'secure_auth_redirect', $secure );
    1007 
    1008         // If https is required and request is http, redirect
    1009         if ( $secure && !is_ssl() && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
    1010                 if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
    1011                         wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
    1012                         exit();
    1013                 } else {
    1014                         wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
    1015                         exit();
    1016                 }
    1017         }
    1018 
    1019         /**
    1020          * Filters the authentication redirect scheme.
    1021          *
    1022          * @since 2.9.0
    1023          *
    1024          * @param string $scheme Authentication redirect scheme. Default empty.
    1025          */
    1026         $scheme = apply_filters( 'auth_redirect_scheme', '' );
    1027 
    1028         if ( $user_id = wp_validate_auth_cookie( '',  $scheme) ) {
    1029                 /**
    1030                  * Fires before the authentication redirect.
    1031                  *
    1032                  * @since 2.8.0
    1033                  *
    1034                  * @param int $user_id User ID.
    1035                  */
    1036                 do_action( 'auth_redirect', $user_id );
    1037 
    1038                 // If the user wants ssl but the session is not ssl, redirect.
    1039                 if ( !$secure && get_user_option('use_ssl', $user_id) && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
     952                if ( ! apply_filters( 'send_auth_cookies', true ) ) {
     953                        return;
     954                }
     955
     956                // Auth cookies
     957                setcookie( AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, ADMIN_COOKIE_PATH, COOKIE_DOMAIN );
     958                setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, ADMIN_COOKIE_PATH, COOKIE_DOMAIN );
     959                setcookie( AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN );
     960                setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN );
     961                setcookie( LOGGED_IN_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
     962                setcookie( LOGGED_IN_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
     963
     964                // Settings cookies
     965                setcookie( 'wp-settings-' . get_current_user_id(), ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
     966                setcookie( 'wp-settings-time-' . get_current_user_id(), ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH );
     967
     968                // Old cookies
     969                setcookie( AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
     970                setcookie( AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
     971                setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
     972                setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
     973
     974                // Even older cookies
     975                setcookie( USER_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
     976                setcookie( PASS_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
     977                setcookie( USER_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
     978                setcookie( PASS_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
     979        }
     980endif;
     981
     982if ( ! function_exists( 'is_user_logged_in' ) ) :
     983        /**
     984         * Checks if the current visitor is a logged in user.
     985         *
     986         * @since 2.0.0
     987         *
     988         * @return bool True if user is logged in, false if not logged in.
     989         */
     990        function is_user_logged_in() {
     991                $user = wp_get_current_user();
     992
     993                return $user->exists();
     994        }
     995endif;
     996
     997if ( ! function_exists( 'auth_redirect' ) ) :
     998        /**
     999         * Checks if a user is logged in, if not it redirects them to the login page.
     1000         *
     1001         * @since 1.5.0
     1002         */
     1003        function auth_redirect() {
     1004                // Checks if a user is logged in, if not redirects them to the login page
     1005
     1006                $secure = ( is_ssl() || force_ssl_admin() );
     1007
     1008                /**
     1009                 * Filters whether to use a secure authentication redirect.
     1010                 *
     1011                 * @since 3.1.0
     1012                 *
     1013                 * @param bool $secure Whether to use a secure authentication redirect. Default false.
     1014                 */
     1015                $secure = apply_filters( 'secure_auth_redirect', $secure );
     1016
     1017                // If https is required and request is http, redirect
     1018                if ( $secure && ! is_ssl() && false !== strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) ) {
    10401019                        if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
    10411020                                wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
    … …  
    10471026                }
    10481027
    1049                 return;  // The cookie is good so we're done
    1050         }
    1051 
    1052         // The cookie is no good so force login
    1053         nocache_headers();
    1054 
    1055         $redirect = ( strpos( $_SERVER['REQUEST_URI'], '/options.php' ) && wp_get_referer() ) ? wp_get_referer() : set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
    1056 
    1057         $login_url = wp_login_url($redirect, true);
    1058 
    1059         wp_redirect($login_url);
    1060         exit();
    1061 }
    1062 endif;
    1063 
    1064 if ( !function_exists('check_admin_referer') ) :
    1065 /**
    1066  * Makes sure that a user was referred from another admin page.
    1067  *
    1068  * To avoid security exploits.
    1069  *
    1070  * @since 1.2.0
    1071  *
    1072  * @param int|string $action    Action nonce.
    1073  * @param string     $query_arg Optional. Key to check for nonce in `$_REQUEST` (since 2.5).
    1074  *                              Default '_wpnonce'.
    1075  * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
    1076  *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
    1077  */
    1078 function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
    1079         if ( -1 == $action )
    1080                 _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2.0' );
    1081 
    1082         $adminurl = strtolower(admin_url());
    1083         $referer = strtolower(wp_get_referer());
    1084         $result = isset($_REQUEST[$query_arg]) ? wp_verify_nonce($_REQUEST[$query_arg], $action) : false;
    1085 
    1086         /**
    1087          * Fires once the admin request has been validated or not.
     1028                /**
     1029                 * Filters the authentication redirect scheme.
     1030                 *
     1031                 * @since 2.9.0
     1032                 *
     1033                 * @param string $scheme Authentication redirect scheme. Default empty.
     1034                 */
     1035                $scheme = apply_filters( 'auth_redirect_scheme', '' );
     1036
     1037                if ( $user_id = wp_validate_auth_cookie( '', $scheme ) ) {
     1038                        /**
     1039                         * Fires before the authentication redirect.
     1040                         *
     1041                         * @since 2.8.0
     1042                         *
     1043                         * @param int $user_id User ID.
     1044                         */
     1045                        do_action( 'auth_redirect', $user_id );
     1046
     1047                        // If the user wants ssl but the session is not ssl, redirect.
     1048                        if ( ! $secure && get_user_option( 'use_ssl', $user_id ) && false !== strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) ) {
     1049                                if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
     1050                                        wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
     1051                                        exit();
     1052                                } else {
     1053                                        wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
     1054                                        exit();
     1055                                }
     1056                        }
     1057
     1058                        return;  // The cookie is good so we're done
     1059                }
     1060
     1061                // The cookie is no good so force login
     1062                nocache_headers();
     1063
     1064                $redirect = ( strpos( $_SERVER['REQUEST_URI'], '/options.php' ) && wp_get_referer() ) ? wp_get_referer() : set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
     1065
     1066                $login_url = wp_login_url( $redirect, true );
     1067
     1068                wp_redirect( $login_url );
     1069                exit();
     1070        }
     1071endif;
     1072
     1073if ( ! function_exists( 'check_admin_referer' ) ) :
     1074        /**
     1075         * Makes sure that a user was referred from another admin page.
     1076         *
     1077         * To avoid security exploits.
     1078         *
     1079         * @since 1.2.0
     1080         *
     1081         * @param int|string $action    Action nonce.
     1082         * @param string     $query_arg Optional. Key to check for nonce in `$_REQUEST` (since 2.5).
     1083         *                              Default '_wpnonce'.
     1084         * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
     1085         *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
     1086         */
     1087        function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
     1088                if ( -1 == $action ) {
     1089                        _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2.0' );
     1090                }
     1091
     1092                $adminurl = strtolower( admin_url() );
     1093                $referer  = strtolower( wp_get_referer() );
     1094                $result   = isset( $_REQUEST[ $query_arg ] ) ? wp_verify_nonce( $_REQUEST[ $query_arg ], $action ) : false;
     1095
     1096                /**
     1097                 * Fires once the admin request has been validated or not.
     1098                 *
     1099                 * @since 1.5.1
     1100                 *
     1101                 * @param string    $action The nonce action.
     1102                 * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
     1103                 *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
     1104                 */
     1105                do_action( 'check_admin_referer', $action, $result );
     1106
     1107                if ( ! $result && ! ( -1 == $action && strpos( $referer, $adminurl ) === 0 ) ) {
     1108                        wp_nonce_ays( $action );
     1109                        die();
     1110                }
     1111
     1112                return $result;
     1113        }
     1114endif;
     1115
     1116if ( ! function_exists( 'check_ajax_referer' ) ) :
     1117        /**
     1118         * Verifies the Ajax request to prevent processing requests external of the blog.
     1119         *
     1120         * @since 2.0.3
     1121         *
     1122         * @param int|string   $action    Action nonce.
     1123         * @param false|string $query_arg Optional. Key to check for the nonce in `$_REQUEST` (since 2.5). If false,
     1124         *                                `$_REQUEST` values will be evaluated for '_ajax_nonce', and '_wpnonce'
     1125         *                                (in that order). Default false.
     1126         * @param bool         $die       Optional. Whether to die early when the nonce cannot be verified.
     1127         *                                Default true.
     1128         * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
     1129         *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
     1130         */
     1131        function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
     1132                if ( -1 == $action ) {
     1133                        _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '4.7' );
     1134                }
     1135
     1136                $nonce = '';
     1137
     1138                if ( $query_arg && isset( $_REQUEST[ $query_arg ] ) ) {
     1139                        $nonce = $_REQUEST[ $query_arg ];
     1140                } elseif ( isset( $_REQUEST['_ajax_nonce'] ) ) {
     1141                        $nonce = $_REQUEST['_ajax_nonce'];
     1142                } elseif ( isset( $_REQUEST['_wpnonce'] ) ) {
     1143                        $nonce = $_REQUEST['_wpnonce'];
     1144                }
     1145
     1146                $result = wp_verify_nonce( $nonce, $action );
     1147
     1148                /**
     1149                 * Fires once the Ajax request has been validated or not.
     1150                 *
     1151                 * @since 2.1.0
     1152                 *
     1153                 * @param string    $action The Ajax nonce action.
     1154                 * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
     1155                 *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
     1156                 */
     1157                do_action( 'check_ajax_referer', $action, $result );
     1158
     1159                if ( $die && false === $result ) {
     1160                        if ( wp_doing_ajax() ) {
     1161                                wp_die( -1, 403 );
     1162                        } else {
     1163                                die( '-1' );
     1164                        }
     1165                }
     1166
     1167                return $result;
     1168        }
     1169endif;
     1170
     1171if ( ! function_exists( 'wp_redirect' ) ) :
     1172        /**
     1173         * Redirects to another page.
     1174         *
     1175         * Note: wp_redirect() does not exit automatically, and should almost always be
     1176         * followed by a call to `exit;`:
     1177         *
     1178         *     wp_redirect( $url );
     1179         *     exit;
     1180         *
     1181         * Exiting can also be selectively manipulated by using wp_redirect() as a conditional
     1182         * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters:
     1183         *
     1184         *     if ( wp_redirect( $url ) ) {
     1185         *         exit;
     1186         *     }
    10881187         *
    10891188         * @since 1.5.1
    10901189         *
    1091          * @param string    $action The nonce action.
    1092          * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
    1093          *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
    1094          */
    1095         do_action( 'check_admin_referer', $action, $result );
    1096 
    1097         if ( ! $result && ! ( -1 == $action && strpos( $referer, $adminurl ) === 0 ) ) {
    1098                 wp_nonce_ays( $action );
    1099                 die();
    1100         }
    1101 
    1102         return $result;
    1103 }
    1104 endif;
    1105 
    1106 if ( !function_exists('check_ajax_referer') ) :
    1107 /**
    1108  * Verifies the Ajax request to prevent processing requests external of the blog.
    1109  *
    1110  * @since 2.0.3
    1111  *
    1112  * @param int|string   $action    Action nonce.
    1113  * @param false|string $query_arg Optional. Key to check for the nonce in `$_REQUEST` (since 2.5). If false,
    1114  *                                `$_REQUEST` values will be evaluated for '_ajax_nonce', and '_wpnonce'
    1115  *                                (in that order). Default false.
    1116  * @param bool         $die       Optional. Whether to die early when the nonce cannot be verified.
    1117  *                                Default true.
    1118  * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
    1119  *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
    1120  */
    1121 function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
    1122         if ( -1 == $action ) {
    1123                 _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '4.7' );
    1124         }
    1125 
    1126         $nonce = '';
    1127 
    1128         if ( $query_arg && isset( $_REQUEST[ $query_arg ] ) )
    1129                 $nonce = $_REQUEST[ $query_arg ];
    1130         elseif ( isset( $_REQUEST['_ajax_nonce'] ) )
    1131                 $nonce = $_REQUEST['_ajax_nonce'];
    1132         elseif ( isset( $_REQUEST['_wpnonce'] ) )
    1133                 $nonce = $_REQUEST['_wpnonce'];
    1134 
    1135         $result = wp_verify_nonce( $nonce, $action );
    1136 
    1137         /**
    1138          * Fires once the Ajax request has been validated or not.
    1139          *
    1140          * @since 2.1.0
    1141          *
    1142          * @param string    $action The Ajax nonce action.
    1143          * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
    1144          *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
    1145          */
    1146         do_action( 'check_ajax_referer', $action, $result );
    1147 
    1148         if ( $die && false === $result ) {
    1149                 if ( wp_doing_ajax() ) {
    1150                         wp_die( -1, 403 );
    1151                 } else {
    1152                         die( '-1' );
    1153                 }
    1154         }
    1155 
    1156         return $result;
    1157 }
    1158 endif;
    1159 
    1160 if ( !function_exists('wp_redirect') ) :
    1161 /**
    1162  * Redirects to another page.
    1163  *
    1164  * Note: wp_redirect() does not exit automatically, and should almost always be
    1165  * followed by a call to `exit;`:
    1166  *
    1167  *     wp_redirect( $url );
    1168  *     exit;
    1169  *
    1170  * Exiting can also be selectively manipulated by using wp_redirect() as a conditional
    1171  * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters:
    1172  *
    1173  *     if ( wp_redirect( $url ) ) {
    1174  *         exit;
    1175  *     }
    1176  *
    1177  * @since 1.5.1
    1178  *
    1179  * @global bool $is_IIS
    1180  *
    1181  * @param string $location The path or URL to redirect to.
    1182  * @param int    $status   Optional. HTTP response status code to use. Default '302' (Moved Temporarily).
    1183  * @return bool False if the redirect was cancelled, true otherwise.
    1184  */
    1185 function wp_redirect($location, $status = 302) {
    1186         global $is_IIS;
    1187 
    1188         /**
    1189          * Filters the redirect location.
    1190          *
    1191          * @since 2.1.0
     1190         * @global bool $is_IIS
    11921191         *
    11931192         * @param string $location The path or URL to redirect to.
    1194          * @param int    $status   The HTTP response status code to use.
    1195          */
    1196         $location = apply_filters( 'wp_redirect', $location, $status );
    1197 
    1198         /**
    1199          * Filters the redirect HTTP response status code to use.
     1193         * @param int    $status   Optional. HTTP response status code to use. Default '302' (Moved Temporarily).
     1194         * @return bool False if the redirect was cancelled, true otherwise.
     1195         */
     1196        function wp_redirect( $location, $status = 302 ) {
     1197                global $is_IIS;
     1198
     1199                /**
     1200                 * Filters the redirect location.
     1201                 *
     1202                 * @since 2.1.0
     1203                 *
     1204                 * @param string $location The path or URL to redirect to.
     1205                 * @param int    $status   The HTTP response status code to use.
     1206                 */
     1207                $location = apply_filters( 'wp_redirect', $location, $status );
     1208
     1209                /**
     1210                 * Filters the redirect HTTP response status code to use.
     1211                 *
     1212                 * @since 2.3.0
     1213                 *
     1214                 * @param int    $status   The HTTP response status code to use.
     1215                 * @param string $location The path or URL to redirect to.
     1216                 */
     1217                $status = apply_filters( 'wp_redirect_status', $status, $location );
     1218
     1219                if ( ! $location ) {
     1220                        return false;
     1221                }
     1222
     1223                $location = wp_sanitize_redirect( $location );
     1224
     1225                if ( ! $is_IIS && PHP_SAPI != 'cgi-fcgi' ) {
     1226                        status_header( $status ); // This causes problems on IIS and some FastCGI setups
     1227                }
     1228
     1229                header( "Location: $location", true, $status );
     1230
     1231                return true;
     1232        }
     1233endif;
     1234
     1235if ( ! function_exists( 'wp_sanitize_redirect' ) ) :
     1236        /**
     1237         * Sanitizes a URL for use in a redirect.
    12001238         *
    12011239         * @since 2.3.0
    12021240         *
    1203          * @param int    $status   The HTTP response status code to use.
    1204          * @param string $location The path or URL to redirect to.
    1205          */
    1206         $status = apply_filters( 'wp_redirect_status', $status, $location );
    1207 
    1208         if ( ! $location )
    1209                 return false;
    1210 
    1211         $location = wp_sanitize_redirect($location);
    1212 
    1213         if ( !$is_IIS && PHP_SAPI != 'cgi-fcgi' )
    1214                 status_header($status); // This causes problems on IIS and some FastCGI setups
    1215 
    1216         header("Location: $location", true, $status);
    1217 
    1218         return true;
    1219 }
    1220 endif;
    1221 
    1222 if ( !function_exists('wp_sanitize_redirect') ) :
    1223 /**
    1224  * Sanitizes a URL for use in a redirect.
    1225  *
    1226  * @since 2.3.0
    1227  *
    1228  * @param string $location The path to redirect to.
    1229  * @return string Redirect-sanitized URL.
    1230  **/
    1231 function wp_sanitize_redirect($location) {
    1232         $regex = '/
     1241         * @param string $location The path to redirect to.
     1242         * @return string Redirect-sanitized URL.
     1243         */
     1244        function wp_sanitize_redirect( $location ) {
     1245                $regex    = '/
    12331246                (
    12341247                        (?: [\xC2-\xDF][\x80-\xBF]        # double-byte sequences   110xxxxx 10xxxxxx
    … …  
    12421255                ){1,40}                              # ...one or more times
    12431256                )/x';
    1244         $location = preg_replace_callback( $regex, '_wp_sanitize_utf8_in_redirect', $location );
    1245         $location = preg_replace('|[^a-z0-9-~+_.?#=&;,/:%!*\[\]()@]|i', '', $location);
    1246         $location = wp_kses_no_null($location);
    1247 
    1248         // remove %0d and %0a from location
    1249         $strip = array('%0d', '%0a', '%0D', '%0A');
    1250         return _deep_replace( $strip, $location );
    1251 }
    1252 
    1253 /**
    1254  * URL encode UTF-8 characters in a URL.
    1255  *
    1256  * @ignore
    1257  * @since 4.2.0
    1258  * @access private
    1259  *
    1260  * @see wp_sanitize_redirect()
    1261  *
    1262  * @param array $matches RegEx matches against the redirect location.
    1263  * @return string URL-encoded version of the first RegEx match.
    1264  */
    1265 function _wp_sanitize_utf8_in_redirect( $matches ) {
    1266         return urlencode( $matches[0] );
    1267 }
    1268 endif;
    1269 
    1270 if ( !function_exists('wp_safe_redirect') ) :
    1271 /**
    1272  * Performs a safe (local) redirect, using wp_redirect().
    1273  *
    1274  * Checks whether the $location is using an allowed host, if it has an absolute
    1275  * path. A plugin can therefore set or remove allowed host(s) to or from the
    1276  * list.
    1277  *
    1278  * If the host is not allowed, then the redirect defaults to wp-admin on the siteurl
    1279  * instead. This prevents malicious redirects which redirect to another host,
    1280  * but only used in a few places.
    1281  *
    1282  * Note: wp_safe_redirect() does not exit automatically, and should almost always be
    1283  * followed by a call to `exit;`:
    1284  *
    1285  *     wp_safe_redirect( $url );
    1286  *     exit;
    1287  *
    1288  * Exiting can also be selectively manipulated by using wp_safe_redirect() as a conditional
    1289  * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters:
    1290  *
    1291  *     if ( wp_safe_redirect( $url ) ) {
    1292  *         exit;
    1293  *     }
    1294  *
    1295  * @since 2.3.0
    1296  * @since 5.0.0 The return value from wp_redirect() is now passed on.
    1297  *
    1298  * @param string $location The path or URL to redirect to.
    1299  * @param int    $status   Optional. HTTP response status code to use. Default '302' (Moved Temporarily).
    1300  * @return bool  $redirect False if the redirect was cancelled, true otherwise.
    1301  */
    1302 function wp_safe_redirect($location, $status = 302) {
    1303 
    1304         // Need to look at the URL the way it will end up in wp_redirect()
    1305         $location = wp_sanitize_redirect($location);
    1306 
    1307         /**
    1308          * Filters the redirect fallback URL for when the provided redirect is not safe (local).
    1309          *
    1310          * @since 4.3.0
    1311          *
    1312          * @param string $fallback_url The fallback URL to use by default.
    1313          * @param int    $status       The HTTP response status code to use.
    1314          */
    1315         $location = wp_validate_redirect( $location, apply_filters( 'wp_safe_redirect_fallback', admin_url(), $status ) );
    1316 
    1317         return wp_redirect( $location, $status );
    1318 }
    1319 endif;
    1320 
    1321 if ( !function_exists('wp_validate_redirect') ) :
    1322 /**
    1323  * Validates a URL for use in a redirect.
    1324  *
    1325  * Checks whether the $location is using an allowed host, if it has an absolute
    1326  * path. A plugin can therefore set or remove allowed host(s) to or from the
    1327  * list.
    1328  *
    1329  * If the host is not allowed, then the redirect is to $default supplied
    1330  *
    1331  * @since 2.8.1
    1332  *
    1333  * @param string $location The redirect to validate
    1334  * @param string $default  The value to return if $location is not allowed
    1335  * @return string redirect-sanitized URL
    1336  **/
    1337 function wp_validate_redirect($location, $default = '') {
    1338         $location = trim( $location, " \t\n\r\0\x08\x0B" );
    1339         // browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'
    1340         if ( substr($location, 0, 2) == '//' )
    1341                 $location = 'http:' . $location;
    1342 
    1343         // In php 5 parse_url may fail if the URL query part contains http://, bug #38143
    1344         $test = ( $cut = strpos($location, '?') ) ? substr( $location, 0, $cut ) : $location;
    1345 
    1346         // @-operator is used to prevent possible warnings in PHP < 5.3.3.
    1347         $lp = @parse_url($test);
    1348 
    1349         // Give up if malformed URL
    1350         if ( false === $lp )
    1351                 return $default;
    1352 
    1353         // Allow only http and https schemes. No data:, etc.
    1354         if ( isset($lp['scheme']) && !('http' == $lp['scheme'] || 'https' == $lp['scheme']) )
    1355                 return $default;
    1356 
    1357         // Reject if certain components are set but host is not. This catches urls like https:host.com for which parse_url does not set the host field.
    1358         if ( ! isset( $lp['host'] ) && ( isset( $lp['scheme'] ) || isset( $lp['user'] ) || isset( $lp['pass'] ) || isset( $lp['port'] ) ) ) {
    1359                 return $default;
    1360         }
    1361 
    1362         // Reject malformed components parse_url() can return on odd inputs.
    1363         foreach ( array( 'user', 'pass', 'host' ) as $component ) {
    1364                 if ( isset( $lp[ $component ] ) && strpbrk( $lp[ $component ], ':/?#@' ) ) {
     1257                $location = preg_replace_callback( $regex, '_wp_sanitize_utf8_in_redirect', $location );
     1258                $location = preg_replace( '|[^a-z0-9-~+_.?#=&;,/:%!*\[\]()@]|i', '', $location );
     1259                $location = wp_kses_no_null( $location );
     1260
     1261                // remove %0d and %0a from location
     1262                $strip = array( '%0d', '%0a', '%0D', '%0A' );
     1263                return _deep_replace( $strip, $location );
     1264        }
     1265
     1266        /**
     1267         * URL encode UTF-8 characters in a URL.
     1268         *
     1269         * @ignore
     1270         * @since 4.2.0
     1271         * @access private
     1272         *
     1273         * @see wp_sanitize_redirect()
     1274         *
     1275         * @param array $matches RegEx matches against the redirect location.
     1276         * @return string URL-encoded version of the first RegEx match.
     1277         */
     1278        function _wp_sanitize_utf8_in_redirect( $matches ) {
     1279                return urlencode( $matches[0] );
     1280        }
     1281endif;
     1282
     1283if ( ! function_exists( 'wp_safe_redirect' ) ) :
     1284        /**
     1285         * Performs a safe (local) redirect, using wp_redirect().
     1286         *
     1287         * Checks whether the $location is using an allowed host, if it has an absolute
     1288         * path. A plugin can therefore set or remove allowed host(s) to or from the
     1289         * list.
     1290         *
     1291         * If the host is not allowed, then the redirect defaults to wp-admin on the siteurl
     1292         * instead. This prevents malicious redirects which redirect to another host,
     1293         * but only used in a few places.
     1294         *
     1295         * Note: wp_safe_redirect() does not exit automatically, and should almost always be
     1296         * followed by a call to `exit;`:
     1297         *
     1298         *     wp_safe_redirect( $url );
     1299         *     exit;
     1300         *
     1301         * Exiting can also be selectively manipulated by using wp_safe_redirect() as a conditional
     1302         * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters:
     1303         *
     1304         *     if ( wp_safe_redirect( $url ) ) {
     1305         *         exit;
     1306         *     }
     1307         *
     1308         * @since 2.3.0
     1309         * @since 5.0.0 The return value from wp_redirect() is now passed on.
     1310         *
     1311         * @param string $location The path or URL to redirect to.
     1312         * @param int    $status   Optional. HTTP response status code to use. Default '302' (Moved Temporarily).
     1313         * @return bool  $redirect False if the redirect was cancelled, true otherwise.
     1314         */
     1315        function wp_safe_redirect( $location, $status = 302 ) {
     1316
     1317                // Need to look at the URL the way it will end up in wp_redirect()
     1318                $location = wp_sanitize_redirect( $location );
     1319
     1320                /**
     1321                 * Filters the redirect fallback URL for when the provided redirect is not safe (local).
     1322                 *
     1323                 * @since 4.3.0
     1324                 *
     1325                 * @param string $fallback_url The fallback URL to use by default.
     1326                 * @param int    $status       The HTTP response status code to use.
     1327                 */
     1328                $location = wp_validate_redirect( $location, apply_filters( 'wp_safe_redirect_fallback', admin_url(), $status ) );
     1329
     1330                return wp_redirect( $location, $status );
     1331        }
     1332endif;
     1333
     1334if ( ! function_exists( 'wp_validate_redirect' ) ) :
     1335        /**
     1336         * Validates a URL for use in a redirect.
     1337         *
     1338         * Checks whether the $location is using an allowed host, if it has an absolute
     1339         * path. A plugin can therefore set or remove allowed host(s) to or from the
     1340         * list.
     1341         *
     1342         * If the host is not allowed, then the redirect is to $default supplied
     1343         *
     1344         * @since 2.8.1
     1345         *
     1346         * @param string $location The redirect to validate
     1347         * @param string $default  The value to return if $location is not allowed
     1348         * @return string redirect-sanitized URL
     1349         */
     1350        function wp_validate_redirect( $location, $default = '' ) {
     1351                $location = trim( $location, " \t\n\r\0\x08\x0B" );
     1352                // browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'
     1353                if ( substr( $location, 0, 2 ) == '//' ) {
     1354                        $location = 'http:' . $location;
     1355                }
     1356
     1357                // In php 5 parse_url may fail if the URL query part contains http://, bug #38143
     1358                $test = ( $cut = strpos( $location, '?' ) ) ? substr( $location, 0, $cut ) : $location;
     1359
     1360                // @-operator is used to prevent possible warnings in PHP < 5.3.3.
     1361                $lp = @parse_url( $test );
     1362
     1363                // Give up if malformed URL
     1364                if ( false === $lp ) {
    13651365                        return $default;
    13661366                }
    1367         }
    1368 
    1369         $wpp = parse_url(home_url());
    1370 
    1371         /**
    1372          * Filters the whitelist of hosts to redirect to.
    1373          *
    1374          * @since 2.3.0
    1375          *
    1376          * @param array       $hosts An array of allowed hosts.
    1377          * @param bool|string $host  The parsed host; empty if not isset.
    1378          */
    1379         $allowed_hosts = (array) apply_filters( 'allowed_redirect_hosts', array($wpp['host']), isset($lp['host']) ? $lp['host'] : '' );
    1380 
    1381         if ( isset($lp['host']) && ( !in_array($lp['host'], $allowed_hosts) && $lp['host'] != strtolower($wpp['host'])) )
    1382                 $location = $default;
    1383 
    1384         return $location;
    1385 }
    1386 endif;
    1387 
    1388 if ( ! function_exists('wp_notify_postauthor') ) :
    1389 /**
    1390  * Notify an author (and/or others) of a comment/trackback/pingback on a post.
    1391  *
    1392  * @since 1.0.0
    1393  *
    1394  * @param int|WP_Comment  $comment_id Comment ID or WP_Comment object.
    1395  * @param string          $deprecated Not used
    1396  * @return bool True on completion. False if no email addresses were specified.
    1397  */
    1398 function wp_notify_postauthor( $comment_id, $deprecated = null ) {
    1399         if ( null !== $deprecated ) {
    1400                 _deprecated_argument( __FUNCTION__, '3.8.0' );
    1401         }
    1402 
    1403         $comment = get_comment( $comment_id );
    1404         if ( empty( $comment ) || empty( $comment->comment_post_ID ) )
    1405                 return false;
    1406 
    1407         $post    = get_post( $comment->comment_post_ID );
    1408         $author  = get_userdata( $post->post_author );
    1409 
    1410         // Who to notify? By default, just the post author, but others can be added.
    1411         $emails = array();
    1412         if ( $author ) {
    1413                 $emails[] = $author->user_email;
    1414         }
    1415 
    1416         /**
    1417          * Filters the list of email addresses to receive a comment notification.
    1418          *
    1419          * By default, only post authors are notified of comments. This filter allows
    1420          * others to be added.
    1421          *
    1422          * @since 3.7.0
    1423          *
    1424          * @param array $emails     An array of email addresses to receive a comment notification.
    1425          * @param int   $comment_id The comment ID.
    1426          */
    1427         $emails = apply_filters( 'comment_notification_recipients', $emails, $comment->comment_ID );
    1428         $emails = array_filter( $emails );
    1429 
    1430         // If there are no addresses to send the comment to, bail.
    1431         if ( ! count( $emails ) ) {
    1432                 return false;
    1433         }
    1434 
    1435         // Facilitate unsetting below without knowing the keys.
    1436         $emails = array_flip( $emails );
    1437 
    1438         /**
    1439          * Filters whether to notify comment authors of their comments on their own posts.
    1440          *
    1441          * By default, comment authors aren't notified of their comments on their own
    1442          * posts. This filter allows you to override that.
    1443          *
    1444          * @since 3.8.0
    1445          *
    1446          * @param bool $notify     Whether to notify the post author of their own comment.
    1447          *                         Default false.
    1448          * @param int  $comment_id The comment ID.
    1449          */
    1450         $notify_author = apply_filters( 'comment_notification_notify_author', false, $comment->comment_ID );
    1451 
    1452         // The comment was left by the author
    1453         if ( $author && ! $notify_author && $comment->user_id == $post->post_author ) {
    1454                 unset( $emails[ $author->user_email ] );
    1455         }
    1456 
    1457         // The author moderated a comment on their own post
    1458         if ( $author && ! $notify_author && $post->post_author == get_current_user_id() ) {
    1459                 unset( $emails[ $author->user_email ] );
    1460         }
    1461 
    1462         // The post author is no longer a member of the blog
    1463         if ( $author && ! $notify_author && ! user_can( $post->post_author, 'read_post', $post->ID ) ) {
    1464                 unset( $emails[ $author->user_email ] );
    1465         }
    1466 
    1467         // If there's no email to send the comment to, bail, otherwise flip array back around for use below
    1468         if ( ! count( $emails ) ) {
    1469                 return false;
    1470         } else {
     1367
     1368                // Allow only http and https schemes. No data:, etc.
     1369                if ( isset( $lp['scheme'] ) && ! ( 'http' == $lp['scheme'] || 'https' == $lp['scheme'] ) ) {
     1370                        return $default;
     1371                }
     1372
     1373                // Reject if certain components are set but host is not. This catches urls like https:host.com for which parse_url does not set the host field.
     1374                if ( ! isset( $lp['host'] ) && ( isset( $lp['scheme'] ) || isset( $lp['user'] ) || isset( $lp['pass'] ) || isset( $lp['port'] ) ) ) {
     1375                        return $default;
     1376                }
     1377
     1378                // Reject malformed components parse_url() can return on odd inputs.
     1379                foreach ( array( 'user', 'pass', 'host' ) as $component ) {
     1380                        if ( isset( $lp[ $component ] ) && strpbrk( $lp[ $component ], ':/?#@' ) ) {
     1381                                return $default;
     1382                        }
     1383                }
     1384
     1385                $wpp = parse_url( home_url() );
     1386
     1387                /**
     1388                 * Filters the whitelist of hosts to redirect to.
     1389                 *
     1390                 * @since 2.3.0
     1391                 *
     1392                 * @param array       $hosts An array of allowed hosts.
     1393                 * @param bool|string $host  The parsed host; empty if not isset.
     1394                 */
     1395                $allowed_hosts = (array) apply_filters( 'allowed_redirect_hosts', array( $wpp['host'] ), isset( $lp['host'] ) ? $lp['host'] : '' );
     1396
     1397                if ( isset( $lp['host'] ) && ( ! in_array( $lp['host'], $allowed_hosts ) && $lp['host'] != strtolower( $wpp['host'] ) ) ) {
     1398                        $location = $default;
     1399                }
     1400
     1401                return $location;
     1402        }
     1403endif;
     1404
     1405if ( ! function_exists( 'wp_notify_postauthor' ) ) :
     1406        /**
     1407         * Notify an author (and/or others) of a comment/trackback/pingback on a post.
     1408         *
     1409         * @since 1.0.0
     1410         *
     1411         * @param int|WP_Comment  $comment_id Comment ID or WP_Comment object.
     1412         * @param string          $deprecated Not used
     1413         * @return bool True on completion. False if no email addresses were specified.
     1414         */
     1415        function wp_notify_postauthor( $comment_id, $deprecated = null ) {
     1416                if ( null !== $deprecated ) {
     1417                        _deprecated_argument( __FUNCTION__, '3.8.0' );
     1418                }
     1419
     1420                $comment = get_comment( $comment_id );
     1421                if ( empty( $comment ) || empty( $comment->comment_post_ID ) ) {
     1422                        return false;
     1423                }
     1424
     1425                $post   = get_post( $comment->comment_post_ID );
     1426                $author = get_userdata( $post->post_author );
     1427
     1428                // Who to notify? By default, just the post author, but others can be added.
     1429                $emails = array();
     1430                if ( $author ) {
     1431                        $emails[] = $author->user_email;
     1432                }
     1433
     1434                /**
     1435                 * Filters the list of email addresses to receive a comment notification.
     1436                 *
     1437                 * By default, only post authors are notified of comments. This filter allows
     1438                 * others to be added.
     1439                 *
     1440                 * @since 3.7.0
     1441                 *
     1442                 * @param array $emails     An array of email addresses to receive a comment notification.
     1443                 * @param int   $comment_id The comment ID.
     1444                 */
     1445                $emails = apply_filters( 'comment_notification_recipients', $emails, $comment->comment_ID );
     1446                $emails = array_filter( $emails );
     1447
     1448                // If there are no addresses to send the comment to, bail.
     1449                if ( ! count( $emails ) ) {
     1450                        return false;
     1451                }
     1452
     1453                // Facilitate unsetting below without knowing the keys.
    14711454                $emails = array_flip( $emails );
    1472         }
    1473 
    1474         $switched_locale = switch_to_locale( get_locale() );
    1475 
    1476         $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
    1477 
    1478         // The blogname option is escaped with esc_html on the way into the database in sanitize_option
    1479         // we want to reverse this for the plain text arena of emails.
    1480         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
    1481         $comment_content = wp_specialchars_decode( $comment->comment_content );
    1482 
    1483         switch ( $comment->comment_type ) {
    1484                 case 'trackback':
    1485                         /* translators: 1: Post title */
    1486                         $notify_message  = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
    1487                         /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
    1488                         $notify_message .= sprintf( __('Website: %1$s (IP address: %2$s, %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
    1489                         $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
    1490                         $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
    1491                         $notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
    1492                         /* translators: 1: blog name, 2: post title */
    1493                         $subject = sprintf( __('[%1$s] Trackback: "%2$s"'), $blogname, $post->post_title );
    1494                         break;
    1495                 case 'pingback':
    1496                         /* translators: 1: Post title */
    1497                         $notify_message  = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
    1498                         /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
    1499                         $notify_message .= sprintf( __('Website: %1$s (IP address: %2$s, %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
    1500                         $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
    1501                         $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
    1502                         $notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
    1503                         /* translators: 1: blog name, 2: post title */
    1504                         $subject = sprintf( __('[%1$s] Pingback: "%2$s"'), $blogname, $post->post_title );
    1505                         break;
    1506                 default: // Comments
    1507                         $notify_message  = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
    1508                         /* translators: 1: comment author, 2: comment author's IP address, 3: comment author's hostname */
    1509                         $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
    1510                         $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
    1511                         $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
    1512                         $notify_message .= sprintf( __('Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
    1513                         $notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
    1514                         /* translators: 1: blog name, 2: post title */
    1515                         $subject = sprintf( __('[%1$s] Comment: "%2$s"'), $blogname, $post->post_title );
    1516                         break;
    1517         }
    1518         $notify_message .= get_permalink($comment->comment_post_ID) . "#comments\r\n\r\n";
    1519         $notify_message .= sprintf( __('Permalink: %s'), get_comment_link( $comment ) ) . "\r\n";
    1520 
    1521         if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
    1522                 if ( EMPTY_TRASH_DAYS ) {
    1523                         $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
     1455
     1456                /**
     1457                 * Filters whether to notify comment authors of their comments on their own posts.
     1458                 *
     1459                 * By default, comment authors aren't notified of their comments on their own
     1460                 * posts. This filter allows you to override that.
     1461                 *
     1462                 * @since 3.8.0
     1463                 *
     1464                 * @param bool $notify     Whether to notify the post author of their own comment.
     1465                 *                         Default false.
     1466                 * @param int  $comment_id The comment ID.
     1467                 */
     1468                $notify_author = apply_filters( 'comment_notification_notify_author', false, $comment->comment_ID );
     1469
     1470                // The comment was left by the author
     1471                if ( $author && ! $notify_author && $comment->user_id == $post->post_author ) {
     1472                        unset( $emails[ $author->user_email ] );
     1473                }
     1474
     1475                // The author moderated a comment on their own post
     1476                if ( $author && ! $notify_author && $post->post_author == get_current_user_id() ) {
     1477                        unset( $emails[ $author->user_email ] );
     1478                }
     1479
     1480                // The post author is no longer a member of the blog
     1481                if ( $author && ! $notify_author && ! user_can( $post->post_author, 'read_post', $post->ID ) ) {
     1482                        unset( $emails[ $author->user_email ] );
     1483                }
     1484
     1485                // If there's no email to send the comment to, bail, otherwise flip array back around for use below
     1486                if ( ! count( $emails ) ) {
     1487                        return false;
    15241488                } else {
    1525                         $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
    1526                 }
    1527                 $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
    1528         }
    1529 
    1530         $wp_email = 'wordpress@' . preg_replace('#^www\.#', '', strtolower($_SERVER['SERVER_NAME']));
    1531 
    1532         if ( '' == $comment->comment_author ) {
    1533                 $from = "From: \"$blogname\" <$wp_email>";
    1534                 if ( '' != $comment->comment_author_email )
    1535                         $reply_to = "Reply-To: $comment->comment_author_email";
    1536         } else {
    1537                 $from = "From: \"$comment->comment_author\" <$wp_email>";
    1538                 if ( '' != $comment->comment_author_email )
    1539                         $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
    1540         }
    1541 
    1542         $message_headers = "$from\n"
    1543                 . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
    1544 
    1545         if ( isset($reply_to) )
    1546                 $message_headers .= $reply_to . "\n";
    1547 
    1548         /**
    1549          * Filters the comment notification email text.
    1550          *
    1551          * @since 1.5.2
    1552          *
    1553          * @param string $notify_message The comment notification email text.
    1554          * @param int    $comment_id     Comment ID.
    1555          */
    1556         $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
    1557 
    1558         /**
    1559          * Filters the comment notification email subject.
    1560          *
    1561          * @since 1.5.2
    1562          *
    1563          * @param string $subject    The comment notification email subject.
    1564          * @param int    $comment_id Comment ID.
    1565          */
    1566         $subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
    1567 
    1568         /**
    1569          * Filters the comment notification email headers.
    1570          *
    1571          * @since 1.5.2
    1572          *
    1573          * @param string $message_headers Headers for the comment notification email.
    1574          * @param int    $comment_id      Comment ID.
    1575          */
    1576         $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
    1577 
    1578         foreach ( $emails as $email ) {
    1579                 @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
    1580         }
    1581 
    1582         if ( $switched_locale ) {
    1583                 restore_previous_locale();
    1584         }
    1585 
    1586         return true;
    1587 }
    1588 endif;
    1589 
    1590 if ( !function_exists('wp_notify_moderator') ) :
    1591 /**
    1592  * Notifies the moderator of the site about a new comment that is awaiting approval.
    1593  *
    1594  * @since 1.0.0
    1595  *
    1596  * @global wpdb $wpdb WordPress database abstraction object.
    1597  *
    1598  * Uses the {@see 'notify_moderator'} filter to determine whether the site moderator
    1599  * should be notified, overriding the site setting.
    1600  *
    1601  * @param int $comment_id Comment ID.
    1602  * @return true Always returns true.
    1603  */
    1604 function wp_notify_moderator($comment_id) {
    1605         global $wpdb;
    1606 
    1607         $maybe_notify = get_option( 'moderation_notify' );
    1608 
    1609         /**
    1610          * Filters whether to send the site moderator email notifications, overriding the site setting.
    1611          *
    1612          * @since 4.4.0
    1613          *
    1614          * @param bool $maybe_notify Whether to notify blog moderator.
    1615          * @param int  $comment_ID   The id of the comment for the notification.
    1616          */
    1617         $maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_id );
    1618 
    1619         if ( ! $maybe_notify ) {
    1620                 return true;
    1621         }
    1622 
    1623         $comment = get_comment($comment_id);
    1624         $post = get_post($comment->comment_post_ID);
    1625         $user = get_userdata( $post->post_author );
    1626         // Send to the administration and to the post author if the author can modify the comment.
    1627         $emails = array( get_option( 'admin_email' ) );
    1628         if ( $user && user_can( $user->ID, 'edit_comment', $comment_id ) && ! empty( $user->user_email ) ) {
    1629                 if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) )
    1630                         $emails[] = $user->user_email;
    1631         }
    1632 
    1633         $switched_locale = switch_to_locale( get_locale() );
    1634 
    1635         $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
    1636         $comments_waiting = $wpdb->get_var("SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'");
    1637 
    1638         // The blogname option is escaped with esc_html on the way into the database in sanitize_option
    1639         // we want to reverse this for the plain text arena of emails.
    1640         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
    1641         $comment_content = wp_specialchars_decode( $comment->comment_content );
    1642 
    1643         switch ( $comment->comment_type ) {
    1644                 case 'trackback':
    1645                         /* translators: 1: Post title */
    1646                         $notify_message  = sprintf( __('A new trackback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
    1647                         $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
    1648                         /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
    1649                         $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
    1650                         /* translators: 1: Trackback/pingback/comment author URL */
    1651                         $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
    1652                         $notify_message .= __('Trackback excerpt: ') . "\r\n" . $comment_content . "\r\n\r\n";
    1653                         break;
    1654                 case 'pingback':
    1655                         /* translators: 1: Post title */
    1656                         $notify_message  = sprintf( __('A new pingback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
    1657                         $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
    1658                         /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
    1659                         $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
    1660                         /* translators: 1: Trackback/pingback/comment author URL */
    1661                         $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
    1662                         $notify_message .= __('Pingback excerpt: ') . "\r\n" . $comment_content . "\r\n\r\n";
    1663                         break;
    1664                 default: // Comments
    1665                         /* translators: 1: Post title */
    1666                         $notify_message  = sprintf( __('A new comment on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
    1667                         $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
    1668                         /* translators: 1: Comment author name, 2: comment author's IP address, 3: comment author's hostname */
    1669                         $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
    1670                         /* translators: 1: Comment author URL */
    1671                         $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
    1672                         /* translators: 1: Trackback/pingback/comment author URL */
    1673                         $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
    1674                         /* translators: 1: Comment text */
    1675                         $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
    1676                         break;
    1677         }
    1678 
    1679         /* translators: Comment moderation. 1: Comment action URL */
    1680         $notify_message .= sprintf( __( 'Approve it: %s' ), admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ) . "\r\n";
    1681 
    1682         if ( EMPTY_TRASH_DAYS ) {
    1683                 /* translators: Comment moderation. 1: Comment action URL */
    1684                 $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) ) . "\r\n";
    1685         } else {
    1686                 /* translators: Comment moderation. 1: Comment action URL */
    1687                 $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ) . "\r\n";
    1688         }
    1689 
    1690         /* translators: Comment moderation. 1: Comment action URL */
    1691         $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ) . "\r\n";
    1692 
    1693         /* translators: Comment moderation. 1: Number of comments awaiting approval */
    1694         $notify_message .= sprintf( _n('Currently %s comment is waiting for approval. Please visit the moderation panel:',
    1695                 'Currently %s comments are waiting for approval. Please visit the moderation panel:', $comments_waiting), number_format_i18n($comments_waiting) ) . "\r\n";
    1696         $notify_message .= admin_url( "edit-comments.php?comment_status=moderated#wpbody-content" ) . "\r\n";
    1697 
    1698         /* translators: Comment moderation notification email subject. 1: Site name, 2: Post title */
    1699         $subject = sprintf( __('[%1$s] Please moderate: "%2$s"'), $blogname, $post->post_title );
    1700         $message_headers = '';
    1701 
    1702         /**
    1703          * Filters the list of recipients for comment moderation emails.
    1704          *
    1705          * @since 3.7.0
    1706          *
    1707          * @param array $emails     List of email addresses to notify for comment moderation.
    1708          * @param int   $comment_id Comment ID.
    1709          */
    1710         $emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
    1711 
    1712         /**
    1713          * Filters the comment moderation email text.
    1714          *
    1715          * @since 1.5.2
    1716          *
    1717          * @param string $notify_message Text of the comment moderation email.
    1718          * @param int    $comment_id     Comment ID.
    1719          */
    1720         $notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
    1721 
    1722         /**
    1723          * Filters the comment moderation email subject.
    1724          *
    1725          * @since 1.5.2
    1726          *
    1727          * @param string $subject    Subject of the comment moderation email.
    1728          * @param int    $comment_id Comment ID.
    1729          */
    1730         $subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
    1731 
    1732         /**
    1733          * Filters the comment moderation email headers.
    1734          *
    1735          * @since 2.8.0
    1736          *
    1737          * @param string $message_headers Headers for the comment moderation email.
    1738          * @param int    $comment_id      Comment ID.
    1739          */
    1740         $message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
    1741 
    1742         foreach ( $emails as $email ) {
    1743                 @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
    1744         }
    1745 
    1746         if ( $switched_locale ) {
    1747                 restore_previous_locale();
    1748         }
    1749 
    1750         return true;
    1751 }
    1752 endif;
    1753 
    1754 if ( !function_exists('wp_password_change_notification') ) :
    1755 /**
    1756  * Notify the blog admin of a user changing password, normally via email.
    1757  *
    1758  * @since 2.7.0
    1759  *
    1760  * @param WP_User $user User object.
    1761  */
    1762 function wp_password_change_notification( $user ) {
    1763         // send a copy of password change notification to the admin
    1764         // but check to see if it's the admin whose password we're changing, and skip this
    1765         if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
    1766                 /* translators: %s: user name */
    1767                 $message = sprintf( __( 'Password changed for user: %s' ), $user->user_login ) . "\r\n";
     1489                        $emails = array_flip( $emails );
     1490                }
     1491
     1492                $switched_locale = switch_to_locale( get_locale() );
     1493
     1494                $comment_author_domain = @gethostbyaddr( $comment->comment_author_IP );
     1495
    17681496                // The blogname option is escaped with esc_html on the way into the database in sanitize_option
    17691497                // we want to reverse this for the plain text arena of emails.
    1770                 $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
    1771 
    1772                 $wp_password_change_notification_email = array(
    1773                         'to'      => get_option( 'admin_email' ),
     1498                $blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
     1499                $comment_content = wp_specialchars_decode( $comment->comment_content );
     1500
     1501                switch ( $comment->comment_type ) {
     1502                        case 'trackback':
     1503                                /* translators: 1: Post title */
     1504                                $notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
     1505                                /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
     1506                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
     1507                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
     1508                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
     1509                                $notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
     1510                                /* translators: 1: blog name, 2: post title */
     1511                                $subject = sprintf( __( '[%1$s] Trackback: "%2$s"' ), $blogname, $post->post_title );
     1512                                break;
     1513                        case 'pingback':
     1514                                /* translators: 1: Post title */
     1515                                $notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
     1516                                /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
     1517                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
     1518                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
     1519                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
     1520                                $notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
     1521                                /* translators: 1: blog name, 2: post title */
     1522                                $subject = sprintf( __( '[%1$s] Pingback: "%2$s"' ), $blogname, $post->post_title );
     1523                                break;
     1524                        default: // Comments
     1525                                $notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
     1526                                /* translators: 1: comment author, 2: comment author's IP address, 3: comment author's hostname */
     1527                                $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
     1528                                $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
     1529                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
     1530                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
     1531                                $notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
     1532                                /* translators: 1: blog name, 2: post title */
     1533                                $subject = sprintf( __( '[%1$s] Comment: "%2$s"' ), $blogname, $post->post_title );
     1534                                break;
     1535                }
     1536                $notify_message .= get_permalink( $comment->comment_post_ID ) . "#comments\r\n\r\n";
     1537                $notify_message .= sprintf( __( 'Permalink: %s' ), get_comment_link( $comment ) ) . "\r\n";
     1538
     1539                if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
     1540                        if ( EMPTY_TRASH_DAYS ) {
     1541                                $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
     1542                        } else {
     1543                                $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
     1544                        }
     1545                        $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
     1546                }
     1547
     1548                $wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
     1549
     1550                if ( '' == $comment->comment_author ) {
     1551                        $from = "From: \"$blogname\" <$wp_email>";
     1552                        if ( '' != $comment->comment_author_email ) {
     1553                                $reply_to = "Reply-To: $comment->comment_author_email";
     1554                        }
     1555                } else {
     1556                        $from = "From: \"$comment->comment_author\" <$wp_email>";
     1557                        if ( '' != $comment->comment_author_email ) {
     1558                                $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
     1559                        }
     1560                }
     1561
     1562                $message_headers = "$from\n"
     1563                . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
     1564
     1565                if ( isset( $reply_to ) ) {
     1566                        $message_headers .= $reply_to . "\n";
     1567                }
     1568
     1569                /**
     1570                 * Filters the comment notification email text.
     1571                 *
     1572                 * @since 1.5.2
     1573                 *
     1574                 * @param string $notify_message The comment notification email text.
     1575                 * @param int    $comment_id     Comment ID.
     1576                 */
     1577                $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
     1578
     1579                /**
     1580                 * Filters the comment notification email subject.
     1581                 *
     1582                 * @since 1.5.2
     1583                 *
     1584                 * @param string $subject    The comment notification email subject.
     1585                 * @param int    $comment_id Comment ID.
     1586                 */
     1587                $subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
     1588
     1589                /**
     1590                 * Filters the comment notification email headers.
     1591                 *
     1592                 * @since 1.5.2
     1593                 *
     1594                 * @param string $message_headers Headers for the comment notification email.
     1595                 * @param int    $comment_id      Comment ID.
     1596                 */
     1597                $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
     1598
     1599                foreach ( $emails as $email ) {
     1600                        @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
     1601                }
     1602
     1603                if ( $switched_locale ) {
     1604                        restore_previous_locale();
     1605                }
     1606
     1607                return true;
     1608        }
     1609endif;
     1610
     1611if ( ! function_exists( 'wp_notify_moderator' ) ) :
     1612        /**
     1613         * Notifies the moderator of the site about a new comment that is awaiting approval.
     1614         *
     1615         * @since 1.0.0
     1616         *
     1617         * @global wpdb $wpdb WordPress database abstraction object.
     1618         *
     1619         * Uses the {@see 'notify_moderator'} filter to determine whether the site moderator
     1620         * should be notified, overriding the site setting.
     1621         *
     1622         * @param int $comment_id Comment ID.
     1623         * @return true Always returns true.
     1624         */
     1625        function wp_notify_moderator( $comment_id ) {
     1626                global $wpdb;
     1627
     1628                $maybe_notify = get_option( 'moderation_notify' );
     1629
     1630                /**
     1631                 * Filters whether to send the site moderator email notifications, overriding the site setting.
     1632                 *
     1633                 * @since 4.4.0
     1634                 *
     1635                 * @param bool $maybe_notify Whether to notify blog moderator.
     1636                 * @param int  $comment_ID   The id of the comment for the notification.
     1637                 */
     1638                $maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_id );
     1639
     1640                if ( ! $maybe_notify ) {
     1641                        return true;
     1642                }
     1643
     1644                $comment = get_comment( $comment_id );
     1645                $post    = get_post( $comment->comment_post_ID );
     1646                $user    = get_userdata( $post->post_author );
     1647                // Send to the administration and to the post author if the author can modify the comment.
     1648                $emails = array( get_option( 'admin_email' ) );
     1649                if ( $user && user_can( $user->ID, 'edit_comment', $comment_id ) && ! empty( $user->user_email ) ) {
     1650                        if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
     1651                                $emails[] = $user->user_email;
     1652                        }
     1653                }
     1654
     1655                $switched_locale = switch_to_locale( get_locale() );
     1656
     1657                $comment_author_domain = @gethostbyaddr( $comment->comment_author_IP );
     1658                $comments_waiting      = $wpdb->get_var( "SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'" );
     1659
     1660                // The blogname option is escaped with esc_html on the way into the database in sanitize_option
     1661                // we want to reverse this for the plain text arena of emails.
     1662                $blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
     1663                $comment_content = wp_specialchars_decode( $comment->comment_content );
     1664
     1665                switch ( $comment->comment_type ) {
     1666                        case 'trackback':
     1667                                /* translators: 1: Post title */
     1668                                $notify_message  = sprintf( __( 'A new trackback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
     1669                                $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
     1670                                /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
     1671                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
     1672                                /* translators: 1: Trackback/pingback/comment author URL */
     1673                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
     1674                                $notify_message .= __( 'Trackback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
     1675                                break;
     1676                        case 'pingback':
     1677                                /* translators: 1: Post title */
     1678                                $notify_message  = sprintf( __( 'A new pingback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
     1679                                $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
     1680                                /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
     1681                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
     1682                                /* translators: 1: Trackback/pingback/comment author URL */
     1683                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
     1684                                $notify_message .= __( 'Pingback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
     1685                                break;
     1686                        default: // Comments
     1687                                /* translators: 1: Post title */
     1688                                $notify_message  = sprintf( __( 'A new comment on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
     1689                                $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
     1690                                /* translators: 1: Comment author name, 2: comment author's IP address, 3: comment author's hostname */
     1691                                $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
     1692                                /* translators: 1: Comment author URL */
     1693                                $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
     1694                                /* translators: 1: Trackback/pingback/comment author URL */
     1695                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
     1696                                /* translators: 1: Comment text */
     1697                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
     1698                                break;
     1699                }
     1700
     1701                /* translators: Comment moderation. 1: Comment action URL */
     1702                $notify_message .= sprintf( __( 'Approve it: %s' ), admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ) . "\r\n";
     1703
     1704                if ( EMPTY_TRASH_DAYS ) {
     1705                        /* translators: Comment moderation. 1: Comment action URL */
     1706                        $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) ) . "\r\n";
     1707                } else {
     1708                        /* translators: Comment moderation. 1: Comment action URL */
     1709                        $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ) . "\r\n";
     1710                }
     1711
     1712                /* translators: Comment moderation. 1: Comment action URL */
     1713                $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ) . "\r\n";
     1714
     1715                /* translators: Comment moderation. 1: Number of comments awaiting approval */
     1716                $notify_message .= sprintf(
     1717                        _n(
     1718                                'Currently %s comment is waiting for approval. Please visit the moderation panel:',
     1719                                'Currently %s comments are waiting for approval. Please visit the moderation panel:', $comments_waiting
     1720                        ), number_format_i18n( $comments_waiting )
     1721                ) . "\r\n";
     1722                $notify_message .= admin_url( 'edit-comments.php?comment_status=moderated#wpbody-content' ) . "\r\n";
     1723
     1724                /* translators: Comment moderation notification email subject. 1: Site name, 2: Post title */
     1725                $subject         = sprintf( __( '[%1$s] Please moderate: "%2$s"' ), $blogname, $post->post_title );
     1726                $message_headers = '';
     1727
     1728                /**
     1729                 * Filters the list of recipients for comment moderation emails.
     1730                 *
     1731                 * @since 3.7.0
     1732                 *
     1733                 * @param array $emails     List of email addresses to notify for comment moderation.
     1734                 * @param int   $comment_id Comment ID.
     1735                 */
     1736                $emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
     1737
     1738                /**
     1739                 * Filters the comment moderation email text.
     1740                 *
     1741                 * @since 1.5.2
     1742                 *
     1743                 * @param string $notify_message Text of the comment moderation email.
     1744                 * @param int    $comment_id     Comment ID.
     1745                 */
     1746                $notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
     1747
     1748                /**
     1749                 * Filters the comment moderation email subject.
     1750                 *
     1751                 * @since 1.5.2
     1752                 *
     1753                 * @param string $subject    Subject of the comment moderation email.
     1754                 * @param int    $comment_id Comment ID.
     1755                 */
     1756                $subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
     1757
     1758                /**
     1759                 * Filters the comment moderation email headers.
     1760                 *
     1761                 * @since 2.8.0
     1762                 *
     1763                 * @param string $message_headers Headers for the comment moderation email.
     1764                 * @param int    $comment_id      Comment ID.
     1765                 */
     1766                $message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
     1767
     1768                foreach ( $emails as $email ) {
     1769                        @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
     1770                }
     1771
     1772                if ( $switched_locale ) {
     1773                        restore_previous_locale();
     1774                }
     1775
     1776                return true;
     1777        }
     1778endif;
     1779
     1780if ( ! function_exists( 'wp_password_change_notification' ) ) :
     1781        /**
     1782         * Notify the blog admin of a user changing password, normally via email.
     1783         *
     1784         * @since 2.7.0
     1785         *
     1786         * @param WP_User $user User object.
     1787         */
     1788        function wp_password_change_notification( $user ) {
     1789                // send a copy of password change notification to the admin
     1790                // but check to see if it's the admin whose password we're changing, and skip this
     1791                if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
     1792                        /* translators: %s: user name */
     1793                        $message = sprintf( __( 'Password changed for user: %s' ), $user->user_login ) . "\r\n";
     1794                        // The blogname option is escaped with esc_html on the way into the database in sanitize_option
     1795                        // we want to reverse this for the plain text arena of emails.
     1796                        $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
     1797
     1798                        $wp_password_change_notification_email = array(
     1799                                'to'      => get_option( 'admin_email' ),
     1800                                /* translators: Password change notification email subject. %s: Site title */
     1801                                'subject' => __( '[%s] Password Changed' ),
     1802                                'message' => $message,
     1803                                'headers' => '',
     1804                        );
     1805
     1806                        /**
     1807                         * Filters the contents of the password change notification email sent to the site admin.
     1808                         *
     1809                         * @since 4.9.0
     1810                         *
     1811                         * @param array   $wp_password_change_notification_email {
     1812                         *     Used to build wp_mail().
     1813                         *
     1814                         *     @type string $to      The intended recipient - site admin email address.
     1815                         *     @type string $subject The subject of the email.
     1816                         *     @type string $message The body of the email.
     1817                         *     @type string $headers The headers of the email.
     1818                         * }
     1819                         * @param WP_User $user     User object for user whose password was changed.
     1820                         * @param string  $blogname The site title.
     1821                         */
     1822                        $wp_password_change_notification_email = apply_filters( 'wp_password_change_notification_email', $wp_password_change_notification_email, $user, $blogname );
     1823
     1824                        wp_mail(
     1825                                $wp_password_change_notification_email['to'],
     1826                                wp_specialchars_decode( sprintf( $wp_password_change_notification_email['subject'], $blogname ) ),
     1827                                $wp_password_change_notification_email['message'],
     1828                                $wp_password_change_notification_email['headers']
     1829                        );
     1830                }
     1831        }
     1832endif;
     1833
     1834if ( ! function_exists( 'wp_new_user_notification' ) ) :
     1835        /**
     1836         * Email login credentials to a newly-registered user.
     1837         *
     1838         * A new user registration notification is also sent to admin email.
     1839         *
     1840         * @since 2.0.0
     1841         * @since 4.3.0 The `$plaintext_pass` parameter was changed to `$notify`.
     1842         * @since 4.3.1 The `$plaintext_pass` parameter was deprecated. `$notify` added as a third parameter.
     1843         * @since 4.6.0 The `$notify` parameter accepts 'user' for sending notification only to the user created.
     1844         *
     1845         * @global wpdb         $wpdb      WordPress database object for queries.
     1846         * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
     1847         *
     1848         * @param int    $user_id    User ID.
     1849         * @param null   $deprecated Not used (argument deprecated).
     1850         * @param string $notify     Optional. Type of notification that should happen. Accepts 'admin' or an empty
     1851         *                           string (admin only), 'user', or 'both' (admin and user). Default empty.
     1852         */
     1853        function wp_new_user_notification( $user_id, $deprecated = null, $notify = '' ) {
     1854                if ( $deprecated !== null ) {
     1855                        _deprecated_argument( __FUNCTION__, '4.3.1' );
     1856                }
     1857
     1858                global $wpdb, $wp_hasher;
     1859                $user = get_userdata( $user_id );
     1860
     1861                // The blogname option is escaped with esc_html on the way into the database in sanitize_option
     1862                // we want to reverse this for the plain text arena of emails.
     1863                $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
     1864
     1865                if ( 'user' !== $notify ) {
     1866                        $switched_locale = switch_to_locale( get_locale() );
     1867
     1868                        /* translators: %s: site title */
     1869                        $message = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
     1870                        /* translators: %s: user login */
     1871                        $message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
     1872                        /* translators: %s: user email address */
     1873                        $message .= sprintf( __( 'Email: %s' ), $user->user_email ) . "\r\n";
     1874
     1875                        $wp_new_user_notification_email_admin = array(
     1876                                'to'      => get_option( 'admin_email' ),
     1877                                /* translators: Password change notification email subject. %s: Site title */
     1878                                'subject' => __( '[%s] New User Registration' ),
     1879                                'message' => $message,
     1880                                'headers' => '',
     1881                        );
     1882
     1883                        /**
     1884                         * Filters the contents of the new user notification email sent to the site admin.
     1885                         *
     1886                         * @since 4.9.0
     1887                         *
     1888                         * @param array   $wp_new_user_notification_email {
     1889                         *     Used to build wp_mail().
     1890                         *
     1891                         *     @type string $to      The intended recipient - site admin email address.
     1892                         *     @type string $subject The subject of the email.
     1893                         *     @type string $message The body of the email.
     1894                         *     @type string $headers The headers of the email.
     1895                         * }
     1896                         * @param WP_User $user     User object for new user.
     1897                         * @param string  $blogname The site title.
     1898                         */
     1899                        $wp_new_user_notification_email_admin = apply_filters( 'wp_new_user_notification_email_admin', $wp_new_user_notification_email_admin, $user, $blogname );
     1900
     1901                        @wp_mail(
     1902                                $wp_new_user_notification_email_admin['to'],
     1903                                wp_specialchars_decode( sprintf( $wp_new_user_notification_email_admin['subject'], $blogname ) ),
     1904                                $wp_new_user_notification_email_admin['message'],
     1905                                $wp_new_user_notification_email_admin['headers']
     1906                        );
     1907
     1908                        if ( $switched_locale ) {
     1909                                restore_previous_locale();
     1910                        }
     1911                }
     1912
     1913                // `$deprecated was pre-4.3 `$plaintext_pass`. An empty `$plaintext_pass` didn't sent a user notification.
     1914                if ( 'admin' === $notify || ( empty( $deprecated ) && empty( $notify ) ) ) {
     1915                        return;
     1916                }
     1917
     1918                // Generate something random for a password reset key.
     1919                $key = wp_generate_password( 20, false );
     1920
     1921                /** This action is documented in wp-login.php */
     1922                do_action( 'retrieve_password_key', $user->user_login, $key );
     1923
     1924                // Now insert the key, hashed, into the DB.
     1925                if ( empty( $wp_hasher ) ) {
     1926                        require_once ABSPATH . WPINC . '/class-phpass.php';
     1927                        $wp_hasher = new PasswordHash( 8, true );
     1928                }
     1929                $hashed = time() . ':' . $wp_hasher->HashPassword( $key );
     1930                $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
     1931
     1932                $switched_locale = switch_to_locale( get_user_locale( $user ) );
     1933
     1934                /* translators: %s: user login */
     1935                $message  = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
     1936                $message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n";
     1937                $message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . ">\r\n\r\n";
     1938
     1939                $message .= wp_login_url() . "\r\n";
     1940
     1941                $wp_new_user_notification_email = array(
     1942                        'to'      => $user->user_email,
    17741943                        /* translators: Password change notification email subject. %s: Site title */
    1775                         'subject' => __( '[%s] Password Changed' ),
     1944                        'subject' => __( '[%s] Your username and password info' ),
    17761945                        'message' => $message,
    17771946                        'headers' => '',
    … …  
    17791948
    17801949                /**
    1781                  * Filters the contents of the password change notification email sent to the site admin.
    1782                  *
    1783                  * @since 4.9.0
    1784                  *
    1785                  * @param array   $wp_password_change_notification_email {
    1786                  *     Used to build wp_mail().
    1787                  *
    1788                  *     @type string $to      The intended recipient - site admin email address.
    1789                  *     @type string $subject The subject of the email.
    1790                  *     @type string $message The body of the email.
    1791                  *     @type string $headers The headers of the email.
    1792                  * }
    1793                  * @param WP_User $user     User object for user whose password was changed.
    1794                  * @param string  $blogname The site title.
    1795                  */
    1796                 $wp_password_change_notification_email = apply_filters( 'wp_password_change_notification_email', $wp_password_change_notification_email, $user, $blogname );
    1797 
    1798                 wp_mail(
    1799                         $wp_password_change_notification_email['to'],
    1800                         wp_specialchars_decode( sprintf( $wp_password_change_notification_email['subject'], $blogname ) ),
    1801                         $wp_password_change_notification_email['message'],
    1802                         $wp_password_change_notification_email['headers']
    1803                 );
    1804         }
    1805 }
    1806 endif;
    1807 
    1808 if ( !function_exists('wp_new_user_notification') ) :
    1809 /**
    1810  * Email login credentials to a newly-registered user.
    1811  *
    1812  * A new user registration notification is also sent to admin email.
    1813  *
    1814  * @since 2.0.0
    1815  * @since 4.3.0 The `$plaintext_pass` parameter was changed to `$notify`.
    1816  * @since 4.3.1 The `$plaintext_pass` parameter was deprecated. `$notify` added as a third parameter.
    1817  * @since 4.6.0 The `$notify` parameter accepts 'user' for sending notification only to the user created.
    1818  *
    1819  * @global wpdb         $wpdb      WordPress database object for queries.
    1820  * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
    1821  *
    1822  * @param int    $user_id    User ID.
    1823  * @param null   $deprecated Not used (argument deprecated).
    1824  * @param string $notify     Optional. Type of notification that should happen. Accepts 'admin' or an empty
    1825  *                           string (admin only), 'user', or 'both' (admin and user). Default empty.
    1826  */
    1827 function wp_new_user_notification( $user_id, $deprecated = null, $notify = '' ) {
    1828         if ( $deprecated !== null ) {
    1829                 _deprecated_argument( __FUNCTION__, '4.3.1' );
    1830         }
    1831 
    1832         global $wpdb, $wp_hasher;
    1833         $user = get_userdata( $user_id );
    1834 
    1835         // The blogname option is escaped with esc_html on the way into the database in sanitize_option
    1836         // we want to reverse this for the plain text arena of emails.
    1837         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
    1838 
    1839         if ( 'user' !== $notify ) {
    1840                 $switched_locale = switch_to_locale( get_locale() );
    1841 
    1842                 /* translators: %s: site title */
    1843                 $message  = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
    1844                 /* translators: %s: user login */
    1845                 $message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
    1846                 /* translators: %s: user email address */
    1847                 $message .= sprintf( __( 'Email: %s' ), $user->user_email ) . "\r\n";
    1848 
    1849                 $wp_new_user_notification_email_admin = array(
    1850                         'to'      => get_option( 'admin_email' ),
    1851                         /* translators: Password change notification email subject. %s: Site title */
    1852                         'subject' => __( '[%s] New User Registration' ),
    1853                         'message' => $message,
    1854                         'headers' => '',
    1855                 );
    1856 
    1857                 /**
    1858                  * Filters the contents of the new user notification email sent to the site admin.
     1950                 * Filters the contents of the new user notification email sent to the new user.
    18591951                 *
    18601952                 * @since 4.9.0
    … …  
    18631955                 *     Used to build wp_mail().
    18641956                 *
    1865                  *     @type string $to      The intended recipient - site admin email address.
     1957                 *     @type string $to      The intended recipient - New user email address.
    18661958                 *     @type string $subject The subject of the email.
    18671959                 *     @type string $message The body of the email.
    … …  
    18711963                 * @param string  $blogname The site title.
    18721964                 */
    1873                 $wp_new_user_notification_email_admin = apply_filters( 'wp_new_user_notification_email_admin', $wp_new_user_notification_email_admin, $user, $blogname );
    1874 
    1875                 @wp_mail(
    1876                         $wp_new_user_notification_email_admin['to'],
    1877                         wp_specialchars_decode( sprintf( $wp_new_user_notification_email_admin['subject'], $blogname ) ),
    1878                         $wp_new_user_notification_email_admin['message'],
    1879                         $wp_new_user_notification_email_admin['headers']
     1965                $wp_new_user_notification_email = apply_filters( 'wp_new_user_notification_email', $wp_new_user_notification_email, $user, $blogname );
     1966
     1967                wp_mail(
     1968                        $wp_new_user_notification_email['to'],
     1969                        wp_specialchars_decode( sprintf( $wp_new_user_notification_email['subject'], $blogname ) ),
     1970                        $wp_new_user_notification_email['message'],
     1971                        $wp_new_user_notification_email['headers']
    18801972                );
    18811973
    … …  
    18841976                }
    18851977        }
    1886 
    1887         // `$deprecated was pre-4.3 `$plaintext_pass`. An empty `$plaintext_pass` didn't sent a user notification.
    1888         if ( 'admin' === $notify || ( empty( $deprecated ) && empty( $notify ) ) ) {
    1889                 return;
    1890         }
    1891 
    1892         // Generate something random for a password reset key.
    1893         $key = wp_generate_password( 20, false );
    1894 
    1895         /** This action is documented in wp-login.php */
    1896         do_action( 'retrieve_password_key', $user->user_login, $key );
    1897 
    1898         // Now insert the key, hashed, into the DB.
    1899         if ( empty( $wp_hasher ) ) {
    1900                 require_once ABSPATH . WPINC . '/class-phpass.php';
    1901                 $wp_hasher = new PasswordHash( 8, true );
    1902         }
    1903         $hashed = time() . ':' . $wp_hasher->HashPassword( $key );
    1904         $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
    1905 
    1906         $switched_locale = switch_to_locale( get_user_locale( $user ) );
    1907 
    1908         /* translators: %s: user login */
    1909         $message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
    1910         $message .= __('To set your password, visit the following address:') . "\r\n\r\n";
    1911         $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user->user_login), 'login') . ">\r\n\r\n";
    1912 
    1913         $message .= wp_login_url() . "\r\n";
    1914 
    1915         $wp_new_user_notification_email = array(
    1916                 'to'      => $user->user_email,
    1917                 /* translators: Password change notification email subject. %s: Site title */
    1918                 'subject' => __( '[%s] Your username and password info' ),
    1919                 'message' => $message,
    1920                 'headers' => '',
    1921         );
    1922 
    1923         /**
    1924          * Filters the contents of the new user notification email sent to the new user.
    1925          *
    1926          * @since 4.9.0
    1927          *
    1928          * @param array   $wp_new_user_notification_email {
    1929          *     Used to build wp_mail().
    1930          *
    1931          *     @type string $to      The intended recipient - New user email address.
    1932          *     @type string $subject The subject of the email.
    1933          *     @type string $message The body of the email.
    1934          *     @type string $headers The headers of the email.
    1935          * }
    1936          * @param WP_User $user     User object for new user.
    1937          * @param string  $blogname The site title.
    1938          */
    1939         $wp_new_user_notification_email = apply_filters( 'wp_new_user_notification_email', $wp_new_user_notification_email, $user, $blogname );
    1940 
    1941         wp_mail(
    1942                 $wp_new_user_notification_email['to'],
    1943                 wp_specialchars_decode( sprintf( $wp_new_user_notification_email['subject'], $blogname ) ),
    1944                 $wp_new_user_notification_email['message'],
    1945                 $wp_new_user_notification_email['headers']
    1946         );
    1947 
    1948         if ( $switched_locale ) {
    1949                 restore_previous_locale();
    1950         }
    1951 }
    1952 endif;
    1953 
    1954 if ( !function_exists('wp_nonce_tick') ) :
    1955 /**
    1956  * Get the time-dependent variable for nonce creation.
    1957  *
    1958  * A nonce has a lifespan of two ticks. Nonces in their second tick may be
    1959  * updated, e.g. by autosave.
    1960  *
    1961  * @since 2.5.0
    1962  *
    1963  * @return float Float value rounded up to the next highest integer.
    1964  */
    1965 function wp_nonce_tick() {
    1966         /**
    1967          * Filters the lifespan of nonces in seconds.
     1978endif;
     1979
     1980if ( ! function_exists( 'wp_nonce_tick' ) ) :
     1981        /**
     1982         * Get the time-dependent variable for nonce creation.
     1983         *
     1984         * A nonce has a lifespan of two ticks. Nonces in their second tick may be
     1985         * updated, e.g. by autosave.
    19681986         *
    19691987         * @since 2.5.0
    19701988         *
    1971          * @param int $lifespan Lifespan of nonces in seconds. Default 86,400 seconds, or one day.
    1972          */
    1973         $nonce_life = apply_filters( 'nonce_life', DAY_IN_SECONDS );
    1974 
    1975         return ceil(time() / ( $nonce_life / 2 ));
    1976 }
    1977 endif;
    1978 
    1979 if ( !function_exists('wp_verify_nonce') ) :
    1980 /**
    1981  * Verify that correct nonce was used with time limit.
    1982  *
    1983  * The user is given an amount of time to use the token, so therefore, since the
    1984  * UID and $action remain the same, the independent variable is the time.
    1985  *
    1986  * @since 2.0.3
    1987  *
    1988  * @param string     $nonce  Nonce that was used in the form to verify
    1989  * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
    1990  * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
    1991  *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
    1992  */
    1993 function wp_verify_nonce( $nonce, $action = -1 ) {
    1994         $nonce = (string) $nonce;
    1995         $user = wp_get_current_user();
    1996         $uid = (int) $user->ID;
    1997         if ( ! $uid ) {
    1998                 /**
    1999                  * Filters whether the user who generated the nonce is logged out.
    2000                  *
    2001                  * @since 3.5.0
    2002                  *
    2003                  * @param int    $uid    ID of the nonce-owning user.
    2004                  * @param string $action The nonce action.
    2005                  */
    2006                 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
    2007         }
    2008 
    2009         if ( empty( $nonce ) ) {
     1989         * @return float Float value rounded up to the next highest integer.
     1990         */
     1991        function wp_nonce_tick() {
     1992                /**
     1993                 * Filters the lifespan of nonces in seconds.
     1994                 *
     1995                 * @since 2.5.0
     1996                 *
     1997                 * @param int $lifespan Lifespan of nonces in seconds. Default 86,400 seconds, or one day.
     1998                 */
     1999                $nonce_life = apply_filters( 'nonce_life', DAY_IN_SECONDS );
     2000
     2001                return ceil( time() / ( $nonce_life / 2 ) );
     2002        }
     2003endif;
     2004
     2005if ( ! function_exists( 'wp_verify_nonce' ) ) :
     2006        /**
     2007         * Verify that correct nonce was used with time limit.
     2008         *
     2009         * The user is given an amount of time to use the token, so therefore, since the
     2010         * UID and $action remain the same, the independent variable is the time.
     2011         *
     2012         * @since 2.0.3
     2013         *
     2014         * @param string     $nonce  Nonce that was used in the form to verify
     2015         * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
     2016         * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
     2017         *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
     2018         */
     2019        function wp_verify_nonce( $nonce, $action = -1 ) {
     2020                $nonce = (string) $nonce;
     2021                $user  = wp_get_current_user();
     2022                $uid   = (int) $user->ID;
     2023                if ( ! $uid ) {
     2024                        /**
     2025                         * Filters whether the user who generated the nonce is logged out.
     2026                         *
     2027                         * @since 3.5.0
     2028                         *
     2029                         * @param int    $uid    ID of the nonce-owning user.
     2030                         * @param string $action The nonce action.
     2031                         */
     2032                        $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
     2033                }
     2034
     2035                if ( empty( $nonce ) ) {
     2036                        return false;
     2037                }
     2038
     2039                $token = wp_get_session_token();
     2040                $i     = wp_nonce_tick();
     2041
     2042                // Nonce generated 0-12 hours ago
     2043                $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
     2044                if ( hash_equals( $expected, $nonce ) ) {
     2045                        return 1;
     2046                }
     2047
     2048                // Nonce generated 12-24 hours ago
     2049                $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
     2050                if ( hash_equals( $expected, $nonce ) ) {
     2051                        return 2;
     2052                }
     2053
     2054                /**
     2055                 * Fires when nonce verification fails.
     2056                 *
     2057                 * @since 4.4.0
     2058                 *
     2059                 * @param string     $nonce  The invalid nonce.
     2060                 * @param string|int $action The nonce action.
     2061                 * @param WP_User    $user   The current user object.
     2062                 * @param string     $token  The user's session token.
     2063                 */
     2064                do_action( 'wp_verify_nonce_failed', $nonce, $action, $user, $token );
     2065
     2066                // Invalid nonce
    20102067                return false;
    20112068        }
    2012 
    2013         $token = wp_get_session_token();
    2014         $i = wp_nonce_tick();
    2015 
    2016         // Nonce generated 0-12 hours ago
    2017         $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10 );
    2018         if ( hash_equals( $expected, $nonce ) ) {
    2019                 return 1;
    2020         }
    2021 
    2022         // Nonce generated 12-24 hours ago
    2023         $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
    2024         if ( hash_equals( $expected, $nonce ) ) {
    2025                 return 2;
    2026         }
    2027 
    2028         /**
    2029          * Fires when nonce verification fails.
    2030          *
    2031          * @since 4.4.0
    2032          *
    2033          * @param string     $nonce  The invalid nonce.
    2034          * @param string|int $action The nonce action.
    2035          * @param WP_User    $user   The current user object.
    2036          * @param string     $token  The user's session token.
    2037          */
    2038         do_action( 'wp_verify_nonce_failed', $nonce, $action, $user, $token );
    2039 
    2040         // Invalid nonce
    2041         return false;
    2042 }
    2043 endif;
    2044 
    2045 if ( !function_exists('wp_create_nonce') ) :
    2046 /**
    2047  * Creates a cryptographic token tied to a specific action, user, user session,
    2048  * and window of time.
    2049  *
    2050  * @since 2.0.3
    2051  * @since 4.0.0 Session tokens were integrated with nonce creation
    2052  *
    2053  * @param string|int $action Scalar value to add context to the nonce.
    2054  * @return string The token.
    2055  */
    2056 function wp_create_nonce($action = -1) {
    2057         $user = wp_get_current_user();
    2058         $uid = (int) $user->ID;
    2059         if ( ! $uid ) {
    2060                 /** This filter is documented in wp-includes/pluggable.php */
    2061                 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
    2062         }
    2063 
    2064         $token = wp_get_session_token();
    2065         $i = wp_nonce_tick();
    2066 
    2067         return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
    2068 }
    2069 endif;
    2070 
    2071 if ( !function_exists('wp_salt') ) :
    2072 /**
    2073  * Get salt to add to hashes.
    2074  *
    2075  * Salts are created using secret keys. Secret keys are located in two places:
    2076  * in the database and in the wp-config.php file. The secret key in the database
    2077  * is randomly generated and will be appended to the secret keys in wp-config.php.
    2078  *
    2079  * The secret keys in wp-config.php should be updated to strong, random keys to maximize
    2080  * security. Below is an example of how the secret key constants are defined.
    2081  * Do not paste this example directly into wp-config.php. Instead, have a
    2082  * {@link https://api.wordpress.org/secret-key/1.1/salt/ secret key created} just
    2083  * for you.
    2084  *
    2085  *     define('AUTH_KEY',         ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON');
    2086  *     define('SECURE_AUTH_KEY',  'LzJ}op]mr|6+![P}Ak:uNdJCJZd>(Hx.-Mh#Tz)pCIU#uGEnfFz|f ;;eU%/U^O~');
    2087  *     define('LOGGED_IN_KEY',    '|i|Ux`9<p-h$aFf(qnT:sDO:D1P^wZ$$/Ra@miTJi9G;ddp_<q}6H1)o|a +&JCM');
    2088  *     define('NONCE_KEY',        '%:R{[P|,s.KuMltH5}cI;/k<Gx~j!f0I)m_sIyu+&NJZ)-iO>z7X>QYR0Z_XnZ@|');
    2089  *     define('AUTH_SALT',        'eZyT)-Naw]F8CwA*VaW#q*|.)g@o}||wf~@C-YSt}(dh_r6EbI#A,y|nU2{B#JBW');
    2090  *     define('SECURE_AUTH_SALT', '!=oLUTXh,QW=H `}`L|9/^4-3 STz},T(w}W<I`.JjPi)<Bmf1v,HpGe}T1:Xt7n');
    2091  *     define('LOGGED_IN_SALT',   '+XSqHc;@Q*K_b|Z?NC[3H!!EONbh.n<+=uKR:>*c(u`g~EJBf#8u#R{mUEZrozmm');
    2092  *     define('NONCE_SALT',       'h`GXHhD>SLWVfg1(1(N{;.V!MoE(SfbA_ksP@&`+AycHcAV$+?@3q+rxV{%^VyKT');
    2093  *
    2094  * Salting passwords helps against tools which has stored hashed values of
    2095  * common dictionary strings. The added values makes it harder to crack.
    2096  *
    2097  * @since 2.5.0
    2098  *
    2099  * @link https://api.wordpress.org/secret-key/1.1/salt/ Create secrets for wp-config.php
    2100  *
    2101  * @staticvar array $cached_salts
    2102  * @staticvar array $duplicated_keys
    2103  *
    2104  * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
    2105  * @return string Salt value
    2106  */
    2107 function wp_salt( $scheme = 'auth' ) {
    2108         static $cached_salts = array();
    2109         if ( isset( $cached_salts[ $scheme ] ) ) {
    2110                 /**
    2111                  * Filters the WordPress salt.
    2112                  *
    2113                  * @since 2.5.0
    2114                  *
    2115                  * @param string $cached_salt Cached salt for the given scheme.
    2116                  * @param string $scheme      Authentication scheme. Values include 'auth',
    2117                  *                            'secure_auth', 'logged_in', and 'nonce'.
    2118                  */
    2119                 return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
    2120         }
    2121 
    2122         static $duplicated_keys;
    2123         if ( null === $duplicated_keys ) {
    2124                 $duplicated_keys = array( 'put your unique phrase here' => true );
    2125                 foreach ( array( 'AUTH', 'SECURE_AUTH', 'LOGGED_IN', 'NONCE', 'SECRET' ) as $first ) {
    2126                         foreach ( array( 'KEY', 'SALT' ) as $second ) {
    2127                                 if ( ! defined( "{$first}_{$second}" ) ) {
    2128                                         continue;
    2129                                 }
    2130                                 $value = constant( "{$first}_{$second}" );
    2131                                 $duplicated_keys[ $value ] = isset( $duplicated_keys[ $value ] );
    2132                         }
    2133                 }
    2134         }
    2135 
    2136         $values = array(
    2137                 'key' => '',
    2138                 'salt' => ''
    2139         );
    2140         if ( defined( 'SECRET_KEY' ) && SECRET_KEY && empty( $duplicated_keys[ SECRET_KEY ] ) ) {
    2141                 $values['key'] = SECRET_KEY;
    2142         }
    2143         if ( 'auth' == $scheme && defined( 'SECRET_SALT' ) && SECRET_SALT && empty( $duplicated_keys[ SECRET_SALT ] ) ) {
    2144                 $values['salt'] = SECRET_SALT;
    2145         }
    2146 
    2147         if ( in_array( $scheme, array( 'auth', 'secure_auth', 'logged_in', 'nonce' ) ) ) {
    2148                 foreach ( array( 'key', 'salt' ) as $type ) {
    2149                         $const = strtoupper( "{$scheme}_{$type}" );
    2150                         if ( defined( $const ) && constant( $const ) && empty( $duplicated_keys[ constant( $const ) ] ) ) {
    2151                                 $values[ $type ] = constant( $const );
    2152                         } elseif ( ! $values[ $type ] ) {
    2153                                 $values[ $type ] = get_site_option( "{$scheme}_{$type}" );
    2154                                 if ( ! $values[ $type ] ) {
    2155                                         $values[ $type ] = wp_generate_password( 64, true, true );
    2156                                         update_site_option( "{$scheme}_{$type}", $values[ $type ] );
     2069endif;
     2070
     2071if ( ! function_exists( 'wp_create_nonce' ) ) :
     2072        /**
     2073         * Creates a cryptographic token tied to a specific action, user, user session,
     2074         * and window of time.
     2075         *
     2076         * @since 2.0.3
     2077         * @since 4.0.0 Session tokens were integrated with nonce creation
     2078         *
     2079         * @param string|int $action Scalar value to add context to the nonce.
     2080         * @return string The token.
     2081         */
     2082        function wp_create_nonce( $action = -1 ) {
     2083                $user = wp_get_current_user();
     2084                $uid  = (int) $user->ID;
     2085                if ( ! $uid ) {
     2086                        /** This filter is documented in wp-includes/pluggable.php */
     2087                        $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
     2088                }
     2089
     2090                $token = wp_get_session_token();
     2091                $i     = wp_nonce_tick();
     2092
     2093                return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
     2094        }
     2095endif;
     2096
     2097if ( ! function_exists( 'wp_salt' ) ) :
     2098        /**
     2099         * Get salt to add to hashes.
     2100         *
     2101         * Salts are created using secret keys. Secret keys are located in two places:
     2102         * in the database and in the wp-config.php file. The secret key in the database
     2103         * is randomly generated and will be appended to the secret keys in wp-config.php.
     2104         *
     2105         * The secret keys in wp-config.php should be updated to strong, random keys to maximize
     2106         * security. Below is an example of how the secret key constants are defined.
     2107         * Do not paste this example directly into wp-config.php. Instead, have a
     2108         * {@link https://api.wordpress.org/secret-key/1.1/salt/ secret key created} just
     2109         * for you.
     2110         *
     2111         *     define('AUTH_KEY',         ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON');
     2112         *     define('SECURE_AUTH_KEY',  'LzJ}op]mr|6+![P}Ak:uNdJCJZd>(Hx.-Mh#Tz)pCIU#uGEnfFz|f ;;eU%/U^O~');
     2113         *     define('LOGGED_IN_KEY',    '|i|Ux`9<p-h$aFf(qnT:sDO:D1P^wZ$$/Ra@miTJi9G;ddp_<q}6H1)o|a +&JCM');
     2114         *     define('NONCE_KEY',        '%:R{[P|,s.KuMltH5}cI;/k<Gx~j!f0I)m_sIyu+&NJZ)-iO>z7X>QYR0Z_XnZ@|');
     2115         *     define('AUTH_SALT',        'eZyT)-Naw]F8CwA*VaW#q*|.)g@o}||wf~@C-YSt}(dh_r6EbI#A,y|nU2{B#JBW');
     2116         *     define('SECURE_AUTH_SALT', '!=oLUTXh,QW=H `}`L|9/^4-3 STz},T(w}W<I`.JjPi)<Bmf1v,HpGe}T1:Xt7n');
     2117         *     define('LOGGED_IN_SALT',   '+XSqHc;@Q*K_b|Z?NC[3H!!EONbh.n<+=uKR:>*c(u`g~EJBf#8u#R{mUEZrozmm');
     2118         *     define('NONCE_SALT',       'h`GXHhD>SLWVfg1(1(N{;.V!MoE(SfbA_ksP@&`+AycHcAV$+?@3q+rxV{%^VyKT');
     2119         *
     2120         * Salting passwords helps against tools which has stored hashed values of
     2121         * common dictionary strings. The added values makes it harder to crack.
     2122         *
     2123         * @since 2.5.0
     2124         *
     2125         * @link https://api.wordpress.org/secret-key/1.1/salt/ Create secrets for wp-config.php
     2126         *
     2127         * @staticvar array $cached_salts
     2128         * @staticvar array $duplicated_keys
     2129         *
     2130         * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
     2131         * @return string Salt value
     2132         */
     2133        function wp_salt( $scheme = 'auth' ) {
     2134                static $cached_salts = array();
     2135                if ( isset( $cached_salts[ $scheme ] ) ) {
     2136                        /**
     2137                         * Filters the WordPress salt.
     2138                         *
     2139                         * @since 2.5.0
     2140                         *
     2141                         * @param string $cached_salt Cached salt for the given scheme.
     2142                         * @param string $scheme      Authentication scheme. Values include 'auth',
     2143                         *                            'secure_auth', 'logged_in', and 'nonce'.
     2144                         */
     2145                        return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
     2146                }
     2147
     2148                static $duplicated_keys;
     2149                if ( null === $duplicated_keys ) {
     2150                        $duplicated_keys = array( 'put your unique phrase here' => true );
     2151                        foreach ( array( 'AUTH', 'SECURE_AUTH', 'LOGGED_IN', 'NONCE', 'SECRET' ) as $first ) {
     2152                                foreach ( array( 'KEY', 'SALT' ) as $second ) {
     2153                                        if ( ! defined( "{$first}_{$second}" ) ) {
     2154                                                continue;
     2155                                        }
     2156                                        $value                     = constant( "{$first}_{$second}" );
     2157                                        $duplicated_keys[ $value ] = isset( $duplicated_keys[ $value ] );
    21572158                                }
    21582159                        }
    21592160                }
    2160         } else {
    2161                 if ( ! $values['key'] ) {
    2162                         $values['key'] = get_site_option( 'secret_key' );
     2161
     2162                $values = array(
     2163                        'key'  => '',
     2164                        'salt' => '',
     2165                );
     2166                if ( defined( 'SECRET_KEY' ) && SECRET_KEY && empty( $duplicated_keys[ SECRET_KEY ] ) ) {
     2167                        $values['key'] = SECRET_KEY;
     2168                }
     2169                if ( 'auth' == $scheme && defined( 'SECRET_SALT' ) && SECRET_SALT && empty( $duplicated_keys[ SECRET_SALT ] ) ) {
     2170                        $values['salt'] = SECRET_SALT;
     2171                }
     2172
     2173                if ( in_array( $scheme, array( 'auth', 'secure_auth', 'logged_in', 'nonce' ) ) ) {
     2174                        foreach ( array( 'key', 'salt' ) as $type ) {
     2175                                $const = strtoupper( "{$scheme}_{$type}" );
     2176                                if ( defined( $const ) && constant( $const ) && empty( $duplicated_keys[ constant( $const ) ] ) ) {
     2177                                        $values[ $type ] = constant( $const );
     2178                                } elseif ( ! $values[ $type ] ) {
     2179                                        $values[ $type ] = get_site_option( "{$scheme}_{$type}" );
     2180                                        if ( ! $values[ $type ] ) {
     2181                                                $values[ $type ] = wp_generate_password( 64, true, true );
     2182                                                update_site_option( "{$scheme}_{$type}", $values[ $type ] );
     2183                                        }
     2184                                }
     2185                        }
     2186                } else {
    21632187                        if ( ! $values['key'] ) {
    2164                                 $values['key'] = wp_generate_password( 64, true, true );
    2165                                 update_site_option( 'secret_key', $values['key'] );
     2188                                $values['key'] = get_site_option( 'secret_key' );
     2189                                if ( ! $values['key'] ) {
     2190                                        $values['key'] = wp_generate_password( 64, true, true );
     2191                                        update_site_option( 'secret_key', $values['key'] );
     2192                                }
    21662193                        }
    2167                 }
    2168                 $values['salt'] = hash_hmac( 'md5', $scheme, $values['key'] );
    2169         }
    2170 
    2171         $cached_salts[ $scheme ] = $values['key'] . $values['salt'];
    2172 
    2173         /** This filter is documented in wp-includes/pluggable.php */
    2174         return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
    2175 }
    2176 endif;
    2177 
    2178 if ( !function_exists('wp_hash') ) :
    2179 /**
    2180  * Get hash of given string.
    2181  *
    2182  * @since 2.0.3
    2183  *
    2184  * @param string $data   Plain text to hash
    2185  * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
    2186  * @return string Hash of $data
    2187  */
    2188 function wp_hash($data, $scheme = 'auth') {
    2189         $salt = wp_salt($scheme);
    2190 
    2191         return hash_hmac('md5', $data, $salt);
    2192 }
    2193 endif;
    2194 
    2195 if ( !function_exists('wp_hash_password') ) :
    2196 /**
    2197  * Create a hash (encrypt) of a plain text password.
    2198  *
    2199  * For integration with other applications, this function can be overwritten to
    2200  * instead use the other package password checking algorithm.
    2201  *
    2202  * @since 2.5.0
    2203  *
    2204  * @global PasswordHash $wp_hasher PHPass object
    2205  *
    2206  * @param string $password Plain text user password to hash
    2207  * @return string The hash string of the password
    2208  */
    2209 function wp_hash_password($password) {
    2210         global $wp_hasher;
    2211 
    2212         if ( empty($wp_hasher) ) {
    2213                 require_once( ABSPATH . WPINC . '/class-phpass.php');
    2214                 // By default, use the portable hash from phpass
    2215                 $wp_hasher = new PasswordHash(8, true);
    2216         }
    2217 
    2218         return $wp_hasher->HashPassword( trim( $password ) );
    2219 }
    2220 endif;
    2221 
    2222 if ( !function_exists('wp_check_password') ) :
    2223 /**
    2224  * Checks the plaintext password against the encrypted Password.
    2225  *
    2226  * Maintains compatibility between old version and the new cookie authentication
    2227  * protocol using PHPass library. The $hash parameter is the encrypted password
    2228  * and the function compares the plain text password when encrypted similarly
    2229  * against the already encrypted password to see if they match.
    2230  *
    2231  * For integration with other applications, this function can be overwritten to
    2232  * instead use the other package password checking algorithm.
    2233  *
    2234  * @since 2.5.0
    2235  *
    2236  * @global PasswordHash $wp_hasher PHPass object used for checking the password
    2237  *      against the $hash + $password
    2238  * @uses PasswordHash::CheckPassword
    2239  *
    2240  * @param string     $password Plaintext user's password
    2241  * @param string     $hash     Hash of the user's password to check against.
    2242  * @param string|int $user_id  Optional. User ID.
    2243  * @return bool False, if the $password does not match the hashed password
    2244  */
    2245 function wp_check_password($password, $hash, $user_id = '') {
    2246         global $wp_hasher;
    2247 
    2248         // If the hash is still md5...
    2249         if ( strlen($hash) <= 32 ) {
    2250                 $check = hash_equals( $hash, md5( $password ) );
    2251                 if ( $check && $user_id ) {
    2252                         // Rehash using new hash.
    2253                         wp_set_password($password, $user_id);
    2254                         $hash = wp_hash_password($password);
    2255                 }
    2256 
    2257                 /**
    2258                  * Filters whether the plaintext password matches the encrypted password.
    2259                  *
    2260                  * @since 2.5.0
    2261                  *
    2262                  * @param bool       $check    Whether the passwords match.
    2263                  * @param string     $password The plaintext password.
    2264                  * @param string     $hash     The hashed password.
    2265                  * @param string|int $user_id  User ID. Can be empty.
    2266                  */
     2194                        $values['salt'] = hash_hmac( 'md5', $scheme, $values['key'] );
     2195                }
     2196
     2197                $cached_salts[ $scheme ] = $values['key'] . $values['salt'];
     2198
     2199                /** This filter is documented in wp-includes/pluggable.php */
     2200                return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
     2201        }
     2202endif;
     2203
     2204if ( ! function_exists( 'wp_hash' ) ) :
     2205        /**
     2206         * Get hash of given string.
     2207         *
     2208         * @since 2.0.3
     2209         *
     2210         * @param string $data   Plain text to hash
     2211         * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
     2212         * @return string Hash of $data
     2213         */
     2214        function wp_hash( $data, $scheme = 'auth' ) {
     2215                $salt = wp_salt( $scheme );
     2216
     2217                return hash_hmac( 'md5', $data, $salt );
     2218        }
     2219endif;
     2220
     2221if ( ! function_exists( 'wp_hash_password' ) ) :
     2222        /**
     2223         * Create a hash (encrypt) of a plain text password.
     2224         *
     2225         * For integration with other applications, this function can be overwritten to
     2226         * instead use the other package password checking algorithm.
     2227         *
     2228         * @since 2.5.0
     2229         *
     2230         * @global PasswordHash $wp_hasher PHPass object
     2231         *
     2232         * @param string $password Plain text user password to hash
     2233         * @return string The hash string of the password
     2234         */
     2235        function wp_hash_password( $password ) {
     2236                global $wp_hasher;
     2237
     2238                if ( empty( $wp_hasher ) ) {
     2239                        require_once( ABSPATH . WPINC . '/class-phpass.php' );
     2240                        // By default, use the portable hash from phpass
     2241                        $wp_hasher = new PasswordHash( 8, true );
     2242                }
     2243
     2244                return $wp_hasher->HashPassword( trim( $password ) );
     2245        }
     2246endif;
     2247
     2248if ( ! function_exists( 'wp_check_password' ) ) :
     2249        /**
     2250         * Checks the plaintext password against the encrypted Password.
     2251         *
     2252         * Maintains compatibility between old version and the new cookie authentication
     2253         * protocol using PHPass library. The $hash parameter is the encrypted password
     2254         * and the function compares the plain text password when encrypted similarly
     2255         * against the already encrypted password to see if they match.
     2256         *
     2257         * For integration with other applications, this function can be overwritten to
     2258         * instead use the other package password checking algorithm.
     2259         *
     2260         * @since 2.5.0
     2261         *
     2262         * @global PasswordHash $wp_hasher PHPass object used for checking the password
     2263         *  against the $hash + $password
     2264         * @uses PasswordHash::CheckPassword
     2265         *
     2266         * @param string     $password Plaintext user's password
     2267         * @param string     $hash     Hash of the user's password to check against.
     2268         * @param string|int $user_id  Optional. User ID.
     2269         * @return bool False, if the $password does not match the hashed password
     2270         */
     2271        function wp_check_password( $password, $hash, $user_id = '' ) {
     2272                global $wp_hasher;
     2273
     2274                // If the hash is still md5...
     2275                if ( strlen( $hash ) <= 32 ) {
     2276                        $check = hash_equals( $hash, md5( $password ) );
     2277                        if ( $check && $user_id ) {
     2278                                // Rehash using new hash.
     2279                                wp_set_password( $password, $user_id );
     2280                                $hash = wp_hash_password( $password );
     2281                        }
     2282
     2283                        /**
     2284                         * Filters whether the plaintext password matches the encrypted password.
     2285                         *
     2286                         * @since 2.5.0
     2287                         *
     2288                         * @param bool       $check    Whether the passwords match.
     2289                         * @param string     $password The plaintext password.
     2290                         * @param string     $hash     The hashed password.
     2291                         * @param string|int $user_id  User ID. Can be empty.
     2292                         */
     2293                        return apply_filters( 'check_password', $check, $password, $hash, $user_id );
     2294                }
     2295
     2296                // If the stored hash is longer than an MD5, presume the
     2297                // new style phpass portable hash.
     2298                if ( empty( $wp_hasher ) ) {
     2299                        require_once( ABSPATH . WPINC . '/class-phpass.php' );
     2300                        // By default, use the portable hash from phpass
     2301                        $wp_hasher = new PasswordHash( 8, true );
     2302                }
     2303
     2304                $check = $wp_hasher->CheckPassword( $password, $hash );
     2305
     2306                /** This filter is documented in wp-includes/pluggable.php */
    22672307                return apply_filters( 'check_password', $check, $password, $hash, $user_id );
    22682308        }
    2269 
    2270         // If the stored hash is longer than an MD5, presume the
    2271         // new style phpass portable hash.
    2272         if ( empty($wp_hasher) ) {
    2273                 require_once( ABSPATH . WPINC . '/class-phpass.php');
    2274                 // By default, use the portable hash from phpass
    2275                 $wp_hasher = new PasswordHash(8, true);
    2276         }
    2277 
    2278         $check = $wp_hasher->CheckPassword($password, $hash);
    2279 
    2280         /** This filter is documented in wp-includes/pluggable.php */
    2281         return apply_filters( 'check_password', $check, $password, $hash, $user_id );
    2282 }
    2283 endif;
    2284 
    2285 if ( !function_exists('wp_generate_password') ) :
    2286 /**
    2287  * Generates a random password drawn from the defined set of characters.
    2288  *
    2289  * @since 2.5.0
    2290  *
    2291  * @param int  $length              Optional. The length of password to generate. Default 12.
    2292  * @param bool $special_chars       Optional. Whether to include standard special characters.
    2293  *                                  Default true.
    2294  * @param bool $extra_special_chars Optional. Whether to include other special characters.
    2295  *                                  Used when generating secret keys and salts. Default false.
    2296  * @return string The random password.
    2297  */
    2298 function wp_generate_password( $length = 12, $special_chars = true, $extra_special_chars = false ) {
    2299         $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    2300         if ( $special_chars )
    2301                 $chars .= '!@#$%^&*()';
    2302         if ( $extra_special_chars )
    2303                 $chars .= '-_ []{}<>~`+=,.;:/?|';
    2304 
    2305         $password = '';
    2306         for ( $i = 0; $i < $length; $i++ ) {
    2307                 $password .= substr($chars, wp_rand(0, strlen($chars) - 1), 1);
    2308         }
    2309 
    2310         /**
    2311          * Filters the randomly-generated password.
    2312          *
    2313          * @since 3.0.0
    2314          *
    2315          * @param string $password The generated password.
    2316          */
    2317         return apply_filters( 'random_password', $password );
    2318 }
    2319 endif;
    2320 
    2321 if ( !function_exists('wp_rand') ) :
    2322 /**
    2323  * Generates a random number
    2324  *
    2325  * @since 2.6.2
    2326  * @since 4.4.0 Uses PHP7 random_int() or the random_compat library if available.
    2327  *
    2328  * @global string $rnd_value
    2329  * @staticvar string $seed
    2330  * @staticvar bool $external_rand_source_available
    2331  *
    2332  * @param int $min Lower limit for the generated number
    2333  * @param int $max Upper limit for the generated number
    2334  * @return int A random number between min and max
    2335  */
    2336 function wp_rand( $min = 0, $max = 0 ) {
    2337         global $rnd_value;
    2338 
    2339         // Some misconfigured 32bit environments (Entropy PHP, for example) truncate integers larger than PHP_INT_MAX to PHP_INT_MAX rather than overflowing them to floats.
    2340         $max_random_number = 3000000000 === 2147483647 ? (float) "4294967295" : 4294967295; // 4294967295 = 0xffffffff
    2341 
    2342         // We only handle Ints, floats are truncated to their integer value.
    2343         $min = (int) $min;
    2344         $max = (int) $max;
    2345 
    2346         // Use PHP's CSPRNG, or a compatible method
    2347         static $use_random_int_functionality = true;
    2348         if ( $use_random_int_functionality ) {
    2349                 try {
    2350                         $_max = ( 0 != $max ) ? $max : $max_random_number;
    2351                         // wp_rand() can accept arguments in either order, PHP cannot.
    2352                         $_max = max( $min, $_max );
    2353                         $_min = min( $min, $_max );
    2354                         $val = random_int( $_min, $_max );
    2355                         if ( false !== $val ) {
    2356                                 return absint( $val );
    2357                         } else {
     2309endif;
     2310
     2311if ( ! function_exists( 'wp_generate_password' ) ) :
     2312        /**
     2313         * Generates a random password drawn from the defined set of characters.
     2314         *
     2315         * @since 2.5.0
     2316         *
     2317         * @param int  $length              Optional. The length of password to generate. Default 12.
     2318         * @param bool $special_chars       Optional. Whether to include standard special characters.
     2319         *                                  Default true.
     2320         * @param bool $extra_special_chars Optional. Whether to include other special characters.
     2321         *                                  Used when generating secret keys and salts. Default false.
     2322         * @return string The random password.
     2323         */
     2324        function wp_generate_password( $length = 12, $special_chars = true, $extra_special_chars = false ) {
     2325                $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
     2326                if ( $special_chars ) {
     2327                        $chars .= '!@#$%^&*()';
     2328                }
     2329                if ( $extra_special_chars ) {
     2330                        $chars .= '-_ []{}<>~`+=,.;:/?|';
     2331                }
     2332
     2333                $password = '';
     2334                for ( $i = 0; $i < $length; $i++ ) {
     2335                        $password .= substr( $chars, wp_rand( 0, strlen( $chars ) - 1 ), 1 );
     2336                }
     2337
     2338                /**
     2339                 * Filters the randomly-generated password.
     2340                 *
     2341                 * @since 3.0.0
     2342                 *
     2343                 * @param string $password The generated password.
     2344                 */
     2345                return apply_filters( 'random_password', $password );
     2346        }
     2347endif;
     2348
     2349if ( ! function_exists( 'wp_rand' ) ) :
     2350        /**
     2351         * Generates a random number
     2352         *
     2353         * @since 2.6.2
     2354         * @since 4.4.0 Uses PHP7 random_int() or the random_compat library if available.
     2355         *
     2356         * @global string $rnd_value
     2357         * @staticvar string $seed
     2358         * @staticvar bool $external_rand_source_available
     2359         *
     2360         * @param int $min Lower limit for the generated number
     2361         * @param int $max Upper limit for the generated number
     2362         * @return int A random number between min and max
     2363         */
     2364        function wp_rand( $min = 0, $max = 0 ) {
     2365                global $rnd_value;
     2366
     2367                // Some misconfigured 32bit environments (Entropy PHP, for example) truncate integers larger than PHP_INT_MAX to PHP_INT_MAX rather than overflowing them to floats.
     2368                $max_random_number = 3000000000 === 2147483647 ? (float) '4294967295' : 4294967295; // 4294967295 = 0xffffffff
     2369
     2370                // We only handle Ints, floats are truncated to their integer value.
     2371                $min = (int) $min;
     2372                $max = (int) $max;
     2373
     2374                // Use PHP's CSPRNG, or a compatible method
     2375                static $use_random_int_functionality = true;
     2376                if ( $use_random_int_functionality ) {
     2377                        try {
     2378                                $_max = ( 0 != $max ) ? $max : $max_random_number;
     2379                                // wp_rand() can accept arguments in either order, PHP cannot.
     2380                                $_max = max( $min, $_max );
     2381                                $_min = min( $min, $_max );
     2382                                $val  = random_int( $_min, $_max );
     2383                                if ( false !== $val ) {
     2384                                        return absint( $val );
     2385                                } else {
     2386                                        $use_random_int_functionality = false;
     2387                                }
     2388                        } catch ( Error $e ) {
     2389                                $use_random_int_functionality = false;
     2390                        } catch ( Exception $e ) {
    23582391                                $use_random_int_functionality = false;
    23592392                        }
    2360                 } catch ( Error $e ) {
    2361                         $use_random_int_functionality = false;
    2362                 } catch ( Exception $e ) {
    2363                         $use_random_int_functionality = false;
    2364                 }
    2365         }
    2366 
    2367         // Reset $rnd_value after 14 uses
    2368         // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
    2369         if ( strlen($rnd_value) < 8 ) {
    2370                 if ( defined( 'WP_SETUP_CONFIG' ) )
    2371                         static $seed = '';
    2372                 else
    2373                         $seed = get_transient('random_seed');
    2374                 $rnd_value = md5( uniqid(microtime() . mt_rand(), true ) . $seed );
    2375                 $rnd_value .= sha1($rnd_value);
    2376                 $rnd_value .= sha1($rnd_value . $seed);
    2377                 $seed = md5($seed . $rnd_value);
    2378                 if ( ! defined( 'WP_SETUP_CONFIG' ) && ! defined( 'WP_INSTALLING' ) ) {
    2379                         set_transient( 'random_seed', $seed );
    2380                 }
    2381         }
    2382 
    2383         // Take the first 8 digits for our value
    2384         $value = substr($rnd_value, 0, 8);
    2385 
    2386         // Strip the first eight, leaving the remainder for the next call to wp_rand().
    2387         $rnd_value = substr($rnd_value, 8);
    2388 
    2389         $value = abs(hexdec($value));
    2390 
    2391         // Reduce the value to be within the min - max range
    2392         if ( $max != 0 )
    2393                 $value = $min + ( $max - $min + 1 ) * $value / ( $max_random_number + 1 );
    2394 
    2395         return abs(intval($value));
    2396 }
    2397 endif;
    2398 
    2399 if ( !function_exists('wp_set_password') ) :
    2400 /**
    2401  * Updates the user's password with a new encrypted one.
    2402  *
    2403  * For integration with other applications, this function can be overwritten to
    2404  * instead use the other package password checking algorithm.
    2405  *
    2406  * Please note: This function should be used sparingly and is really only meant for single-time
    2407  * application. Leveraging this improperly in a plugin or theme could result in an endless loop
    2408  * of password resets if precautions are not taken to ensure it does not execute on every page load.
    2409  *
    2410  * @since 2.5.0
    2411  *
    2412  * @global wpdb $wpdb WordPress database abstraction object.
    2413  *
    2414  * @param string $password The plaintext new user password
    2415  * @param int    $user_id  User ID
    2416  */
    2417 function wp_set_password( $password, $user_id ) {
    2418         global $wpdb;
    2419 
    2420         $hash = wp_hash_password( $password );
    2421         $wpdb->update($wpdb->users, array('user_pass' => $hash, 'user_activation_key' => ''), array('ID' => $user_id) );
    2422 
    2423         wp_cache_delete($user_id, 'users');
    2424 }
    2425 endif;
    2426 
    2427 if ( !function_exists( 'get_avatar' ) ) :
    2428 /**
    2429  * Retrieve the avatar `<img>` tag for a user, email address, MD5 hash, comment, or post.
    2430  *
    2431  * @since 2.5.0
    2432  * @since 4.2.0 Optional `$args` parameter added.
    2433  *
    2434  * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
    2435  *                           user email, WP_User object, WP_Post object, or WP_Comment object.
    2436  * @param int    $size       Optional. Height and width of the avatar image file in pixels. Default 96.
    2437  * @param string $default    Optional. URL for the default image or a default type. Accepts '404'
    2438  *                           (return a 404 instead of a default image), 'retro' (8bit), 'monsterid'
    2439  *                           (monster), 'wavatar' (cartoon face), 'indenticon' (the "quilt"),
    2440  *                           'mystery', 'mm', or 'mysteryman' (The Oyster Man), 'blank' (transparent GIF),
    2441  *                           or 'gravatar_default' (the Gravatar logo). Default is the value of the
    2442  *                           'avatar_default' option, with a fallback of 'mystery'.
    2443  * @param string $alt        Optional. Alternative text to use in &lt;img&gt; tag. Default empty.
    2444  * @param array  $args       {
    2445  *     Optional. Extra arguments to retrieve the avatar.
    2446  *
    2447  *     @type int          $height        Display height of the avatar in pixels. Defaults to $size.
    2448  *     @type int          $width         Display width of the avatar in pixels. Defaults to $size.
    2449  *     @type bool         $force_default Whether to always show the default image, never the Gravatar. Default false.
    2450  *     @type string       $rating        What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are
    2451  *                                       judged in that order. Default is the value of the 'avatar_rating' option.
    2452  *     @type string       $scheme        URL scheme to use. See set_url_scheme() for accepted values.
    2453  *                                       Default null.
    2454  *     @type array|string $class         Array or string of additional classes to add to the &lt;img&gt; element.
    2455  *                                       Default null.
    2456  *     @type bool         $force_display Whether to always show the avatar - ignores the show_avatars option.
    2457  *                                       Default false.
    2458  *     @type string       $extra_attr    HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
    2459  * }
    2460  * @return false|string `<img>` tag for the user's avatar. False on failure.
    2461  */
    2462 function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '', $args = null ) {
    2463         $defaults = array(
    2464                 // get_avatar_data() args.
    2465                 'size'          => 96,
    2466                 'height'        => null,
    2467                 'width'         => null,
    2468                 'default'       => get_option( 'avatar_default', 'mystery' ),
    2469                 'force_default' => false,
    2470                 'rating'        => get_option( 'avatar_rating' ),
    2471                 'scheme'        => null,
    2472                 'alt'           => '',
    2473                 'class'         => null,
    2474                 'force_display' => false,
    2475                 'extra_attr'    => '',
    2476         );
    2477 
    2478         if ( empty( $args ) ) {
    2479                 $args = array();
    2480         }
    2481 
    2482         $args['size']    = (int) $size;
    2483         $args['default'] = $default;
    2484         $args['alt']     = $alt;
    2485 
    2486         $args = wp_parse_args( $args, $defaults );
    2487 
    2488         if ( empty( $args['height'] ) ) {
    2489                 $args['height'] = $args['size'];
    2490         }
    2491         if ( empty( $args['width'] ) ) {
    2492                 $args['width'] = $args['size'];
    2493         }
    2494 
    2495         if ( is_object( $id_or_email ) && isset( $id_or_email->comment_ID ) ) {
    2496                 $id_or_email = get_comment( $id_or_email );
    2497         }
    2498 
    2499         /**
    2500          * Filters whether to retrieve the avatar URL early.
    2501          *
    2502          * Passing a non-null value will effectively short-circuit get_avatar(), passing
    2503          * the value through the {@see 'get_avatar'} filter and returning early.
    2504          *
    2505          * @since 4.2.0
    2506          *
    2507          * @param string $avatar      HTML for the user's avatar. Default null.
    2508          * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
    2509          *                            user email, WP_User object, WP_Post object, or WP_Comment object.
    2510          * @param array  $args        Arguments passed to get_avatar_url(), after processing.
    2511          */
    2512         $avatar = apply_filters( 'pre_get_avatar', null, $id_or_email, $args );
    2513 
    2514         if ( ! is_null( $avatar ) ) {
    2515                 /** This filter is documented in wp-includes/pluggable.php */
     2393                }
     2394
     2395                // Reset $rnd_value after 14 uses
     2396                // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
     2397                if ( strlen( $rnd_value ) < 8 ) {
     2398                        if ( defined( 'WP_SETUP_CONFIG' ) ) {
     2399                                static $seed = '';
     2400                        } else {
     2401                                $seed = get_transient( 'random_seed' );
     2402                        }
     2403                        $rnd_value  = md5( uniqid( microtime() . mt_rand(), true ) . $seed );
     2404                        $rnd_value .= sha1( $rnd_value );
     2405                        $rnd_value .= sha1( $rnd_value . $seed );
     2406                        $seed       = md5( $seed . $rnd_value );
     2407                        if ( ! defined( 'WP_SETUP_CONFIG' ) && ! defined( 'WP_INSTALLING' ) ) {
     2408                                set_transient( 'random_seed', $seed );
     2409                        }
     2410                }
     2411
     2412                // Take the first 8 digits for our value
     2413                $value = substr( $rnd_value, 0, 8 );
     2414
     2415                // Strip the first eight, leaving the remainder for the next call to wp_rand().
     2416                $rnd_value = substr( $rnd_value, 8 );
     2417
     2418                $value = abs( hexdec( $value ) );
     2419
     2420                // Reduce the value to be within the min - max range
     2421                if ( $max != 0 ) {
     2422                        $value = $min + ( $max - $min + 1 ) * $value / ( $max_random_number + 1 );
     2423                }
     2424
     2425                return abs( intval( $value ) );
     2426        }
     2427endif;
     2428
     2429if ( ! function_exists( 'wp_set_password' ) ) :
     2430        /**
     2431         * Updates the user's password with a new encrypted one.
     2432         *
     2433         * For integration with other applications, this function can be overwritten to
     2434         * instead use the other package password checking algorithm.
     2435         *
     2436         * Please note: This function should be used sparingly and is really only meant for single-time
     2437         * application. Leveraging this improperly in a plugin or theme could result in an endless loop
     2438         * of password resets if precautions are not taken to ensure it does not execute on every page load.
     2439         *
     2440         * @since 2.5.0
     2441         *
     2442         * @global wpdb $wpdb WordPress database abstraction object.
     2443         *
     2444         * @param string $password The plaintext new user password
     2445         * @param int    $user_id  User ID
     2446         */
     2447        function wp_set_password( $password, $user_id ) {
     2448                global $wpdb;
     2449
     2450                $hash = wp_hash_password( $password );
     2451                $wpdb->update(
     2452                        $wpdb->users, array(
     2453                                'user_pass'           => $hash,
     2454                                'user_activation_key' => '',
     2455                        ), array( 'ID' => $user_id )
     2456                );
     2457
     2458                wp_cache_delete( $user_id, 'users' );
     2459        }
     2460endif;
     2461
     2462if ( ! function_exists( 'get_avatar' ) ) :
     2463        /**
     2464         * Retrieve the avatar `<img>` tag for a user, email address, MD5 hash, comment, or post.
     2465         *
     2466         * @since 2.5.0
     2467         * @since 4.2.0 Optional `$args` parameter added.
     2468         *
     2469         * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
     2470         *                           user email, WP_User object, WP_Post object, or WP_Comment object.
     2471         * @param int    $size       Optional. Height and width of the avatar image file in pixels. Default 96.
     2472         * @param string $default    Optional. URL for the default image or a default type. Accepts '404'
     2473         *                           (return a 404 instead of a default image), 'retro' (8bit), 'monsterid'
     2474         *                           (monster), 'wavatar' (cartoon face), 'indenticon' (the "quilt"),
     2475         *                           'mystery', 'mm', or 'mysteryman' (The Oyster Man), 'blank' (transparent GIF),
     2476         *                           or 'gravatar_default' (the Gravatar logo). Default is the value of the
     2477         *                           'avatar_default' option, with a fallback of 'mystery'.
     2478         * @param string $alt        Optional. Alternative text to use in &lt;img&gt; tag. Default empty.
     2479         * @param array  $args       {
     2480         *     Optional. Extra arguments to retrieve the avatar.
     2481         *
     2482         *     @type int          $height        Display height of the avatar in pixels. Defaults to $size.
     2483         *     @type int          $width         Display width of the avatar in pixels. Defaults to $size.
     2484         *     @type bool         $force_default Whether to always show the default image, never the Gravatar. Default false.
     2485         *     @type string       $rating        What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are
     2486         *                                       judged in that order. Default is the value of the 'avatar_rating' option.
     2487         *     @type string       $scheme        URL scheme to use. See set_url_scheme() for accepted values.
     2488         *                                       Default null.
     2489         *     @type array|string $class         Array or string of additional classes to add to the &lt;img&gt; element.
     2490         *                                       Default null.
     2491         *     @type bool         $force_display Whether to always show the avatar - ignores the show_avatars option.
     2492         *                                       Default false.
     2493         *     @type string       $extra_attr    HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
     2494         * }
     2495         * @return false|string `<img>` tag for the user's avatar. False on failure.
     2496         */
     2497        function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '', $args = null ) {
     2498                $defaults = array(
     2499                        // get_avatar_data() args.
     2500                        'size'          => 96,
     2501                        'height'        => null,
     2502                        'width'         => null,
     2503                        'default'       => get_option( 'avatar_default', 'mystery' ),
     2504                        'force_default' => false,
     2505                        'rating'        => get_option( 'avatar_rating' ),
     2506                        'scheme'        => null,
     2507                        'alt'           => '',
     2508                        'class'         => null,
     2509                        'force_display' => false,
     2510                        'extra_attr'    => '',
     2511                );
     2512
     2513                if ( empty( $args ) ) {
     2514                        $args = array();
     2515                }
     2516
     2517                $args['size']    = (int) $size;
     2518                $args['default'] = $default;
     2519                $args['alt']     = $alt;
     2520
     2521                $args = wp_parse_args( $args, $defaults );
     2522
     2523                if ( empty( $args['height'] ) ) {
     2524                        $args['height'] = $args['size'];
     2525                }
     2526                if ( empty( $args['width'] ) ) {
     2527                        $args['width'] = $args['size'];
     2528                }
     2529
     2530                if ( is_object( $id_or_email ) && isset( $id_or_email->comment_ID ) ) {
     2531                        $id_or_email = get_comment( $id_or_email );
     2532                }
     2533
     2534                /**
     2535                 * Filters whether to retrieve the avatar URL early.
     2536                 *
     2537                 * Passing a non-null value will effectively short-circuit get_avatar(), passing
     2538                 * the value through the {@see 'get_avatar'} filter and returning early.
     2539                 *
     2540                 * @since 4.2.0
     2541                 *
     2542                 * @param string $avatar      HTML for the user's avatar. Default null.
     2543                 * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
     2544                 *                            user email, WP_User object, WP_Post object, or WP_Comment object.
     2545                 * @param array  $args        Arguments passed to get_avatar_url(), after processing.
     2546                 */
     2547                $avatar = apply_filters( 'pre_get_avatar', null, $id_or_email, $args );
     2548
     2549                if ( ! is_null( $avatar ) ) {
     2550                        /** This filter is documented in wp-includes/pluggable.php */
     2551                        return apply_filters( 'get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args );
     2552                }
     2553
     2554                if ( ! $args['force_display'] && ! get_option( 'show_avatars' ) ) {
     2555                        return false;
     2556                }
     2557
     2558                $url2x = get_avatar_url( $id_or_email, array_merge( $args, array( 'size' => $args['size'] * 2 ) ) );
     2559
     2560                $args = get_avatar_data( $id_or_email, $args );
     2561
     2562                $url = $args['url'];
     2563
     2564                if ( ! $url || is_wp_error( $url ) ) {
     2565                        return false;
     2566                }
     2567
     2568                $class = array( 'avatar', 'avatar-' . (int) $args['size'], 'photo' );
     2569
     2570                if ( ! $args['found_avatar'] || $args['force_default'] ) {
     2571                        $class[] = 'avatar-default';
     2572                }
     2573
     2574                if ( $args['class'] ) {
     2575                        if ( is_array( $args['class'] ) ) {
     2576                                $class = array_merge( $class, $args['class'] );
     2577                        } else {
     2578                                $class[] = $args['class'];
     2579                        }
     2580                }
     2581
     2582                $avatar = sprintf(
     2583                        "<img alt='%s' src='%s' srcset='%s' class='%s' height='%d' width='%d' %s/>",
     2584                        esc_attr( $args['alt'] ),
     2585                        esc_url( $url ),
     2586                        esc_url( $url2x ) . ' 2x',
     2587                        esc_attr( join( ' ', $class ) ),
     2588                        (int) $args['height'],
     2589                        (int) $args['width'],
     2590                        $args['extra_attr']
     2591                );
     2592
     2593                /**
     2594                 * Filters the avatar to retrieve.
     2595                 *
     2596                 * @since 2.5.0
     2597                 * @since 4.2.0 The `$args` parameter was added.
     2598                 *
     2599                 * @param string $avatar      &lt;img&gt; tag for the user's avatar.
     2600                 * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
     2601                 *                            user email, WP_User object, WP_Post object, or WP_Comment object.
     2602                 * @param int    $size        Square avatar width and height in pixels to retrieve.
     2603                 * @param string $default     URL for the default image or a default type. Accepts '404', 'retro', 'monsterid',
     2604                 *                            'wavatar', 'indenticon','mystery' (or 'mm', or 'mysteryman'), 'blank', or 'gravatar_default'.
     2605                 *                            Default is the value of the 'avatar_default' option, with a fallback of 'mystery'.
     2606                 * @param string $alt         Alternative text to use in the avatar image tag. Default empty.
     2607                 * @param array  $args        Arguments passed to get_avatar_data(), after processing.
     2608                 */
    25162609                return apply_filters( 'get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args );
    25172610        }
    2518 
    2519         if ( ! $args['force_display'] && ! get_option( 'show_avatars' ) ) {
    2520                 return false;
    2521         }
    2522 
    2523         $url2x = get_avatar_url( $id_or_email, array_merge( $args, array( 'size' => $args['size'] * 2 ) ) );
    2524 
    2525         $args = get_avatar_data( $id_or_email, $args );
    2526 
    2527         $url = $args['url'];
    2528 
    2529         if ( ! $url || is_wp_error( $url ) ) {
    2530                 return false;
    2531         }
    2532 
    2533         $class = array( 'avatar', 'avatar-' . (int) $args['size'], 'photo' );
    2534 
    2535         if ( ! $args['found_avatar'] || $args['force_default'] ) {
    2536                 $class[] = 'avatar-default';
    2537         }
    2538 
    2539         if ( $args['class'] ) {
    2540                 if ( is_array( $args['class'] ) ) {
    2541                         $class = array_merge( $class, $args['class'] );
     2611endif;
     2612
     2613if ( ! function_exists( 'wp_text_diff' ) ) :
     2614        /**
     2615         * Displays a human readable HTML representation of the difference between two strings.
     2616         *
     2617         * The Diff is available for getting the changes between versions. The output is
     2618         * HTML, so the primary use is for displaying the changes. If the two strings
     2619         * are equivalent, then an empty string will be returned.
     2620         *
     2621         * The arguments supported and can be changed are listed below.
     2622         *
     2623         * 'title' : Default is an empty string. Titles the diff in a manner compatible
     2624         *      with the output.
     2625         * 'title_left' : Default is an empty string. Change the HTML to the left of the
     2626         *      title.
     2627         * 'title_right' : Default is an empty string. Change the HTML to the right of
     2628         *      the title.
     2629         *
     2630         * @since 2.6.0
     2631         *
     2632         * @see wp_parse_args() Used to change defaults to user defined settings.
     2633         * @uses Text_Diff
     2634         * @uses WP_Text_Diff_Renderer_Table
     2635         *
     2636         * @param string       $left_string  "old" (left) version of string
     2637         * @param string       $right_string "new" (right) version of string
     2638         * @param string|array $args         Optional. Change 'title', 'title_left', and 'title_right' defaults.
     2639         * @return string Empty string if strings are equivalent or HTML with differences.
     2640         */
     2641        function wp_text_diff( $left_string, $right_string, $args = null ) {
     2642                $defaults = array(
     2643                        'title'       => '',
     2644                        'title_left'  => '',
     2645                        'title_right' => '',
     2646                );
     2647                $args     = wp_parse_args( $args, $defaults );
     2648
     2649                if ( ! class_exists( 'WP_Text_Diff_Renderer_Table', false ) ) {
     2650                        require( ABSPATH . WPINC . '/wp-diff.php' );
     2651                }
     2652
     2653                $left_string  = normalize_whitespace( $left_string );
     2654                $right_string = normalize_whitespace( $right_string );
     2655
     2656                $left_lines  = explode( "\n", $left_string );
     2657                $right_lines = explode( "\n", $right_string );
     2658                $text_diff   = new Text_Diff( $left_lines, $right_lines );
     2659                $renderer    = new WP_Text_Diff_Renderer_Table( $args );
     2660                $diff        = $renderer->render( $text_diff );
     2661
     2662                if ( ! $diff ) {
     2663                        return '';
     2664                }
     2665
     2666                $r = "<table class='diff'>\n";
     2667
     2668                if ( ! empty( $args['show_split_view'] ) ) {
     2669                        $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
    25422670                } else {
    2543                         $class[] = $args['class'];
    2544                 }
    2545         }
    2546 
    2547         $avatar = sprintf(
    2548                 "<img alt='%s' src='%s' srcset='%s' class='%s' height='%d' width='%d' %s/>",
    2549                 esc_attr( $args['alt'] ),
    2550                 esc_url( $url ),
    2551                 esc_url( $url2x ) . ' 2x',
    2552                 esc_attr( join( ' ', $class ) ),
    2553                 (int) $args['height'],
    2554                 (int) $args['width'],
    2555                 $args['extra_attr']
    2556         );
    2557 
    2558         /**
    2559          * Filters the avatar to retrieve.
    2560          *
    2561          * @since 2.5.0
    2562          * @since 4.2.0 The `$args` parameter was added.
    2563          *
    2564          * @param string $avatar      &lt;img&gt; tag for the user's avatar.
    2565          * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
    2566          *                            user email, WP_User object, WP_Post object, or WP_Comment object.
    2567          * @param int    $size        Square avatar width and height in pixels to retrieve.
    2568          * @param string $default     URL for the default image or a default type. Accepts '404', 'retro', 'monsterid',
    2569          *                            'wavatar', 'indenticon','mystery' (or 'mm', or 'mysteryman'), 'blank', or 'gravatar_default'.
    2570          *                            Default is the value of the 'avatar_default' option, with a fallback of 'mystery'.
    2571          * @param string $alt         Alternative text to use in the avatar image tag. Default empty.
    2572          * @param array  $args        Arguments passed to get_avatar_data(), after processing.
    2573          */
    2574         return apply_filters( 'get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args );
    2575 }
    2576 endif;
    2577 
    2578 if ( !function_exists( 'wp_text_diff' ) ) :
    2579 /**
    2580  * Displays a human readable HTML representation of the difference between two strings.
    2581  *
    2582  * The Diff is available for getting the changes between versions. The output is
    2583  * HTML, so the primary use is for displaying the changes. If the two strings
    2584  * are equivalent, then an empty string will be returned.
    2585  *
    2586  * The arguments supported and can be changed are listed below.
    2587  *
    2588  * 'title' : Default is an empty string. Titles the diff in a manner compatible
    2589  *              with the output.
    2590  * 'title_left' : Default is an empty string. Change the HTML to the left of the
    2591  *              title.
    2592  * 'title_right' : Default is an empty string. Change the HTML to the right of
    2593  *              the title.
    2594  *
    2595  * @since 2.6.0
    2596  *
    2597  * @see wp_parse_args() Used to change defaults to user defined settings.
    2598  * @uses Text_Diff
    2599  * @uses WP_Text_Diff_Renderer_Table
    2600  *
    2601  * @param string       $left_string  "old" (left) version of string
    2602  * @param string       $right_string "new" (right) version of string
    2603  * @param string|array $args         Optional. Change 'title', 'title_left', and 'title_right' defaults.
    2604  * @return string Empty string if strings are equivalent or HTML with differences.
    2605  */
    2606 function wp_text_diff( $left_string, $right_string, $args = null ) {
    2607         $defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
    2608         $args = wp_parse_args( $args, $defaults );
    2609 
    2610         if ( ! class_exists( 'WP_Text_Diff_Renderer_Table', false ) )
    2611                 require( ABSPATH . WPINC . '/wp-diff.php' );
    2612 
    2613         $left_string  = normalize_whitespace($left_string);
    2614         $right_string = normalize_whitespace($right_string);
    2615 
    2616         $left_lines  = explode("\n", $left_string);
    2617         $right_lines = explode("\n", $right_string);
    2618         $text_diff = new Text_Diff($left_lines, $right_lines);
    2619         $renderer  = new WP_Text_Diff_Renderer_Table( $args );
    2620         $diff = $renderer->render($text_diff);
    2621 
    2622         if ( !$diff )
    2623                 return '';
    2624 
    2625         $r  = "<table class='diff'>\n";
    2626 
    2627         if ( ! empty( $args[ 'show_split_view' ] ) ) {
    2628                 $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
    2629         } else {
    2630                 $r .= "<col class='content' />";
    2631         }
    2632 
    2633         if ( $args['title'] || $args['title_left'] || $args['title_right'] )
    2634                 $r .= "<thead>";
    2635         if ( $args['title'] )
    2636                 $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
    2637         if ( $args['title_left'] || $args['title_right'] ) {
    2638                 $r .= "<tr class='diff-sub-title'>\n";
    2639                 $r .= "\t<td></td><th>$args[title_left]</th>\n";
    2640                 $r .= "\t<td></td><th>$args[title_right]</th>\n";
    2641                 $r .= "</tr>\n";
    2642         }
    2643         if ( $args['title'] || $args['title_left'] || $args['title_right'] )
    2644                 $r .= "</thead>\n";
    2645 
    2646         $r .= "<tbody>\n$diff\n</tbody>\n";
    2647         $r .= "</table>";
    2648 
    2649         return $r;
    2650 }
    2651 endif;
    2652 
     2671                        $r .= "<col class='content' />";
     2672                }
     2673
     2674                if ( $args['title'] || $args['title_left'] || $args['title_right'] ) {
     2675                        $r .= '<thead>';
     2676                }
     2677                if ( $args['title'] ) {
     2678                        $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
     2679                }
     2680                if ( $args['title_left'] || $args['title_right'] ) {
     2681                        $r .= "<tr class='diff-sub-title'>\n";
     2682                        $r .= "\t<td></td><th>$args[title_left]</th>\n";
     2683                        $r .= "\t<td></td><th>$args[title_right]</th>\n";
     2684                        $r .= "</tr>\n";
     2685                }
     2686                if ( $args['title'] || $args['title_left'] || $args['title_right'] ) {
     2687                        $r .= "</thead>\n";
     2688                }
     2689
     2690                $r .= "<tbody>\n$diff\n</tbody>\n";
     2691                $r .= '</table>';
     2692
     2693                return $r;
     2694        }
     2695endif;
     2696
Note: See TracChangeset for help on using the changeset viewer.