~canonical-sysadmins/wordpress/5.1.1

« back to all changes in this revision

Viewing changes to wp-includes/pluggable.php

  • Committer: Barry Price
  • Date: 2019-02-22 03:51:26 UTC
  • mfrom: (1.2.12 upstream)
  • Revision ID: barry.price@canonical.com-20190222035126-o28k38qs8jfyjsxt
Merge WP5.1 from upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 * @package WordPress
7
7
 */
8
8
 
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;
 
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
28
 
29
 
        // If `$id` matches the user who's already current, there's nothing to do.
30
 
        if ( isset( $current_user )
 
29
                // If `$id` matches the user who's already current, there's nothing to do.
 
30
                if ( isset( $current_user )
31
31
                && ( $current_user instanceof WP_User )
32
32
                && ( $id == $current_user->ID )
33
33
                && ( 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
 
35
49
                return $current_user;
36
50
        }
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 ) );
 
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
 
 
105
                $user = new WP_User;
 
106
                $user->init( $userdata );
 
107
 
 
108
                return $user;
 
109
        }
 
110
endif;
 
111
 
 
112
if ( ! 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
        }
 
142
endif;
 
143
 
 
144
if ( ! 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();
232
229
                } 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] ) );
245
 
                                        }
246
 
                                        continue;
247
 
                                }
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;
305
 
                                }
306
 
                        }
307
 
                }
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
 
}
 
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;
 
249
                                        }
 
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 ) {
 
410
                                        continue;
 
411
                                }
 
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;
 
473
                                }
 
474
                        }
 
475
                }
 
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
        }
500
507
endif;
501
508
 
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
 
 
 
509
if ( ! function_exists( 'wp_authenticate' ) ) :
518
510
        /**
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
 
511
         * Authenticate a user, confirming the login credentials are valid.
 
512
         *
 
513
         * @since 2.5.0
525
514
         * @since 4.5.0 `$username` now accepts an email address.
526
515
         *
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.
599
 
                 *
600
 
                 * @since 2.7.0
601
 
                 *
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.
 
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
        }
 
563
endif;
 
564
 
 
565
if ( ! 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
        }
 
582
endif;
 
583
 
 
584
if ( ! 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.
 
687
                 *
 
688
                 * @since 2.7.0
 
689
                 *
 
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
        }
 
697
endif;
 
698
 
 
699
if ( ! function_exists( 'wp_generate_auth_cookie' ) ) :
 
700
        /**
 
701
         * Generate authentication cookie contents.
728
702
         *
729
703
         * @since 2.5.0
730
704
         * @since 4.0.0 The `$token` parameter was added.
731
705
         *
732
 
         * @param string $cookie     Authentication cookie.
733
 
         * @param int    $user_id    User ID.
 
706
         * @param int    $user_id    User ID
734
707
         * @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.
 
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.
737
711
         */
738
 
        return apply_filters( 'auth_cookie', $cookie, $user_id, $expiration, $scheme, $token );
739
 
}
 
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
        }
740
747
endif;
741
748
 
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() ) {
 
749
if ( ! 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':
766
766
                                        $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 ) {
775
789
                        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
        }
 
796
endif;
 
797
 
 
798
if ( ! 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 value.
 
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' or 'secure_auth'.
 
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 value.
 
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
        }
 
935
endif;
 
936
 
 
937
if ( ! 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
 
826
951
                /** 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
 
        // Post password cookie
972
 
        setcookie( 'wp-postpass_' . COOKIEHASH, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
973
 
}
974
 
endif;
975
 
 
976
 
if ( !function_exists('is_user_logged_in') ) :
977
 
/**
978
 
 * Determines whether the current visitor is a logged in user.
979
 
 *
980
 
 * For more information on this and similar theme functions, check out
981
 
 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
982
 
 * Conditional Tags} article in the Theme Developer Handbook.
983
 
 *
984
 
 * @since 2.0.0
985
 
 *
986
 
 * @return bool True if user is logged in, false if not logged in.
987
 
 */
988
 
function is_user_logged_in() {
989
 
        $user = wp_get_current_user();
990
 
 
991
 
        return $user->exists();
992
 
}
993
 
endif;
994
 
 
995
 
if ( !function_exists('auth_redirect') ) :
996
 
/**
997
 
 * Checks if a user is logged in, if not it redirects them to the login page.
998
 
 *
999
 
 * @since 1.5.0
1000
 
 */
1001
 
function auth_redirect() {
1002
 
        // Checks if a user is logged in, if not redirects them to the login page
1003
 
 
1004
 
        $secure = ( is_ssl() || force_ssl_admin() );
1005
 
 
1006
 
        /**
1007
 
         * Filters whether to use a secure authentication redirect.
1008
 
         *
1009
 
         * @since 3.1.0
1010
 
         *
1011
 
         * @param bool $secure Whether to use a secure authentication redirect. Default false.
1012
 
         */
1013
 
        $secure = apply_filters( 'secure_auth_redirect', $secure );
1014
 
 
1015
 
        // If https is required and request is http, redirect
1016
 
        if ( $secure && !is_ssl() && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
1017
 
                if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
1018
 
                        wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
1019
 
                        exit();
1020
 
                } else {
1021
 
                        wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
1022
 
                        exit();
 
952
                if ( ! apply_filters( 'send_auth_cookies', true ) ) {
 
953
                        return;
1023
954
                }
1024
 
        }
1025
 
 
1026
 
        /**
1027
 
         * Filters the authentication redirect scheme.
1028
 
         *
1029
 
         * @since 2.9.0
1030
 
         *
1031
 
         * @param string $scheme Authentication redirect scheme. Default empty.
1032
 
         */
1033
 
        $scheme = apply_filters( 'auth_redirect_scheme', '' );
1034
 
 
1035
 
        if ( $user_id = wp_validate_auth_cookie( '',  $scheme) ) {
 
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
 
 
980
                // Post password cookie
 
981
                setcookie( 'wp-postpass_' . COOKIEHASH, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN );
 
982
        }
 
983
endif;
 
984
 
 
985
if ( ! function_exists( 'is_user_logged_in' ) ) :
 
986
        /**
 
987
         * Determines whether the current visitor is a logged in user.
 
988
         *
 
989
         * For more information on this and similar theme functions, check out
 
990
         * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
 
991
         * Conditional Tags} article in the Theme Developer Handbook.
 
992
         *
 
993
         * @since 2.0.0
 
994
         *
 
995
         * @return bool True if user is logged in, false if not logged in.
 
996
         */
 
997
        function is_user_logged_in() {
 
998
                $user = wp_get_current_user();
 
999
 
 
1000
                return $user->exists();
 
1001
        }
 
1002
endif;
 
1003
 
 
1004
if ( ! function_exists( 'auth_redirect' ) ) :
 
1005
        /**
 
1006
         * Checks if a user is logged in, if not it redirects them to the login page.
 
1007
         *
 
1008
         * @since 1.5.0
 
1009
         */
 
1010
        function auth_redirect() {
 
1011
                // Checks if a user is logged in, if not redirects them to the login page
 
1012
 
 
1013
                $secure = ( is_ssl() || force_ssl_admin() );
 
1014
 
1036
1015
                /**
1037
 
                 * Fires before the authentication redirect.
1038
 
                 *
1039
 
                 * @since 2.8.0
1040
 
                 *
1041
 
                 * @param int $user_id User ID.
 
1016
                 * Filters whether to use a secure authentication redirect.
 
1017
                 *
 
1018
                 * @since 3.1.0
 
1019
                 *
 
1020
                 * @param bool $secure Whether to use a secure authentication redirect. Default false.
1042
1021
                 */
1043
 
                do_action( 'auth_redirect', $user_id );
 
1022
                $secure = apply_filters( 'secure_auth_redirect', $secure );
1044
1023
 
1045
 
                // If the user wants ssl but the session is not ssl, redirect.
1046
 
                if ( !$secure && get_user_option('use_ssl', $user_id) && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
 
1024
                // If https is required and request is http, redirect
 
1025
                if ( $secure && ! is_ssl() && false !== strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) ) {
1047
1026
                        if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
1048
1027
                                wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
1049
1028
                                exit();
1053
1032
                        }
1054
1033
                }
1055
1034
 
1056
 
                return;  // The cookie is good so we're done
1057
 
        }
1058
 
 
1059
 
        // The cookie is no good so force login
1060
 
        nocache_headers();
1061
 
 
1062
 
        $redirect = ( strpos( $_SERVER['REQUEST_URI'], '/options.php' ) && wp_get_referer() ) ? wp_get_referer() : set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
1063
 
 
1064
 
        $login_url = wp_login_url($redirect, true);
1065
 
 
1066
 
        wp_redirect($login_url);
1067
 
        exit();
1068
 
}
1069
 
endif;
1070
 
 
1071
 
if ( !function_exists('check_admin_referer') ) :
1072
 
/**
1073
 
 * Makes sure that a user was referred from another admin page.
1074
 
 *
1075
 
 * To avoid security exploits.
1076
 
 *
1077
 
 * @since 1.2.0
1078
 
 *
1079
 
 * @param int|string $action    Action nonce.
1080
 
 * @param string     $query_arg Optional. Key to check for nonce in `$_REQUEST` (since 2.5).
1081
 
 *                              Default '_wpnonce'.
1082
 
 * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
1083
 
 *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
1084
 
 */
1085
 
function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
1086
 
        if ( -1 == $action )
1087
 
                _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2.0' );
1088
 
 
1089
 
        $adminurl = strtolower(admin_url());
1090
 
        $referer = strtolower(wp_get_referer());
1091
 
        $result = isset($_REQUEST[$query_arg]) ? wp_verify_nonce($_REQUEST[$query_arg], $action) : false;
1092
 
 
1093
 
        /**
1094
 
         * Fires once the admin request has been validated or not.
 
1035
                /**
 
1036
                 * Filters the authentication redirect scheme.
 
1037
                 *
 
1038
                 * @since 2.9.0
 
1039
                 *
 
1040
                 * @param string $scheme Authentication redirect scheme. Default empty.
 
1041
                 */
 
1042
                $scheme = apply_filters( 'auth_redirect_scheme', '' );
 
1043
 
 
1044
                if ( $user_id = wp_validate_auth_cookie( '', $scheme ) ) {
 
1045
                        /**
 
1046
                         * Fires before the authentication redirect.
 
1047
                         *
 
1048
                         * @since 2.8.0
 
1049
                         *
 
1050
                         * @param int $user_id User ID.
 
1051
                         */
 
1052
                        do_action( 'auth_redirect', $user_id );
 
1053
 
 
1054
                        // If the user wants ssl but the session is not ssl, redirect.
 
1055
                        if ( ! $secure && get_user_option( 'use_ssl', $user_id ) && false !== strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) ) {
 
1056
                                if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
 
1057
                                        wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
 
1058
                                        exit();
 
1059
                                } else {
 
1060
                                        wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
 
1061
                                        exit();
 
1062
                                }
 
1063
                        }
 
1064
 
 
1065
                        return;  // The cookie is good so we're done
 
1066
                }
 
1067
 
 
1068
                // The cookie is no good so force login
 
1069
                nocache_headers();
 
1070
 
 
1071
                $redirect = ( strpos( $_SERVER['REQUEST_URI'], '/options.php' ) && wp_get_referer() ) ? wp_get_referer() : set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
 
1072
 
 
1073
                $login_url = wp_login_url( $redirect, true );
 
1074
 
 
1075
                wp_redirect( $login_url );
 
1076
                exit();
 
1077
        }
 
1078
endif;
 
1079
 
 
1080
if ( ! function_exists( 'check_admin_referer' ) ) :
 
1081
        /**
 
1082
         * Makes sure that a user was referred from another admin page.
 
1083
         *
 
1084
         * To avoid security exploits.
 
1085
         *
 
1086
         * @since 1.2.0
 
1087
         *
 
1088
         * @param int|string $action    Action nonce.
 
1089
         * @param string     $query_arg Optional. Key to check for nonce in `$_REQUEST` (since 2.5).
 
1090
         *                              Default '_wpnonce'.
 
1091
         * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
 
1092
         *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
 
1093
         */
 
1094
        function check_admin_referer( $action = -1, $query_arg = '_wpnonce' ) {
 
1095
                if ( -1 == $action ) {
 
1096
                        _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2.0' );
 
1097
                }
 
1098
 
 
1099
                $adminurl = strtolower( admin_url() );
 
1100
                $referer  = strtolower( wp_get_referer() );
 
1101
                $result   = isset( $_REQUEST[ $query_arg ] ) ? wp_verify_nonce( $_REQUEST[ $query_arg ], $action ) : false;
 
1102
 
 
1103
                /**
 
1104
                 * Fires once the admin request has been validated or not.
 
1105
                 *
 
1106
                 * @since 1.5.1
 
1107
                 *
 
1108
                 * @param string    $action The nonce action.
 
1109
                 * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
 
1110
                 *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
 
1111
                 */
 
1112
                do_action( 'check_admin_referer', $action, $result );
 
1113
 
 
1114
                if ( ! $result && ! ( -1 == $action && strpos( $referer, $adminurl ) === 0 ) ) {
 
1115
                        wp_nonce_ays( $action );
 
1116
                        die();
 
1117
                }
 
1118
 
 
1119
                return $result;
 
1120
        }
 
1121
endif;
 
1122
 
 
1123
if ( ! function_exists( 'check_ajax_referer' ) ) :
 
1124
        /**
 
1125
         * Verifies the Ajax request to prevent processing requests external of the blog.
 
1126
         *
 
1127
         * @since 2.0.3
 
1128
         *
 
1129
         * @param int|string   $action    Action nonce.
 
1130
         * @param false|string $query_arg Optional. Key to check for the nonce in `$_REQUEST` (since 2.5). If false,
 
1131
         *                                `$_REQUEST` values will be evaluated for '_ajax_nonce', and '_wpnonce'
 
1132
         *                                (in that order). Default false.
 
1133
         * @param bool         $die       Optional. Whether to die early when the nonce cannot be verified.
 
1134
         *                                Default true.
 
1135
         * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
 
1136
         *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
 
1137
         */
 
1138
        function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
 
1139
                if ( -1 == $action ) {
 
1140
                        _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '4.7' );
 
1141
                }
 
1142
 
 
1143
                $nonce = '';
 
1144
 
 
1145
                if ( $query_arg && isset( $_REQUEST[ $query_arg ] ) ) {
 
1146
                        $nonce = $_REQUEST[ $query_arg ];
 
1147
                } elseif ( isset( $_REQUEST['_ajax_nonce'] ) ) {
 
1148
                        $nonce = $_REQUEST['_ajax_nonce'];
 
1149
                } elseif ( isset( $_REQUEST['_wpnonce'] ) ) {
 
1150
                        $nonce = $_REQUEST['_wpnonce'];
 
1151
                }
 
1152
 
 
1153
                $result = wp_verify_nonce( $nonce, $action );
 
1154
 
 
1155
                /**
 
1156
                 * Fires once the Ajax request has been validated or not.
 
1157
                 *
 
1158
                 * @since 2.1.0
 
1159
                 *
 
1160
                 * @param string    $action The Ajax nonce action.
 
1161
                 * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
 
1162
                 *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
 
1163
                 */
 
1164
                do_action( 'check_ajax_referer', $action, $result );
 
1165
 
 
1166
                if ( $die && false === $result ) {
 
1167
                        if ( wp_doing_ajax() ) {
 
1168
                                wp_die( -1, 403 );
 
1169
                        } else {
 
1170
                                die( '-1' );
 
1171
                        }
 
1172
                }
 
1173
 
 
1174
                return $result;
 
1175
        }
 
1176
endif;
 
1177
 
 
1178
if ( ! function_exists( 'wp_redirect' ) ) :
 
1179
        /**
 
1180
         * Redirects to another page.
 
1181
         *
 
1182
         * Note: wp_redirect() does not exit automatically, and should almost always be
 
1183
         * followed by a call to `exit;`:
 
1184
         *
 
1185
         *     wp_redirect( $url );
 
1186
         *     exit;
 
1187
         *
 
1188
         * Exiting can also be selectively manipulated by using wp_redirect() as a conditional
 
1189
         * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters:
 
1190
         *
 
1191
         *     if ( wp_redirect( $url ) ) {
 
1192
         *         exit;
 
1193
         *     }
1095
1194
         *
1096
1195
         * @since 1.5.1
1097
 
         *
1098
 
         * @param string    $action The nonce action.
1099
 
         * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
1100
 
         *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
1101
 
         */
1102
 
        do_action( 'check_admin_referer', $action, $result );
1103
 
 
1104
 
        if ( ! $result && ! ( -1 == $action && strpos( $referer, $adminurl ) === 0 ) ) {
1105
 
                wp_nonce_ays( $action );
1106
 
                die();
1107
 
        }
1108
 
 
1109
 
        return $result;
1110
 
}
1111
 
endif;
1112
 
 
1113
 
if ( !function_exists('check_ajax_referer') ) :
1114
 
/**
1115
 
 * Verifies the Ajax request to prevent processing requests external of the blog.
1116
 
 *
1117
 
 * @since 2.0.3
1118
 
 *
1119
 
 * @param int|string   $action    Action nonce.
1120
 
 * @param false|string $query_arg Optional. Key to check for the nonce in `$_REQUEST` (since 2.5). If false,
1121
 
 *                                `$_REQUEST` values will be evaluated for '_ajax_nonce', and '_wpnonce'
1122
 
 *                                (in that order). Default false.
1123
 
 * @param bool         $die       Optional. Whether to die early when the nonce cannot be verified.
1124
 
 *                                Default true.
1125
 
 * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
1126
 
 *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
1127
 
 */
1128
 
function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
1129
 
        if ( -1 == $action ) {
1130
 
                _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '4.7' );
1131
 
        }
1132
 
 
1133
 
        $nonce = '';
1134
 
 
1135
 
        if ( $query_arg && isset( $_REQUEST[ $query_arg ] ) )
1136
 
                $nonce = $_REQUEST[ $query_arg ];
1137
 
        elseif ( isset( $_REQUEST['_ajax_nonce'] ) )
1138
 
                $nonce = $_REQUEST['_ajax_nonce'];
1139
 
        elseif ( isset( $_REQUEST['_wpnonce'] ) )
1140
 
                $nonce = $_REQUEST['_wpnonce'];
1141
 
 
1142
 
        $result = wp_verify_nonce( $nonce, $action );
1143
 
 
1144
 
        /**
1145
 
         * Fires once the Ajax request has been validated or not.
1146
 
         *
1147
 
         * @since 2.1.0
1148
 
         *
1149
 
         * @param string    $action The Ajax nonce action.
1150
 
         * @param false|int $result False if the nonce is invalid, 1 if the nonce is valid and generated between
1151
 
         *                          0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
1152
 
         */
1153
 
        do_action( 'check_ajax_referer', $action, $result );
1154
 
 
1155
 
        if ( $die && false === $result ) {
1156
 
                if ( wp_doing_ajax() ) {
1157
 
                        wp_die( -1, 403 );
1158
 
                } else {
1159
 
                        die( '-1' );
1160
 
                }
1161
 
        }
1162
 
 
1163
 
        return $result;
1164
 
}
1165
 
endif;
1166
 
 
1167
 
if ( !function_exists('wp_redirect') ) :
1168
 
/**
1169
 
 * Redirects to another page.
1170
 
 *
1171
 
 * Note: wp_redirect() does not exit automatically, and should almost always be
1172
 
 * followed by a call to `exit;`:
1173
 
 *
1174
 
 *     wp_redirect( $url );
1175
 
 *     exit;
1176
 
 *
1177
 
 * Exiting can also be selectively manipulated by using wp_redirect() as a conditional
1178
 
 * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} hooks:
1179
 
 *
1180
 
 *     if ( wp_redirect( $url ) ) {
1181
 
 *         exit;
1182
 
 *     }
1183
 
 *
1184
 
 * @since 1.5.1
1185
 
 *
1186
 
 * @global bool $is_IIS
1187
 
 *
1188
 
 * @param string $location The path to redirect to.
1189
 
 * @param int    $status   Status code to use.
1190
 
 * @return bool False if $location is not provided, true otherwise.
1191
 
 */
1192
 
function wp_redirect($location, $status = 302) {
1193
 
        global $is_IIS;
1194
 
 
1195
 
        /**
1196
 
         * Filters the redirect location.
1197
 
         *
1198
 
         * @since 2.1.0
1199
 
         *
1200
 
         * @param string $location The path to redirect to.
1201
 
         * @param int    $status   Status code to use.
1202
 
         */
1203
 
        $location = apply_filters( 'wp_redirect', $location, $status );
1204
 
 
1205
 
        /**
1206
 
         * Filters the redirect status code.
 
1196
         * @since 5.1.0 The `$x_redirect_by` parameter was added.
 
1197
         *
 
1198
         * @global bool $is_IIS
 
1199
         *
 
1200
         * @param string $location      The path or URL to redirect to.
 
1201
         * @param int    $status        Optional. HTTP response status code to use. Default '302' (Moved Temporarily).
 
1202
         * @param string $x_redirect_by Optional. The application doing the redirect. Default 'WordPress'.
 
1203
         * @return bool False if the redirect was cancelled, true otherwise.
 
1204
         */
 
1205
        function wp_redirect( $location, $status = 302, $x_redirect_by = 'WordPress' ) {
 
1206
                global $is_IIS;
 
1207
 
 
1208
                /**
 
1209
                 * Filters the redirect location.
 
1210
                 *
 
1211
                 * @since 2.1.0
 
1212
                 *
 
1213
                 * @param string $location The path or URL to redirect to.
 
1214
                 * @param int    $status   The HTTP response status code to use.
 
1215
                 */
 
1216
                $location = apply_filters( 'wp_redirect', $location, $status );
 
1217
 
 
1218
                /**
 
1219
                 * Filters the redirect HTTP response status code to use.
 
1220
                 *
 
1221
                 * @since 2.3.0
 
1222
                 *
 
1223
                 * @param int    $status   The HTTP response status code to use.
 
1224
                 * @param string $location The path or URL to redirect to.
 
1225
                 */
 
1226
                $status = apply_filters( 'wp_redirect_status', $status, $location );
 
1227
 
 
1228
                if ( ! $location ) {
 
1229
                        return false;
 
1230
                }
 
1231
 
 
1232
                $location = wp_sanitize_redirect( $location );
 
1233
 
 
1234
                if ( ! $is_IIS && PHP_SAPI != 'cgi-fcgi' ) {
 
1235
                        status_header( $status ); // This causes problems on IIS and some FastCGI setups
 
1236
                }
 
1237
 
 
1238
                /**
 
1239
                 * Filters the X-Redirect-By header.
 
1240
                 *
 
1241
                 * Allows applications to identify themselves when they're doing a redirect.
 
1242
                 *
 
1243
                 * @since 5.1.0
 
1244
                 *
 
1245
                 * @param string $x_redirect_by The application doing the redirect.
 
1246
                 * @param int    $status        Status code to use.
 
1247
                 * @param string $location      The path to redirect to.
 
1248
                 */
 
1249
                $x_redirect_by = apply_filters( 'x_redirect_by', $x_redirect_by, $status, $location );
 
1250
                if ( is_string( $x_redirect_by ) ) {
 
1251
                        header( "X-Redirect-By: $x_redirect_by" );
 
1252
                }
 
1253
 
 
1254
                header( "Location: $location", true, $status );
 
1255
 
 
1256
                return true;
 
1257
        }
 
1258
endif;
 
1259
 
 
1260
if ( ! function_exists( 'wp_sanitize_redirect' ) ) :
 
1261
        /**
 
1262
         * Sanitizes a URL for use in a redirect.
1207
1263
         *
1208
1264
         * @since 2.3.0
1209
1265
         *
1210
 
         * @param int    $status   Status code to use.
1211
1266
         * @param string $location The path to redirect to.
 
1267
         * @return string Redirect-sanitized URL.
1212
1268
         */
1213
 
        $status = apply_filters( 'wp_redirect_status', $status, $location );
1214
 
 
1215
 
        if ( ! $location )
1216
 
                return false;
1217
 
 
1218
 
        $location = wp_sanitize_redirect($location);
1219
 
 
1220
 
        if ( !$is_IIS && PHP_SAPI != 'cgi-fcgi' )
1221
 
                status_header($status); // This causes problems on IIS and some FastCGI setups
1222
 
 
1223
 
        header("Location: $location", true, $status);
1224
 
 
1225
 
        return true;
1226
 
}
1227
 
endif;
1228
 
 
1229
 
if ( !function_exists('wp_sanitize_redirect') ) :
1230
 
/**
1231
 
 * Sanitizes a URL for use in a redirect.
1232
 
 *
1233
 
 * @since 2.3.0
1234
 
 *
1235
 
 * @param string $location The path to redirect to.
1236
 
 * @return string Redirect-sanitized URL.
1237
 
 **/
1238
 
function wp_sanitize_redirect($location) {
1239
 
        $regex = '/
 
1269
        function wp_sanitize_redirect( $location ) {
 
1270
                $regex    = '/
1240
1271
                (
1241
1272
                        (?: [\xC2-\xDF][\x80-\xBF]        # double-byte sequences   110xxxxx 10xxxxxx
1242
1273
                        |   \xE0[\xA0-\xBF][\x80-\xBF]    # triple-byte sequences   1110xxxx 10xxxxxx * 2
1248
1279
                        |   \xF4[\x80-\x8F][\x80-\xBF]{2}
1249
1280
                ){1,40}                              # ...one or more times
1250
1281
                )/x';
1251
 
        $location = preg_replace_callback( $regex, '_wp_sanitize_utf8_in_redirect', $location );
1252
 
        $location = preg_replace('|[^a-z0-9-~+_.?#=&;,/:%!*\[\]()@]|i', '', $location);
1253
 
        $location = wp_kses_no_null($location);
1254
 
 
1255
 
        // remove %0d and %0a from location
1256
 
        $strip = array('%0d', '%0a', '%0D', '%0A');
1257
 
        return _deep_replace( $strip, $location );
1258
 
}
1259
 
 
1260
 
/**
1261
 
 * URL encode UTF-8 characters in a URL.
1262
 
 *
1263
 
 * @ignore
1264
 
 * @since 4.2.0
1265
 
 * @access private
1266
 
 *
1267
 
 * @see wp_sanitize_redirect()
1268
 
 *
1269
 
 * @param array $matches RegEx matches against the redirect location.
1270
 
 * @return string URL-encoded version of the first RegEx match.
1271
 
 */
1272
 
function _wp_sanitize_utf8_in_redirect( $matches ) {
1273
 
        return urlencode( $matches[0] );
1274
 
}
1275
 
endif;
1276
 
 
1277
 
if ( !function_exists('wp_safe_redirect') ) :
1278
 
/**
1279
 
 * Performs a safe (local) redirect, using wp_redirect().
1280
 
 *
1281
 
 * Checks whether the $location is using an allowed host, if it has an absolute
1282
 
 * path. A plugin can therefore set or remove allowed host(s) to or from the
1283
 
 * list.
1284
 
 *
1285
 
 * If the host is not allowed, then the redirect defaults to wp-admin on the siteurl
1286
 
 * instead. This prevents malicious redirects which redirect to another host,
1287
 
 * but only used in a few places.
1288
 
 *
1289
 
 * @since 2.3.0
1290
 
 *
1291
 
 * @param string $location The path to redirect to.
1292
 
 * @param int    $status   Status code to use.
1293
 
 */
1294
 
function wp_safe_redirect($location, $status = 302) {
1295
 
 
1296
 
        // Need to look at the URL the way it will end up in wp_redirect()
1297
 
        $location = wp_sanitize_redirect($location);
 
1282
                $location = preg_replace_callback( $regex, '_wp_sanitize_utf8_in_redirect', $location );
 
1283
                $location = preg_replace( '|[^a-z0-9-~+_.?#=&;,/:%!*\[\]()@]|i', '', $location );
 
1284
                $location = wp_kses_no_null( $location );
 
1285
 
 
1286
                // remove %0d and %0a from location
 
1287
                $strip = array( '%0d', '%0a', '%0D', '%0A' );
 
1288
                return _deep_replace( $strip, $location );
 
1289
        }
1298
1290
 
1299
1291
        /**
1300
 
         * Filters the redirect fallback URL for when the provided redirect is not safe (local).
1301
 
         *
1302
 
         * @since 4.3.0
1303
 
         *
1304
 
         * @param string $fallback_url The fallback URL to use by default.
1305
 
         * @param int    $status       The redirect status.
 
1292
         * URL encode UTF-8 characters in a URL.
 
1293
         *
 
1294
         * @ignore
 
1295
         * @since 4.2.0
 
1296
         * @access private
 
1297
         *
 
1298
         * @see wp_sanitize_redirect()
 
1299
         *
 
1300
         * @param array $matches RegEx matches against the redirect location.
 
1301
         * @return string URL-encoded version of the first RegEx match.
1306
1302
         */
1307
 
        $location = wp_validate_redirect( $location, apply_filters( 'wp_safe_redirect_fallback', admin_url(), $status ) );
1308
 
 
1309
 
        wp_redirect($location, $status);
1310
 
}
 
1303
        function _wp_sanitize_utf8_in_redirect( $matches ) {
 
1304
                return urlencode( $matches[0] );
 
1305
        }
1311
1306
endif;
1312
1307
 
1313
 
if ( !function_exists('wp_validate_redirect') ) :
1314
 
/**
1315
 
 * Validates a URL for use in a redirect.
1316
 
 *
1317
 
 * Checks whether the $location is using an allowed host, if it has an absolute
1318
 
 * path. A plugin can therefore set or remove allowed host(s) to or from the
1319
 
 * list.
1320
 
 *
1321
 
 * If the host is not allowed, then the redirect is to $default supplied
1322
 
 *
1323
 
 * @since 2.8.1
1324
 
 *
1325
 
 * @param string $location The redirect to validate
1326
 
 * @param string $default  The value to return if $location is not allowed
1327
 
 * @return string redirect-sanitized URL
1328
 
 **/
1329
 
function wp_validate_redirect($location, $default = '') {
1330
 
        $location = trim( $location, " \t\n\r\0\x08\x0B" );
1331
 
        // browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'
1332
 
        if ( substr($location, 0, 2) == '//' )
1333
 
                $location = 'http:' . $location;
1334
 
 
1335
 
        // In php 5 parse_url may fail if the URL query part contains http://, bug #38143
1336
 
        $test = ( $cut = strpos($location, '?') ) ? substr( $location, 0, $cut ) : $location;
1337
 
 
1338
 
        // @-operator is used to prevent possible warnings in PHP < 5.3.3.
1339
 
        $lp = @parse_url($test);
1340
 
 
1341
 
        // Give up if malformed URL
1342
 
        if ( false === $lp )
1343
 
                return $default;
1344
 
 
1345
 
        // Allow only http and https schemes. No data:, etc.
1346
 
        if ( isset($lp['scheme']) && !('http' == $lp['scheme'] || 'https' == $lp['scheme']) )
1347
 
                return $default;
1348
 
 
1349
 
        // 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.
1350
 
        if ( ! isset( $lp['host'] ) && ( isset( $lp['scheme'] ) || isset( $lp['user'] ) || isset( $lp['pass'] ) || isset( $lp['port'] ) ) ) {
1351
 
                return $default;
1352
 
        }
1353
 
 
1354
 
        // Reject malformed components parse_url() can return on odd inputs.
1355
 
        foreach ( array( 'user', 'pass', 'host' ) as $component ) {
1356
 
                if ( isset( $lp[ $component ] ) && strpbrk( $lp[ $component ], ':/?#@' ) ) {
1357
 
                        return $default;
1358
 
                }
1359
 
        }
1360
 
 
1361
 
        $wpp = parse_url(home_url());
1362
 
 
 
1308
if ( ! function_exists( 'wp_safe_redirect' ) ) :
1363
1309
        /**
1364
 
         * Filters the whitelist of hosts to redirect to.
 
1310
         * Performs a safe (local) redirect, using wp_redirect().
 
1311
         *
 
1312
         * Checks whether the $location is using an allowed host, if it has an absolute
 
1313
         * path. A plugin can therefore set or remove allowed host(s) to or from the
 
1314
         * list.
 
1315
         *
 
1316
         * If the host is not allowed, then the redirect defaults to wp-admin on the siteurl
 
1317
         * instead. This prevents malicious redirects which redirect to another host,
 
1318
         * but only used in a few places.
 
1319
         *
 
1320
         * Note: wp_safe_redirect() does not exit automatically, and should almost always be
 
1321
         * followed by a call to `exit;`:
 
1322
         *
 
1323
         *     wp_safe_redirect( $url );
 
1324
         *     exit;
 
1325
         *
 
1326
         * Exiting can also be selectively manipulated by using wp_safe_redirect() as a conditional
 
1327
         * in conjunction with the {@see 'wp_redirect'} and {@see 'wp_redirect_location'} filters:
 
1328
         *
 
1329
         *     if ( wp_safe_redirect( $url ) ) {
 
1330
         *         exit;
 
1331
         *     }
1365
1332
         *
1366
1333
         * @since 2.3.0
1367
 
         *
1368
 
         * @param array       $hosts An array of allowed hosts.
1369
 
         * @param bool|string $host  The parsed host; empty if not isset.
1370
 
         */
1371
 
        $allowed_hosts = (array) apply_filters( 'allowed_redirect_hosts', array($wpp['host']), isset($lp['host']) ? $lp['host'] : '' );
1372
 
 
1373
 
        if ( isset($lp['host']) && ( !in_array($lp['host'], $allowed_hosts) && $lp['host'] != strtolower($wpp['host'])) )
1374
 
                $location = $default;
1375
 
 
1376
 
        return $location;
1377
 
}
1378
 
endif;
1379
 
 
1380
 
if ( ! function_exists('wp_notify_postauthor') ) :
1381
 
/**
1382
 
 * Notify an author (and/or others) of a comment/trackback/pingback on a post.
1383
 
 *
1384
 
 * @since 1.0.0
1385
 
 *
1386
 
 * @param int|WP_Comment  $comment_id Comment ID or WP_Comment object.
1387
 
 * @param string          $deprecated Not used
1388
 
 * @return bool True on completion. False if no email addresses were specified.
1389
 
 */
1390
 
function wp_notify_postauthor( $comment_id, $deprecated = null ) {
1391
 
        if ( null !== $deprecated ) {
1392
 
                _deprecated_argument( __FUNCTION__, '3.8.0' );
1393
 
        }
1394
 
 
1395
 
        $comment = get_comment( $comment_id );
1396
 
        if ( empty( $comment ) || empty( $comment->comment_post_ID ) )
1397
 
                return false;
1398
 
 
1399
 
        $post    = get_post( $comment->comment_post_ID );
1400
 
        $author  = get_userdata( $post->post_author );
1401
 
 
1402
 
        // Who to notify? By default, just the post author, but others can be added.
1403
 
        $emails = array();
1404
 
        if ( $author ) {
1405
 
                $emails[] = $author->user_email;
1406
 
        }
1407
 
 
1408
 
        /**
1409
 
         * Filters the list of email addresses to receive a comment notification.
1410
 
         *
1411
 
         * By default, only post authors are notified of comments. This filter allows
1412
 
         * others to be added.
1413
 
         *
1414
 
         * @since 3.7.0
1415
 
         *
1416
 
         * @param array $emails     An array of email addresses to receive a comment notification.
1417
 
         * @param int   $comment_id The comment ID.
1418
 
         */
1419
 
        $emails = apply_filters( 'comment_notification_recipients', $emails, $comment->comment_ID );
1420
 
        $emails = array_filter( $emails );
1421
 
 
1422
 
        // If there are no addresses to send the comment to, bail.
1423
 
        if ( ! count( $emails ) ) {
1424
 
                return false;
1425
 
        }
1426
 
 
1427
 
        // Facilitate unsetting below without knowing the keys.
1428
 
        $emails = array_flip( $emails );
1429
 
 
1430
 
        /**
1431
 
         * Filters whether to notify comment authors of their comments on their own posts.
1432
 
         *
1433
 
         * By default, comment authors aren't notified of their comments on their own
1434
 
         * posts. This filter allows you to override that.
1435
 
         *
1436
 
         * @since 3.8.0
1437
 
         *
1438
 
         * @param bool $notify     Whether to notify the post author of their own comment.
1439
 
         *                         Default false.
1440
 
         * @param int  $comment_id The comment ID.
1441
 
         */
1442
 
        $notify_author = apply_filters( 'comment_notification_notify_author', false, $comment->comment_ID );
1443
 
 
1444
 
        // The comment was left by the author
1445
 
        if ( $author && ! $notify_author && $comment->user_id == $post->post_author ) {
1446
 
                unset( $emails[ $author->user_email ] );
1447
 
        }
1448
 
 
1449
 
        // The author moderated a comment on their own post
1450
 
        if ( $author && ! $notify_author && $post->post_author == get_current_user_id() ) {
1451
 
                unset( $emails[ $author->user_email ] );
1452
 
        }
1453
 
 
1454
 
        // The post author is no longer a member of the blog
1455
 
        if ( $author && ! $notify_author && ! user_can( $post->post_author, 'read_post', $post->ID ) ) {
1456
 
                unset( $emails[ $author->user_email ] );
1457
 
        }
1458
 
 
1459
 
        // If there's no email to send the comment to, bail, otherwise flip array back around for use below
1460
 
        if ( ! count( $emails ) ) {
1461
 
                return false;
1462
 
        } else {
 
1334
         * @since 5.1.0 The return value from wp_redirect() is now passed on, and the `$x_redirect_by` parameter was added.
 
1335
         *
 
1336
         * @param string $location      The path or URL to redirect to.
 
1337
         * @param int    $status        Optional. HTTP response status code to use. Default '302' (Moved Temporarily).
 
1338
         * @param string $x_redirect_by Optional. The application doing the redirect. Default 'WordPress'.
 
1339
         * @return bool  $redirect False if the redirect was cancelled, true otherwise.
 
1340
         */
 
1341
        function wp_safe_redirect( $location, $status = 302, $x_redirect_by = 'WordPress' ) {
 
1342
 
 
1343
                // Need to look at the URL the way it will end up in wp_redirect()
 
1344
                $location = wp_sanitize_redirect( $location );
 
1345
 
 
1346
                /**
 
1347
                 * Filters the redirect fallback URL for when the provided redirect is not safe (local).
 
1348
                 *
 
1349
                 * @since 4.3.0
 
1350
                 *
 
1351
                 * @param string $fallback_url The fallback URL to use by default.
 
1352
                 * @param int    $status       The HTTP response status code to use.
 
1353
                 */
 
1354
                $location = wp_validate_redirect( $location, apply_filters( 'wp_safe_redirect_fallback', admin_url(), $status ) );
 
1355
 
 
1356
                return wp_redirect( $location, $status, $x_redirect_by );
 
1357
        }
 
1358
endif;
 
1359
 
 
1360
if ( ! function_exists( 'wp_validate_redirect' ) ) :
 
1361
        /**
 
1362
         * Validates a URL for use in a redirect.
 
1363
         *
 
1364
         * Checks whether the $location is using an allowed host, if it has an absolute
 
1365
         * path. A plugin can therefore set or remove allowed host(s) to or from the
 
1366
         * list.
 
1367
         *
 
1368
         * If the host is not allowed, then the redirect is to $default supplied
 
1369
         *
 
1370
         * @since 2.8.1
 
1371
         *
 
1372
         * @param string $location The redirect to validate
 
1373
         * @param string $default  The value to return if $location is not allowed
 
1374
         * @return string redirect-sanitized URL
 
1375
         */
 
1376
        function wp_validate_redirect( $location, $default = '' ) {
 
1377
                $location = trim( $location, " \t\n\r\0\x08\x0B" );
 
1378
                // browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'
 
1379
                if ( substr( $location, 0, 2 ) == '//' ) {
 
1380
                        $location = 'http:' . $location;
 
1381
                }
 
1382
 
 
1383
                // In php 5 parse_url may fail if the URL query part contains http://, bug #38143
 
1384
                $test = ( $cut = strpos( $location, '?' ) ) ? substr( $location, 0, $cut ) : $location;
 
1385
 
 
1386
                // @-operator is used to prevent possible warnings in PHP < 5.3.3.
 
1387
                $lp = @parse_url( $test );
 
1388
 
 
1389
                // Give up if malformed URL
 
1390
                if ( false === $lp ) {
 
1391
                        return $default;
 
1392
                }
 
1393
 
 
1394
                // Allow only http and https schemes. No data:, etc.
 
1395
                if ( isset( $lp['scheme'] ) && ! ( 'http' == $lp['scheme'] || 'https' == $lp['scheme'] ) ) {
 
1396
                        return $default;
 
1397
                }
 
1398
 
 
1399
                // 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.
 
1400
                if ( ! isset( $lp['host'] ) && ( isset( $lp['scheme'] ) || isset( $lp['user'] ) || isset( $lp['pass'] ) || isset( $lp['port'] ) ) ) {
 
1401
                        return $default;
 
1402
                }
 
1403
 
 
1404
                // Reject malformed components parse_url() can return on odd inputs.
 
1405
                foreach ( array( 'user', 'pass', 'host' ) as $component ) {
 
1406
                        if ( isset( $lp[ $component ] ) && strpbrk( $lp[ $component ], ':/?#@' ) ) {
 
1407
                                return $default;
 
1408
                        }
 
1409
                }
 
1410
 
 
1411
                $wpp = parse_url( home_url() );
 
1412
 
 
1413
                /**
 
1414
                 * Filters the whitelist of hosts to redirect to.
 
1415
                 *
 
1416
                 * @since 2.3.0
 
1417
                 *
 
1418
                 * @param array       $hosts An array of allowed hosts.
 
1419
                 * @param bool|string $host  The parsed host; empty if not isset.
 
1420
                 */
 
1421
                $allowed_hosts = (array) apply_filters( 'allowed_redirect_hosts', array( $wpp['host'] ), isset( $lp['host'] ) ? $lp['host'] : '' );
 
1422
 
 
1423
                if ( isset( $lp['host'] ) && ( ! in_array( $lp['host'], $allowed_hosts ) && $lp['host'] != strtolower( $wpp['host'] ) ) ) {
 
1424
                        $location = $default;
 
1425
                }
 
1426
 
 
1427
                return $location;
 
1428
        }
 
1429
endif;
 
1430
 
 
1431
if ( ! function_exists( 'wp_notify_postauthor' ) ) :
 
1432
        /**
 
1433
         * Notify an author (and/or others) of a comment/trackback/pingback on a post.
 
1434
         *
 
1435
         * @since 1.0.0
 
1436
         *
 
1437
         * @param int|WP_Comment  $comment_id Comment ID or WP_Comment object.
 
1438
         * @param string          $deprecated Not used
 
1439
         * @return bool True on completion. False if no email addresses were specified.
 
1440
         */
 
1441
        function wp_notify_postauthor( $comment_id, $deprecated = null ) {
 
1442
                if ( null !== $deprecated ) {
 
1443
                        _deprecated_argument( __FUNCTION__, '3.8.0' );
 
1444
                }
 
1445
 
 
1446
                $comment = get_comment( $comment_id );
 
1447
                if ( empty( $comment ) || empty( $comment->comment_post_ID ) ) {
 
1448
                        return false;
 
1449
                }
 
1450
 
 
1451
                $post   = get_post( $comment->comment_post_ID );
 
1452
                $author = get_userdata( $post->post_author );
 
1453
 
 
1454
                // Who to notify? By default, just the post author, but others can be added.
 
1455
                $emails = array();
 
1456
                if ( $author ) {
 
1457
                        $emails[] = $author->user_email;
 
1458
                }
 
1459
 
 
1460
                /**
 
1461
                 * Filters the list of email addresses to receive a comment notification.
 
1462
                 *
 
1463
                 * By default, only post authors are notified of comments. This filter allows
 
1464
                 * others to be added.
 
1465
                 *
 
1466
                 * @since 3.7.0
 
1467
                 *
 
1468
                 * @param array $emails     An array of email addresses to receive a comment notification.
 
1469
                 * @param int   $comment_id The comment ID.
 
1470
                 */
 
1471
                $emails = apply_filters( 'comment_notification_recipients', $emails, $comment->comment_ID );
 
1472
                $emails = array_filter( $emails );
 
1473
 
 
1474
                // If there are no addresses to send the comment to, bail.
 
1475
                if ( ! count( $emails ) ) {
 
1476
                        return false;
 
1477
                }
 
1478
 
 
1479
                // Facilitate unsetting below without knowing the keys.
1463
1480
                $emails = array_flip( $emails );
1464
 
        }
1465
 
 
1466
 
        $switched_locale = switch_to_locale( get_locale() );
1467
 
 
1468
 
        $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
1469
 
 
1470
 
        // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1471
 
        // we want to reverse this for the plain text arena of emails.
1472
 
        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1473
 
        $comment_content = wp_specialchars_decode( $comment->comment_content );
1474
 
 
1475
 
        switch ( $comment->comment_type ) {
1476
 
                case 'trackback':
1477
 
                        /* translators: 1: Post title */
1478
 
                        $notify_message  = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
1479
 
                        /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
1480
 
                        $notify_message .= sprintf( __('Website: %1$s (IP address: %2$s, %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1481
 
                        $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
1482
 
                        $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
1483
 
                        $notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
1484
 
                        /* translators: 1: blog name, 2: post title */
1485
 
                        $subject = sprintf( __('[%1$s] Trackback: "%2$s"'), $blogname, $post->post_title );
1486
 
                        break;
1487
 
                case 'pingback':
1488
 
                        /* translators: 1: Post title */
1489
 
                        $notify_message  = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
1490
 
                        /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
1491
 
                        $notify_message .= sprintf( __('Website: %1$s (IP address: %2$s, %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1492
 
                        $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
1493
 
                        $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
1494
 
                        $notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
1495
 
                        /* translators: 1: blog name, 2: post title */
1496
 
                        $subject = sprintf( __('[%1$s] Pingback: "%2$s"'), $blogname, $post->post_title );
1497
 
                        break;
1498
 
                default: // Comments
1499
 
                        $notify_message  = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
1500
 
                        /* translators: 1: comment author, 2: comment author's IP address, 3: comment author's hostname */
1501
 
                        $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1502
 
                        $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
1503
 
                        $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
1504
 
                        $notify_message .= sprintf( __('Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
1505
 
                        $notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
1506
 
                        /* translators: 1: blog name, 2: post title */
1507
 
                        $subject = sprintf( __('[%1$s] Comment: "%2$s"'), $blogname, $post->post_title );
1508
 
                        break;
1509
 
        }
1510
 
        $notify_message .= get_permalink($comment->comment_post_ID) . "#comments\r\n\r\n";
1511
 
        $notify_message .= sprintf( __('Permalink: %s'), get_comment_link( $comment ) ) . "\r\n";
1512
 
 
1513
 
        if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
 
1481
 
 
1482
                /**
 
1483
                 * Filters whether to notify comment authors of their comments on their own posts.
 
1484
                 *
 
1485
                 * By default, comment authors aren't notified of their comments on their own
 
1486
                 * posts. This filter allows you to override that.
 
1487
                 *
 
1488
                 * @since 3.8.0
 
1489
                 *
 
1490
                 * @param bool $notify     Whether to notify the post author of their own comment.
 
1491
                 *                         Default false.
 
1492
                 * @param int  $comment_id The comment ID.
 
1493
                 */
 
1494
                $notify_author = apply_filters( 'comment_notification_notify_author', false, $comment->comment_ID );
 
1495
 
 
1496
                // The comment was left by the author
 
1497
                if ( $author && ! $notify_author && $comment->user_id == $post->post_author ) {
 
1498
                        unset( $emails[ $author->user_email ] );
 
1499
                }
 
1500
 
 
1501
                // The author moderated a comment on their own post
 
1502
                if ( $author && ! $notify_author && $post->post_author == get_current_user_id() ) {
 
1503
                        unset( $emails[ $author->user_email ] );
 
1504
                }
 
1505
 
 
1506
                // The post author is no longer a member of the blog
 
1507
                if ( $author && ! $notify_author && ! user_can( $post->post_author, 'read_post', $post->ID ) ) {
 
1508
                        unset( $emails[ $author->user_email ] );
 
1509
                }
 
1510
 
 
1511
                // If there's no email to send the comment to, bail, otherwise flip array back around for use below
 
1512
                if ( ! count( $emails ) ) {
 
1513
                        return false;
 
1514
                } else {
 
1515
                        $emails = array_flip( $emails );
 
1516
                }
 
1517
 
 
1518
                $switched_locale = switch_to_locale( get_locale() );
 
1519
 
 
1520
                $comment_author_domain = @gethostbyaddr( $comment->comment_author_IP );
 
1521
 
 
1522
                // The blogname option is escaped with esc_html on the way into the database in sanitize_option
 
1523
                // we want to reverse this for the plain text arena of emails.
 
1524
                $blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
 
1525
                $comment_content = wp_specialchars_decode( $comment->comment_content );
 
1526
 
 
1527
                switch ( $comment->comment_type ) {
 
1528
                        case 'trackback':
 
1529
                                /* translators: %s: post title */
 
1530
                                $notify_message = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
 
1531
                                /* translators: 1: trackback/pingback website name, 2: website IP address, 3: website hostname */
 
1532
                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
 
1533
                                /* translators: %s: trackback/pingback/comment author URL */
 
1534
                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
 
1535
                                /* translators: %s: comment text */
 
1536
                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
 
1537
                                $notify_message .= __( 'You can see all trackbacks on this post here:' ) . "\r\n";
 
1538
                                /* translators: 1: blog name, 2: post title */
 
1539
                                $subject = sprintf( __( '[%1$s] Trackback: "%2$s"' ), $blogname, $post->post_title );
 
1540
                                break;
 
1541
                        case 'pingback':
 
1542
                                /* translators: %s: post title */
 
1543
                                $notify_message = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
 
1544
                                /* translators: 1: trackback/pingback website name, 2: website IP address, 3: website hostname */
 
1545
                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
 
1546
                                /* translators: %s: trackback/pingback/comment author URL */
 
1547
                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
 
1548
                                /* translators: %s: comment text */
 
1549
                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
 
1550
                                $notify_message .= __( 'You can see all pingbacks on this post here:' ) . "\r\n";
 
1551
                                /* translators: 1: blog name, 2: post title */
 
1552
                                $subject = sprintf( __( '[%1$s] Pingback: "%2$s"' ), $blogname, $post->post_title );
 
1553
                                break;
 
1554
                        default: // Comments
 
1555
                                /* translators: %s: post title */
 
1556
                                $notify_message = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
 
1557
                                /* translators: 1: comment author's name, 2: comment author's IP address, 3: comment author's hostname */
 
1558
                                $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
 
1559
                                /* translators: %s: comment author email */
 
1560
                                $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
 
1561
                                /* translators: %s: trackback/pingback/comment author URL */
 
1562
                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
 
1563
                                /* translators: %s: comment text */
 
1564
                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
 
1565
                                $notify_message .= __( 'You can see all comments on this post here:' ) . "\r\n";
 
1566
                                /* translators: 1: blog name, 2: post title */
 
1567
                                $subject = sprintf( __( '[%1$s] Comment: "%2$s"' ), $blogname, $post->post_title );
 
1568
                                break;
 
1569
                }
 
1570
                $notify_message .= get_permalink( $comment->comment_post_ID ) . "#comments\r\n\r\n";
 
1571
                $notify_message .= sprintf( __( 'Permalink: %s' ), get_comment_link( $comment ) ) . "\r\n";
 
1572
 
 
1573
                if ( user_can( $post->post_author, 'edit_comment', $comment->comment_ID ) ) {
 
1574
                        if ( EMPTY_TRASH_DAYS ) {
 
1575
                                /* translators: Comment moderation. %s: Comment action URL */
 
1576
                                $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
 
1577
                        } else {
 
1578
                                /* translators: Comment moderation. %s: Comment action URL */
 
1579
                                $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
 
1580
                        }
 
1581
                        /* translators: Comment moderation. %s: Comment action URL */
 
1582
                        $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
 
1583
                }
 
1584
 
 
1585
                $wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) );
 
1586
 
 
1587
                if ( '' == $comment->comment_author ) {
 
1588
                        $from = "From: \"$blogname\" <$wp_email>";
 
1589
                        if ( '' != $comment->comment_author_email ) {
 
1590
                                $reply_to = "Reply-To: $comment->comment_author_email";
 
1591
                        }
 
1592
                } else {
 
1593
                        $from = "From: \"$comment->comment_author\" <$wp_email>";
 
1594
                        if ( '' != $comment->comment_author_email ) {
 
1595
                                $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
 
1596
                        }
 
1597
                }
 
1598
 
 
1599
                $message_headers = "$from\n"
 
1600
                . 'Content-Type: text/plain; charset="' . get_option( 'blog_charset' ) . "\"\n";
 
1601
 
 
1602
                if ( isset( $reply_to ) ) {
 
1603
                        $message_headers .= $reply_to . "\n";
 
1604
                }
 
1605
 
 
1606
                /**
 
1607
                 * Filters the comment notification email text.
 
1608
                 *
 
1609
                 * @since 1.5.2
 
1610
                 *
 
1611
                 * @param string $notify_message The comment notification email text.
 
1612
                 * @param int    $comment_id     Comment ID.
 
1613
                 */
 
1614
                $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
 
1615
 
 
1616
                /**
 
1617
                 * Filters the comment notification email subject.
 
1618
                 *
 
1619
                 * @since 1.5.2
 
1620
                 *
 
1621
                 * @param string $subject    The comment notification email subject.
 
1622
                 * @param int    $comment_id Comment ID.
 
1623
                 */
 
1624
                $subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
 
1625
 
 
1626
                /**
 
1627
                 * Filters the comment notification email headers.
 
1628
                 *
 
1629
                 * @since 1.5.2
 
1630
                 *
 
1631
                 * @param string $message_headers Headers for the comment notification email.
 
1632
                 * @param int    $comment_id      Comment ID.
 
1633
                 */
 
1634
                $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
 
1635
 
 
1636
                foreach ( $emails as $email ) {
 
1637
                        @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
 
1638
                }
 
1639
 
 
1640
                if ( $switched_locale ) {
 
1641
                        restore_previous_locale();
 
1642
                }
 
1643
 
 
1644
                return true;
 
1645
        }
 
1646
endif;
 
1647
 
 
1648
if ( ! function_exists( 'wp_notify_moderator' ) ) :
 
1649
        /**
 
1650
         * Notifies the moderator of the site about a new comment that is awaiting approval.
 
1651
         *
 
1652
         * @since 1.0.0
 
1653
         *
 
1654
         * @global wpdb $wpdb WordPress database abstraction object.
 
1655
         *
 
1656
         * Uses the {@see 'notify_moderator'} filter to determine whether the site moderator
 
1657
         * should be notified, overriding the site setting.
 
1658
         *
 
1659
         * @param int $comment_id Comment ID.
 
1660
         * @return true Always returns true.
 
1661
         */
 
1662
        function wp_notify_moderator( $comment_id ) {
 
1663
                global $wpdb;
 
1664
 
 
1665
                $maybe_notify = get_option( 'moderation_notify' );
 
1666
 
 
1667
                /**
 
1668
                 * Filters whether to send the site moderator email notifications, overriding the site setting.
 
1669
                 *
 
1670
                 * @since 4.4.0
 
1671
                 *
 
1672
                 * @param bool $maybe_notify Whether to notify blog moderator.
 
1673
                 * @param int  $comment_ID   The id of the comment for the notification.
 
1674
                 */
 
1675
                $maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_id );
 
1676
 
 
1677
                if ( ! $maybe_notify ) {
 
1678
                        return true;
 
1679
                }
 
1680
 
 
1681
                $comment = get_comment( $comment_id );
 
1682
                $post    = get_post( $comment->comment_post_ID );
 
1683
                $user    = get_userdata( $post->post_author );
 
1684
                // Send to the administration and to the post author if the author can modify the comment.
 
1685
                $emails = array( get_option( 'admin_email' ) );
 
1686
                if ( $user && user_can( $user->ID, 'edit_comment', $comment_id ) && ! empty( $user->user_email ) ) {
 
1687
                        if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
 
1688
                                $emails[] = $user->user_email;
 
1689
                        }
 
1690
                }
 
1691
 
 
1692
                $switched_locale = switch_to_locale( get_locale() );
 
1693
 
 
1694
                $comment_author_domain = @gethostbyaddr( $comment->comment_author_IP );
 
1695
                $comments_waiting      = $wpdb->get_var( "SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'" );
 
1696
 
 
1697
                // The blogname option is escaped with esc_html on the way into the database in sanitize_option
 
1698
                // we want to reverse this for the plain text arena of emails.
 
1699
                $blogname        = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
 
1700
                $comment_content = wp_specialchars_decode( $comment->comment_content );
 
1701
 
 
1702
                switch ( $comment->comment_type ) {
 
1703
                        case 'trackback':
 
1704
                                /* translators: %s: post title */
 
1705
                                $notify_message  = sprintf( __( 'A new trackback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
 
1706
                                $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
 
1707
                                /* translators: 1: trackback/pingback website name, 2: website IP address, 3: website hostname */
 
1708
                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
 
1709
                                /* translators: %s: trackback/pingback/comment author URL */
 
1710
                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
 
1711
                                $notify_message .= __( 'Trackback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
 
1712
                                break;
 
1713
                        case 'pingback':
 
1714
                                /* translators: %s: post title */
 
1715
                                $notify_message  = sprintf( __( 'A new pingback on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
 
1716
                                $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
 
1717
                                /* translators: 1: trackback/pingback website name, 2: website IP address, 3: website hostname */
 
1718
                                $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
 
1719
                                /* translators: %s: trackback/pingback/comment author URL */
 
1720
                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
 
1721
                                $notify_message .= __( 'Pingback excerpt: ' ) . "\r\n" . $comment_content . "\r\n\r\n";
 
1722
                                break;
 
1723
                        default: // Comments
 
1724
                                /* translators: %s: post title */
 
1725
                                $notify_message  = sprintf( __( 'A new comment on the post "%s" is waiting for your approval' ), $post->post_title ) . "\r\n";
 
1726
                                $notify_message .= get_permalink( $comment->comment_post_ID ) . "\r\n\r\n";
 
1727
                                /* translators: 1: comment author's name, 2: comment author's IP address, 3: comment author's hostname */
 
1728
                                $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
 
1729
                                /* translators: %s: comment author email */
 
1730
                                $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
 
1731
                                /* translators: %s: trackback/pingback/comment author URL */
 
1732
                                $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
 
1733
                                /* translators: %s: comment text */
 
1734
                                $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
 
1735
                                break;
 
1736
                }
 
1737
 
 
1738
                /* translators: Comment moderation. %s: Comment action URL */
 
1739
                $notify_message .= sprintf( __( 'Approve it: %s' ), admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ) . "\r\n";
 
1740
 
1514
1741
                if ( EMPTY_TRASH_DAYS ) {
1515
 
                        $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
 
1742
                        /* translators: Comment moderation. %s: Comment action URL */
 
1743
                        $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) ) . "\r\n";
1516
1744
                } else {
1517
 
                        $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
1518
 
                }
1519
 
                $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment->comment_ID}#wpbody-content" ) ) . "\r\n";
1520
 
        }
1521
 
 
1522
 
        $wp_email = 'wordpress@' . preg_replace('#^www\.#', '', strtolower($_SERVER['SERVER_NAME']));
1523
 
 
1524
 
        if ( '' == $comment->comment_author ) {
1525
 
                $from = "From: \"$blogname\" <$wp_email>";
1526
 
                if ( '' != $comment->comment_author_email )
1527
 
                        $reply_to = "Reply-To: $comment->comment_author_email";
1528
 
        } else {
1529
 
                $from = "From: \"$comment->comment_author\" <$wp_email>";
1530
 
                if ( '' != $comment->comment_author_email )
1531
 
                        $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
1532
 
        }
1533
 
 
1534
 
        $message_headers = "$from\n"
1535
 
                . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
1536
 
 
1537
 
        if ( isset($reply_to) )
1538
 
                $message_headers .= $reply_to . "\n";
1539
 
 
1540
 
        /**
1541
 
         * Filters the comment notification email text.
1542
 
         *
1543
 
         * @since 1.5.2
1544
 
         *
1545
 
         * @param string $notify_message The comment notification email text.
1546
 
         * @param int    $comment_id     Comment ID.
1547
 
         */
1548
 
        $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment->comment_ID );
1549
 
 
1550
 
        /**
1551
 
         * Filters the comment notification email subject.
1552
 
         *
1553
 
         * @since 1.5.2
1554
 
         *
1555
 
         * @param string $subject    The comment notification email subject.
1556
 
         * @param int    $comment_id Comment ID.
1557
 
         */
1558
 
        $subject = apply_filters( 'comment_notification_subject', $subject, $comment->comment_ID );
1559
 
 
1560
 
        /**
1561
 
         * Filters the comment notification email headers.
1562
 
         *
1563
 
         * @since 1.5.2
1564
 
         *
1565
 
         * @param string $message_headers Headers for the comment notification email.
1566
 
         * @param int    $comment_id      Comment ID.
1567
 
         */
1568
 
        $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment->comment_ID );
1569
 
 
1570
 
        foreach ( $emails as $email ) {
1571
 
                @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
1572
 
        }
1573
 
 
1574
 
        if ( $switched_locale ) {
1575
 
                restore_previous_locale();
1576
 
        }
1577
 
 
1578
 
        return true;
1579
 
}
1580
 
endif;
1581
 
 
1582
 
if ( !function_exists('wp_notify_moderator') ) :
1583
 
/**
1584
 
 * Notifies the moderator of the site about a new comment that is awaiting approval.
1585
 
 *
1586
 
 * @since 1.0.0
1587
 
 *
1588
 
 * @global wpdb $wpdb WordPress database abstraction object.
1589
 
 *
1590
 
 * Uses the {@see 'notify_moderator'} filter to determine whether the site moderator
1591
 
 * should be notified, overriding the site setting.
1592
 
 *
1593
 
 * @param int $comment_id Comment ID.
1594
 
 * @return true Always returns true.
1595
 
 */
1596
 
function wp_notify_moderator($comment_id) {
1597
 
        global $wpdb;
1598
 
 
1599
 
        $maybe_notify = get_option( 'moderation_notify' );
1600
 
 
1601
 
        /**
1602
 
         * Filters whether to send the site moderator email notifications, overriding the site setting.
1603
 
         *
1604
 
         * @since 4.4.0
1605
 
         *
1606
 
         * @param bool $maybe_notify Whether to notify blog moderator.
1607
 
         * @param int  $comment_ID   The id of the comment for the notification.
1608
 
         */
1609
 
        $maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_id );
1610
 
 
1611
 
        if ( ! $maybe_notify ) {
 
1745
                        /* translators: Comment moderation. %s: Comment action URL */
 
1746
                        $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ) . "\r\n";
 
1747
                }
 
1748
 
 
1749
                /* translators: Comment moderation. %s: Comment action URL */
 
1750
                $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ) . "\r\n";
 
1751
 
 
1752
                /* translators: Comment moderation. %s: Number of comments awaiting approval */
 
1753
                $notify_message .= sprintf(
 
1754
                        _n(
 
1755
                                'Currently %s comment is waiting for approval. Please visit the moderation panel:',
 
1756
                                'Currently %s comments are waiting for approval. Please visit the moderation panel:',
 
1757
                                $comments_waiting
 
1758
                        ),
 
1759
                        number_format_i18n( $comments_waiting )
 
1760
                ) . "\r\n";
 
1761
                $notify_message .= admin_url( 'edit-comments.php?comment_status=moderated#wpbody-content' ) . "\r\n";
 
1762
 
 
1763
                /* translators: Comment moderation notification email subject. 1: Site name, 2: Post title */
 
1764
                $subject         = sprintf( __( '[%1$s] Please moderate: "%2$s"' ), $blogname, $post->post_title );
 
1765
                $message_headers = '';
 
1766
 
 
1767
                /**
 
1768
                 * Filters the list of recipients for comment moderation emails.
 
1769
                 *
 
1770
                 * @since 3.7.0
 
1771
                 *
 
1772
                 * @param array $emails     List of email addresses to notify for comment moderation.
 
1773
                 * @param int   $comment_id Comment ID.
 
1774
                 */
 
1775
                $emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
 
1776
 
 
1777
                /**
 
1778
                 * Filters the comment moderation email text.
 
1779
                 *
 
1780
                 * @since 1.5.2
 
1781
                 *
 
1782
                 * @param string $notify_message Text of the comment moderation email.
 
1783
                 * @param int    $comment_id     Comment ID.
 
1784
                 */
 
1785
                $notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
 
1786
 
 
1787
                /**
 
1788
                 * Filters the comment moderation email subject.
 
1789
                 *
 
1790
                 * @since 1.5.2
 
1791
                 *
 
1792
                 * @param string $subject    Subject of the comment moderation email.
 
1793
                 * @param int    $comment_id Comment ID.
 
1794
                 */
 
1795
                $subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
 
1796
 
 
1797
                /**
 
1798
                 * Filters the comment moderation email headers.
 
1799
                 *
 
1800
                 * @since 2.8.0
 
1801
                 *
 
1802
                 * @param string $message_headers Headers for the comment moderation email.
 
1803
                 * @param int    $comment_id      Comment ID.
 
1804
                 */
 
1805
                $message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
 
1806
 
 
1807
                foreach ( $emails as $email ) {
 
1808
                        @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
 
1809
                }
 
1810
 
 
1811
                if ( $switched_locale ) {
 
1812
                        restore_previous_locale();
 
1813
                }
 
1814
 
1612
1815
                return true;
1613
1816
        }
1614
 
 
1615
 
        $comment = get_comment($comment_id);
1616
 
        $post = get_post($comment->comment_post_ID);
1617
 
        $user = get_userdata( $post->post_author );
1618
 
        // Send to the administration and to the post author if the author can modify the comment.
1619
 
        $emails = array( get_option( 'admin_email' ) );
1620
 
        if ( $user && user_can( $user->ID, 'edit_comment', $comment_id ) && ! empty( $user->user_email ) ) {
1621
 
                if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) )
1622
 
                        $emails[] = $user->user_email;
1623
 
        }
1624
 
 
1625
 
        $switched_locale = switch_to_locale( get_locale() );
1626
 
 
1627
 
        $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
1628
 
        $comments_waiting = $wpdb->get_var("SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'");
1629
 
 
1630
 
        // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1631
 
        // we want to reverse this for the plain text arena of emails.
1632
 
        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1633
 
        $comment_content = wp_specialchars_decode( $comment->comment_content );
1634
 
 
1635
 
        switch ( $comment->comment_type ) {
1636
 
                case 'trackback':
1637
 
                        /* translators: 1: Post title */
1638
 
                        $notify_message  = sprintf( __('A new trackback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1639
 
                        $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1640
 
                        /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
1641
 
                        $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1642
 
                        /* translators: 1: Trackback/pingback/comment author URL */
1643
 
                        $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
1644
 
                        $notify_message .= __('Trackback excerpt: ') . "\r\n" . $comment_content . "\r\n\r\n";
1645
 
                        break;
1646
 
                case 'pingback':
1647
 
                        /* translators: 1: Post title */
1648
 
                        $notify_message  = sprintf( __('A new pingback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1649
 
                        $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1650
 
                        /* translators: 1: Trackback/pingback website name, 2: website IP address, 3: website hostname */
1651
 
                        $notify_message .= sprintf( __( 'Website: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1652
 
                        /* translators: 1: Trackback/pingback/comment author URL */
1653
 
                        $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
1654
 
                        $notify_message .= __('Pingback excerpt: ') . "\r\n" . $comment_content . "\r\n\r\n";
1655
 
                        break;
1656
 
                default: // Comments
1657
 
                        /* translators: 1: Post title */
1658
 
                        $notify_message  = sprintf( __('A new comment on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1659
 
                        $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1660
 
                        /* translators: 1: Comment author name, 2: comment author's IP address, 3: comment author's hostname */
1661
 
                        $notify_message .= sprintf( __( 'Author: %1$s (IP address: %2$s, %3$s)' ), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1662
 
                        /* translators: 1: Comment author URL */
1663
 
                        $notify_message .= sprintf( __( 'Email: %s' ), $comment->comment_author_email ) . "\r\n";
1664
 
                        /* translators: 1: Trackback/pingback/comment author URL */
1665
 
                        $notify_message .= sprintf( __( 'URL: %s' ), $comment->comment_author_url ) . "\r\n";
1666
 
                        /* translators: 1: Comment text */
1667
 
                        $notify_message .= sprintf( __( 'Comment: %s' ), "\r\n" . $comment_content ) . "\r\n\r\n";
1668
 
                        break;
1669
 
        }
1670
 
 
1671
 
        /* translators: Comment moderation. 1: Comment action URL */
1672
 
        $notify_message .= sprintf( __( 'Approve it: %s' ), admin_url( "comment.php?action=approve&c={$comment_id}#wpbody-content" ) ) . "\r\n";
1673
 
 
1674
 
        if ( EMPTY_TRASH_DAYS ) {
1675
 
                /* translators: Comment moderation. 1: Comment action URL */
1676
 
                $notify_message .= sprintf( __( 'Trash it: %s' ), admin_url( "comment.php?action=trash&c={$comment_id}#wpbody-content" ) ) . "\r\n";
1677
 
        } else {
1678
 
                /* translators: Comment moderation. 1: Comment action URL */
1679
 
                $notify_message .= sprintf( __( 'Delete it: %s' ), admin_url( "comment.php?action=delete&c={$comment_id}#wpbody-content" ) ) . "\r\n";
1680
 
        }
1681
 
 
1682
 
        /* translators: Comment moderation. 1: Comment action URL */
1683
 
        $notify_message .= sprintf( __( 'Spam it: %s' ), admin_url( "comment.php?action=spam&c={$comment_id}#wpbody-content" ) ) . "\r\n";
1684
 
 
1685
 
        /* translators: Comment moderation. 1: Number of comments awaiting approval */
1686
 
        $notify_message .= sprintf( _n('Currently %s comment is waiting for approval. Please visit the moderation panel:',
1687
 
                'Currently %s comments are waiting for approval. Please visit the moderation panel:', $comments_waiting), number_format_i18n($comments_waiting) ) . "\r\n";
1688
 
        $notify_message .= admin_url( "edit-comments.php?comment_status=moderated#wpbody-content" ) . "\r\n";
1689
 
 
1690
 
        /* translators: Comment moderation notification email subject. 1: Site name, 2: Post title */
1691
 
        $subject = sprintf( __('[%1$s] Please moderate: "%2$s"'), $blogname, $post->post_title );
1692
 
        $message_headers = '';
1693
 
 
1694
 
        /**
1695
 
         * Filters the list of recipients for comment moderation emails.
1696
 
         *
1697
 
         * @since 3.7.0
1698
 
         *
1699
 
         * @param array $emails     List of email addresses to notify for comment moderation.
1700
 
         * @param int   $comment_id Comment ID.
1701
 
         */
1702
 
        $emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
1703
 
 
1704
 
        /**
1705
 
         * Filters the comment moderation email text.
1706
 
         *
1707
 
         * @since 1.5.2
1708
 
         *
1709
 
         * @param string $notify_message Text of the comment moderation email.
1710
 
         * @param int    $comment_id     Comment ID.
1711
 
         */
1712
 
        $notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
1713
 
 
1714
 
        /**
1715
 
         * Filters the comment moderation email subject.
1716
 
         *
1717
 
         * @since 1.5.2
1718
 
         *
1719
 
         * @param string $subject    Subject of the comment moderation email.
1720
 
         * @param int    $comment_id Comment ID.
1721
 
         */
1722
 
        $subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
1723
 
 
1724
 
        /**
1725
 
         * Filters the comment moderation email headers.
1726
 
         *
1727
 
         * @since 2.8.0
1728
 
         *
1729
 
         * @param string $message_headers Headers for the comment moderation email.
1730
 
         * @param int    $comment_id      Comment ID.
1731
 
         */
1732
 
        $message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
1733
 
 
1734
 
        foreach ( $emails as $email ) {
1735
 
                @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
1736
 
        }
1737
 
 
1738
 
        if ( $switched_locale ) {
1739
 
                restore_previous_locale();
1740
 
        }
1741
 
 
1742
 
        return true;
1743
 
}
1744
 
endif;
1745
 
 
1746
 
if ( !function_exists('wp_password_change_notification') ) :
1747
 
/**
1748
 
 * Notify the blog admin of a user changing password, normally via email.
1749
 
 *
1750
 
 * @since 2.7.0
1751
 
 *
1752
 
 * @param WP_User $user User object.
1753
 
 */
1754
 
function wp_password_change_notification( $user ) {
1755
 
        // send a copy of password change notification to the admin
1756
 
        // but check to see if it's the admin whose password we're changing, and skip this
1757
 
        if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
1758
 
                /* translators: %s: user name */
1759
 
                $message = sprintf( __( 'Password changed for user: %s' ), $user->user_login ) . "\r\n";
 
1817
endif;
 
1818
 
 
1819
if ( ! function_exists( 'wp_password_change_notification' ) ) :
 
1820
        /**
 
1821
         * Notify the blog admin of a user changing password, normally via email.
 
1822
         *
 
1823
         * @since 2.7.0
 
1824
         *
 
1825
         * @param WP_User $user User object.
 
1826
         */
 
1827
        function wp_password_change_notification( $user ) {
 
1828
                // send a copy of password change notification to the admin
 
1829
                // but check to see if it's the admin whose password we're changing, and skip this
 
1830
                if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
 
1831
                        /* translators: %s: user name */
 
1832
                        $message = sprintf( __( 'Password changed for user: %s' ), $user->user_login ) . "\r\n";
 
1833
                        // The blogname option is escaped with esc_html on the way into the database in sanitize_option
 
1834
                        // we want to reverse this for the plain text arena of emails.
 
1835
                        $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
 
1836
 
 
1837
                        $wp_password_change_notification_email = array(
 
1838
                                'to'      => get_option( 'admin_email' ),
 
1839
                                /* translators: Password change notification email subject. %s: Site title */
 
1840
                                'subject' => __( '[%s] Password Changed' ),
 
1841
                                'message' => $message,
 
1842
                                'headers' => '',
 
1843
                        );
 
1844
 
 
1845
                        /**
 
1846
                         * Filters the contents of the password change notification email sent to the site admin.
 
1847
                         *
 
1848
                         * @since 4.9.0
 
1849
                         *
 
1850
                         * @param array   $wp_password_change_notification_email {
 
1851
                         *     Used to build wp_mail().
 
1852
                         *
 
1853
                         *     @type string $to      The intended recipient - site admin email address.
 
1854
                         *     @type string $subject The subject of the email.
 
1855
                         *     @type string $message The body of the email.
 
1856
                         *     @type string $headers The headers of the email.
 
1857
                         * }
 
1858
                         * @param WP_User $user     User object for user whose password was changed.
 
1859
                         * @param string  $blogname The site title.
 
1860
                         */
 
1861
                        $wp_password_change_notification_email = apply_filters( 'wp_password_change_notification_email', $wp_password_change_notification_email, $user, $blogname );
 
1862
 
 
1863
                        wp_mail(
 
1864
                                $wp_password_change_notification_email['to'],
 
1865
                                wp_specialchars_decode( sprintf( $wp_password_change_notification_email['subject'], $blogname ) ),
 
1866
                                $wp_password_change_notification_email['message'],
 
1867
                                $wp_password_change_notification_email['headers']
 
1868
                        );
 
1869
                }
 
1870
        }
 
1871
endif;
 
1872
 
 
1873
if ( ! function_exists( 'wp_new_user_notification' ) ) :
 
1874
        /**
 
1875
         * Email login credentials to a newly-registered user.
 
1876
         *
 
1877
         * A new user registration notification is also sent to admin email.
 
1878
         *
 
1879
         * @since 2.0.0
 
1880
         * @since 4.3.0 The `$plaintext_pass` parameter was changed to `$notify`.
 
1881
         * @since 4.3.1 The `$plaintext_pass` parameter was deprecated. `$notify` added as a third parameter.
 
1882
         * @since 4.6.0 The `$notify` parameter accepts 'user' for sending notification only to the user created.
 
1883
         *
 
1884
         * @global wpdb         $wpdb      WordPress database object for queries.
 
1885
         * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
 
1886
         *
 
1887
         * @param int    $user_id    User ID.
 
1888
         * @param null   $deprecated Not used (argument deprecated).
 
1889
         * @param string $notify     Optional. Type of notification that should happen. Accepts 'admin' or an empty
 
1890
         *                           string (admin only), 'user', or 'both' (admin and user). Default empty.
 
1891
         */
 
1892
        function wp_new_user_notification( $user_id, $deprecated = null, $notify = '' ) {
 
1893
                if ( $deprecated !== null ) {
 
1894
                        _deprecated_argument( __FUNCTION__, '4.3.1' );
 
1895
                }
 
1896
 
 
1897
                // Accepts only 'user', 'admin' , 'both' or default '' as $notify
 
1898
                if ( ! in_array( $notify, array( 'user', 'admin', 'both', '' ), true ) ) {
 
1899
                        return;
 
1900
                }
 
1901
 
 
1902
                global $wpdb, $wp_hasher;
 
1903
                $user = get_userdata( $user_id );
 
1904
 
1760
1905
                // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1761
1906
                // we want to reverse this for the plain text arena of emails.
1762
 
                $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1763
 
 
1764
 
                $wp_password_change_notification_email = array(
1765
 
                        'to'      => get_option( 'admin_email' ),
1766
 
                        /* translators: Password change notification email subject. %s: Site title */
1767
 
                        'subject' => __( '[%s] Password Changed' ),
1768
 
                        'message' => $message,
1769
 
                        'headers' => '',
1770
 
                );
1771
 
 
1772
 
                /**
1773
 
                 * Filters the contents of the password change notification email sent to the site admin.
1774
 
                 *
1775
 
                 * @since 4.9.0
1776
 
                 *
1777
 
                 * @param array   $wp_password_change_notification_email {
1778
 
                 *     Used to build wp_mail().
1779
 
                 *
1780
 
                 *     @type string $to      The intended recipient - site admin email address.
1781
 
                 *     @type string $subject The subject of the email.
1782
 
                 *     @type string $message The body of the email.
1783
 
                 *     @type string $headers The headers of the email.
1784
 
                 * }
1785
 
                 * @param WP_User $user     User object for user whose password was changed.
1786
 
                 * @param string  $blogname The site title.
1787
 
                 */
1788
 
                $wp_password_change_notification_email = apply_filters( 'wp_password_change_notification_email', $wp_password_change_notification_email, $user, $blogname );
1789
 
 
1790
 
                wp_mail(
1791
 
                        $wp_password_change_notification_email['to'],
1792
 
                        wp_specialchars_decode( sprintf( $wp_password_change_notification_email['subject'], $blogname ) ),
1793
 
                        $wp_password_change_notification_email['message'],
1794
 
                        $wp_password_change_notification_email['headers']
1795
 
                );
1796
 
        }
1797
 
}
1798
 
endif;
1799
 
 
1800
 
if ( !function_exists('wp_new_user_notification') ) :
1801
 
/**
1802
 
 * Email login credentials to a newly-registered user.
1803
 
 *
1804
 
 * A new user registration notification is also sent to admin email.
1805
 
 *
1806
 
 * @since 2.0.0
1807
 
 * @since 4.3.0 The `$plaintext_pass` parameter was changed to `$notify`.
1808
 
 * @since 4.3.1 The `$plaintext_pass` parameter was deprecated. `$notify` added as a third parameter.
1809
 
 * @since 4.6.0 The `$notify` parameter accepts 'user' for sending notification only to the user created.
1810
 
 *
1811
 
 * @global wpdb         $wpdb      WordPress database object for queries.
1812
 
 * @global PasswordHash $wp_hasher Portable PHP password hashing framework instance.
1813
 
 *
1814
 
 * @param int    $user_id    User ID.
1815
 
 * @param null   $deprecated Not used (argument deprecated).
1816
 
 * @param string $notify     Optional. Type of notification that should happen. Accepts 'admin' or an empty
1817
 
 *                           string (admin only), 'user', or 'both' (admin and user). Default empty.
1818
 
 */
1819
 
function wp_new_user_notification( $user_id, $deprecated = null, $notify = '' ) {
1820
 
        if ( $deprecated !== null ) {
1821
 
                _deprecated_argument( __FUNCTION__, '4.3.1' );
1822
 
        }
1823
 
 
1824
 
        global $wpdb, $wp_hasher;
1825
 
        $user = get_userdata( $user_id );
1826
 
 
1827
 
        // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1828
 
        // we want to reverse this for the plain text arena of emails.
1829
 
        $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1830
 
 
1831
 
        if ( 'user' !== $notify ) {
1832
 
                $switched_locale = switch_to_locale( get_locale() );
1833
 
 
1834
 
                /* translators: %s: site title */
1835
 
                $message  = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
 
1907
                $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
 
1908
 
 
1909
                if ( 'user' !== $notify ) {
 
1910
                        $switched_locale = switch_to_locale( get_locale() );
 
1911
 
 
1912
                        /* translators: %s: site title */
 
1913
                        $message = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "\r\n\r\n";
 
1914
                        /* translators: %s: user login */
 
1915
                        $message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
 
1916
                        /* translators: %s: user email address */
 
1917
                        $message .= sprintf( __( 'Email: %s' ), $user->user_email ) . "\r\n";
 
1918
 
 
1919
                        $wp_new_user_notification_email_admin = array(
 
1920
                                'to'      => get_option( 'admin_email' ),
 
1921
                                /* translators: Password change notification email subject. %s: Site title */
 
1922
                                'subject' => __( '[%s] New User Registration' ),
 
1923
                                'message' => $message,
 
1924
                                'headers' => '',
 
1925
                        );
 
1926
 
 
1927
                        /**
 
1928
                         * Filters the contents of the new user notification email sent to the site admin.
 
1929
                         *
 
1930
                         * @since 4.9.0
 
1931
                         *
 
1932
                         * @param array   $wp_new_user_notification_email {
 
1933
                         *     Used to build wp_mail().
 
1934
                         *
 
1935
                         *     @type string $to      The intended recipient - site admin email address.
 
1936
                         *     @type string $subject The subject of the email.
 
1937
                         *     @type string $message The body of the email.
 
1938
                         *     @type string $headers The headers of the email.
 
1939
                         * }
 
1940
                         * @param WP_User $user     User object for new user.
 
1941
                         * @param string  $blogname The site title.
 
1942
                         */
 
1943
                        $wp_new_user_notification_email_admin = apply_filters( 'wp_new_user_notification_email_admin', $wp_new_user_notification_email_admin, $user, $blogname );
 
1944
 
 
1945
                        @wp_mail(
 
1946
                                $wp_new_user_notification_email_admin['to'],
 
1947
                                wp_specialchars_decode( sprintf( $wp_new_user_notification_email_admin['subject'], $blogname ) ),
 
1948
                                $wp_new_user_notification_email_admin['message'],
 
1949
                                $wp_new_user_notification_email_admin['headers']
 
1950
                        );
 
1951
 
 
1952
                        if ( $switched_locale ) {
 
1953
                                restore_previous_locale();
 
1954
                        }
 
1955
                }
 
1956
 
 
1957
                // `$deprecated was pre-4.3 `$plaintext_pass`. An empty `$plaintext_pass` didn't sent a user notification.
 
1958
                if ( 'admin' === $notify || ( empty( $deprecated ) && empty( $notify ) ) ) {
 
1959
                        return;
 
1960
                }
 
1961
 
 
1962
                // Generate something random for a password reset key.
 
1963
                $key = wp_generate_password( 20, false );
 
1964
 
 
1965
                /** This action is documented in wp-login.php */
 
1966
                do_action( 'retrieve_password_key', $user->user_login, $key );
 
1967
 
 
1968
                // Now insert the key, hashed, into the DB.
 
1969
                if ( empty( $wp_hasher ) ) {
 
1970
                        require_once ABSPATH . WPINC . '/class-phpass.php';
 
1971
                        $wp_hasher = new PasswordHash( 8, true );
 
1972
                }
 
1973
                $hashed = time() . ':' . $wp_hasher->HashPassword( $key );
 
1974
                $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
 
1975
 
 
1976
                $switched_locale = switch_to_locale( get_user_locale( $user ) );
 
1977
 
1836
1978
                /* translators: %s: user login */
1837
 
                $message .= sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
1838
 
                /* translators: %s: user email address */
1839
 
                $message .= sprintf( __( 'Email: %s' ), $user->user_email ) . "\r\n";
1840
 
 
1841
 
                $wp_new_user_notification_email_admin = array(
1842
 
                        'to'      => get_option( 'admin_email' ),
 
1979
                $message  = sprintf( __( 'Username: %s' ), $user->user_login ) . "\r\n\r\n";
 
1980
                $message .= __( 'To set your password, visit the following address:' ) . "\r\n\r\n";
 
1981
                $message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user->user_login ), 'login' ) . ">\r\n\r\n";
 
1982
 
 
1983
                $message .= wp_login_url() . "\r\n";
 
1984
 
 
1985
                $wp_new_user_notification_email = array(
 
1986
                        'to'      => $user->user_email,
1843
1987
                        /* translators: Password change notification email subject. %s: Site title */
1844
 
                        'subject' => __( '[%s] New User Registration' ),
 
1988
                        'subject' => __( '[%s] Your username and password info' ),
1845
1989
                        'message' => $message,
1846
1990
                        'headers' => '',
1847
1991
                );
1848
1992
 
1849
1993
                /**
1850
 
                 * Filters the contents of the new user notification email sent to the site admin.
 
1994
                 * Filters the contents of the new user notification email sent to the new user.
1851
1995
                 *
1852
1996
                 * @since 4.9.0
1853
1997
                 *
1854
1998
                 * @param array   $wp_new_user_notification_email {
1855
1999
                 *     Used to build wp_mail().
1856
2000
                 *
1857
 
                 *     @type string $to      The intended recipient - site admin email address.
 
2001
                 *     @type string $to      The intended recipient - New user email address.
1858
2002
                 *     @type string $subject The subject of the email.
1859
2003
                 *     @type string $message The body of the email.
1860
2004
                 *     @type string $headers The headers of the email.
1862
2006
                 * @param WP_User $user     User object for new user.
1863
2007
                 * @param string  $blogname The site title.
1864
2008
                 */
1865
 
                $wp_new_user_notification_email_admin = apply_filters( 'wp_new_user_notification_email_admin', $wp_new_user_notification_email_admin, $user, $blogname );
 
2009
                $wp_new_user_notification_email = apply_filters( 'wp_new_user_notification_email', $wp_new_user_notification_email, $user, $blogname );
1866
2010
 
1867
 
                @wp_mail(
1868
 
                        $wp_new_user_notification_email_admin['to'],
1869
 
                        wp_specialchars_decode( sprintf( $wp_new_user_notification_email_admin['subject'], $blogname ) ),
1870
 
                        $wp_new_user_notification_email_admin['message'],
1871
 
                        $wp_new_user_notification_email_admin['headers']
 
2011
                wp_mail(
 
2012
                        $wp_new_user_notification_email['to'],
 
2013
                        wp_specialchars_decode( sprintf( $wp_new_user_notification_email['subject'], $blogname ) ),
 
2014
                        $wp_new_user_notification_email['message'],
 
2015
                        $wp_new_user_notification_email['headers']
1872
2016
                );
1873
2017
 
1874
2018
                if ( $switched_locale ) {
1875
2019
                        restore_previous_locale();
1876
2020
                }
1877
2021
        }
1878
 
 
1879
 
        // `$deprecated was pre-4.3 `$plaintext_pass`. An empty `$plaintext_pass` didn't sent a user notification.
1880
 
        if ( 'admin' === $notify || ( empty( $deprecated ) && empty( $notify ) ) ) {
1881
 
                return;
1882
 
        }
1883
 
 
1884
 
        // Generate something random for a password reset key.
1885
 
        $key = wp_generate_password( 20, false );
1886
 
 
1887
 
        /** This action is documented in wp-login.php */
1888
 
        do_action( 'retrieve_password_key', $user->user_login, $key );
1889
 
 
1890
 
        // Now insert the key, hashed, into the DB.
1891
 
        if ( empty( $wp_hasher ) ) {
1892
 
                require_once ABSPATH . WPINC . '/class-phpass.php';
1893
 
                $wp_hasher = new PasswordHash( 8, true );
1894
 
        }
1895
 
        $hashed = time() . ':' . $wp_hasher->HashPassword( $key );
1896
 
        $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user->user_login ) );
1897
 
 
1898
 
        $switched_locale = switch_to_locale( get_user_locale( $user ) );
1899
 
 
1900
 
        /* translators: %s: user login */
1901
 
        $message = sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
1902
 
        $message .= __('To set your password, visit the following address:') . "\r\n\r\n";
1903
 
        $message .= '<' . network_site_url("wp-login.php?action=rp&key=$key&login=" . rawurlencode($user->user_login), 'login') . ">\r\n\r\n";
1904
 
 
1905
 
        $message .= wp_login_url() . "\r\n";
1906
 
 
1907
 
        $wp_new_user_notification_email = array(
1908
 
                'to'      => $user->user_email,
1909
 
                /* translators: Password change notification email subject. %s: Site title */
1910
 
                'subject' => __( '[%s] Your username and password info' ),
1911
 
                'message' => $message,
1912
 
                'headers' => '',
1913
 
        );
1914
 
 
1915
 
        /**
1916
 
         * Filters the contents of the new user notification email sent to the new user.
1917
 
         *
1918
 
         * @since 4.9.0
1919
 
         *
1920
 
         * @param array   $wp_new_user_notification_email {
1921
 
         *     Used to build wp_mail().
1922
 
         *
1923
 
         *     @type string $to      The intended recipient - New user email address.
1924
 
         *     @type string $subject The subject of the email.
1925
 
         *     @type string $message The body of the email.
1926
 
         *     @type string $headers The headers of the email.
1927
 
         * }
1928
 
         * @param WP_User $user     User object for new user.
1929
 
         * @param string  $blogname The site title.
1930
 
         */
1931
 
        $wp_new_user_notification_email = apply_filters( 'wp_new_user_notification_email', $wp_new_user_notification_email, $user, $blogname );
1932
 
 
1933
 
        wp_mail(
1934
 
                $wp_new_user_notification_email['to'],
1935
 
                wp_specialchars_decode( sprintf( $wp_new_user_notification_email['subject'], $blogname ) ),
1936
 
                $wp_new_user_notification_email['message'],
1937
 
                $wp_new_user_notification_email['headers']
1938
 
        );
1939
 
 
1940
 
        if ( $switched_locale ) {
1941
 
                restore_previous_locale();
1942
 
        }
1943
 
}
1944
2022
endif;
1945
2023
 
1946
 
if ( !function_exists('wp_nonce_tick') ) :
1947
 
/**
1948
 
 * Get the time-dependent variable for nonce creation.
1949
 
 *
1950
 
 * A nonce has a lifespan of two ticks. Nonces in their second tick may be
1951
 
 * updated, e.g. by autosave.
1952
 
 *
1953
 
 * @since 2.5.0
1954
 
 *
1955
 
 * @return float Float value rounded up to the next highest integer.
1956
 
 */
1957
 
function wp_nonce_tick() {
 
2024
if ( ! function_exists( 'wp_nonce_tick' ) ) :
1958
2025
        /**
1959
 
         * Filters the lifespan of nonces in seconds.
 
2026
         * Get the time-dependent variable for nonce creation.
 
2027
         *
 
2028
         * A nonce has a lifespan of two ticks. Nonces in their second tick may be
 
2029
         * updated, e.g. by autosave.
1960
2030
         *
1961
2031
         * @since 2.5.0
1962
2032
         *
1963
 
         * @param int $lifespan Lifespan of nonces in seconds. Default 86,400 seconds, or one day.
 
2033
         * @return float Float value rounded up to the next highest integer.
1964
2034
         */
1965
 
        $nonce_life = apply_filters( 'nonce_life', DAY_IN_SECONDS );
 
2035
        function wp_nonce_tick() {
 
2036
                /**
 
2037
                 * Filters the lifespan of nonces in seconds.
 
2038
                 *
 
2039
                 * @since 2.5.0
 
2040
                 *
 
2041
                 * @param int $lifespan Lifespan of nonces in seconds. Default 86,400 seconds, or one day.
 
2042
                 */
 
2043
                $nonce_life = apply_filters( 'nonce_life', DAY_IN_SECONDS );
1966
2044
 
1967
 
        return ceil(time() / ( $nonce_life / 2 ));
1968
 
}
 
2045
                return ceil( time() / ( $nonce_life / 2 ) );
 
2046
        }
1969
2047
endif;
1970
2048
 
1971
 
if ( !function_exists('wp_verify_nonce') ) :
1972
 
/**
1973
 
 * Verify that correct nonce was used with time limit.
1974
 
 *
1975
 
 * The user is given an amount of time to use the token, so therefore, since the
1976
 
 * UID and $action remain the same, the independent variable is the time.
1977
 
 *
1978
 
 * @since 2.0.3
1979
 
 *
1980
 
 * @param string     $nonce  Nonce that was used in the form to verify
1981
 
 * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
1982
 
 * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
1983
 
 *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
1984
 
 */
1985
 
function wp_verify_nonce( $nonce, $action = -1 ) {
1986
 
        $nonce = (string) $nonce;
1987
 
        $user = wp_get_current_user();
1988
 
        $uid = (int) $user->ID;
1989
 
        if ( ! $uid ) {
 
2049
if ( ! function_exists( 'wp_verify_nonce' ) ) :
 
2050
        /**
 
2051
         * Verify that correct nonce was used with time limit.
 
2052
         *
 
2053
         * The user is given an amount of time to use the token, so therefore, since the
 
2054
         * UID and $action remain the same, the independent variable is the time.
 
2055
         *
 
2056
         * @since 2.0.3
 
2057
         *
 
2058
         * @param string     $nonce  Nonce that was used in the form to verify
 
2059
         * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
 
2060
         * @return false|int False if the nonce is invalid, 1 if the nonce is valid and generated between
 
2061
         *                   0-12 hours ago, 2 if the nonce is valid and generated between 12-24 hours ago.
 
2062
         */
 
2063
        function wp_verify_nonce( $nonce, $action = -1 ) {
 
2064
                $nonce = (string) $nonce;
 
2065
                $user  = wp_get_current_user();
 
2066
                $uid   = (int) $user->ID;
 
2067
                if ( ! $uid ) {
 
2068
                        /**
 
2069
                         * Filters whether the user who generated the nonce is logged out.
 
2070
                         *
 
2071
                         * @since 3.5.0
 
2072
                         *
 
2073
                         * @param int    $uid    ID of the nonce-owning user.
 
2074
                         * @param string $action The nonce action.
 
2075
                         */
 
2076
                        $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
 
2077
                }
 
2078
 
 
2079
                if ( empty( $nonce ) ) {
 
2080
                        return false;
 
2081
                }
 
2082
 
 
2083
                $token = wp_get_session_token();
 
2084
                $i     = wp_nonce_tick();
 
2085
 
 
2086
                // Nonce generated 0-12 hours ago
 
2087
                $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
 
2088
                if ( hash_equals( $expected, $nonce ) ) {
 
2089
                        return 1;
 
2090
                }
 
2091
 
 
2092
                // Nonce generated 12-24 hours ago
 
2093
                $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
 
2094
                if ( hash_equals( $expected, $nonce ) ) {
 
2095
                        return 2;
 
2096
                }
 
2097
 
1990
2098
                /**
1991
 
                 * Filters whether the user who generated the nonce is logged out.
1992
 
                 *
1993
 
                 * @since 3.5.0
1994
 
                 *
1995
 
                 * @param int    $uid    ID of the nonce-owning user.
1996
 
                 * @param string $action The nonce action.
 
2099
                 * Fires when nonce verification fails.
 
2100
                 *
 
2101
                 * @since 4.4.0
 
2102
                 *
 
2103
                 * @param string     $nonce  The invalid nonce.
 
2104
                 * @param string|int $action The nonce action.
 
2105
                 * @param WP_User    $user   The current user object.
 
2106
                 * @param string     $token  The user's session token.
1997
2107
                 */
1998
 
                $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
1999
 
        }
 
2108
                do_action( 'wp_verify_nonce_failed', $nonce, $action, $user, $token );
2000
2109
 
2001
 
        if ( empty( $nonce ) ) {
 
2110
                // Invalid nonce
2002
2111
                return false;
2003
2112
        }
2004
 
 
2005
 
        $token = wp_get_session_token();
2006
 
        $i = wp_nonce_tick();
2007
 
 
2008
 
        // Nonce generated 0-12 hours ago
2009
 
        $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10 );
2010
 
        if ( hash_equals( $expected, $nonce ) ) {
2011
 
                return 1;
2012
 
        }
2013
 
 
2014
 
        // Nonce generated 12-24 hours ago
2015
 
        $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
2016
 
        if ( hash_equals( $expected, $nonce ) ) {
2017
 
                return 2;
2018
 
        }
2019
 
 
2020
 
        /**
2021
 
         * Fires when nonce verification fails.
2022
 
         *
2023
 
         * @since 4.4.0
2024
 
         *
2025
 
         * @param string     $nonce  The invalid nonce.
2026
 
         * @param string|int $action The nonce action.
2027
 
         * @param WP_User    $user   The current user object.
2028
 
         * @param string     $token  The user's session token.
2029
 
         */
2030
 
        do_action( 'wp_verify_nonce_failed', $nonce, $action, $user, $token );
2031
 
 
2032
 
        // Invalid nonce
2033
 
        return false;
2034
 
}
2035
 
endif;
2036
 
 
2037
 
if ( !function_exists('wp_create_nonce') ) :
2038
 
/**
2039
 
 * Creates a cryptographic token tied to a specific action, user, user session,
2040
 
 * and window of time.
2041
 
 *
2042
 
 * @since 2.0.3
2043
 
 * @since 4.0.0 Session tokens were integrated with nonce creation
2044
 
 *
2045
 
 * @param string|int $action Scalar value to add context to the nonce.
2046
 
 * @return string The token.
2047
 
 */
2048
 
function wp_create_nonce($action = -1) {
2049
 
        $user = wp_get_current_user();
2050
 
        $uid = (int) $user->ID;
2051
 
        if ( ! $uid ) {
 
2113
endif;
 
2114
 
 
2115
if ( ! function_exists( 'wp_create_nonce' ) ) :
 
2116
        /**
 
2117
         * Creates a cryptographic token tied to a specific action, user, user session,
 
2118
         * and window of time.
 
2119
         *
 
2120
         * @since 2.0.3
 
2121
         * @since 4.0.0 Session tokens were integrated with nonce creation
 
2122
         *
 
2123
         * @param string|int $action Scalar value to add context to the nonce.
 
2124
         * @return string The token.
 
2125
         */
 
2126
        function wp_create_nonce( $action = -1 ) {
 
2127
                $user = wp_get_current_user();
 
2128
                $uid  = (int) $user->ID;
 
2129
                if ( ! $uid ) {
 
2130
                        /** This filter is documented in wp-includes/pluggable.php */
 
2131
                        $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
 
2132
                }
 
2133
 
 
2134
                $token = wp_get_session_token();
 
2135
                $i     = wp_nonce_tick();
 
2136
 
 
2137
                return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
 
2138
        }
 
2139
endif;
 
2140
 
 
2141
if ( ! function_exists( 'wp_salt' ) ) :
 
2142
        /**
 
2143
         * Get salt to add to hashes.
 
2144
         *
 
2145
         * Salts are created using secret keys. Secret keys are located in two places:
 
2146
         * in the database and in the wp-config.php file. The secret key in the database
 
2147
         * is randomly generated and will be appended to the secret keys in wp-config.php.
 
2148
         *
 
2149
         * The secret keys in wp-config.php should be updated to strong, random keys to maximize
 
2150
         * security. Below is an example of how the secret key constants are defined.
 
2151
         * Do not paste this example directly into wp-config.php. Instead, have a
 
2152
         * {@link https://api.wordpress.org/secret-key/1.1/salt/ secret key created} just
 
2153
         * for you.
 
2154
         *
 
2155
         *     define('AUTH_KEY',         ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON');
 
2156
         *     define('SECURE_AUTH_KEY',  'LzJ}op]mr|6+![P}Ak:uNdJCJZd>(Hx.-Mh#Tz)pCIU#uGEnfFz|f ;;eU%/U^O~');
 
2157
         *     define('LOGGED_IN_KEY',    '|i|Ux`9<p-h$aFf(qnT:sDO:D1P^wZ$$/Ra@miTJi9G;ddp_<q}6H1)o|a +&JCM');
 
2158
         *     define('NONCE_KEY',        '%:R{[P|,s.KuMltH5}cI;/k<Gx~j!f0I)m_sIyu+&NJZ)-iO>z7X>QYR0Z_XnZ@|');
 
2159
         *     define('AUTH_SALT',        'eZyT)-Naw]F8CwA*VaW#q*|.)g@o}||wf~@C-YSt}(dh_r6EbI#A,y|nU2{B#JBW');
 
2160
         *     define('SECURE_AUTH_SALT', '!=oLUTXh,QW=H `}`L|9/^4-3 STz},T(w}W<I`.JjPi)<Bmf1v,HpGe}T1:Xt7n');
 
2161
         *     define('LOGGED_IN_SALT',   '+XSqHc;@Q*K_b|Z?NC[3H!!EONbh.n<+=uKR:>*c(u`g~EJBf#8u#R{mUEZrozmm');
 
2162
         *     define('NONCE_SALT',       'h`GXHhD>SLWVfg1(1(N{;.V!MoE(SfbA_ksP@&`+AycHcAV$+?@3q+rxV{%^VyKT');
 
2163
         *
 
2164
         * Salting passwords helps against tools which has stored hashed values of
 
2165
         * common dictionary strings. The added values makes it harder to crack.
 
2166
         *
 
2167
         * @since 2.5.0
 
2168
         *
 
2169
         * @link https://api.wordpress.org/secret-key/1.1/salt/ Create secrets for wp-config.php
 
2170
         *
 
2171
         * @staticvar array $cached_salts
 
2172
         * @staticvar array $duplicated_keys
 
2173
         *
 
2174
         * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
 
2175
         * @return string Salt value
 
2176
         */
 
2177
        function wp_salt( $scheme = 'auth' ) {
 
2178
                static $cached_salts = array();
 
2179
                if ( isset( $cached_salts[ $scheme ] ) ) {
 
2180
                        /**
 
2181
                         * Filters the WordPress salt.
 
2182
                         *
 
2183
                         * @since 2.5.0
 
2184
                         *
 
2185
                         * @param string $cached_salt Cached salt for the given scheme.
 
2186
                         * @param string $scheme      Authentication scheme. Values include 'auth',
 
2187
                         *                            'secure_auth', 'logged_in', and 'nonce'.
 
2188
                         */
 
2189
                        return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
 
2190
                }
 
2191
 
 
2192
                static $duplicated_keys;
 
2193
                if ( null === $duplicated_keys ) {
 
2194
                        $duplicated_keys = array( 'put your unique phrase here' => true );
 
2195
                        foreach ( array( 'AUTH', 'SECURE_AUTH', 'LOGGED_IN', 'NONCE', 'SECRET' ) as $first ) {
 
2196
                                foreach ( array( 'KEY', 'SALT' ) as $second ) {
 
2197
                                        if ( ! defined( "{$first}_{$second}" ) ) {
 
2198
                                                continue;
 
2199
                                        }
 
2200
                                        $value                     = constant( "{$first}_{$second}" );
 
2201
                                        $duplicated_keys[ $value ] = isset( $duplicated_keys[ $value ] );
 
2202
                                }
 
2203
                        }
 
2204
                }
 
2205
 
 
2206
                $values = array(
 
2207
                        'key'  => '',
 
2208
                        'salt' => '',
 
2209
                );
 
2210
                if ( defined( 'SECRET_KEY' ) && SECRET_KEY && empty( $duplicated_keys[ SECRET_KEY ] ) ) {
 
2211
                        $values['key'] = SECRET_KEY;
 
2212
                }
 
2213
                if ( 'auth' == $scheme && defined( 'SECRET_SALT' ) && SECRET_SALT && empty( $duplicated_keys[ SECRET_SALT ] ) ) {
 
2214
                        $values['salt'] = SECRET_SALT;
 
2215
                }
 
2216
 
 
2217
                if ( in_array( $scheme, array( 'auth', 'secure_auth', 'logged_in', 'nonce' ) ) ) {
 
2218
                        foreach ( array( 'key', 'salt' ) as $type ) {
 
2219
                                $const = strtoupper( "{$scheme}_{$type}" );
 
2220
                                if ( defined( $const ) && constant( $const ) && empty( $duplicated_keys[ constant( $const ) ] ) ) {
 
2221
                                        $values[ $type ] = constant( $const );
 
2222
                                } elseif ( ! $values[ $type ] ) {
 
2223
                                        $values[ $type ] = get_site_option( "{$scheme}_{$type}" );
 
2224
                                        if ( ! $values[ $type ] ) {
 
2225
                                                $values[ $type ] = wp_generate_password( 64, true, true );
 
2226
                                                update_site_option( "{$scheme}_{$type}", $values[ $type ] );
 
2227
                                        }
 
2228
                                }
 
2229
                        }
 
2230
                } else {
 
2231
                        if ( ! $values['key'] ) {
 
2232
                                $values['key'] = get_site_option( 'secret_key' );
 
2233
                                if ( ! $values['key'] ) {
 
2234
                                        $values['key'] = wp_generate_password( 64, true, true );
 
2235
                                        update_site_option( 'secret_key', $values['key'] );
 
2236
                                }
 
2237
                        }
 
2238
                        $values['salt'] = hash_hmac( 'md5', $scheme, $values['key'] );
 
2239
                }
 
2240
 
 
2241
                $cached_salts[ $scheme ] = $values['key'] . $values['salt'];
 
2242
 
2052
2243
                /** This filter is documented in wp-includes/pluggable.php */
2053
 
                $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
2054
 
        }
2055
 
 
2056
 
        $token = wp_get_session_token();
2057
 
        $i = wp_nonce_tick();
2058
 
 
2059
 
        return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
2060
 
}
2061
 
endif;
2062
 
 
2063
 
if ( !function_exists('wp_salt') ) :
2064
 
/**
2065
 
 * Get salt to add to hashes.
2066
 
 *
2067
 
 * Salts are created using secret keys. Secret keys are located in two places:
2068
 
 * in the database and in the wp-config.php file. The secret key in the database
2069
 
 * is randomly generated and will be appended to the secret keys in wp-config.php.
2070
 
 *
2071
 
 * The secret keys in wp-config.php should be updated to strong, random keys to maximize
2072
 
 * security. Below is an example of how the secret key constants are defined.
2073
 
 * Do not paste this example directly into wp-config.php. Instead, have a
2074
 
 * {@link https://api.wordpress.org/secret-key/1.1/salt/ secret key created} just
2075
 
 * for you.
2076
 
 *
2077
 
 *     define('AUTH_KEY',         ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON');
2078
 
 *     define('SECURE_AUTH_KEY',  'LzJ}op]mr|6+![P}Ak:uNdJCJZd>(Hx.-Mh#Tz)pCIU#uGEnfFz|f ;;eU%/U^O~');
2079
 
 *     define('LOGGED_IN_KEY',    '|i|Ux`9<p-h$aFf(qnT:sDO:D1P^wZ$$/Ra@miTJi9G;ddp_<q}6H1)o|a +&JCM');
2080
 
 *     define('NONCE_KEY',        '%:R{[P|,s.KuMltH5}cI;/k<Gx~j!f0I)m_sIyu+&NJZ)-iO>z7X>QYR0Z_XnZ@|');
2081
 
 *     define('AUTH_SALT',        'eZyT)-Naw]F8CwA*VaW#q*|.)g@o}||wf~@C-YSt}(dh_r6EbI#A,y|nU2{B#JBW');
2082
 
 *     define('SECURE_AUTH_SALT', '!=oLUTXh,QW=H `}`L|9/^4-3 STz},T(w}W<I`.JjPi)<Bmf1v,HpGe}T1:Xt7n');
2083
 
 *     define('LOGGED_IN_SALT',   '+XSqHc;@Q*K_b|Z?NC[3H!!EONbh.n<+=uKR:>*c(u`g~EJBf#8u#R{mUEZrozmm');
2084
 
 *     define('NONCE_SALT',       'h`GXHhD>SLWVfg1(1(N{;.V!MoE(SfbA_ksP@&`+AycHcAV$+?@3q+rxV{%^VyKT');
2085
 
 *
2086
 
 * Salting passwords helps against tools which has stored hashed values of
2087
 
 * common dictionary strings. The added values makes it harder to crack.
2088
 
 *
2089
 
 * @since 2.5.0
2090
 
 *
2091
 
 * @link https://api.wordpress.org/secret-key/1.1/salt/ Create secrets for wp-config.php
2092
 
 *
2093
 
 * @staticvar array $cached_salts
2094
 
 * @staticvar array $duplicated_keys
2095
 
 *
2096
 
 * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
2097
 
 * @return string Salt value
2098
 
 */
2099
 
function wp_salt( $scheme = 'auth' ) {
2100
 
        static $cached_salts = array();
2101
 
        if ( isset( $cached_salts[ $scheme ] ) ) {
2102
 
                /**
2103
 
                 * Filters the WordPress salt.
2104
 
                 *
2105
 
                 * @since 2.5.0
2106
 
                 *
2107
 
                 * @param string $cached_salt Cached salt for the given scheme.
2108
 
                 * @param string $scheme      Authentication scheme. Values include 'auth',
2109
 
                 *                            'secure_auth', 'logged_in', and 'nonce'.
2110
 
                 */
2111
2244
                return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
2112
2245
        }
2113
 
 
2114
 
        static $duplicated_keys;
2115
 
        if ( null === $duplicated_keys ) {
2116
 
                $duplicated_keys = array( 'put your unique phrase here' => true );
2117
 
                foreach ( array( 'AUTH', 'SECURE_AUTH', 'LOGGED_IN', 'NONCE', 'SECRET' ) as $first ) {
2118
 
                        foreach ( array( 'KEY', 'SALT' ) as $second ) {
2119
 
                                if ( ! defined( "{$first}_{$second}" ) ) {
2120
 
                                        continue;
2121
 
                                }
2122
 
                                $value = constant( "{$first}_{$second}" );
2123
 
                                $duplicated_keys[ $value ] = isset( $duplicated_keys[ $value ] );
2124
 
                        }
2125
 
                }
2126
 
        }
2127
 
 
2128
 
        $values = array(
2129
 
                'key' => '',
2130
 
                'salt' => ''
2131
 
        );
2132
 
        if ( defined( 'SECRET_KEY' ) && SECRET_KEY && empty( $duplicated_keys[ SECRET_KEY ] ) ) {
2133
 
                $values['key'] = SECRET_KEY;
2134
 
        }
2135
 
        if ( 'auth' == $scheme && defined( 'SECRET_SALT' ) && SECRET_SALT && empty( $duplicated_keys[ SECRET_SALT ] ) ) {
2136
 
                $values['salt'] = SECRET_SALT;
2137
 
        }
2138
 
 
2139
 
        if ( in_array( $scheme, array( 'auth', 'secure_auth', 'logged_in', 'nonce' ) ) ) {
2140
 
                foreach ( array( 'key', 'salt' ) as $type ) {
2141
 
                        $const = strtoupper( "{$scheme}_{$type}" );
2142
 
                        if ( defined( $const ) && constant( $const ) && empty( $duplicated_keys[ constant( $const ) ] ) ) {
2143
 
                                $values[ $type ] = constant( $const );
2144
 
                        } elseif ( ! $values[ $type ] ) {
2145
 
                                $values[ $type ] = get_site_option( "{$scheme}_{$type}" );
2146
 
                                if ( ! $values[ $type ] ) {
2147
 
                                        $values[ $type ] = wp_generate_password( 64, true, true );
2148
 
                                        update_site_option( "{$scheme}_{$type}", $values[ $type ] );
2149
 
                                }
2150
 
                        }
2151
 
                }
2152
 
        } else {
2153
 
                if ( ! $values['key'] ) {
2154
 
                        $values['key'] = get_site_option( 'secret_key' );
2155
 
                        if ( ! $values['key'] ) {
2156
 
                                $values['key'] = wp_generate_password( 64, true, true );
2157
 
                                update_site_option( 'secret_key', $values['key'] );
2158
 
                        }
2159
 
                }
2160
 
                $values['salt'] = hash_hmac( 'md5', $scheme, $values['key'] );
2161
 
        }
2162
 
 
2163
 
        $cached_salts[ $scheme ] = $values['key'] . $values['salt'];
2164
 
 
2165
 
        /** This filter is documented in wp-includes/pluggable.php */
2166
 
        return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
2167
 
}
2168
 
endif;
2169
 
 
2170
 
if ( !function_exists('wp_hash') ) :
2171
 
/**
2172
 
 * Get hash of given string.
2173
 
 *
2174
 
 * @since 2.0.3
2175
 
 *
2176
 
 * @param string $data   Plain text to hash
2177
 
 * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
2178
 
 * @return string Hash of $data
2179
 
 */
2180
 
function wp_hash($data, $scheme = 'auth') {
2181
 
        $salt = wp_salt($scheme);
2182
 
 
2183
 
        return hash_hmac('md5', $data, $salt);
2184
 
}
2185
 
endif;
2186
 
 
2187
 
if ( !function_exists('wp_hash_password') ) :
2188
 
/**
2189
 
 * Create a hash (encrypt) of a plain text password.
2190
 
 *
2191
 
 * For integration with other applications, this function can be overwritten to
2192
 
 * instead use the other package password checking algorithm.
2193
 
 *
2194
 
 * @since 2.5.0
2195
 
 *
2196
 
 * @global PasswordHash $wp_hasher PHPass object
2197
 
 *
2198
 
 * @param string $password Plain text user password to hash
2199
 
 * @return string The hash string of the password
2200
 
 */
2201
 
function wp_hash_password($password) {
2202
 
        global $wp_hasher;
2203
 
 
2204
 
        if ( empty($wp_hasher) ) {
2205
 
                require_once( ABSPATH . WPINC . '/class-phpass.php');
2206
 
                // By default, use the portable hash from phpass
2207
 
                $wp_hasher = new PasswordHash(8, true);
2208
 
        }
2209
 
 
2210
 
        return $wp_hasher->HashPassword( trim( $password ) );
2211
 
}
2212
 
endif;
2213
 
 
2214
 
if ( !function_exists('wp_check_password') ) :
2215
 
/**
2216
 
 * Checks the plaintext password against the encrypted Password.
2217
 
 *
2218
 
 * Maintains compatibility between old version and the new cookie authentication
2219
 
 * protocol using PHPass library. The $hash parameter is the encrypted password
2220
 
 * and the function compares the plain text password when encrypted similarly
2221
 
 * against the already encrypted password to see if they match.
2222
 
 *
2223
 
 * For integration with other applications, this function can be overwritten to
2224
 
 * instead use the other package password checking algorithm.
2225
 
 *
2226
 
 * @since 2.5.0
2227
 
 *
2228
 
 * @global PasswordHash $wp_hasher PHPass object used for checking the password
2229
 
 *      against the $hash + $password
2230
 
 * @uses PasswordHash::CheckPassword
2231
 
 *
2232
 
 * @param string     $password Plaintext user's password
2233
 
 * @param string     $hash     Hash of the user's password to check against.
2234
 
 * @param string|int $user_id  Optional. User ID.
2235
 
 * @return bool False, if the $password does not match the hashed password
2236
 
 */
2237
 
function wp_check_password($password, $hash, $user_id = '') {
2238
 
        global $wp_hasher;
2239
 
 
2240
 
        // If the hash is still md5...
2241
 
        if ( strlen($hash) <= 32 ) {
2242
 
                $check = hash_equals( $hash, md5( $password ) );
2243
 
                if ( $check && $user_id ) {
2244
 
                        // Rehash using new hash.
2245
 
                        wp_set_password($password, $user_id);
2246
 
                        $hash = wp_hash_password($password);
2247
 
                }
2248
 
 
2249
 
                /**
2250
 
                 * Filters whether the plaintext password matches the encrypted password.
2251
 
                 *
2252
 
                 * @since 2.5.0
2253
 
                 *
2254
 
                 * @param bool       $check    Whether the passwords match.
2255
 
                 * @param string     $password The plaintext password.
2256
 
                 * @param string     $hash     The hashed password.
2257
 
                 * @param string|int $user_id  User ID. Can be empty.
2258
 
                 */
 
2246
endif;
 
2247
 
 
2248
if ( ! function_exists( 'wp_hash' ) ) :
 
2249
        /**
 
2250
         * Get hash of given string.
 
2251
         *
 
2252
         * @since 2.0.3
 
2253
         *
 
2254
         * @param string $data   Plain text to hash
 
2255
         * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
 
2256
         * @return string Hash of $data
 
2257
         */
 
2258
        function wp_hash( $data, $scheme = 'auth' ) {
 
2259
                $salt = wp_salt( $scheme );
 
2260
 
 
2261
                return hash_hmac( 'md5', $data, $salt );
 
2262
        }
 
2263
endif;
 
2264
 
 
2265
if ( ! function_exists( 'wp_hash_password' ) ) :
 
2266
        /**
 
2267
         * Create a hash (encrypt) of a plain text password.
 
2268
         *
 
2269
         * For integration with other applications, this function can be overwritten to
 
2270
         * instead use the other package password checking algorithm.
 
2271
         *
 
2272
         * @since 2.5.0
 
2273
         *
 
2274
         * @global PasswordHash $wp_hasher PHPass object
 
2275
         *
 
2276
         * @param string $password Plain text user password to hash
 
2277
         * @return string The hash string of the password
 
2278
         */
 
2279
        function wp_hash_password( $password ) {
 
2280
                global $wp_hasher;
 
2281
 
 
2282
                if ( empty( $wp_hasher ) ) {
 
2283
                        require_once( ABSPATH . WPINC . '/class-phpass.php' );
 
2284
                        // By default, use the portable hash from phpass
 
2285
                        $wp_hasher = new PasswordHash( 8, true );
 
2286
                }
 
2287
 
 
2288
                return $wp_hasher->HashPassword( trim( $password ) );
 
2289
        }
 
2290
endif;
 
2291
 
 
2292
if ( ! function_exists( 'wp_check_password' ) ) :
 
2293
        /**
 
2294
         * Checks the plaintext password against the encrypted Password.
 
2295
         *
 
2296
         * Maintains compatibility between old version and the new cookie authentication
 
2297
         * protocol using PHPass library. The $hash parameter is the encrypted password
 
2298
         * and the function compares the plain text password when encrypted similarly
 
2299
         * against the already encrypted password to see if they match.
 
2300
         *
 
2301
         * For integration with other applications, this function can be overwritten to
 
2302
         * instead use the other package password checking algorithm.
 
2303
         *
 
2304
         * @since 2.5.0
 
2305
         *
 
2306
         * @global PasswordHash $wp_hasher PHPass object used for checking the password
 
2307
         *  against the $hash + $password
 
2308
         * @uses PasswordHash::CheckPassword
 
2309
         *
 
2310
         * @param string     $password Plaintext user's password
 
2311
         * @param string     $hash     Hash of the user's password to check against.
 
2312
         * @param string|int $user_id  Optional. User ID.
 
2313
         * @return bool False, if the $password does not match the hashed password
 
2314
         */
 
2315
        function wp_check_password( $password, $hash, $user_id = '' ) {
 
2316
                global $wp_hasher;
 
2317
 
 
2318
                // If the hash is still md5...
 
2319
                if ( strlen( $hash ) <= 32 ) {
 
2320
                        $check = hash_equals( $hash, md5( $password ) );
 
2321
                        if ( $check && $user_id ) {
 
2322
                                // Rehash using new hash.
 
2323
                                wp_set_password( $password, $user_id );
 
2324
                                $hash = wp_hash_password( $password );
 
2325
                        }
 
2326
 
 
2327
                        /**
 
2328
                         * Filters whether the plaintext password matches the encrypted password.
 
2329
                         *
 
2330
                         * @since 2.5.0
 
2331
                         *
 
2332
                         * @param bool       $check    Whether the passwords match.
 
2333
                         * @param string     $password The plaintext password.
 
2334
                         * @param string     $hash     The hashed password.
 
2335
                         * @param string|int $user_id  User ID. Can be empty.
 
2336
                         */
 
2337
                        return apply_filters( 'check_password', $check, $password, $hash, $user_id );
 
2338
                }
 
2339
 
 
2340
                // If the stored hash is longer than an MD5, presume the
 
2341
                // new style phpass portable hash.
 
2342
                if ( empty( $wp_hasher ) ) {
 
2343
                        require_once( ABSPATH . WPINC . '/class-phpass.php' );
 
2344
                        // By default, use the portable hash from phpass
 
2345
                        $wp_hasher = new PasswordHash( 8, true );
 
2346
                }
 
2347
 
 
2348
                $check = $wp_hasher->CheckPassword( $password, $hash );
 
2349
 
 
2350
                /** This filter is documented in wp-includes/pluggable.php */
2259
2351
                return apply_filters( 'check_password', $check, $password, $hash, $user_id );
2260
2352
        }
2261
 
 
2262
 
        // If the stored hash is longer than an MD5, presume the
2263
 
        // new style phpass portable hash.
2264
 
        if ( empty($wp_hasher) ) {
2265
 
                require_once( ABSPATH . WPINC . '/class-phpass.php');
2266
 
                // By default, use the portable hash from phpass
2267
 
                $wp_hasher = new PasswordHash(8, true);
2268
 
        }
2269
 
 
2270
 
        $check = $wp_hasher->CheckPassword($password, $hash);
2271
 
 
2272
 
        /** This filter is documented in wp-includes/pluggable.php */
2273
 
        return apply_filters( 'check_password', $check, $password, $hash, $user_id );
2274
 
}
2275
 
endif;
2276
 
 
2277
 
if ( !function_exists('wp_generate_password') ) :
2278
 
/**
2279
 
 * Generates a random password drawn from the defined set of characters.
2280
 
 *
2281
 
 * @since 2.5.0
2282
 
 *
2283
 
 * @param int  $length              Optional. The length of password to generate. Default 12.
2284
 
 * @param bool $special_chars       Optional. Whether to include standard special characters.
2285
 
 *                                  Default true.
2286
 
 * @param bool $extra_special_chars Optional. Whether to include other special characters.
2287
 
 *                                  Used when generating secret keys and salts. Default false.
2288
 
 * @return string The random password.
2289
 
 */
2290
 
function wp_generate_password( $length = 12, $special_chars = true, $extra_special_chars = false ) {
2291
 
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
2292
 
        if ( $special_chars )
2293
 
                $chars .= '!@#$%^&*()';
2294
 
        if ( $extra_special_chars )
2295
 
                $chars .= '-_ []{}<>~`+=,.;:/?|';
2296
 
 
2297
 
        $password = '';
2298
 
        for ( $i = 0; $i < $length; $i++ ) {
2299
 
                $password .= substr($chars, wp_rand(0, strlen($chars) - 1), 1);
2300
 
        }
2301
 
 
2302
 
        /**
2303
 
         * Filters the randomly-generated password.
2304
 
         *
2305
 
         * @since 3.0.0
2306
 
         *
2307
 
         * @param string $password The generated password.
2308
 
         */
2309
 
        return apply_filters( 'random_password', $password );
2310
 
}
2311
 
endif;
2312
 
 
2313
 
if ( !function_exists('wp_rand') ) :
2314
 
/**
2315
 
 * Generates a random number
2316
 
 *
2317
 
 * @since 2.6.2
2318
 
 * @since 4.4.0 Uses PHP7 random_int() or the random_compat library if available.
2319
 
 *
2320
 
 * @global string $rnd_value
2321
 
 * @staticvar string $seed
2322
 
 * @staticvar bool $external_rand_source_available
2323
 
 *
2324
 
 * @param int $min Lower limit for the generated number
2325
 
 * @param int $max Upper limit for the generated number
2326
 
 * @return int A random number between min and max
2327
 
 */
2328
 
function wp_rand( $min = 0, $max = 0 ) {
2329
 
        global $rnd_value;
2330
 
 
2331
 
        // 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.
2332
 
        $max_random_number = 3000000000 === 2147483647 ? (float) "4294967295" : 4294967295; // 4294967295 = 0xffffffff
2333
 
 
2334
 
        // We only handle Ints, floats are truncated to their integer value.
2335
 
        $min = (int) $min;
2336
 
        $max = (int) $max;
2337
 
 
2338
 
        // Use PHP's CSPRNG, or a compatible method
2339
 
        static $use_random_int_functionality = true;
2340
 
        if ( $use_random_int_functionality ) {
2341
 
                try {
2342
 
                        $_max = ( 0 != $max ) ? $max : $max_random_number;
2343
 
                        // wp_rand() can accept arguments in either order, PHP cannot.
2344
 
                        $_max = max( $min, $_max );
2345
 
                        $_min = min( $min, $_max );
2346
 
                        $val = random_int( $_min, $_max );
2347
 
                        if ( false !== $val ) {
2348
 
                                return absint( $val );
2349
 
                        } else {
2350
 
                                $use_random_int_functionality = false;
2351
 
                        }
2352
 
                } catch ( Error $e ) {
2353
 
                        $use_random_int_functionality = false;
2354
 
                } catch ( Exception $e ) {
2355
 
                        $use_random_int_functionality = false;
2356
 
                }
2357
 
        }
2358
 
 
2359
 
        // Reset $rnd_value after 14 uses
2360
 
        // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
2361
 
        if ( strlen($rnd_value) < 8 ) {
2362
 
                if ( defined( 'WP_SETUP_CONFIG' ) )
2363
 
                        static $seed = '';
2364
 
                else
2365
 
                        $seed = get_transient('random_seed');
2366
 
                $rnd_value = md5( uniqid(microtime() . mt_rand(), true ) . $seed );
2367
 
                $rnd_value .= sha1($rnd_value);
2368
 
                $rnd_value .= sha1($rnd_value . $seed);
2369
 
                $seed = md5($seed . $rnd_value);
2370
 
                if ( ! defined( 'WP_SETUP_CONFIG' ) && ! defined( 'WP_INSTALLING' ) ) {
2371
 
                        set_transient( 'random_seed', $seed );
2372
 
                }
2373
 
        }
2374
 
 
2375
 
        // Take the first 8 digits for our value
2376
 
        $value = substr($rnd_value, 0, 8);
2377
 
 
2378
 
        // Strip the first eight, leaving the remainder for the next call to wp_rand().
2379
 
        $rnd_value = substr($rnd_value, 8);
2380
 
 
2381
 
        $value = abs(hexdec($value));
2382
 
 
2383
 
        // Reduce the value to be within the min - max range
2384
 
        if ( $max != 0 )
2385
 
                $value = $min + ( $max - $min + 1 ) * $value / ( $max_random_number + 1 );
2386
 
 
2387
 
        return abs(intval($value));
2388
 
}
2389
 
endif;
2390
 
 
2391
 
if ( !function_exists('wp_set_password') ) :
2392
 
/**
2393
 
 * Updates the user's password with a new encrypted one.
2394
 
 *
2395
 
 * For integration with other applications, this function can be overwritten to
2396
 
 * instead use the other package password checking algorithm.
2397
 
 *
2398
 
 * Please note: This function should be used sparingly and is really only meant for single-time
2399
 
 * application. Leveraging this improperly in a plugin or theme could result in an endless loop
2400
 
 * of password resets if precautions are not taken to ensure it does not execute on every page load.
2401
 
 *
2402
 
 * @since 2.5.0
2403
 
 *
2404
 
 * @global wpdb $wpdb WordPress database abstraction object.
2405
 
 *
2406
 
 * @param string $password The plaintext new user password
2407
 
 * @param int    $user_id  User ID
2408
 
 */
2409
 
function wp_set_password( $password, $user_id ) {
2410
 
        global $wpdb;
2411
 
 
2412
 
        $hash = wp_hash_password( $password );
2413
 
        $wpdb->update($wpdb->users, array('user_pass' => $hash, 'user_activation_key' => ''), array('ID' => $user_id) );
2414
 
 
2415
 
        wp_cache_delete($user_id, 'users');
2416
 
}
2417
 
endif;
2418
 
 
2419
 
if ( !function_exists( 'get_avatar' ) ) :
2420
 
/**
2421
 
 * Retrieve the avatar `<img>` tag for a user, email address, MD5 hash, comment, or post.
2422
 
 *
2423
 
 * @since 2.5.0
2424
 
 * @since 4.2.0 Optional `$args` parameter added.
2425
 
 *
2426
 
 * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
2427
 
 *                           user email, WP_User object, WP_Post object, or WP_Comment object.
2428
 
 * @param int    $size       Optional. Height and width of the avatar image file in pixels. Default 96.
2429
 
 * @param string $default    Optional. URL for the default image or a default type. Accepts '404'
2430
 
 *                           (return a 404 instead of a default image), 'retro' (8bit), 'monsterid'
2431
 
 *                           (monster), 'wavatar' (cartoon face), 'indenticon' (the "quilt"),
2432
 
 *                           'mystery', 'mm', or 'mysteryman' (The Oyster Man), 'blank' (transparent GIF),
2433
 
 *                           or 'gravatar_default' (the Gravatar logo). Default is the value of the
2434
 
 *                           'avatar_default' option, with a fallback of 'mystery'.
2435
 
 * @param string $alt        Optional. Alternative text to use in &lt;img&gt; tag. Default empty.
2436
 
 * @param array  $args       {
2437
 
 *     Optional. Extra arguments to retrieve the avatar.
2438
 
 *
2439
 
 *     @type int          $height        Display height of the avatar in pixels. Defaults to $size.
2440
 
 *     @type int          $width         Display width of the avatar in pixels. Defaults to $size.
2441
 
 *     @type bool         $force_default Whether to always show the default image, never the Gravatar. Default false.
2442
 
 *     @type string       $rating        What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are
2443
 
 *                                       judged in that order. Default is the value of the 'avatar_rating' option.
2444
 
 *     @type string       $scheme        URL scheme to use. See set_url_scheme() for accepted values.
2445
 
 *                                       Default null.
2446
 
 *     @type array|string $class         Array or string of additional classes to add to the &lt;img&gt; element.
2447
 
 *                                       Default null.
2448
 
 *     @type bool         $force_display Whether to always show the avatar - ignores the show_avatars option.
2449
 
 *                                       Default false.
2450
 
 *     @type string       $extra_attr    HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
2451
 
 * }
2452
 
 * @return false|string `<img>` tag for the user's avatar. False on failure.
2453
 
 */
2454
 
function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '', $args = null ) {
2455
 
        $defaults = array(
2456
 
                // get_avatar_data() args.
2457
 
                'size'          => 96,
2458
 
                'height'        => null,
2459
 
                'width'         => null,
2460
 
                'default'       => get_option( 'avatar_default', 'mystery' ),
2461
 
                'force_default' => false,
2462
 
                'rating'        => get_option( 'avatar_rating' ),
2463
 
                'scheme'        => null,
2464
 
                'alt'           => '',
2465
 
                'class'         => null,
2466
 
                'force_display' => false,
2467
 
                'extra_attr'    => '',
2468
 
        );
2469
 
 
2470
 
        if ( empty( $args ) ) {
2471
 
                $args = array();
2472
 
        }
2473
 
 
2474
 
        $args['size']    = (int) $size;
2475
 
        $args['default'] = $default;
2476
 
        $args['alt']     = $alt;
2477
 
 
2478
 
        $args = wp_parse_args( $args, $defaults );
2479
 
 
2480
 
        if ( empty( $args['height'] ) ) {
2481
 
                $args['height'] = $args['size'];
2482
 
        }
2483
 
        if ( empty( $args['width'] ) ) {
2484
 
                $args['width'] = $args['size'];
2485
 
        }
2486
 
 
2487
 
        if ( is_object( $id_or_email ) && isset( $id_or_email->comment_ID ) ) {
2488
 
                $id_or_email = get_comment( $id_or_email );
2489
 
        }
2490
 
 
2491
 
        /**
2492
 
         * Filters whether to retrieve the avatar URL early.
2493
 
         *
2494
 
         * Passing a non-null value will effectively short-circuit get_avatar(), passing
2495
 
         * the value through the {@see 'get_avatar'} filter and returning early.
2496
 
         *
2497
 
         * @since 4.2.0
2498
 
         *
2499
 
         * @param string $avatar      HTML for the user's avatar. Default null.
2500
 
         * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
2501
 
         *                            user email, WP_User object, WP_Post object, or WP_Comment object.
2502
 
         * @param array  $args        Arguments passed to get_avatar_url(), after processing.
2503
 
         */
2504
 
        $avatar = apply_filters( 'pre_get_avatar', null, $id_or_email, $args );
2505
 
 
2506
 
        if ( ! is_null( $avatar ) ) {
2507
 
                /** This filter is documented in wp-includes/pluggable.php */
 
2353
endif;
 
2354
 
 
2355
if ( ! function_exists( 'wp_generate_password' ) ) :
 
2356
        /**
 
2357
         * Generates a random password drawn from the defined set of characters.
 
2358
         *
 
2359
         * Uses wp_rand() is used to create passwords with far less predictability
 
2360
         * than similar native PHP functions like `rand()` or `mt_rand()`.
 
2361
         *
 
2362
         * @since 2.5.0
 
2363
         *
 
2364
         * @param int  $length              Optional. The length of password to generate. Default 12.
 
2365
         * @param bool $special_chars       Optional. Whether to include standard special characters.
 
2366
         *                                  Default true.
 
2367
         * @param bool $extra_special_chars Optional. Whether to include other special characters.
 
2368
         *                                  Used when generating secret keys and salts. Default false.
 
2369
         * @return string The random password.
 
2370
         */
 
2371
        function wp_generate_password( $length = 12, $special_chars = true, $extra_special_chars = false ) {
 
2372
                $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
 
2373
                if ( $special_chars ) {
 
2374
                        $chars .= '!@#$%^&*()';
 
2375
                }
 
2376
                if ( $extra_special_chars ) {
 
2377
                        $chars .= '-_ []{}<>~`+=,.;:/?|';
 
2378
                }
 
2379
 
 
2380
                $password = '';
 
2381
                for ( $i = 0; $i < $length; $i++ ) {
 
2382
                        $password .= substr( $chars, wp_rand( 0, strlen( $chars ) - 1 ), 1 );
 
2383
                }
 
2384
 
 
2385
                /**
 
2386
                 * Filters the randomly-generated password.
 
2387
                 *
 
2388
                 * @since 3.0.0
 
2389
                 *
 
2390
                 * @param string $password The generated password.
 
2391
                 */
 
2392
                return apply_filters( 'random_password', $password );
 
2393
        }
 
2394
endif;
 
2395
 
 
2396
if ( ! function_exists( 'wp_rand' ) ) :
 
2397
        /**
 
2398
         * Generates a random number.
 
2399
         *
 
2400
         * @since 2.6.2
 
2401
         * @since 4.4.0 Uses PHP7 random_int() or the random_compat library if available.
 
2402
         *
 
2403
         * @global string $rnd_value
 
2404
         * @staticvar string $seed
 
2405
         * @staticvar bool $use_random_int_functionality
 
2406
         *
 
2407
         * @param int $min Lower limit for the generated number
 
2408
         * @param int $max Upper limit for the generated number
 
2409
         * @return int A random number between min and max
 
2410
         */
 
2411
        function wp_rand( $min = 0, $max = 0 ) {
 
2412
                global $rnd_value;
 
2413
 
 
2414
                // 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.
 
2415
                $max_random_number = 3000000000 === 2147483647 ? (float) '4294967295' : 4294967295; // 4294967295 = 0xffffffff
 
2416
 
 
2417
                // We only handle Ints, floats are truncated to their integer value.
 
2418
                $min = (int) $min;
 
2419
                $max = (int) $max;
 
2420
 
 
2421
                // Use PHP's CSPRNG, or a compatible method
 
2422
                static $use_random_int_functionality = true;
 
2423
                if ( $use_random_int_functionality ) {
 
2424
                        try {
 
2425
                                $_max = ( 0 != $max ) ? $max : $max_random_number;
 
2426
                                // wp_rand() can accept arguments in either order, PHP cannot.
 
2427
                                $_max = max( $min, $_max );
 
2428
                                $_min = min( $min, $_max );
 
2429
                                $val  = random_int( $_min, $_max );
 
2430
                                if ( false !== $val ) {
 
2431
                                        return absint( $val );
 
2432
                                } else {
 
2433
                                        $use_random_int_functionality = false;
 
2434
                                }
 
2435
                        } catch ( Error $e ) {
 
2436
                                $use_random_int_functionality = false;
 
2437
                        } catch ( Exception $e ) {
 
2438
                                $use_random_int_functionality = false;
 
2439
                        }
 
2440
                }
 
2441
 
 
2442
                // Reset $rnd_value after 14 uses
 
2443
                // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
 
2444
                if ( strlen( $rnd_value ) < 8 ) {
 
2445
                        if ( defined( 'WP_SETUP_CONFIG' ) ) {
 
2446
                                static $seed = '';
 
2447
                        } else {
 
2448
                                $seed = get_transient( 'random_seed' );
 
2449
                        }
 
2450
                        $rnd_value  = md5( uniqid( microtime() . mt_rand(), true ) . $seed );
 
2451
                        $rnd_value .= sha1( $rnd_value );
 
2452
                        $rnd_value .= sha1( $rnd_value . $seed );
 
2453
                        $seed       = md5( $seed . $rnd_value );
 
2454
                        if ( ! defined( 'WP_SETUP_CONFIG' ) && ! defined( 'WP_INSTALLING' ) ) {
 
2455
                                set_transient( 'random_seed', $seed );
 
2456
                        }
 
2457
                }
 
2458
 
 
2459
                // Take the first 8 digits for our value
 
2460
                $value = substr( $rnd_value, 0, 8 );
 
2461
 
 
2462
                // Strip the first eight, leaving the remainder for the next call to wp_rand().
 
2463
                $rnd_value = substr( $rnd_value, 8 );
 
2464
 
 
2465
                $value = abs( hexdec( $value ) );
 
2466
 
 
2467
                // Reduce the value to be within the min - max range
 
2468
                if ( $max != 0 ) {
 
2469
                        $value = $min + ( $max - $min + 1 ) * $value / ( $max_random_number + 1 );
 
2470
                }
 
2471
 
 
2472
                return abs( intval( $value ) );
 
2473
        }
 
2474
endif;
 
2475
 
 
2476
if ( ! function_exists( 'wp_set_password' ) ) :
 
2477
        /**
 
2478
         * Updates the user's password with a new encrypted one.
 
2479
         *
 
2480
         * For integration with other applications, this function can be overwritten to
 
2481
         * instead use the other package password checking algorithm.
 
2482
         *
 
2483
         * Please note: This function should be used sparingly and is really only meant for single-time
 
2484
         * application. Leveraging this improperly in a plugin or theme could result in an endless loop
 
2485
         * of password resets if precautions are not taken to ensure it does not execute on every page load.
 
2486
         *
 
2487
         * @since 2.5.0
 
2488
         *
 
2489
         * @global wpdb $wpdb WordPress database abstraction object.
 
2490
         *
 
2491
         * @param string $password The plaintext new user password
 
2492
         * @param int    $user_id  User ID
 
2493
         */
 
2494
        function wp_set_password( $password, $user_id ) {
 
2495
                global $wpdb;
 
2496
 
 
2497
                $hash = wp_hash_password( $password );
 
2498
                $wpdb->update(
 
2499
                        $wpdb->users,
 
2500
                        array(
 
2501
                                'user_pass'           => $hash,
 
2502
                                'user_activation_key' => '',
 
2503
                        ),
 
2504
                        array( 'ID' => $user_id )
 
2505
                );
 
2506
 
 
2507
                wp_cache_delete( $user_id, 'users' );
 
2508
        }
 
2509
endif;
 
2510
 
 
2511
if ( ! function_exists( 'get_avatar' ) ) :
 
2512
        /**
 
2513
         * Retrieve the avatar `<img>` tag for a user, email address, MD5 hash, comment, or post.
 
2514
         *
 
2515
         * @since 2.5.0
 
2516
         * @since 4.2.0 Optional `$args` parameter added.
 
2517
         *
 
2518
         * @param mixed $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
 
2519
         *                           user email, WP_User object, WP_Post object, or WP_Comment object.
 
2520
         * @param int    $size       Optional. Height and width of the avatar image file in pixels. Default 96.
 
2521
         * @param string $default    Optional. URL for the default image or a default type. Accepts '404'
 
2522
         *                           (return a 404 instead of a default image), 'retro' (8bit), 'monsterid'
 
2523
         *                           (monster), 'wavatar' (cartoon face), 'indenticon' (the "quilt"),
 
2524
         *                           'mystery', 'mm', or 'mysteryman' (The Oyster Man), 'blank' (transparent GIF),
 
2525
         *                           or 'gravatar_default' (the Gravatar logo). Default is the value of the
 
2526
         *                           'avatar_default' option, with a fallback of 'mystery'.
 
2527
         * @param string $alt        Optional. Alternative text to use in &lt;img&gt; tag. Default empty.
 
2528
         * @param array  $args       {
 
2529
         *     Optional. Extra arguments to retrieve the avatar.
 
2530
         *
 
2531
         *     @type int          $height        Display height of the avatar in pixels. Defaults to $size.
 
2532
         *     @type int          $width         Display width of the avatar in pixels. Defaults to $size.
 
2533
         *     @type bool         $force_default Whether to always show the default image, never the Gravatar. Default false.
 
2534
         *     @type string       $rating        What rating to display avatars up to. Accepts 'G', 'PG', 'R', 'X', and are
 
2535
         *                                       judged in that order. Default is the value of the 'avatar_rating' option.
 
2536
         *     @type string       $scheme        URL scheme to use. See set_url_scheme() for accepted values.
 
2537
         *                                       Default null.
 
2538
         *     @type array|string $class         Array or string of additional classes to add to the &lt;img&gt; element.
 
2539
         *                                       Default null.
 
2540
         *     @type bool         $force_display Whether to always show the avatar - ignores the show_avatars option.
 
2541
         *                                       Default false.
 
2542
         *     @type string       $extra_attr    HTML attributes to insert in the IMG element. Is not sanitized. Default empty.
 
2543
         * }
 
2544
         * @return false|string `<img>` tag for the user's avatar. False on failure.
 
2545
         */
 
2546
        function get_avatar( $id_or_email, $size = 96, $default = '', $alt = '', $args = null ) {
 
2547
                $defaults = array(
 
2548
                        // get_avatar_data() args.
 
2549
                        'size'          => 96,
 
2550
                        'height'        => null,
 
2551
                        'width'         => null,
 
2552
                        'default'       => get_option( 'avatar_default', 'mystery' ),
 
2553
                        'force_default' => false,
 
2554
                        'rating'        => get_option( 'avatar_rating' ),
 
2555
                        'scheme'        => null,
 
2556
                        'alt'           => '',
 
2557
                        'class'         => null,
 
2558
                        'force_display' => false,
 
2559
                        'extra_attr'    => '',
 
2560
                );
 
2561
 
 
2562
                if ( empty( $args ) ) {
 
2563
                        $args = array();
 
2564
                }
 
2565
 
 
2566
                $args['size']    = (int) $size;
 
2567
                $args['default'] = $default;
 
2568
                $args['alt']     = $alt;
 
2569
 
 
2570
                $args = wp_parse_args( $args, $defaults );
 
2571
 
 
2572
                if ( empty( $args['height'] ) ) {
 
2573
                        $args['height'] = $args['size'];
 
2574
                }
 
2575
                if ( empty( $args['width'] ) ) {
 
2576
                        $args['width'] = $args['size'];
 
2577
                }
 
2578
 
 
2579
                if ( is_object( $id_or_email ) && isset( $id_or_email->comment_ID ) ) {
 
2580
                        $id_or_email = get_comment( $id_or_email );
 
2581
                }
 
2582
 
 
2583
                /**
 
2584
                 * Filters whether to retrieve the avatar URL early.
 
2585
                 *
 
2586
                 * Passing a non-null value will effectively short-circuit get_avatar(), passing
 
2587
                 * the value through the {@see 'get_avatar'} filter and returning early.
 
2588
                 *
 
2589
                 * @since 4.2.0
 
2590
                 *
 
2591
                 * @param string $avatar      HTML for the user's avatar. Default null.
 
2592
                 * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
 
2593
                 *                            user email, WP_User object, WP_Post object, or WP_Comment object.
 
2594
                 * @param array  $args        Arguments passed to get_avatar_url(), after processing.
 
2595
                 */
 
2596
                $avatar = apply_filters( 'pre_get_avatar', null, $id_or_email, $args );
 
2597
 
 
2598
                if ( ! is_null( $avatar ) ) {
 
2599
                        /** This filter is documented in wp-includes/pluggable.php */
 
2600
                        return apply_filters( 'get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args );
 
2601
                }
 
2602
 
 
2603
                if ( ! $args['force_display'] && ! get_option( 'show_avatars' ) ) {
 
2604
                        return false;
 
2605
                }
 
2606
 
 
2607
                $url2x = get_avatar_url( $id_or_email, array_merge( $args, array( 'size' => $args['size'] * 2 ) ) );
 
2608
 
 
2609
                $args = get_avatar_data( $id_or_email, $args );
 
2610
 
 
2611
                $url = $args['url'];
 
2612
 
 
2613
                if ( ! $url || is_wp_error( $url ) ) {
 
2614
                        return false;
 
2615
                }
 
2616
 
 
2617
                $class = array( 'avatar', 'avatar-' . (int) $args['size'], 'photo' );
 
2618
 
 
2619
                if ( ! $args['found_avatar'] || $args['force_default'] ) {
 
2620
                        $class[] = 'avatar-default';
 
2621
                }
 
2622
 
 
2623
                if ( $args['class'] ) {
 
2624
                        if ( is_array( $args['class'] ) ) {
 
2625
                                $class = array_merge( $class, $args['class'] );
 
2626
                        } else {
 
2627
                                $class[] = $args['class'];
 
2628
                        }
 
2629
                }
 
2630
 
 
2631
                $avatar = sprintf(
 
2632
                        "<img alt='%s' src='%s' srcset='%s' class='%s' height='%d' width='%d' %s/>",
 
2633
                        esc_attr( $args['alt'] ),
 
2634
                        esc_url( $url ),
 
2635
                        esc_url( $url2x ) . ' 2x',
 
2636
                        esc_attr( join( ' ', $class ) ),
 
2637
                        (int) $args['height'],
 
2638
                        (int) $args['width'],
 
2639
                        $args['extra_attr']
 
2640
                );
 
2641
 
 
2642
                /**
 
2643
                 * Filters the avatar to retrieve.
 
2644
                 *
 
2645
                 * @since 2.5.0
 
2646
                 * @since 4.2.0 The `$args` parameter was added.
 
2647
                 *
 
2648
                 * @param string $avatar      &lt;img&gt; tag for the user's avatar.
 
2649
                 * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
 
2650
                 *                            user email, WP_User object, WP_Post object, or WP_Comment object.
 
2651
                 * @param int    $size        Square avatar width and height in pixels to retrieve.
 
2652
                 * @param string $default     URL for the default image or a default type. Accepts '404', 'retro', 'monsterid',
 
2653
                 *                            'wavatar', 'indenticon','mystery' (or 'mm', or 'mysteryman'), 'blank', or 'gravatar_default'.
 
2654
                 *                            Default is the value of the 'avatar_default' option, with a fallback of 'mystery'.
 
2655
                 * @param string $alt         Alternative text to use in the avatar image tag. Default empty.
 
2656
                 * @param array  $args        Arguments passed to get_avatar_data(), after processing.
 
2657
                 */
2508
2658
                return apply_filters( 'get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args );
2509
2659
        }
2510
 
 
2511
 
        if ( ! $args['force_display'] && ! get_option( 'show_avatars' ) ) {
2512
 
                return false;
2513
 
        }
2514
 
 
2515
 
        $url2x = get_avatar_url( $id_or_email, array_merge( $args, array( 'size' => $args['size'] * 2 ) ) );
2516
 
 
2517
 
        $args = get_avatar_data( $id_or_email, $args );
2518
 
 
2519
 
        $url = $args['url'];
2520
 
 
2521
 
        if ( ! $url || is_wp_error( $url ) ) {
2522
 
                return false;
2523
 
        }
2524
 
 
2525
 
        $class = array( 'avatar', 'avatar-' . (int) $args['size'], 'photo' );
2526
 
 
2527
 
        if ( ! $args['found_avatar'] || $args['force_default'] ) {
2528
 
                $class[] = 'avatar-default';
2529
 
        }
2530
 
 
2531
 
        if ( $args['class'] ) {
2532
 
                if ( is_array( $args['class'] ) ) {
2533
 
                        $class = array_merge( $class, $args['class'] );
2534
 
                } else {
2535
 
                        $class[] = $args['class'];
2536
 
                }
2537
 
        }
2538
 
 
2539
 
        $avatar = sprintf(
2540
 
                "<img alt='%s' src='%s' srcset='%s' class='%s' height='%d' width='%d' %s/>",
2541
 
                esc_attr( $args['alt'] ),
2542
 
                esc_url( $url ),
2543
 
                esc_url( $url2x ) . ' 2x',
2544
 
                esc_attr( join( ' ', $class ) ),
2545
 
                (int) $args['height'],
2546
 
                (int) $args['width'],
2547
 
                $args['extra_attr']
2548
 
        );
2549
 
 
 
2660
endif;
 
2661
 
 
2662
if ( ! function_exists( 'wp_text_diff' ) ) :
2550
2663
        /**
2551
 
         * Filters the avatar to retrieve.
2552
 
         *
2553
 
         * @since 2.5.0
2554
 
         * @since 4.2.0 The `$args` parameter was added.
2555
 
         *
2556
 
         * @param string $avatar      &lt;img&gt; tag for the user's avatar.
2557
 
         * @param mixed  $id_or_email The Gravatar to retrieve. Accepts a user_id, gravatar md5 hash,
2558
 
         *                            user email, WP_User object, WP_Post object, or WP_Comment object.
2559
 
         * @param int    $size        Square avatar width and height in pixels to retrieve.
2560
 
         * @param string $default     URL for the default image or a default type. Accepts '404', 'retro', 'monsterid',
2561
 
         *                            'wavatar', 'indenticon','mystery' (or 'mm', or 'mysteryman'), 'blank', or 'gravatar_default'.
2562
 
         *                            Default is the value of the 'avatar_default' option, with a fallback of 'mystery'.
2563
 
         * @param string $alt         Alternative text to use in the avatar image tag. Default empty.
2564
 
         * @param array  $args        Arguments passed to get_avatar_data(), after processing.
 
2664
         * Displays a human readable HTML representation of the difference between two strings.
 
2665
         *
 
2666
         * The Diff is available for getting the changes between versions. The output is
 
2667
         * HTML, so the primary use is for displaying the changes. If the two strings
 
2668
         * are equivalent, then an empty string will be returned.
 
2669
         *
 
2670
         * The arguments supported and can be changed are listed below.
 
2671
         *
 
2672
         * 'title' : Default is an empty string. Titles the diff in a manner compatible
 
2673
         *      with the output.
 
2674
         * 'title_left' : Default is an empty string. Change the HTML to the left of the
 
2675
         *      title.
 
2676
         * 'title_right' : Default is an empty string. Change the HTML to the right of
 
2677
         *      the title.
 
2678
         *
 
2679
         * @since 2.6.0
 
2680
         *
 
2681
         * @see wp_parse_args() Used to change defaults to user defined settings.
 
2682
         * @uses Text_Diff
 
2683
         * @uses WP_Text_Diff_Renderer_Table
 
2684
         *
 
2685
         * @param string       $left_string  "old" (left) version of string
 
2686
         * @param string       $right_string "new" (right) version of string
 
2687
         * @param string|array $args         Optional. Change 'title', 'title_left', and 'title_right' defaults.
 
2688
         * @return string Empty string if strings are equivalent or HTML with differences.
2565
2689
         */
2566
 
        return apply_filters( 'get_avatar', $avatar, $id_or_email, $args['size'], $args['default'], $args['alt'], $args );
2567
 
}
2568
 
endif;
2569
 
 
2570
 
if ( !function_exists( 'wp_text_diff' ) ) :
2571
 
/**
2572
 
 * Displays a human readable HTML representation of the difference between two strings.
2573
 
 *
2574
 
 * The Diff is available for getting the changes between versions. The output is
2575
 
 * HTML, so the primary use is for displaying the changes. If the two strings
2576
 
 * are equivalent, then an empty string will be returned.
2577
 
 *
2578
 
 * The arguments supported and can be changed are listed below.
2579
 
 *
2580
 
 * 'title' : Default is an empty string. Titles the diff in a manner compatible
2581
 
 *              with the output.
2582
 
 * 'title_left' : Default is an empty string. Change the HTML to the left of the
2583
 
 *              title.
2584
 
 * 'title_right' : Default is an empty string. Change the HTML to the right of
2585
 
 *              the title.
2586
 
 *
2587
 
 * @since 2.6.0
2588
 
 *
2589
 
 * @see wp_parse_args() Used to change defaults to user defined settings.
2590
 
 * @uses Text_Diff
2591
 
 * @uses WP_Text_Diff_Renderer_Table
2592
 
 *
2593
 
 * @param string       $left_string  "old" (left) version of string
2594
 
 * @param string       $right_string "new" (right) version of string
2595
 
 * @param string|array $args         Optional. Change 'title', 'title_left', and 'title_right' defaults.
2596
 
 * @return string Empty string if strings are equivalent or HTML with differences.
2597
 
 */
2598
 
function wp_text_diff( $left_string, $right_string, $args = null ) {
2599
 
        $defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
2600
 
        $args = wp_parse_args( $args, $defaults );
2601
 
 
2602
 
        if ( ! class_exists( 'WP_Text_Diff_Renderer_Table', false ) )
2603
 
                require( ABSPATH . WPINC . '/wp-diff.php' );
2604
 
 
2605
 
        $left_string  = normalize_whitespace($left_string);
2606
 
        $right_string = normalize_whitespace($right_string);
2607
 
 
2608
 
        $left_lines  = explode("\n", $left_string);
2609
 
        $right_lines = explode("\n", $right_string);
2610
 
        $text_diff = new Text_Diff($left_lines, $right_lines);
2611
 
        $renderer  = new WP_Text_Diff_Renderer_Table( $args );
2612
 
        $diff = $renderer->render($text_diff);
2613
 
 
2614
 
        if ( !$diff )
2615
 
                return '';
2616
 
 
2617
 
        $r  = "<table class='diff'>\n";
2618
 
 
2619
 
        if ( ! empty( $args[ 'show_split_view' ] ) ) {
2620
 
                $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
2621
 
        } else {
2622
 
                $r .= "<col class='content' />";
2623
 
        }
2624
 
 
2625
 
        if ( $args['title'] || $args['title_left'] || $args['title_right'] )
2626
 
                $r .= "<thead>";
2627
 
        if ( $args['title'] )
2628
 
                $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
2629
 
        if ( $args['title_left'] || $args['title_right'] ) {
2630
 
                $r .= "<tr class='diff-sub-title'>\n";
2631
 
                $r .= "\t<td></td><th>$args[title_left]</th>\n";
2632
 
                $r .= "\t<td></td><th>$args[title_right]</th>\n";
2633
 
                $r .= "</tr>\n";
2634
 
        }
2635
 
        if ( $args['title'] || $args['title_left'] || $args['title_right'] )
2636
 
                $r .= "</thead>\n";
2637
 
 
2638
 
        $r .= "<tbody>\n$diff\n</tbody>\n";
2639
 
        $r .= "</table>";
2640
 
 
2641
 
        return $r;
2642
 
}
 
2690
        function wp_text_diff( $left_string, $right_string, $args = null ) {
 
2691
                $defaults = array(
 
2692
                        'title'       => '',
 
2693
                        'title_left'  => '',
 
2694
                        'title_right' => '',
 
2695
                );
 
2696
                $args     = wp_parse_args( $args, $defaults );
 
2697
 
 
2698
                if ( ! class_exists( 'WP_Text_Diff_Renderer_Table', false ) ) {
 
2699
                        require( ABSPATH . WPINC . '/wp-diff.php' );
 
2700
                }
 
2701
 
 
2702
                $left_string  = normalize_whitespace( $left_string );
 
2703
                $right_string = normalize_whitespace( $right_string );
 
2704
 
 
2705
                $left_lines  = explode( "\n", $left_string );
 
2706
                $right_lines = explode( "\n", $right_string );
 
2707
                $text_diff   = new Text_Diff( $left_lines, $right_lines );
 
2708
                $renderer    = new WP_Text_Diff_Renderer_Table( $args );
 
2709
                $diff        = $renderer->render( $text_diff );
 
2710
 
 
2711
                if ( ! $diff ) {
 
2712
                        return '';
 
2713
                }
 
2714
 
 
2715
                $r = "<table class='diff'>\n";
 
2716
 
 
2717
                if ( ! empty( $args['show_split_view'] ) ) {
 
2718
                        $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
 
2719
                } else {
 
2720
                        $r .= "<col class='content' />";
 
2721
                }
 
2722
 
 
2723
                if ( $args['title'] || $args['title_left'] || $args['title_right'] ) {
 
2724
                        $r .= '<thead>';
 
2725
                }
 
2726
                if ( $args['title'] ) {
 
2727
                        $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
 
2728
                }
 
2729
                if ( $args['title_left'] || $args['title_right'] ) {
 
2730
                        $r .= "<tr class='diff-sub-title'>\n";
 
2731
                        $r .= "\t<td></td><th>$args[title_left]</th>\n";
 
2732
                        $r .= "\t<td></td><th>$args[title_right]</th>\n";
 
2733
                        $r .= "</tr>\n";
 
2734
                }
 
2735
                if ( $args['title'] || $args['title_left'] || $args['title_right'] ) {
 
2736
                        $r .= "</thead>\n";
 
2737
                }
 
2738
 
 
2739
                $r .= "<tbody>\n$diff\n</tbody>\n";
 
2740
                $r .= '</table>';
 
2741
 
 
2742
                return $r;
 
2743
        }
2643
2744
endif;
2644
2745