[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> pluggable.php (source)

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


Generated: Fri May 25 03:56:23 2012 Hosted by follow the white rabbit.