WordPress 3.9.2
[autoinstalls/wordpress.git] / wp-includes / pluggable.php
1 <?php
2 /**
3  * These functions can be replaced via plugins. If plugins do not redefine these
4  * functions, then these will be used instead.
5  *
6  * @package WordPress
7  */
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 object $current_user The current user object which holds the user data.
21  *
22  * @param int $id User ID
23  * @param string $name User's username
24  * @return WP_User Current user User object
25  */
26 function wp_set_current_user($id, $name = '') {
27         global $current_user;
28
29         if ( isset( $current_user ) && ( $current_user instanceof WP_User ) && ( $id == $current_user->ID ) )
30                 return $current_user;
31
32         $current_user = new WP_User( $id, $name );
33
34         setup_userdata( $current_user->ID );
35
36         /**
37          * Fires after the current user is set.
38          *
39          * @since 2.0.1
40          */
41         do_action( 'set_current_user' );
42
43         return $current_user;
44 }
45 endif;
46
47 if ( !function_exists('wp_get_current_user') ) :
48 /**
49  * Retrieve the current user object.
50  *
51  * @since 2.0.3
52  *
53  * @return WP_User Current user WP_User object
54  */
55 function wp_get_current_user() {
56         global $current_user;
57
58         get_currentuserinfo();
59
60         return $current_user;
61 }
62 endif;
63
64 if ( !function_exists('get_currentuserinfo') ) :
65 /**
66  * Populate global variables with information about the currently logged in user.
67  *
68  * Will set the current user, if the current user is not set. The current user
69  * will be set to the logged-in person. If no user is logged-in, then it will
70  * set the current user to 0, which is invalid and won't have any permissions.
71  *
72  * @since 0.71
73  *
74  * @uses $current_user Checks if the current user is set
75  * @uses wp_validate_auth_cookie() Retrieves current logged in user.
76  *
77  * @return bool|null False on XML-RPC Request and invalid auth cookie. Null when current user set.
78  */
79 function get_currentuserinfo() {
80         global $current_user;
81
82         if ( ! empty( $current_user ) ) {
83                 if ( $current_user instanceof WP_User )
84                         return;
85
86                 // Upgrade stdClass to WP_User
87                 if ( is_object( $current_user ) && isset( $current_user->ID ) ) {
88                         $cur_id = $current_user->ID;
89                         $current_user = null;
90                         wp_set_current_user( $cur_id );
91                         return;
92                 }
93
94                 // $current_user has a junk value. Force to WP_User with ID 0.
95                 $current_user = null;
96                 wp_set_current_user( 0 );
97                 return false;
98         }
99
100         if ( defined('XMLRPC_REQUEST') && XMLRPC_REQUEST ) {
101                 wp_set_current_user( 0 );
102                 return false;
103         }
104
105         /**
106          * Filter the current user.
107          *
108          * The default filters use this to determine the current user from the
109          * request's cookies, if available.
110          *
111          * Returning a value of false will effectively short-circuit setting
112          * the current user.
113          *
114          * @since 3.9.0
115          *
116          * @param int|bool $user_id User ID if one has been determined, false otherwise.
117          */
118         $user_id = apply_filters( 'determine_current_user', false );
119         if ( ! $user_id ) {
120                 wp_set_current_user( 0 );
121                 return false;
122         }
123
124         wp_set_current_user( $user_id );
125 }
126 endif;
127
128 if ( !function_exists('get_userdata') ) :
129 /**
130  * Retrieve user info by user ID.
131  *
132  * @since 0.71
133  *
134  * @param int $user_id User ID
135  * @return WP_User|bool WP_User object on success, false on failure.
136  */
137 function get_userdata( $user_id ) {
138         return get_user_by( 'id', $user_id );
139 }
140 endif;
141
142 if ( !function_exists('get_user_by') ) :
143 /**
144  * Retrieve user info by a given field
145  *
146  * @since 2.8.0
147  *
148  * @param string $field The field to retrieve the user with. id | slug | email | login
149  * @param int|string $value A value for $field. A user ID, slug, email address, or login name.
150  * @return WP_User|bool WP_User object on success, false on failure.
151  */
152 function get_user_by( $field, $value ) {
153         $userdata = WP_User::get_data_by( $field, $value );
154
155         if ( !$userdata )
156                 return false;
157
158         $user = new WP_User;
159         $user->init( $userdata );
160
161         return $user;
162 }
163 endif;
164
165 if ( !function_exists('cache_users') ) :
166 /**
167  * Retrieve info for user lists to prevent multiple queries by get_userdata()
168  *
169  * @since 3.0.0
170  *
171  * @param array $user_ids User ID numbers list
172  */
173 function cache_users( $user_ids ) {
174         global $wpdb;
175
176         $clean = _get_non_cached_ids( $user_ids, 'users' );
177
178         if ( empty( $clean ) )
179                 return;
180
181         $list = implode( ',', $clean );
182
183         $users = $wpdb->get_results( "SELECT * FROM $wpdb->users WHERE ID IN ($list)" );
184
185         $ids = array();
186         foreach ( $users as $user ) {
187                 update_user_caches( $user );
188                 $ids[] = $user->ID;
189         }
190         update_meta_cache( 'user', $ids );
191 }
192 endif;
193
194 if ( !function_exists( 'wp_mail' ) ) :
195 /**
196  * Send mail, similar to PHP's mail
197  *
198  * A true return value does not automatically mean that the user received the
199  * email successfully. It just only means that the method used was able to
200  * process the request without any errors.
201  *
202  * Using the two 'wp_mail_from' and 'wp_mail_from_name' hooks allow from
203  * creating a from address like 'Name <email@address.com>' when both are set. If
204  * just 'wp_mail_from' is set, then just the email address will be used with no
205  * name.
206  *
207  * The default content type is 'text/plain' which does not allow using HTML.
208  * However, you can set the content type of the email by using the
209  * 'wp_mail_content_type' filter.
210  *
211  * The default charset is based on the charset used on the blog. The charset can
212  * be set using the 'wp_mail_charset' filter.
213  *
214  * @since 1.2.1
215  *
216  * @uses PHPMailer
217  *
218  * @param string|array $to Array or comma-separated list of email addresses to send message.
219  * @param string $subject Email subject
220  * @param string $message Message contents
221  * @param string|array $headers Optional. Additional headers.
222  * @param string|array $attachments Optional. Files to attach.
223  * @return bool Whether the email contents were sent successfully.
224  */
225 function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
226         // Compact the input, apply the filters, and extract them back out
227
228         /**
229          * Filter the wp_mail() arguments.
230          *
231          * @since 2.2.0
232          *
233          * @param array $args A compacted array of wp_mail() arguments, including the "to" email,
234          *                    subject, message, headers, and attachments values.
235          */
236         extract( apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) ) );
237
238         if ( !is_array($attachments) )
239                 $attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
240
241         global $phpmailer;
242
243         // (Re)create it, if it's gone missing
244         if ( !is_object( $phpmailer ) || !is_a( $phpmailer, 'PHPMailer' ) ) {
245                 require_once ABSPATH . WPINC . '/class-phpmailer.php';
246                 require_once ABSPATH . WPINC . '/class-smtp.php';
247                 $phpmailer = new PHPMailer( true );
248         }
249
250         // Headers
251         if ( empty( $headers ) ) {
252                 $headers = array();
253         } else {
254                 if ( !is_array( $headers ) ) {
255                         // Explode the headers out, so this function can take both
256                         // string headers and an array of headers.
257                         $tempheaders = explode( "\n", str_replace( "\r\n", "\n", $headers ) );
258                 } else {
259                         $tempheaders = $headers;
260                 }
261                 $headers = array();
262                 $cc = array();
263                 $bcc = array();
264
265                 // If it's actually got contents
266                 if ( !empty( $tempheaders ) ) {
267                         // Iterate through the raw headers
268                         foreach ( (array) $tempheaders as $header ) {
269                                 if ( strpos($header, ':') === false ) {
270                                         if ( false !== stripos( $header, 'boundary=' ) ) {
271                                                 $parts = preg_split('/boundary=/i', trim( $header ) );
272                                                 $boundary = trim( str_replace( array( "'", '"' ), '', $parts[1] ) );
273                                         }
274                                         continue;
275                                 }
276                                 // Explode them out
277                                 list( $name, $content ) = explode( ':', trim( $header ), 2 );
278
279                                 // Cleanup crew
280                                 $name    = trim( $name    );
281                                 $content = trim( $content );
282
283                                 switch ( strtolower( $name ) ) {
284                                         // Mainly for legacy -- process a From: header if it's there
285                                         case 'from':
286                                                 if ( strpos($content, '<' ) !== false ) {
287                                                         // So... making my life hard again?
288                                                         $from_name = substr( $content, 0, strpos( $content, '<' ) - 1 );
289                                                         $from_name = str_replace( '"', '', $from_name );
290                                                         $from_name = trim( $from_name );
291
292                                                         $from_email = substr( $content, strpos( $content, '<' ) + 1 );
293                                                         $from_email = str_replace( '>', '', $from_email );
294                                                         $from_email = trim( $from_email );
295                                                 } else {
296                                                         $from_email = trim( $content );
297                                                 }
298                                                 break;
299                                         case 'content-type':
300                                                 if ( strpos( $content, ';' ) !== false ) {
301                                                         list( $type, $charset ) = explode( ';', $content );
302                                                         $content_type = trim( $type );
303                                                         if ( false !== stripos( $charset, 'charset=' ) ) {
304                                                                 $charset = trim( str_replace( array( 'charset=', '"' ), '', $charset ) );
305                                                         } elseif ( false !== stripos( $charset, 'boundary=' ) ) {
306                                                                 $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '"' ), '', $charset ) );
307                                                                 $charset = '';
308                                                         }
309                                                 } else {
310                                                         $content_type = trim( $content );
311                                                 }
312                                                 break;
313                                         case 'cc':
314                                                 $cc = array_merge( (array) $cc, explode( ',', $content ) );
315                                                 break;
316                                         case 'bcc':
317                                                 $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
318                                                 break;
319                                         default:
320                                                 // Add it to our grand headers array
321                                                 $headers[trim( $name )] = trim( $content );
322                                                 break;
323                                 }
324                         }
325                 }
326         }
327
328         // Empty out the values that may be set
329         $phpmailer->ClearAllRecipients();
330         $phpmailer->ClearAttachments();
331         $phpmailer->ClearCustomHeaders();
332         $phpmailer->ClearReplyTos();
333
334         // From email and name
335         // If we don't have a name from the input headers
336         if ( !isset( $from_name ) )
337                 $from_name = 'WordPress';
338
339         /* If we don't have an email from the input headers default to wordpress@$sitename
340          * Some hosts will block outgoing mail from this address if it doesn't exist but
341          * there's no easy alternative. Defaulting to admin_email might appear to be another
342          * option but some hosts may refuse to relay mail from an unknown domain. See
343          * http://trac.wordpress.org/ticket/5007.
344          */
345
346         if ( !isset( $from_email ) ) {
347                 // Get the site domain and get rid of www.
348                 $sitename = strtolower( $_SERVER['SERVER_NAME'] );
349                 if ( substr( $sitename, 0, 4 ) == 'www.' ) {
350                         $sitename = substr( $sitename, 4 );
351                 }
352
353                 $from_email = 'wordpress@' . $sitename;
354         }
355
356         /**
357          * Filter the email address to send from.
358          *
359          * @since 2.2.0
360          *
361          * @param string $from_email Email address to send from.
362          */
363         $phpmailer->From = apply_filters( 'wp_mail_from', $from_email );
364
365         /**
366          * Filter the name to associate with the "from" email address.
367          *
368          * @since 2.3.0
369          *
370          * @param string $from_name Name associated with the "from" email address.
371          */
372         $phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name );
373
374         // Set destination addresses
375         if ( !is_array( $to ) )
376                 $to = explode( ',', $to );
377
378         foreach ( (array) $to as $recipient ) {
379                 try {
380                         // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
381                         $recipient_name = '';
382                         if( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {
383                                 if ( count( $matches ) == 3 ) {
384                                         $recipient_name = $matches[1];
385                                         $recipient = $matches[2];
386                                 }
387                         }
388                         $phpmailer->AddAddress( $recipient, $recipient_name);
389                 } catch ( phpmailerException $e ) {
390                         continue;
391                 }
392         }
393
394         // Set mail's subject and body
395         $phpmailer->Subject = $subject;
396         $phpmailer->Body    = $message;
397
398         // Add any CC and BCC recipients
399         if ( !empty( $cc ) ) {
400                 foreach ( (array) $cc as $recipient ) {
401                         try {
402                                 // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
403                                 $recipient_name = '';
404                                 if( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {
405                                         if ( count( $matches ) == 3 ) {
406                                                 $recipient_name = $matches[1];
407                                                 $recipient = $matches[2];
408                                         }
409                                 }
410                                 $phpmailer->AddCc( $recipient, $recipient_name );
411                         } catch ( phpmailerException $e ) {
412                                 continue;
413                         }
414                 }
415         }
416
417         if ( !empty( $bcc ) ) {
418                 foreach ( (array) $bcc as $recipient) {
419                         try {
420                                 // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
421                                 $recipient_name = '';
422                                 if( preg_match( '/(.*)<(.+)>/', $recipient, $matches ) ) {
423                                         if ( count( $matches ) == 3 ) {
424                                                 $recipient_name = $matches[1];
425                                                 $recipient = $matches[2];
426                                         }
427                                 }
428                                 $phpmailer->AddBcc( $recipient, $recipient_name );
429                         } catch ( phpmailerException $e ) {
430                                 continue;
431                         }
432                 }
433         }
434
435         // Set to use PHP's mail()
436         $phpmailer->IsMail();
437
438         // Set Content-Type and charset
439         // If we don't have a content-type from the input headers
440         if ( !isset( $content_type ) )
441                 $content_type = 'text/plain';
442
443         /**
444          * Filter the wp_mail() content type.
445          *
446          * @since 2.3.0
447          *
448          * @param string $content_type Default wp_mail() content type.
449          */
450         $content_type = apply_filters( 'wp_mail_content_type', $content_type );
451
452         $phpmailer->ContentType = $content_type;
453
454         // Set whether it's plaintext, depending on $content_type
455         if ( 'text/html' == $content_type )
456                 $phpmailer->IsHTML( true );
457
458         // If we don't have a charset from the input headers
459         if ( !isset( $charset ) )
460                 $charset = get_bloginfo( 'charset' );
461
462         // Set the content-type and charset
463
464         /**
465          * Filter the default wp_mail() charset.
466          *
467          * @since 2.3.0
468          *
469          * @param string $charset Default email charset.
470          */
471         $phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
472
473         // Set custom headers
474         if ( !empty( $headers ) ) {
475                 foreach( (array) $headers as $name => $content ) {
476                         $phpmailer->AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
477                 }
478
479                 if ( false !== stripos( $content_type, 'multipart' ) && ! empty($boundary) )
480                         $phpmailer->AddCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
481         }
482
483         if ( !empty( $attachments ) ) {
484                 foreach ( $attachments as $attachment ) {
485                         try {
486                                 $phpmailer->AddAttachment($attachment);
487                         } catch ( phpmailerException $e ) {
488                                 continue;
489                         }
490                 }
491         }
492
493         /**
494          * Fires after PHPMailer is initialized.
495          *
496          * @since 2.2.0
497          *
498          * @param PHPMailer &$phpmailer The PHPMailer instance, passed by reference.
499          */
500         do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
501
502         // Send!
503         try {
504                 return $phpmailer->Send();
505         } catch ( phpmailerException $e ) {
506                 return false;
507         }
508 }
509 endif;
510
511 if ( !function_exists('wp_authenticate') ) :
512 /**
513  * Checks a user's login information and logs them in if it checks out.
514  *
515  * @since 2.5.0
516  *
517  * @param string $username User's username
518  * @param string $password User's password
519  * @return WP_User|WP_Error WP_User object if login successful, otherwise WP_Error object.
520  */
521 function wp_authenticate($username, $password) {
522         $username = sanitize_user($username);
523         $password = trim($password);
524
525         /**
526          * Filter the user to authenticate.
527          *
528          * If a non-null value is passed, the filter will effectively short-circuit
529          * authentication, returning an error instead.
530          *
531          * @since 2.8.0
532          *
533          * @param null|WP_User $user     User to authenticate.
534          * @param string       $username User login.
535          * @param string       $password User password
536          */
537         $user = apply_filters( 'authenticate', null, $username, $password );
538
539         if ( $user == null ) {
540                 // TODO what should the error message be? (Or would these even happen?)
541                 // Only needed if all authentication handlers fail to return anything.
542                 $user = new WP_Error('authentication_failed', __('<strong>ERROR</strong>: Invalid username or incorrect password.'));
543         }
544
545         $ignore_codes = array('empty_username', 'empty_password');
546
547         if (is_wp_error($user) && !in_array($user->get_error_code(), $ignore_codes) ) {
548                 /**
549                  * Fires after a user login has failed.
550                  *
551                  * @since 2.5.0
552                  *
553                  * @param string $username User login.
554                  */
555                 do_action( 'wp_login_failed', $username );
556         }
557
558         return $user;
559 }
560 endif;
561
562 if ( !function_exists('wp_logout') ) :
563 /**
564  * Log the current user out.
565  *
566  * @since 2.5.0
567  */
568 function wp_logout() {
569         wp_clear_auth_cookie();
570
571         /**
572          * Fires after a user is logged-out.
573          *
574          * @since 1.5.0
575          */
576         do_action( 'wp_logout' );
577 }
578 endif;
579
580 if ( !function_exists('wp_validate_auth_cookie') ) :
581 /**
582  * Validates authentication cookie.
583  *
584  * The checks include making sure that the authentication cookie is set and
585  * pulling in the contents (if $cookie is not used).
586  *
587  * Makes sure the cookie is not expired. Verifies the hash in cookie is what is
588  * should be and compares the two.
589  *
590  * @since 2.5.0
591  *
592  * @param string $cookie Optional. If used, will validate contents instead of cookie's
593  * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
594  * @return bool|int False if invalid cookie, User ID if valid.
595  */
596 function wp_validate_auth_cookie($cookie = '', $scheme = '') {
597         if ( ! $cookie_elements = wp_parse_auth_cookie($cookie, $scheme) ) {
598                 /**
599                  * Fires if an authentication cookie is malformed.
600                  *
601                  * @since 2.7.0
602                  *
603                  * @param string $cookie Malformed auth cookie.
604                  * @param string $scheme Authentication scheme. Values include 'auth', 'secure_auth',
605                  *                       or 'logged_in'.
606                  */
607                 do_action( 'auth_cookie_malformed', $cookie, $scheme );
608                 return false;
609         }
610
611         extract($cookie_elements, EXTR_OVERWRITE);
612
613         $expired = $expiration;
614
615         // Allow a grace period for POST and AJAX requests
616         if ( defined('DOING_AJAX') || 'POST' == $_SERVER['REQUEST_METHOD'] )
617                 $expired += HOUR_IN_SECONDS;
618
619         // Quick check to see if an honest cookie has expired
620         if ( $expired < time() ) {
621                 /**
622                  * Fires once an authentication cookie has expired.
623                  *
624                  * @since 2.7.0
625                  *
626                  * @param array $cookie_elements An array of data for the authentication cookie.
627                  */
628                 do_action( 'auth_cookie_expired', $cookie_elements );
629                 return false;
630         }
631
632         $user = get_user_by('login', $username);
633         if ( ! $user ) {
634                 /**
635                  * Fires if a bad username is entered in the user authentication process.
636                  *
637                  * @since 2.7.0
638                  *
639                  * @param array $cookie_elements An array of data for the authentication cookie.
640                  */
641                 do_action( 'auth_cookie_bad_username', $cookie_elements );
642                 return false;
643         }
644
645         $pass_frag = substr($user->user_pass, 8, 4);
646
647         $key = wp_hash($username . $pass_frag . '|' . $expiration, $scheme);
648         $hash = hash_hmac('md5', $username . '|' . $expiration, $key);
649
650         if ( ! hash_equals( $hash, $hmac ) ) {
651                 /**
652                  * Fires if a bad authentication cookie hash is encountered.
653                  *
654                  * @since 2.7.0
655                  *
656                  * @param array $cookie_elements An array of data for the authentication cookie.
657                  */
658                 do_action( 'auth_cookie_bad_hash', $cookie_elements );
659                 return false;
660         }
661
662         if ( $expiration < time() ) // AJAX/POST grace period set above
663                 $GLOBALS['login_grace_period'] = 1;
664
665         /**
666          * Fires once an authentication cookie has been validated.
667          *
668          * @since 2.7.0
669          *
670          * @param array   $cookie_elements An array of data for the authentication cookie.
671          * @param WP_User $user            User object.
672          */
673         do_action( 'auth_cookie_valid', $cookie_elements, $user );
674
675         return $user->ID;
676 }
677 endif;
678
679 if ( !function_exists('wp_generate_auth_cookie') ) :
680 /**
681  * Generate authentication cookie contents.
682  *
683  * @since 2.5.0
684  *
685  * @param int $user_id User ID
686  * @param int $expiration Cookie expiration in seconds
687  * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
688  * @return string Authentication cookie contents
689  */
690 function wp_generate_auth_cookie($user_id, $expiration, $scheme = 'auth') {
691         $user = get_userdata($user_id);
692
693         $pass_frag = substr($user->user_pass, 8, 4);
694
695         $key = wp_hash($user->user_login . $pass_frag . '|' . $expiration, $scheme);
696         $hash = hash_hmac('md5', $user->user_login . '|' . $expiration, $key);
697
698         $cookie = $user->user_login . '|' . $expiration . '|' . $hash;
699
700         /**
701          * Filter the authentication cookie.
702          *
703          * @since 2.5.0
704          *
705          * @param string $cookie     Authentication cookie.
706          * @param int    $user_id    User ID.
707          * @param int    $expiration Authentication cookie expiration in seconds.
708          * @param string $scheme     Cookie scheme used. Accepts 'auth', 'secure_auth', or 'logged_in'.
709          */
710         return apply_filters( 'auth_cookie', $cookie, $user_id, $expiration, $scheme );
711 }
712 endif;
713
714 if ( !function_exists('wp_parse_auth_cookie') ) :
715 /**
716  * Parse a cookie into its components
717  *
718  * @since 2.7.0
719  *
720  * @param string $cookie
721  * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
722  * @return array Authentication cookie components
723  */
724 function wp_parse_auth_cookie($cookie = '', $scheme = '') {
725         if ( empty($cookie) ) {
726                 switch ($scheme){
727                         case 'auth':
728                                 $cookie_name = AUTH_COOKIE;
729                                 break;
730                         case 'secure_auth':
731                                 $cookie_name = SECURE_AUTH_COOKIE;
732                                 break;
733                         case "logged_in":
734                                 $cookie_name = LOGGED_IN_COOKIE;
735                                 break;
736                         default:
737                                 if ( is_ssl() ) {
738                                         $cookie_name = SECURE_AUTH_COOKIE;
739                                         $scheme = 'secure_auth';
740                                 } else {
741                                         $cookie_name = AUTH_COOKIE;
742                                         $scheme = 'auth';
743                                 }
744             }
745
746                 if ( empty($_COOKIE[$cookie_name]) )
747                         return false;
748                 $cookie = $_COOKIE[$cookie_name];
749         }
750
751         $cookie_elements = explode('|', $cookie);
752         if ( count($cookie_elements) != 3 )
753                 return false;
754
755         list($username, $expiration, $hmac) = $cookie_elements;
756
757         return compact('username', 'expiration', 'hmac', 'scheme');
758 }
759 endif;
760
761 if ( !function_exists('wp_set_auth_cookie') ) :
762 /**
763  * Sets the authentication cookies based on user ID.
764  *
765  * The $remember parameter increases the time that the cookie will be kept. The
766  * default the cookie is kept without remembering is two days. When $remember is
767  * set, the cookies will be kept for 14 days or two weeks.
768  *
769  * @since 2.5.0
770  *
771  * @param int $user_id User ID
772  * @param bool $remember Whether to remember the user
773  */
774 function wp_set_auth_cookie($user_id, $remember = false, $secure = '') {
775         if ( $remember ) {
776                 /**
777                  * Filter the duration of the authentication cookie expiration period.
778                  *
779                  * @since 2.8.0
780                  *
781                  * @param int  $length   Duration of the expiration period in seconds.
782                  * @param int  $user_id  User ID.
783                  * @param bool $remember Whether to remember the user login. Default false.
784                  */
785                 $expiration = time() + apply_filters( 'auth_cookie_expiration', 14 * DAY_IN_SECONDS, $user_id, $remember );
786
787                 /*
788                  * Ensure the browser will continue to send the cookie after the expiration time is reached.
789                  * Needed for the login grace period in wp_validate_auth_cookie().
790                  */
791                 $expire = $expiration + ( 12 * HOUR_IN_SECONDS );
792         } else {
793                 /** This filter is documented in wp-includes/pluggable.php */
794                 $expiration = time() + apply_filters( 'auth_cookie_expiration', 2 * DAY_IN_SECONDS, $user_id, $remember );
795                 $expire = 0;
796         }
797
798         if ( '' === $secure )
799                 $secure = is_ssl();
800
801         /**
802          * Filter whether the connection is secure.
803          *
804          * @since 3.1.0
805          *
806          * @param bool $secure  Whether the connection is secure.
807          * @param int  $user_id User ID.
808          */
809         $secure = apply_filters( 'secure_auth_cookie', $secure, $user_id );
810
811         /**
812          * Filter whether to use a secure cookie when logged-in.
813          *
814          * @since 3.1.0
815          *
816          * @param bool $cookie  Whether to use a secure cookie when logged-in.
817          * @param int  $user_id User ID.
818          * @param bool $secure  Whether the connection is secure.
819          */
820         $secure_logged_in_cookie = apply_filters( 'secure_logged_in_cookie', false, $user_id, $secure );
821
822         if ( $secure ) {
823                 $auth_cookie_name = SECURE_AUTH_COOKIE;
824                 $scheme = 'secure_auth';
825         } else {
826                 $auth_cookie_name = AUTH_COOKIE;
827                 $scheme = 'auth';
828         }
829
830         $auth_cookie = wp_generate_auth_cookie($user_id, $expiration, $scheme);
831         $logged_in_cookie = wp_generate_auth_cookie($user_id, $expiration, 'logged_in');
832
833         /**
834          * Fires immediately before the authentication cookie is set.
835          *
836          * @since 2.5.0
837          *
838          * @param string $auth_cookie Authentication cookie.
839          * @param int    $expire      Login grace period in seconds. Default 43,200 seconds, or 12 hours.
840          * @param int    $expiration  Duration in seconds the authentication cookie should be valid.
841          *                            Default 1,209,600 seconds, or 14 days.
842          * @param int    $user_id     User ID.
843          * @param string $scheme      Authentication scheme. Values include 'auth', 'secure_auth', or 'logged_in'.
844          */
845         do_action( 'set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme );
846
847         /**
848          * Fires immediately before the secure authentication cookie is set.
849          *
850          * @since 2.6.0
851          *
852          * @param string $logged_in_cookie The logged-in cookie.
853          * @param int    $expire           Login grace period in seconds. Default 43,200 seconds, or 12 hours.
854          * @param int    $expiration       Duration in seconds the authentication cookie should be valid.
855          *                                 Default 1,209,600 seconds, or 14 days.
856          * @param int    $user_id          User ID.
857          * @param string $scheme           Authentication scheme. Default 'logged_in'.
858          */
859         do_action( 'set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in' );
860
861         setcookie($auth_cookie_name, $auth_cookie, $expire, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);
862         setcookie($auth_cookie_name, $auth_cookie, $expire, ADMIN_COOKIE_PATH, COOKIE_DOMAIN, $secure, true);
863         setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);
864         if ( COOKIEPATH != SITECOOKIEPATH )
865                 setcookie(LOGGED_IN_COOKIE, $logged_in_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_logged_in_cookie, true);
866 }
867 endif;
868
869 if ( !function_exists('wp_clear_auth_cookie') ) :
870 /**
871  * Removes all of the cookies associated with authentication.
872  *
873  * @since 2.5.0
874  */
875 function wp_clear_auth_cookie() {
876         /**
877          * Fires just before the authentication cookies are cleared.
878          *
879          * @since 2.7.0
880          */
881         do_action( 'clear_auth_cookie' );
882
883         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, ADMIN_COOKIE_PATH,   COOKIE_DOMAIN );
884         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, ADMIN_COOKIE_PATH,   COOKIE_DOMAIN );
885         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN );
886         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, PLUGINS_COOKIE_PATH, COOKIE_DOMAIN );
887         setcookie( LOGGED_IN_COOKIE,   ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,          COOKIE_DOMAIN );
888         setcookie( LOGGED_IN_COOKIE,   ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH,      COOKIE_DOMAIN );
889
890         // Old cookies
891         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
892         setcookie( AUTH_COOKIE,        ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
893         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
894         setcookie( SECURE_AUTH_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
895
896         // Even older cookies
897         setcookie( USER_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
898         setcookie( PASS_COOKIE, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH,     COOKIE_DOMAIN );
899         setcookie( USER_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
900         setcookie( PASS_COOKIE, ' ', time() - YEAR_IN_SECONDS, SITECOOKIEPATH, COOKIE_DOMAIN );
901 }
902 endif;
903
904 if ( !function_exists('is_user_logged_in') ) :
905 /**
906  * Checks if the current visitor is a logged in user.
907  *
908  * @since 2.0.0
909  *
910  * @return bool True if user is logged in, false if not logged in.
911  */
912 function is_user_logged_in() {
913         $user = wp_get_current_user();
914
915         if ( ! $user->exists() )
916                 return false;
917
918         return true;
919 }
920 endif;
921
922 if ( !function_exists('auth_redirect') ) :
923 /**
924  * Checks if a user is logged in, if not it redirects them to the login page.
925  *
926  * @since 1.5.0
927  */
928 function auth_redirect() {
929         // Checks if a user is logged in, if not redirects them to the login page
930
931         $secure = ( is_ssl() || force_ssl_admin() );
932
933         /**
934          * Filter whether to use a secure authentication redirect.
935          *
936          * @since 3.1.0
937          *
938          * @param bool $secure Whether to use a secure authentication redirect. Default false.
939          */
940         $secure = apply_filters( 'secure_auth_redirect', $secure );
941
942         // If https is required and request is http, redirect
943         if ( $secure && !is_ssl() && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
944                 if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
945                         wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
946                         exit();
947                 } else {
948                         wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
949                         exit();
950                 }
951         }
952
953         if ( is_user_admin() ) {
954                 $scheme = 'logged_in';
955         } else {
956                 /**
957                  * Filter the authentication redirect scheme.
958                  *
959                  * @since 2.9.0
960                  *
961                  * @param string $scheme Authentication redirect scheme. Default empty.
962                  */
963                 $scheme = apply_filters( 'auth_redirect_scheme', '' );
964         }
965
966         if ( $user_id = wp_validate_auth_cookie( '',  $scheme) ) {
967                 /**
968                  * Fires before the authentication redirect.
969                  *
970                  * @since 2.8.0
971                  *
972                  * @param int $user_id User ID.
973                  */
974                 do_action( 'auth_redirect', $user_id );
975
976                 // If the user wants ssl but the session is not ssl, redirect.
977                 if ( !$secure && get_user_option('use_ssl', $user_id) && false !== strpos($_SERVER['REQUEST_URI'], 'wp-admin') ) {
978                         if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
979                                 wp_redirect( set_url_scheme( $_SERVER['REQUEST_URI'], 'https' ) );
980                                 exit();
981                         } else {
982                                 wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
983                                 exit();
984                         }
985                 }
986
987                 return;  // The cookie is good so we're done
988         }
989
990         // The cookie is no good so force login
991         nocache_headers();
992
993         $redirect = ( strpos( $_SERVER['REQUEST_URI'], '/options.php' ) && wp_get_referer() ) ? wp_get_referer() : set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
994
995         $login_url = wp_login_url($redirect, true);
996
997         wp_redirect($login_url);
998         exit();
999 }
1000 endif;
1001
1002 if ( !function_exists('check_admin_referer') ) :
1003 /**
1004  * Makes sure that a user was referred from another admin page.
1005  *
1006  * To avoid security exploits.
1007  *
1008  * @since 1.2.0
1009  *
1010  * @param string $action Action nonce
1011  * @param string $query_arg where to look for nonce in $_REQUEST (since 2.5)
1012  */
1013 function check_admin_referer($action = -1, $query_arg = '_wpnonce') {
1014         if ( -1 == $action )
1015                 _doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2' );
1016
1017         $adminurl = strtolower(admin_url());
1018         $referer = strtolower(wp_get_referer());
1019         $result = isset($_REQUEST[$query_arg]) ? wp_verify_nonce($_REQUEST[$query_arg], $action) : false;
1020         if ( !$result && !(-1 == $action && strpos($referer, $adminurl) === 0) ) {
1021                 wp_nonce_ays($action);
1022                 die();
1023         }
1024
1025         /**
1026          * Fires once the admin request has been validated or not.
1027          *
1028          * @since 1.5.1
1029          *
1030          * @param string $action The nonce action.
1031          * @param bool   $result Whether the admin request nonce was validated.
1032          */
1033         do_action( 'check_admin_referer', $action, $result );
1034         return $result;
1035 }
1036 endif;
1037
1038 if ( !function_exists('check_ajax_referer') ) :
1039 /**
1040  * Verifies the AJAX request to prevent processing requests external of the blog.
1041  *
1042  * @since 2.0.3
1043  *
1044  * @param string $action Action nonce
1045  * @param string $query_arg where to look for nonce in $_REQUEST (since 2.5)
1046  */
1047 function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
1048         $nonce = '';
1049
1050         if ( $query_arg && isset( $_REQUEST[ $query_arg ] ) )
1051                 $nonce = $_REQUEST[ $query_arg ];
1052         elseif ( isset( $_REQUEST['_ajax_nonce'] ) )
1053                 $nonce = $_REQUEST['_ajax_nonce'];
1054         elseif ( isset( $_REQUEST['_wpnonce'] ) )
1055                 $nonce = $_REQUEST['_wpnonce'];
1056
1057         $result = wp_verify_nonce( $nonce, $action );
1058
1059         if ( $die && false == $result ) {
1060                 if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
1061                         wp_die( -1 );
1062                 else
1063                         die( '-1' );
1064         }
1065
1066         /**
1067          * Fires once the AJAX request has been validated or not.
1068          *
1069          * @since 2.1.0
1070          *
1071          * @param string $action The AJAX nonce action.
1072          * @param bool   $result Whether the AJAX request nonce was validated.
1073          */
1074         do_action( 'check_ajax_referer', $action, $result );
1075
1076         return $result;
1077 }
1078 endif;
1079
1080 if ( !function_exists('wp_redirect') ) :
1081 /**
1082  * Redirects to another page.
1083  *
1084  * @since 1.5.1
1085  *
1086  * @param string $location The path to redirect to.
1087  * @param int $status Status code to use.
1088  * @return bool False if $location is not provided, true otherwise.
1089  */
1090 function wp_redirect($location, $status = 302) {
1091         global $is_IIS;
1092
1093         /**
1094          * Filter the redirect location.
1095          *
1096          * @since 2.1.0
1097          *
1098          * @param string $location The path to redirect to.
1099          * @param int    $status   Status code to use.
1100          */
1101         $location = apply_filters( 'wp_redirect', $location, $status );
1102
1103         /**
1104          * Filter the redirect status code.
1105          *
1106          * @since 2.3.0
1107          *
1108          * @param int    $status   Status code to use.
1109          * @param string $location The path to redirect to.
1110          */
1111         $status = apply_filters( 'wp_redirect_status', $status, $location );
1112
1113         if ( ! $location )
1114                 return false;
1115
1116         $location = wp_sanitize_redirect($location);
1117
1118         if ( !$is_IIS && php_sapi_name() != 'cgi-fcgi' )
1119                 status_header($status); // This causes problems on IIS and some FastCGI setups
1120
1121         header("Location: $location", true, $status);
1122
1123         return true;
1124 }
1125 endif;
1126
1127 if ( !function_exists('wp_sanitize_redirect') ) :
1128 /**
1129  * Sanitizes a URL for use in a redirect.
1130  *
1131  * @since 2.3.0
1132  *
1133  * @return string redirect-sanitized URL
1134  **/
1135 function wp_sanitize_redirect($location) {
1136         $location = preg_replace('|[^a-z0-9-~+_.?#=&;,/:%!]|i', '', $location);
1137         $location = wp_kses_no_null($location);
1138
1139         // remove %0d and %0a from location
1140         $strip = array('%0d', '%0a', '%0D', '%0A');
1141         $location = _deep_replace($strip, $location);
1142         return $location;
1143 }
1144 endif;
1145
1146 if ( !function_exists('wp_safe_redirect') ) :
1147 /**
1148  * Performs a safe (local) redirect, using wp_redirect().
1149  *
1150  * Checks whether the $location is using an allowed host, if it has an absolute
1151  * path. A plugin can therefore set or remove allowed host(s) to or from the
1152  * list.
1153  *
1154  * If the host is not allowed, then the redirect is to wp-admin on the siteurl
1155  * instead. This prevents malicious redirects which redirect to another host,
1156  * but only used in a few places.
1157  *
1158  * @since 2.3.0
1159  *
1160  * @uses wp_validate_redirect() To validate the redirect is to an allowed host.
1161  *
1162  * @return void Does not return anything
1163  **/
1164 function wp_safe_redirect($location, $status = 302) {
1165
1166         // Need to look at the URL the way it will end up in wp_redirect()
1167         $location = wp_sanitize_redirect($location);
1168
1169         $location = wp_validate_redirect($location, admin_url());
1170
1171         wp_redirect($location, $status);
1172 }
1173 endif;
1174
1175 if ( !function_exists('wp_validate_redirect') ) :
1176 /**
1177  * Validates a URL for use in a redirect.
1178  *
1179  * Checks whether the $location is using an allowed host, if it has an absolute
1180  * path. A plugin can therefore set or remove allowed host(s) to or from the
1181  * list.
1182  *
1183  * If the host is not allowed, then the redirect is to $default supplied
1184  *
1185  * @since 2.8.1
1186  *
1187  * @param string $location The redirect to validate
1188  * @param string $default The value to return if $location is not allowed
1189  * @return string redirect-sanitized URL
1190  **/
1191 function wp_validate_redirect($location, $default = '') {
1192         $location = trim( $location );
1193         // browsers will assume 'http' is your protocol, and will obey a redirect to a URL starting with '//'
1194         if ( substr($location, 0, 2) == '//' )
1195                 $location = 'http:' . $location;
1196
1197         // In php 5 parse_url may fail if the URL query part contains http://, bug #38143
1198         $test = ( $cut = strpos($location, '?') ) ? substr( $location, 0, $cut ) : $location;
1199
1200         $lp  = parse_url($test);
1201
1202         // Give up if malformed URL
1203         if ( false === $lp )
1204                 return $default;
1205
1206         // Allow only http and https schemes. No data:, etc.
1207         if ( isset($lp['scheme']) && !('http' == $lp['scheme'] || 'https' == $lp['scheme']) )
1208                 return $default;
1209
1210         // Reject if scheme is set but host is not. This catches urls like https:host.com for which parse_url does not set the host field.
1211         if ( isset($lp['scheme'])  && !isset($lp['host']) )
1212                 return $default;
1213
1214         $wpp = parse_url(home_url());
1215
1216         /**
1217          * Filter the whitelist of hosts to redirect to.
1218          *
1219          * @since 2.3.0
1220          *
1221          * @param array       $hosts An array of allowed hosts.
1222          * @param bool|string $host  The parsed host; empty if not isset.
1223          */
1224         $allowed_hosts = (array) apply_filters( 'allowed_redirect_hosts', array($wpp['host']), isset($lp['host']) ? $lp['host'] : '' );
1225
1226         if ( isset($lp['host']) && ( !in_array($lp['host'], $allowed_hosts) && $lp['host'] != strtolower($wpp['host'])) )
1227                 $location = $default;
1228
1229         return $location;
1230 }
1231 endif;
1232
1233 if ( ! function_exists('wp_notify_postauthor') ) :
1234 /**
1235  * Notify an author (and/or others) of a comment/trackback/pingback on a post.
1236  *
1237  * @since 1.0.0
1238  *
1239  * @param int $comment_id Comment ID
1240  * @param string $deprecated Not used
1241  * @return bool True on completion. False if no email addresses were specified.
1242  */
1243 function wp_notify_postauthor( $comment_id, $deprecated = null ) {
1244         if ( null !== $deprecated ) {
1245                 _deprecated_argument( __FUNCTION__, '3.8' );
1246         }
1247
1248         $comment = get_comment( $comment_id );
1249         if ( empty( $comment ) )
1250                 return false;
1251
1252         $post    = get_post( $comment->comment_post_ID );
1253         $author  = get_userdata( $post->post_author );
1254
1255         // Who to notify? By default, just the post author, but others can be added.
1256         $emails = array();
1257         if ( $author ) {
1258                 $emails[] = $author->user_email;
1259         }
1260
1261         /**
1262          * Filter the list of email addresses to receive a comment notification.
1263          *
1264          * By default, only post authors are notified of comments. This filter allows
1265          * others to be added.
1266          *
1267          * @since 3.7.0
1268          *
1269          * @param array $emails     An array of email addresses to receive a comment notification.
1270          * @param int   $comment_id The comment ID.
1271          */
1272         $emails = apply_filters( 'comment_notification_recipients', $emails, $comment_id );
1273         $emails = array_filter( $emails );
1274
1275         // If there are no addresses to send the comment to, bail.
1276         if ( ! count( $emails ) ) {
1277                 return false;
1278         }
1279
1280         // Facilitate unsetting below without knowing the keys.
1281         $emails = array_flip( $emails );
1282
1283         /**
1284          * Filter whether to notify comment authors of their comments on their own posts.
1285          *
1286          * By default, comment authors aren't notified of their comments on their own
1287          * posts. This filter allows you to override that.
1288          *
1289          * @since 3.8.0
1290          *
1291          * @param bool $notify     Whether to notify the post author of their own comment.
1292          *                         Default false.
1293          * @param int  $comment_id The comment ID.
1294          */
1295         $notify_author = apply_filters( 'comment_notification_notify_author', false, $comment_id );
1296
1297         // The comment was left by the author
1298         if ( $author && ! $notify_author && $comment->user_id == $post->post_author ) {
1299                 unset( $emails[ $author->user_email ] );
1300         }
1301
1302         // The author moderated a comment on their own post
1303         if ( $author && ! $notify_author && $post->post_author == get_current_user_id() ) {
1304                 unset( $emails[ $author->user_email ] );
1305         }
1306
1307         // The post author is no longer a member of the blog
1308         if ( $author && ! $notify_author && ! user_can( $post->post_author, 'read_post', $post->ID ) ) {
1309                 unset( $emails[ $author->user_email ] );
1310         }
1311
1312         // If there's no email to send the comment to, bail, otherwise flip array back around for use below
1313         if ( ! count( $emails ) ) {
1314                 return false;
1315         } else {
1316                 $emails = array_flip( $emails );
1317         }
1318
1319         $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
1320
1321         // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1322         // we want to reverse this for the plain text arena of emails.
1323         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1324
1325         switch ( $comment->comment_type ) {
1326                 case 'trackback':
1327                         $notify_message  = sprintf( __( 'New trackback on your post "%s"' ), $post->post_title ) . "\r\n";
1328                         /* translators: 1: website name, 2: author IP, 3: author domain */
1329                         $notify_message .= sprintf( __('Website: %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1330                         $notify_message .= sprintf( __('URL    : %s'), $comment->comment_author_url ) . "\r\n";
1331                         $notify_message .= __('Excerpt: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1332                         $notify_message .= __('You can see all trackbacks on this post here: ') . "\r\n";
1333                         /* translators: 1: blog name, 2: post title */
1334                         $subject = sprintf( __('[%1$s] Trackback: "%2$s"'), $blogname, $post->post_title );
1335                         break;
1336                 case 'pingback':
1337                         $notify_message  = sprintf( __( 'New pingback on your post "%s"' ), $post->post_title ) . "\r\n";
1338                         /* translators: 1: comment author, 2: author IP, 3: author domain */
1339                         $notify_message .= sprintf( __('Website: %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1340                         $notify_message .= sprintf( __('URL    : %s'), $comment->comment_author_url ) . "\r\n";
1341                         $notify_message .= __('Excerpt: ') . "\r\n" . sprintf('[...] %s [...]', $comment->comment_content ) . "\r\n\r\n";
1342                         $notify_message .= __('You can see all pingbacks on this post here: ') . "\r\n";
1343                         /* translators: 1: blog name, 2: post title */
1344                         $subject = sprintf( __('[%1$s] Pingback: "%2$s"'), $blogname, $post->post_title );
1345                         break;
1346                 default: // Comments
1347                         $notify_message  = sprintf( __( 'New comment on your post "%s"' ), $post->post_title ) . "\r\n";
1348                         /* translators: 1: comment author, 2: author IP, 3: author domain */
1349                         $notify_message .= sprintf( __('Author : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1350                         $notify_message .= sprintf( __('E-mail : %s'), $comment->comment_author_email ) . "\r\n";
1351                         $notify_message .= sprintf( __('URL    : %s'), $comment->comment_author_url ) . "\r\n";
1352                         $notify_message .= sprintf( __('Whois  : http://whois.arin.net/rest/ip/%s'), $comment->comment_author_IP ) . "\r\n";
1353                         $notify_message .= __('Comment: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1354                         $notify_message .= __('You can see all comments on this post here: ') . "\r\n";
1355                         /* translators: 1: blog name, 2: post title */
1356                         $subject = sprintf( __('[%1$s] Comment: "%2$s"'), $blogname, $post->post_title );
1357                         break;
1358         }
1359         $notify_message .= get_permalink($comment->comment_post_ID) . "#comments\r\n\r\n";
1360         $notify_message .= sprintf( __('Permalink: %s'), get_comment_link( $comment_id ) ) . "\r\n";
1361
1362         if ( user_can( $post->post_author, 'edit_comment', $comment_id ) ) {
1363                 if ( EMPTY_TRASH_DAYS )
1364                         $notify_message .= sprintf( __('Trash it: %s'), admin_url("comment.php?action=trash&c=$comment_id") ) . "\r\n";
1365                 else
1366                         $notify_message .= sprintf( __('Delete it: %s'), admin_url("comment.php?action=delete&c=$comment_id") ) . "\r\n";
1367                 $notify_message .= sprintf( __('Spam it: %s'), admin_url("comment.php?action=spam&c=$comment_id") ) . "\r\n";
1368         }
1369
1370         $wp_email = 'wordpress@' . preg_replace('#^www\.#', '', strtolower($_SERVER['SERVER_NAME']));
1371
1372         if ( '' == $comment->comment_author ) {
1373                 $from = "From: \"$blogname\" <$wp_email>";
1374                 if ( '' != $comment->comment_author_email )
1375                         $reply_to = "Reply-To: $comment->comment_author_email";
1376         } else {
1377                 $from = "From: \"$comment->comment_author\" <$wp_email>";
1378                 if ( '' != $comment->comment_author_email )
1379                         $reply_to = "Reply-To: \"$comment->comment_author_email\" <$comment->comment_author_email>";
1380         }
1381
1382         $message_headers = "$from\n"
1383                 . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n";
1384
1385         if ( isset($reply_to) )
1386                 $message_headers .= $reply_to . "\n";
1387
1388         /**
1389          * Filter the comment notification email text.
1390          *
1391          * @since 1.5.2
1392          *
1393          * @param string $notify_message The comment notification email text.
1394          * @param int    $comment_id     Comment ID.
1395          */
1396         $notify_message = apply_filters( 'comment_notification_text', $notify_message, $comment_id );
1397
1398         /**
1399          * Filter the comment notification email subject.
1400          *
1401          * @since 1.5.2
1402          *
1403          * @param string $subject    The comment notification email subject.
1404          * @param int    $comment_id Comment ID.
1405          */
1406         $subject = apply_filters( 'comment_notification_subject', $subject, $comment_id );
1407
1408         /**
1409          * Filter the comment notification email headers.
1410          *
1411          * @since 1.5.2
1412          *
1413          * @param string $message_headers Headers for the comment notification email.
1414          * @param int    $comment_id      Comment ID.
1415          */
1416         $message_headers = apply_filters( 'comment_notification_headers', $message_headers, $comment_id );
1417
1418         foreach ( $emails as $email ) {
1419                 @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
1420         }
1421
1422         return true;
1423 }
1424 endif;
1425
1426 if ( !function_exists('wp_notify_moderator') ) :
1427 /**
1428  * Notifies the moderator of the blog about a new comment that is awaiting approval.
1429  *
1430  * @since 1.0.0
1431  *
1432  * @uses $wpdb
1433  *
1434  * @param int $comment_id Comment ID
1435  * @return bool Always returns true
1436  */
1437 function wp_notify_moderator($comment_id) {
1438         global $wpdb;
1439
1440         if ( 0 == get_option( 'moderation_notify' ) )
1441                 return true;
1442
1443         $comment = get_comment($comment_id);
1444         $post = get_post($comment->comment_post_ID);
1445         $user = get_userdata( $post->post_author );
1446         // Send to the administration and to the post author if the author can modify the comment.
1447         $emails = array( get_option( 'admin_email' ) );
1448         if ( user_can( $user->ID, 'edit_comment', $comment_id ) && ! empty( $user->user_email ) ) {
1449                 if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) )
1450                         $emails[] = $user->user_email;
1451         }
1452
1453         $comment_author_domain = @gethostbyaddr($comment->comment_author_IP);
1454         $comments_waiting = $wpdb->get_var("SELECT count(comment_ID) FROM $wpdb->comments WHERE comment_approved = '0'");
1455
1456         // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1457         // we want to reverse this for the plain text arena of emails.
1458         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1459
1460         switch ( $comment->comment_type ) {
1461                 case 'trackback':
1462                         $notify_message  = sprintf( __('A new trackback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1463                         $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1464                         $notify_message .= sprintf( __('Website : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1465                         $notify_message .= sprintf( __('URL    : %s'), $comment->comment_author_url ) . "\r\n";
1466                         $notify_message .= __('Trackback excerpt: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1467                         break;
1468                 case 'pingback':
1469                         $notify_message  = sprintf( __('A new pingback on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1470                         $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1471                         $notify_message .= sprintf( __('Website : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1472                         $notify_message .= sprintf( __('URL    : %s'), $comment->comment_author_url ) . "\r\n";
1473                         $notify_message .= __('Pingback excerpt: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1474                         break;
1475                 default: // Comments
1476                         $notify_message  = sprintf( __('A new comment on the post "%s" is waiting for your approval'), $post->post_title ) . "\r\n";
1477                         $notify_message .= get_permalink($comment->comment_post_ID) . "\r\n\r\n";
1478                         $notify_message .= sprintf( __('Author : %1$s (IP: %2$s , %3$s)'), $comment->comment_author, $comment->comment_author_IP, $comment_author_domain ) . "\r\n";
1479                         $notify_message .= sprintf( __('E-mail : %s'), $comment->comment_author_email ) . "\r\n";
1480                         $notify_message .= sprintf( __('URL    : %s'), $comment->comment_author_url ) . "\r\n";
1481                         $notify_message .= sprintf( __('Whois  : http://whois.arin.net/rest/ip/%s'), $comment->comment_author_IP ) . "\r\n";
1482                         $notify_message .= __('Comment: ') . "\r\n" . $comment->comment_content . "\r\n\r\n";
1483                         break;
1484         }
1485
1486         $notify_message .= sprintf( __('Approve it: %s'),  admin_url("comment.php?action=approve&c=$comment_id") ) . "\r\n";
1487         if ( EMPTY_TRASH_DAYS )
1488                 $notify_message .= sprintf( __('Trash it: %s'), admin_url("comment.php?action=trash&c=$comment_id") ) . "\r\n";
1489         else
1490                 $notify_message .= sprintf( __('Delete it: %s'), admin_url("comment.php?action=delete&c=$comment_id") ) . "\r\n";
1491         $notify_message .= sprintf( __('Spam it: %s'), admin_url("comment.php?action=spam&c=$comment_id") ) . "\r\n";
1492
1493         $notify_message .= sprintf( _n('Currently %s comment is waiting for approval. Please visit the moderation panel:',
1494                 'Currently %s comments are waiting for approval. Please visit the moderation panel:', $comments_waiting), number_format_i18n($comments_waiting) ) . "\r\n";
1495         $notify_message .= admin_url("edit-comments.php?comment_status=moderated") . "\r\n";
1496
1497         $subject = sprintf( __('[%1$s] Please moderate: "%2$s"'), $blogname, $post->post_title );
1498         $message_headers = '';
1499
1500         /**
1501          * Filter the list of recipients for comment moderation emails.
1502          *
1503          * @since 3.7.0
1504          *
1505          * @param array $emails     List of email addresses to notify for comment moderation.
1506          * @param int   $comment_id Comment ID.
1507          */
1508         $emails = apply_filters( 'comment_moderation_recipients', $emails, $comment_id );
1509
1510         /**
1511          * Filter the comment moderation email text.
1512          *
1513          * @since 1.5.2
1514          *
1515          * @param string $notify_message Text of the comment moderation email.
1516          * @param int    $comment_id     Comment ID.
1517          */
1518         $notify_message = apply_filters( 'comment_moderation_text', $notify_message, $comment_id );
1519
1520         /**
1521          * Filter the comment moderation email subject.
1522          *
1523          * @since 1.5.2
1524          *
1525          * @param string $subject    Subject of the comment moderation email.
1526          * @param int    $comment_id Comment ID.
1527          */
1528         $subject = apply_filters( 'comment_moderation_subject', $subject, $comment_id );
1529
1530         /**
1531          * Filter the comment moderation email headers.
1532          *
1533          * @since 2.8.0
1534          *
1535          * @param string $message_headers Headers for the comment moderation email.
1536          * @param int    $comment_id      Comment ID.
1537          */
1538         $message_headers = apply_filters( 'comment_moderation_headers', $message_headers, $comment_id );
1539
1540         foreach ( $emails as $email ) {
1541                 @wp_mail( $email, wp_specialchars_decode( $subject ), $notify_message, $message_headers );
1542         }
1543
1544         return true;
1545 }
1546 endif;
1547
1548 if ( !function_exists('wp_password_change_notification') ) :
1549 /**
1550  * Notify the blog admin of a user changing password, normally via email.
1551  *
1552  * @since 2.7.0
1553  *
1554  * @param object $user User Object
1555  */
1556 function wp_password_change_notification(&$user) {
1557         // send a copy of password change notification to the admin
1558         // but check to see if it's the admin whose password we're changing, and skip this
1559         if ( 0 !== strcasecmp( $user->user_email, get_option( 'admin_email' ) ) ) {
1560                 $message = sprintf(__('Password Lost and Changed for user: %s'), $user->user_login) . "\r\n";
1561                 // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1562                 // we want to reverse this for the plain text arena of emails.
1563                 $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1564                 wp_mail(get_option('admin_email'), sprintf(__('[%s] Password Lost/Changed'), $blogname), $message);
1565         }
1566 }
1567 endif;
1568
1569 if ( !function_exists('wp_new_user_notification') ) :
1570 /**
1571  * Email login credentials to a newly-registered user.
1572  *
1573  * A new user registration notification is also sent to admin email.
1574  *
1575  * @since 2.0.0
1576  *
1577  * @param int    $user_id        User ID.
1578  * @param string $plaintext_pass Optional. The user's plaintext password. Default empty.
1579  */
1580 function wp_new_user_notification($user_id, $plaintext_pass = '') {
1581         $user = get_userdata( $user_id );
1582
1583         // The blogname option is escaped with esc_html on the way into the database in sanitize_option
1584         // we want to reverse this for the plain text arena of emails.
1585         $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
1586
1587         $message  = sprintf(__('New user registration on your site %s:'), $blogname) . "\r\n\r\n";
1588         $message .= sprintf(__('Username: %s'), $user->user_login) . "\r\n\r\n";
1589         $message .= sprintf(__('E-mail: %s'), $user->user_email) . "\r\n";
1590
1591         @wp_mail(get_option('admin_email'), sprintf(__('[%s] New User Registration'), $blogname), $message);
1592
1593         if ( empty($plaintext_pass) )
1594                 return;
1595
1596         $message  = sprintf(__('Username: %s'), $user->user_login) . "\r\n";
1597         $message .= sprintf(__('Password: %s'), $plaintext_pass) . "\r\n";
1598         $message .= wp_login_url() . "\r\n";
1599
1600         wp_mail($user->user_email, sprintf(__('[%s] Your username and password'), $blogname), $message);
1601
1602 }
1603 endif;
1604
1605 if ( !function_exists('wp_nonce_tick') ) :
1606 /**
1607  * Get the time-dependent variable for nonce creation.
1608  *
1609  * A nonce has a lifespan of two ticks. Nonces in their second tick may be
1610  * updated, e.g. by autosave.
1611  *
1612  * @since 2.5.0
1613  *
1614  * @return int
1615  */
1616 function wp_nonce_tick() {
1617         /**
1618          * Filter the lifespan of nonces in seconds.
1619          *
1620          * @since 2.5.0
1621          *
1622          * @param int $lifespan Lifespan of nonces in seconds. Default 86,400 seconds, or one day.
1623          */
1624         $nonce_life = apply_filters( 'nonce_life', DAY_IN_SECONDS );
1625
1626         return ceil(time() / ( $nonce_life / 2 ));
1627 }
1628 endif;
1629
1630 if ( !function_exists('wp_verify_nonce') ) :
1631 /**
1632  * Verify that correct nonce was used with time limit.
1633  *
1634  * The user is given an amount of time to use the token, so therefore, since the
1635  * UID and $action remain the same, the independent variable is the time.
1636  *
1637  * @since 2.0.3
1638  *
1639  * @param string $nonce Nonce that was used in the form to verify
1640  * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
1641  * @return bool Whether the nonce check passed or failed.
1642  */
1643 function wp_verify_nonce($nonce, $action = -1) {
1644         $user = wp_get_current_user();
1645         $uid = (int) $user->ID;
1646         if ( ! $uid ) {
1647                 /**
1648                  * Filter whether the user who generated the nonce is logged out.
1649                  *
1650                  * @since 3.5.0
1651                  *
1652                  * @param int    $uid    ID of the nonce-owning user.
1653                  * @param string $action The nonce action.
1654                  */
1655                 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
1656         }
1657
1658         $i = wp_nonce_tick();
1659
1660         // Nonce generated 0-12 hours ago
1661         $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid, 'nonce'), -12, 10 );
1662         if ( hash_equals( $expected, $nonce ) ) {
1663                 return 1;
1664         }
1665
1666         // Nonce generated 12-24 hours ago
1667         $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid, 'nonce' ), -12, 10 );
1668         if ( hash_equals( $expected, $nonce ) ) {
1669                 return 2;
1670         }
1671
1672         // Invalid nonce
1673         return false;
1674 }
1675 endif;
1676
1677 if ( !function_exists('wp_create_nonce') ) :
1678 /**
1679  * Creates a random, one time use token.
1680  *
1681  * @since 2.0.3
1682  *
1683  * @param string|int $action Scalar value to add context to the nonce.
1684  * @return string The one use form token
1685  */
1686 function wp_create_nonce($action = -1) {
1687         $user = wp_get_current_user();
1688         $uid = (int) $user->ID;
1689         if ( ! $uid ) {
1690                 /** This filter is documented in wp-includes/pluggable.php */
1691                 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
1692         }
1693
1694         $i = wp_nonce_tick();
1695
1696         return substr(wp_hash($i . '|' . $action . '|' . $uid, 'nonce'), -12, 10);
1697 }
1698 endif;
1699
1700 if ( !function_exists('wp_salt') ) :
1701 /**
1702  * Get salt to add to hashes.
1703  *
1704  * Salts are created using secret keys. Secret keys are located in two places:
1705  * in the database and in the wp-config.php file. The secret key in the database
1706  * is randomly generated and will be appended to the secret keys in wp-config.php.
1707  *
1708  * The secret keys in wp-config.php should be updated to strong, random keys to maximize
1709  * security. Below is an example of how the secret key constants are defined.
1710  * Do not paste this example directly into wp-config.php. Instead, have a
1711  * {@link https://api.wordpress.org/secret-key/1.1/salt/ secret key created} just
1712  * for you.
1713  *
1714  * <code>
1715  * define('AUTH_KEY',         ' Xakm<o xQy rw4EMsLKM-?!T+,PFF})H4lzcW57AF0U@N@< >M%G4Yt>f`z]MON');
1716  * define('SECURE_AUTH_KEY',  'LzJ}op]mr|6+![P}Ak:uNdJCJZd>(Hx.-Mh#Tz)pCIU#uGEnfFz|f ;;eU%/U^O~');
1717  * define('LOGGED_IN_KEY',    '|i|Ux`9<p-h$aFf(qnT:sDO:D1P^wZ$$/Ra@miTJi9G;ddp_<q}6H1)o|a +&JCM');
1718  * define('NONCE_KEY',        '%:R{[P|,s.KuMltH5}cI;/k<Gx~j!f0I)m_sIyu+&NJZ)-iO>z7X>QYR0Z_XnZ@|');
1719  * define('AUTH_SALT',        'eZyT)-Naw]F8CwA*VaW#q*|.)g@o}||wf~@C-YSt}(dh_r6EbI#A,y|nU2{B#JBW');
1720  * define('SECURE_AUTH_SALT', '!=oLUTXh,QW=H `}`L|9/^4-3 STz},T(w}W<I`.JjPi)<Bmf1v,HpGe}T1:Xt7n');
1721  * define('LOGGED_IN_SALT',   '+XSqHc;@Q*K_b|Z?NC[3H!!EONbh.n<+=uKR:>*c(u`g~EJBf#8u#R{mUEZrozmm');
1722  * define('NONCE_SALT',       'h`GXHhD>SLWVfg1(1(N{;.V!MoE(SfbA_ksP@&`+AycHcAV$+?@3q+rxV{%^VyKT');
1723  * </code>
1724  *
1725  * Salting passwords helps against tools which has stored hashed values of
1726  * common dictionary strings. The added values makes it harder to crack.
1727  *
1728  * @since 2.5.0
1729  *
1730  * @link https://api.wordpress.org/secret-key/1.1/salt/ Create secrets for wp-config.php
1731  *
1732  * @param string $scheme Authentication scheme (auth, secure_auth, logged_in, nonce)
1733  * @return string Salt value
1734  */
1735 function wp_salt( $scheme = 'auth' ) {
1736         static $cached_salts = array();
1737         if ( isset( $cached_salts[ $scheme ] ) ) {
1738                 /**
1739                  * Filter the WordPress salt.
1740                  *
1741                  * @since 2.5.0
1742                  *
1743                  * @param string $cached_salt Cached salt for the given scheme.
1744                  * @param string $scheme      Authentication scheme. Values include 'auth',
1745                  *                            'secure_auth', 'logged_in', and 'nonce'.
1746                  */
1747                 return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
1748         }
1749
1750         static $duplicated_keys;
1751         if ( null === $duplicated_keys ) {
1752                 $duplicated_keys = array( 'put your unique phrase here' => true );
1753                 foreach ( array( 'AUTH', 'SECURE_AUTH', 'LOGGED_IN', 'NONCE', 'SECRET' ) as $first ) {
1754                         foreach ( array( 'KEY', 'SALT' ) as $second ) {
1755                                 if ( ! defined( "{$first}_{$second}" ) )
1756                                         continue;
1757                                 $value = constant( "{$first}_{$second}" );
1758                                 $duplicated_keys[ $value ] = isset( $duplicated_keys[ $value ] );
1759                         }
1760                 }
1761         }
1762
1763         $key = $salt = '';
1764         if ( defined( 'SECRET_KEY' ) && SECRET_KEY && empty( $duplicated_keys[ SECRET_KEY ] ) )
1765                 $key = SECRET_KEY;
1766         if ( 'auth' == $scheme && defined( 'SECRET_SALT' ) && SECRET_SALT && empty( $duplicated_keys[ SECRET_SALT ] ) )
1767                 $salt = SECRET_SALT;
1768
1769         if ( in_array( $scheme, array( 'auth', 'secure_auth', 'logged_in', 'nonce' ) ) ) {
1770                 foreach ( array( 'key', 'salt' ) as $type ) {
1771                         $const = strtoupper( "{$scheme}_{$type}" );
1772                         if ( defined( $const ) && constant( $const ) && empty( $duplicated_keys[ constant( $const ) ] ) ) {
1773                                 $$type = constant( $const );
1774                         } elseif ( ! $$type ) {
1775                                 $$type = get_site_option( "{$scheme}_{$type}" );
1776                                 if ( ! $$type ) {
1777                                         $$type = wp_generate_password( 64, true, true );
1778                                         update_site_option( "{$scheme}_{$type}", $$type );
1779                                 }
1780                         }
1781                 }
1782         } else {
1783                 if ( ! $key ) {
1784                         $key = get_site_option( 'secret_key' );
1785                         if ( ! $key ) {
1786                                 $key = wp_generate_password( 64, true, true );
1787                                 update_site_option( 'secret_key', $key );
1788                         }
1789                 }
1790                 $salt = hash_hmac( 'md5', $scheme, $key );
1791         }
1792
1793         $cached_salts[ $scheme ] = $key . $salt;
1794
1795         /** This filter is documented in wp-includes/pluggable.php */
1796         return apply_filters( 'salt', $cached_salts[ $scheme ], $scheme );
1797 }
1798 endif;
1799
1800 if ( !function_exists('wp_hash') ) :
1801 /**
1802  * Get hash of given string.
1803  *
1804  * @since 2.0.3
1805  * @uses wp_salt() Get WordPress salt
1806  *
1807  * @param string $data Plain text to hash
1808  * @return string Hash of $data
1809  */
1810 function wp_hash($data, $scheme = 'auth') {
1811         $salt = wp_salt($scheme);
1812
1813         return hash_hmac('md5', $data, $salt);
1814 }
1815 endif;
1816
1817 if ( !function_exists('wp_hash_password') ) :
1818 /**
1819  * Create a hash (encrypt) of a plain text password.
1820  *
1821  * For integration with other applications, this function can be overwritten to
1822  * instead use the other package password checking algorithm.
1823  *
1824  * @since 2.5.0
1825  *
1826  * @global object $wp_hasher PHPass object
1827  * @uses PasswordHash::HashPassword
1828  *
1829  * @param string $password Plain text user password to hash
1830  * @return string The hash string of the password
1831  */
1832 function wp_hash_password($password) {
1833         global $wp_hasher;
1834
1835         if ( empty($wp_hasher) ) {
1836                 require_once( ABSPATH . 'wp-includes/class-phpass.php');
1837                 // By default, use the portable hash from phpass
1838                 $wp_hasher = new PasswordHash(8, true);
1839         }
1840
1841         return $wp_hasher->HashPassword( trim( $password ) );
1842 }
1843 endif;
1844
1845 if ( !function_exists('wp_check_password') ) :
1846 /**
1847  * Checks the plaintext password against the encrypted Password.
1848  *
1849  * Maintains compatibility between old version and the new cookie authentication
1850  * protocol using PHPass library. The $hash parameter is the encrypted password
1851  * and the function compares the plain text password when encrypted similarly
1852  * against the already encrypted password to see if they match.
1853  *
1854  * For integration with other applications, this function can be overwritten to
1855  * instead use the other package password checking algorithm.
1856  *
1857  * @since 2.5.0
1858  *
1859  * @global object $wp_hasher PHPass object used for checking the password
1860  *      against the $hash + $password
1861  * @uses PasswordHash::CheckPassword
1862  *
1863  * @param string $password Plaintext user's password
1864  * @param string $hash Hash of the user's password to check against.
1865  * @return bool False, if the $password does not match the hashed password
1866  */
1867 function wp_check_password($password, $hash, $user_id = '') {
1868         global $wp_hasher;
1869
1870         // If the hash is still md5...
1871         if ( strlen($hash) <= 32 ) {
1872                 $check = ( $hash == md5($password) );
1873                 if ( $check && $user_id ) {
1874                         // Rehash using new hash.
1875                         wp_set_password($password, $user_id);
1876                         $hash = wp_hash_password($password);
1877                 }
1878
1879                 /**
1880                  * Filter whether the plaintext password matches the encrypted password.
1881                  *
1882                  * @since 2.5.0
1883                  *
1884                  * @param bool   $check   Whether the passwords match.
1885                  * @param string $hash    The hashed password.
1886                  * @param int    $user_id User ID.
1887                  */
1888                 return apply_filters( 'check_password', $check, $password, $hash, $user_id );
1889         }
1890
1891         // If the stored hash is longer than an MD5, presume the
1892         // new style phpass portable hash.
1893         if ( empty($wp_hasher) ) {
1894                 require_once( ABSPATH . 'wp-includes/class-phpass.php');
1895                 // By default, use the portable hash from phpass
1896                 $wp_hasher = new PasswordHash(8, true);
1897         }
1898
1899         $check = $wp_hasher->CheckPassword($password, $hash);
1900
1901         /** This filter is documented in wp-includes/pluggable.php */
1902         return apply_filters( 'check_password', $check, $password, $hash, $user_id );
1903 }
1904 endif;
1905
1906 if ( !function_exists('wp_generate_password') ) :
1907 /**
1908  * Generates a random password drawn from the defined set of characters.
1909  *
1910  * @since 2.5.0
1911  *
1912  * @param int $length The length of password to generate
1913  * @param bool $special_chars Whether to include standard special characters. Default true.
1914  * @param bool $extra_special_chars Whether to include other special characters. Used when
1915  *   generating secret keys and salts. Default false.
1916  * @return string The random password
1917  **/
1918 function wp_generate_password( $length = 12, $special_chars = true, $extra_special_chars = false ) {
1919         $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
1920         if ( $special_chars )
1921                 $chars .= '!@#$%^&*()';
1922         if ( $extra_special_chars )
1923                 $chars .= '-_ []{}<>~`+=,.;:/?|';
1924
1925         $password = '';
1926         for ( $i = 0; $i < $length; $i++ ) {
1927                 $password .= substr($chars, wp_rand(0, strlen($chars) - 1), 1);
1928         }
1929
1930         /**
1931          * Filter the randomly-generated password.
1932          *
1933          * @since 3.0.0
1934          *
1935          * @param string $password The generated password.
1936          */
1937         return apply_filters( 'random_password', $password );
1938 }
1939 endif;
1940
1941 if ( !function_exists('wp_rand') ) :
1942 /**
1943  * Generates a random number
1944  *
1945  * @since 2.6.2
1946  *
1947  * @param int $min Lower limit for the generated number
1948  * @param int $max Upper limit for the generated number
1949  * @return int A random number between min and max
1950  */
1951 function wp_rand( $min = 0, $max = 0 ) {
1952         global $rnd_value;
1953
1954         // Reset $rnd_value after 14 uses
1955         // 32(md5) + 40(sha1) + 40(sha1) / 8 = 14 random numbers from $rnd_value
1956         if ( strlen($rnd_value) < 8 ) {
1957                 if ( defined( 'WP_SETUP_CONFIG' ) )
1958                         static $seed = '';
1959                 else
1960                         $seed = get_transient('random_seed');
1961                 $rnd_value = md5( uniqid(microtime() . mt_rand(), true ) . $seed );
1962                 $rnd_value .= sha1($rnd_value);
1963                 $rnd_value .= sha1($rnd_value . $seed);
1964                 $seed = md5($seed . $rnd_value);
1965                 if ( ! defined( 'WP_SETUP_CONFIG' ) )
1966                         set_transient('random_seed', $seed);
1967         }
1968
1969         // Take the first 8 digits for our value
1970         $value = substr($rnd_value, 0, 8);
1971
1972         // Strip the first eight, leaving the remainder for the next call to wp_rand().
1973         $rnd_value = substr($rnd_value, 8);
1974
1975         $value = abs(hexdec($value));
1976
1977         // 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.
1978         $max_random_number = 3000000000 === 2147483647 ? (float) "4294967295" : 4294967295; // 4294967295 = 0xffffffff
1979
1980         // Reduce the value to be within the min - max range
1981         if ( $max != 0 )
1982                 $value = $min + ( $max - $min + 1 ) * $value / ( $max_random_number + 1 );
1983
1984         return abs(intval($value));
1985 }
1986 endif;
1987
1988 if ( !function_exists('wp_set_password') ) :
1989 /**
1990  * Updates the user's password with a new encrypted one.
1991  *
1992  * For integration with other applications, this function can be overwritten to
1993  * instead use the other package password checking algorithm.
1994  *
1995  * @since 2.5.0
1996  *
1997  * @uses $wpdb WordPress database object for queries
1998  * @uses wp_hash_password() Used to encrypt the user's password before passing to the database
1999  *
2000  * @param string $password The plaintext new user password
2001  * @param int $user_id User ID
2002  */
2003 function wp_set_password( $password, $user_id ) {
2004         global $wpdb;
2005
2006         $hash = wp_hash_password( $password );
2007         $wpdb->update($wpdb->users, array('user_pass' => $hash, 'user_activation_key' => ''), array('ID' => $user_id) );
2008
2009         wp_cache_delete($user_id, 'users');
2010 }
2011 endif;
2012
2013 if ( !function_exists( 'get_avatar' ) ) :
2014 /**
2015  * Retrieve the avatar for a user who provided a user ID or email address.
2016  *
2017  * @since 2.5.0
2018  *
2019  * @param int|string|object $id_or_email A user ID,  email address, or comment object
2020  * @param int $size Size of the avatar image
2021  * @param string $default URL to a default image to use if no avatar is available
2022  * @param string $alt Alternative text to use in image tag. Defaults to blank
2023  * @return string <img> tag for the user's avatar
2024 */
2025 function get_avatar( $id_or_email, $size = '96', $default = '', $alt = false ) {
2026         if ( ! get_option('show_avatars') )
2027                 return false;
2028
2029         if ( false === $alt)
2030                 $safe_alt = '';
2031         else
2032                 $safe_alt = esc_attr( $alt );
2033
2034         if ( !is_numeric($size) )
2035                 $size = '96';
2036
2037         $email = '';
2038         if ( is_numeric($id_or_email) ) {
2039                 $id = (int) $id_or_email;
2040                 $user = get_userdata($id);
2041                 if ( $user )
2042                         $email = $user->user_email;
2043         } elseif ( is_object($id_or_email) ) {
2044                 // No avatar for pingbacks or trackbacks
2045
2046                 /**
2047                  * Filter the list of allowed comment types for retrieving avatars.
2048                  *
2049                  * @since 3.0.0
2050                  *
2051                  * @param array $types An array of content types. Default only contains 'comment'.
2052                  */
2053                 $allowed_comment_types = apply_filters( 'get_avatar_comment_types', array( 'comment' ) );
2054                 if ( ! empty( $id_or_email->comment_type ) && ! in_array( $id_or_email->comment_type, (array) $allowed_comment_types ) )
2055                         return false;
2056
2057                 if ( ! empty( $id_or_email->user_id ) ) {
2058                         $id = (int) $id_or_email->user_id;
2059                         $user = get_userdata($id);
2060                         if ( $user )
2061                                 $email = $user->user_email;
2062                 }
2063
2064                 if ( ! $email && ! empty( $id_or_email->comment_author_email ) )
2065                         $email = $id_or_email->comment_author_email;
2066         } else {
2067                 $email = $id_or_email;
2068         }
2069
2070         if ( empty($default) ) {
2071                 $avatar_default = get_option('avatar_default');
2072                 if ( empty($avatar_default) )
2073                         $default = 'mystery';
2074                 else
2075                         $default = $avatar_default;
2076         }
2077
2078         if ( !empty($email) )
2079                 $email_hash = md5( strtolower( trim( $email ) ) );
2080
2081         if ( is_ssl() ) {
2082                 $host = 'https://secure.gravatar.com';
2083         } else {
2084                 if ( !empty($email) )
2085                         $host = sprintf( "http://%d.gravatar.com", ( hexdec( $email_hash[0] ) % 2 ) );
2086                 else
2087                         $host = 'http://0.gravatar.com';
2088         }
2089
2090         if ( 'mystery' == $default )
2091                 $default = "$host/avatar/ad516503a11cd5ca435acc9bb6523536?s={$size}"; // ad516503a11cd5ca435acc9bb6523536 == md5('unknown@gravatar.com')
2092         elseif ( 'blank' == $default )
2093                 $default = $email ? 'blank' : includes_url( 'images/blank.gif' );
2094         elseif ( !empty($email) && 'gravatar_default' == $default )
2095                 $default = '';
2096         elseif ( 'gravatar_default' == $default )
2097                 $default = "$host/avatar/?s={$size}";
2098         elseif ( empty($email) )
2099                 $default = "$host/avatar/?d=$default&amp;s={$size}";
2100         elseif ( strpos($default, 'http://') === 0 )
2101                 $default = add_query_arg( 's', $size, $default );
2102
2103         if ( !empty($email) ) {
2104                 $out = "$host/avatar/";
2105                 $out .= $email_hash;
2106                 $out .= '?s='.$size;
2107                 $out .= '&amp;d=' . urlencode( $default );
2108
2109                 $rating = get_option('avatar_rating');
2110                 if ( !empty( $rating ) )
2111                         $out .= "&amp;r={$rating}";
2112
2113                 $out = str_replace( '&#038;', '&amp;', esc_url( $out ) );
2114                 $avatar = "<img alt='{$safe_alt}' src='{$out}' class='avatar avatar-{$size} photo' height='{$size}' width='{$size}' />";
2115         } else {
2116                 $out = esc_url( $default );
2117                 $avatar = "<img alt='{$safe_alt}' src='{$out}' class='avatar avatar-{$size} photo avatar-default' height='{$size}' width='{$size}' />";
2118         }
2119
2120         /**
2121          * Filter the avatar to retrieve.
2122          *
2123          * @since 2.5.0
2124          *
2125          * @param string            $avatar      Image tag for the user's avatar.
2126          * @param int|object|string $id_or_email A user ID, email address, or comment object.
2127          * @param int               $size        Square avatar width and height in pixels to retrieve.
2128          * @param string            $alt         Alternative text to use in the avatar image tag.
2129          *                                       Default empty.
2130          */
2131         return apply_filters( 'get_avatar', $avatar, $id_or_email, $size, $default, $alt );
2132 }
2133 endif;
2134
2135 if ( !function_exists( 'wp_text_diff' ) ) :
2136 /**
2137  * Displays a human readable HTML representation of the difference between two strings.
2138  *
2139  * The Diff is available for getting the changes between versions. The output is
2140  * HTML, so the primary use is for displaying the changes. If the two strings
2141  * are equivalent, then an empty string will be returned.
2142  *
2143  * The arguments supported and can be changed are listed below.
2144  *
2145  * 'title' : Default is an empty string. Titles the diff in a manner compatible
2146  *              with the output.
2147  * 'title_left' : Default is an empty string. Change the HTML to the left of the
2148  *              title.
2149  * 'title_right' : Default is an empty string. Change the HTML to the right of
2150  *              the title.
2151  *
2152  * @since 2.6.0
2153  *
2154  * @see wp_parse_args() Used to change defaults to user defined settings.
2155  * @uses Text_Diff
2156  * @uses WP_Text_Diff_Renderer_Table
2157  *
2158  * @param string $left_string "old" (left) version of string
2159  * @param string $right_string "new" (right) version of string
2160  * @param string|array $args Optional. Change 'title', 'title_left', and 'title_right' defaults.
2161  * @return string Empty string if strings are equivalent or HTML with differences.
2162  */
2163 function wp_text_diff( $left_string, $right_string, $args = null ) {
2164         $defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
2165         $args = wp_parse_args( $args, $defaults );
2166
2167         if ( !class_exists( 'WP_Text_Diff_Renderer_Table' ) )
2168                 require( ABSPATH . WPINC . '/wp-diff.php' );
2169
2170         $left_string  = normalize_whitespace($left_string);
2171         $right_string = normalize_whitespace($right_string);
2172
2173         $left_lines  = explode("\n", $left_string);
2174         $right_lines = explode("\n", $right_string);
2175         $text_diff = new Text_Diff($left_lines, $right_lines);
2176         $renderer  = new WP_Text_Diff_Renderer_Table( $args );
2177         $diff = $renderer->render($text_diff);
2178
2179         if ( !$diff )
2180                 return '';
2181
2182         $r  = "<table class='diff'>\n";
2183
2184         if ( ! empty( $args[ 'show_split_view' ] ) ) {
2185                 $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
2186         } else {
2187                 $r .= "<col class='content' />";
2188         }
2189
2190         if ( $args['title'] || $args['title_left'] || $args['title_right'] )
2191                 $r .= "<thead>";
2192         if ( $args['title'] )
2193                 $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
2194         if ( $args['title_left'] || $args['title_right'] ) {
2195                 $r .= "<tr class='diff-sub-title'>\n";
2196                 $r .= "\t<td></td><th>$args[title_left]</th>\n";
2197                 $r .= "\t<td></td><th>$args[title_right]</th>\n";
2198                 $r .= "</tr>\n";
2199         }
2200         if ( $args['title'] || $args['title_left'] || $args['title_right'] )
2201                 $r .= "</thead>\n";
2202
2203         $r .= "<tbody>\n$diff\n</tbody>\n";
2204         $r .= "</table>";
2205
2206         return $r;
2207 }
2208 endif;
2209
2210 if ( ! function_exists( 'hash_equals' ) ) :
2211 /**
2212  * Compare two strings in constant time.
2213  *
2214  * This function is NOT pluggable. It is in this file (in addition to
2215  * compat.php) to prevent errors if, during an update, pluggable.php
2216  * copies over but compat.php does not.
2217  *
2218  * This function was added in PHP 5.6.
2219  * It can leak the length of a string.
2220  *
2221  * @since 3.9.2
2222  *
2223  * @param string $a Expected string.
2224  * @param string $b Actual string.
2225  * @return bool Whether strings are equal.
2226  */
2227 function hash_equals( $a, $b ) {
2228         $a_length = strlen( $a );
2229         if ( $a_length !== strlen( $b ) ) {
2230                 return false;
2231         }
2232         $result = 0;
2233
2234         // Do not attempt to "optimize" this.
2235         for ( $i = 0; $i < $a_length; $i++ ) {
2236                 $result |= ord( $a[ $i ] ) ^ ord( $b[ $i ] );
2237         }
2238
2239         return $result === 0;
2240 }
2241 endif;