[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

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

   1  <?php
   2  /**
   3   * Main WordPress API
   4   *
   5   * @package WordPress
   6   */
   7  
   8  require ( ABSPATH . WPINC . '/option.php' );
   9  
  10  /**
  11   * Converts MySQL DATETIME field to user specified date format.
  12   *
  13   * If $dateformatstring has 'G' value, then gmmktime() function will be used to
  14   * make the time. If $dateformatstring is set to 'U', then mktime() function
  15   * will be used to make the time.
  16   *
  17   * The $translate will only be used, if it is set to true and it is by default
  18   * and if the $wp_locale object has the month and weekday set.
  19   *
  20   * @since 0.71
  21   *
  22   * @param string $dateformatstring Either 'G', 'U', or php date format.
  23   * @param string $mysqlstring Time from mysql DATETIME field.
  24   * @param bool $translate Optional. Default is true. Will switch format to locale.
  25   * @return string Date formatted by $dateformatstring or locale (if available).
  26   */
  27  function mysql2date( $dateformatstring, $mysqlstring, $translate = true ) {
  28      $m = $mysqlstring;
  29      if ( empty( $m ) )
  30          return false;
  31  
  32      if ( 'G' == $dateformatstring )
  33          return strtotime( $m . ' +0000' );
  34  
  35      $i = strtotime( $m );
  36  
  37      if ( 'U' == $dateformatstring )
  38          return $i;
  39  
  40      if ( $translate )
  41          return date_i18n( $dateformatstring, $i );
  42      else
  43          return date( $dateformatstring, $i );
  44  }
  45  
  46  /**
  47   * Retrieve the current time based on specified type.
  48   *
  49   * The 'mysql' type will return the time in the format for MySQL DATETIME field.
  50   * The 'timestamp' type will return the current timestamp.
  51   *
  52   * If $gmt is set to either '1' or 'true', then both types will use GMT time.
  53   * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
  54   *
  55   * @since 1.0.0
  56   *
  57   * @param string $type Either 'mysql' or 'timestamp'.
  58   * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false.
  59   * @return int|string String if $type is 'gmt', int if $type is 'timestamp'.
  60   */
  61  function current_time( $type, $gmt = 0 ) {
  62      switch ( $type ) {
  63          case 'mysql':
  64              return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * 3600 ) ) );
  65              break;
  66          case 'timestamp':
  67              return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * 3600 );
  68              break;
  69      }
  70  }
  71  
  72  /**
  73   * Retrieve the date in localized format, based on timestamp.
  74   *
  75   * If the locale specifies the locale month and weekday, then the locale will
  76   * take over the format for the date. If it isn't, then the date format string
  77   * will be used instead.
  78   *
  79   * @since 0.71
  80   *
  81   * @param string $dateformatstring Format to display the date.
  82   * @param int $unixtimestamp Optional. Unix timestamp.
  83   * @param bool $gmt Optional, default is false. Whether to convert to GMT for time.
  84   * @return string The date, translated if locale specifies it.
  85   */
  86  function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
  87      global $wp_locale;
  88      $i = $unixtimestamp;
  89  
  90      if ( false === $i ) {
  91          if ( ! $gmt )
  92              $i = current_time( 'timestamp' );
  93          else
  94              $i = time();
  95          // we should not let date() interfere with our
  96          // specially computed timestamp
  97          $gmt = true;
  98      }
  99  
 100      // store original value for language with untypical grammars
 101      // see http://core.trac.wordpress.org/ticket/9396
 102      $req_format = $dateformatstring;
 103  
 104      $datefunc = $gmt? 'gmdate' : 'date';
 105  
 106      if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
 107          $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
 108          $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
 109          $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
 110          $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
 111          $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
 112          $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
 113          $dateformatstring = ' '.$dateformatstring;
 114          $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
 115          $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
 116          $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
 117          $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
 118          $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
 119          $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
 120  
 121          $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
 122      }
 123      $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
 124      $timezone_formats_re = implode( '|', $timezone_formats );
 125      if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
 126          $timezone_string = get_option( 'timezone_string' );
 127          if ( $timezone_string ) {
 128              $timezone_object = timezone_open( $timezone_string );
 129              $date_object = date_create( null, $timezone_object );
 130              foreach( $timezone_formats as $timezone_format ) {
 131                  if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
 132                      $formatted = date_format( $date_object, $timezone_format );
 133                      $dateformatstring = ' '.$dateformatstring;
 134                      $dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
 135                      $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
 136                  }
 137              }
 138          }
 139      }
 140      $j = @$datefunc( $dateformatstring, $i );
 141      // allow plugins to redo this entirely for languages with untypical grammars
 142      $j = apply_filters('date_i18n', $j, $req_format, $i, $gmt);
 143      return $j;
 144  }
 145  
 146  /**
 147   * Convert integer number to format based on the locale.
 148   *
 149   * @since 2.3.0
 150   *
 151   * @param int $number The number to convert based on locale.
 152   * @param int $decimals Precision of the number of decimal places.
 153   * @return string Converted number in string format.
 154   */
 155  function number_format_i18n( $number, $decimals = 0 ) {
 156      global $wp_locale;
 157      $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
 158      return apply_filters( 'number_format_i18n', $formatted );
 159  }
 160  
 161  /**
 162   * Convert number of bytes largest unit bytes will fit into.
 163   *
 164   * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts
 165   * number of bytes to human readable number by taking the number of that unit
 166   * that the bytes will go into it. Supports TB value.
 167   *
 168   * Please note that integers in PHP are limited to 32 bits, unless they are on
 169   * 64 bit architecture, then they have 64 bit size. If you need to place the
 170   * larger size then what PHP integer type will hold, then use a string. It will
 171   * be converted to a double, which should always have 64 bit length.
 172   *
 173   * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
 174   * @link http://en.wikipedia.org/wiki/Byte
 175   *
 176   * @since 2.3.0
 177   *
 178   * @param int|string $bytes Number of bytes. Note max integer size for integers.
 179   * @param int $decimals Precision of number of decimal places. Deprecated.
 180   * @return bool|string False on failure. Number string on success.
 181   */
 182  function size_format( $bytes, $decimals = 0 ) {
 183      $quant = array(
 184          // ========================= Origin ====
 185          'TB' => 1099511627776,  // pow( 1024, 4)
 186          'GB' => 1073741824,     // pow( 1024, 3)
 187          'MB' => 1048576,        // pow( 1024, 2)
 188          'kB' => 1024,           // pow( 1024, 1)
 189          'B ' => 1,              // pow( 1024, 0)
 190      );
 191      foreach ( $quant as $unit => $mag )
 192          if ( doubleval($bytes) >= $mag )
 193              return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
 194  
 195      return false;
 196  }
 197  
 198  /**
 199   * Get the week start and end from the datetime or date string from mysql.
 200   *
 201   * @since 0.71
 202   *
 203   * @param string $mysqlstring Date or datetime field type from mysql.
 204   * @param int $start_of_week Optional. Start of the week as an integer.
 205   * @return array Keys are 'start' and 'end'.
 206   */
 207  function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
 208      $my = substr( $mysqlstring, 0, 4 ); // Mysql string Year
 209      $mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month
 210      $md = substr( $mysqlstring, 5, 2 ); // Mysql string day
 211      $day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day.
 212      $weekday = date( 'w', $day ); // The day of the week from the timestamp
 213      if ( !is_numeric($start_of_week) )
 214          $start_of_week = get_option( 'start_of_week' );
 215  
 216      if ( $weekday < $start_of_week )
 217          $weekday += 7;
 218  
 219      $start = $day - 86400 * ( $weekday - $start_of_week ); // The most recent week start day on or before $day
 220      $end = $start + 604799; // $start + 7 days - 1 second
 221      return compact( 'start', 'end' );
 222  }
 223  
 224  /**
 225   * Unserialize value only if it was serialized.
 226   *
 227   * @since 2.0.0
 228   *
 229   * @param string $original Maybe unserialized original, if is needed.
 230   * @return mixed Unserialized data can be any type.
 231   */
 232  function maybe_unserialize( $original ) {
 233      if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
 234          return @unserialize( $original );
 235      return $original;
 236  }
 237  
 238  /**
 239   * Check value to find if it was serialized.
 240   *
 241   * If $data is not an string, then returned value will always be false.
 242   * Serialized data is always a string.
 243   *
 244   * @since 2.0.5
 245   *
 246   * @param mixed $data Value to check to see if was serialized.
 247   * @return bool False if not serialized and true if it was.
 248   */
 249  function is_serialized( $data ) {
 250      // if it isn't a string, it isn't serialized
 251      if ( ! is_string( $data ) )
 252          return false;
 253      $data = trim( $data );
 254       if ( 'N;' == $data )
 255          return true;
 256      $length = strlen( $data );
 257      if ( $length < 4 )
 258          return false;
 259      if ( ':' !== $data[1] )
 260          return false;
 261      $lastc = $data[$length-1];
 262      if ( ';' !== $lastc && '}' !== $lastc )
 263          return false;
 264      $token = $data[0];
 265      switch ( $token ) {
 266          case 's' :
 267              if ( '"' !== $data[$length-2] )
 268                  return false;
 269          case 'a' :
 270          case 'O' :
 271              return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
 272          case 'b' :
 273          case 'i' :
 274          case 'd' :
 275              return (bool) preg_match( "/^{$token}:[0-9.E-]+;\$/", $data );
 276      }
 277      return false;
 278  }
 279  
 280  /**
 281   * Check whether serialized data is of string type.
 282   *
 283   * @since 2.0.5
 284   *
 285   * @param mixed $data Serialized data
 286   * @return bool False if not a serialized string, true if it is.
 287   */
 288  function is_serialized_string( $data ) {
 289      // if it isn't a string, it isn't a serialized string
 290      if ( !is_string( $data ) )
 291          return false;
 292      $data = trim( $data );
 293      $length = strlen( $data );
 294      if ( $length < 4 )
 295          return false;
 296      elseif ( ':' !== $data[1] )
 297          return false;
 298      elseif ( ';' !== $data[$length-1] )
 299          return false;
 300      elseif ( $data[0] !== 's' )
 301          return false;
 302      elseif ( '"' !== $data[$length-2] )
 303          return false;
 304      else
 305          return true;
 306  }
 307  
 308  /**
 309   * Serialize data, if needed.
 310   *
 311   * @since 2.0.5
 312   *
 313   * @param mixed $data Data that might be serialized.
 314   * @return mixed A scalar data
 315   */
 316  function maybe_serialize( $data ) {
 317      if ( is_array( $data ) || is_object( $data ) )
 318          return serialize( $data );
 319  
 320      // Double serialization is required for backward compatibility.
 321      // See http://core.trac.wordpress.org/ticket/12930
 322      if ( is_serialized( $data ) )
 323          return serialize( $data );
 324  
 325      return $data;
 326  }
 327  
 328  /**
 329   * Retrieve post title from XMLRPC XML.
 330   *
 331   * If the title element is not part of the XML, then the default post title from
 332   * the $post_default_title will be used instead.
 333   *
 334   * @package WordPress
 335   * @subpackage XMLRPC
 336   * @since 0.71
 337   *
 338   * @global string $post_default_title Default XMLRPC post title.
 339   *
 340   * @param string $content XMLRPC XML Request content
 341   * @return string Post title
 342   */
 343  function xmlrpc_getposttitle( $content ) {
 344      global $post_default_title;
 345      if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
 346          $post_title = $matchtitle[1];
 347      } else {
 348          $post_title = $post_default_title;
 349      }
 350      return $post_title;
 351  }
 352  
 353  /**
 354   * Retrieve the post category or categories from XMLRPC XML.
 355   *
 356   * If the category element is not found, then the default post category will be
 357   * used. The return type then would be what $post_default_category. If the
 358   * category is found, then it will always be an array.
 359   *
 360   * @package WordPress
 361   * @subpackage XMLRPC
 362   * @since 0.71
 363   *
 364   * @global string $post_default_category Default XMLRPC post category.
 365   *
 366   * @param string $content XMLRPC XML Request content
 367   * @return string|array List of categories or category name.
 368   */
 369  function xmlrpc_getpostcategory( $content ) {
 370      global $post_default_category;
 371      if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
 372          $post_category = trim( $matchcat[1], ',' );
 373          $post_category = explode( ',', $post_category );
 374      } else {
 375          $post_category = $post_default_category;
 376      }
 377      return $post_category;
 378  }
 379  
 380  /**
 381   * XMLRPC XML content without title and category elements.
 382   *
 383   * @package WordPress
 384   * @subpackage XMLRPC
 385   * @since 0.71
 386   *
 387   * @param string $content XMLRPC XML Request content
 388   * @return string XMLRPC XML Request content without title and category elements.
 389   */
 390  function xmlrpc_removepostdata( $content ) {
 391      $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
 392      $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
 393      $content = trim( $content );
 394      return $content;
 395  }
 396  
 397  /**
 398   * Open the file handle for debugging.
 399   *
 400   * This function is used for XMLRPC feature, but it is general purpose enough
 401   * to be used in anywhere.
 402   *
 403   * @see fopen() for mode options.
 404   * @package WordPress
 405   * @subpackage Debug
 406   * @since 0.71
 407   * @uses $debug Used for whether debugging is enabled.
 408   *
 409   * @param string $filename File path to debug file.
 410   * @param string $mode Same as fopen() mode parameter.
 411   * @return bool|resource File handle. False on failure.
 412   */
 413  function debug_fopen( $filename, $mode ) {
 414      global $debug;
 415      if ( 1 == $debug ) {
 416          $fp = fopen( $filename, $mode );
 417          return $fp;
 418      } else {
 419          return false;
 420      }
 421  }
 422  
 423  /**
 424   * Write contents to the file used for debugging.
 425   *
 426   * Technically, this can be used to write to any file handle when the global
 427   * $debug is set to 1 or true.
 428   *
 429   * @package WordPress
 430   * @subpackage Debug
 431   * @since 0.71
 432   * @uses $debug Used for whether debugging is enabled.
 433   *
 434   * @param resource $fp File handle for debugging file.
 435   * @param string $string Content to write to debug file.
 436   */
 437  function debug_fwrite( $fp, $string ) {
 438      global $debug;
 439      if ( 1 == $debug )
 440          fwrite( $fp, $string );
 441  }
 442  
 443  /**
 444   * Close the debugging file handle.
 445   *
 446   * Technically, this can be used to close any file handle when the global $debug
 447   * is set to 1 or true.
 448   *
 449   * @package WordPress
 450   * @subpackage Debug
 451   * @since 0.71
 452   * @uses $debug Used for whether debugging is enabled.
 453   *
 454   * @param resource $fp Debug File handle.
 455   */
 456  function debug_fclose( $fp ) {
 457      global $debug;
 458      if ( 1 == $debug )
 459          fclose( $fp );
 460  }
 461  
 462  /**
 463   * Check content for video and audio links to add as enclosures.
 464   *
 465   * Will not add enclosures that have already been added and will
 466   * remove enclosures that are no longer in the post. This is called as
 467   * pingbacks and trackbacks.
 468   *
 469   * @package WordPress
 470   * @since 1.5.0
 471   *
 472   * @uses $wpdb
 473   *
 474   * @param string $content Post Content
 475   * @param int $post_ID Post ID
 476   */
 477  function do_enclose( $content, $post_ID ) {
 478      global $wpdb;
 479  
 480      //TODO: Tidy this ghetto code up and make the debug code optional
 481      include_once ( ABSPATH . WPINC . '/class-IXR.php' );
 482  
 483      $log = debug_fopen( ABSPATH . 'enclosures.log', 'a' );
 484      $post_links = array();
 485      debug_fwrite( $log, 'BEGIN ' . date( 'YmdHis', time() ) . "\n" );
 486  
 487      $pung = get_enclosed( $post_ID );
 488  
 489      $ltrs = '\w';
 490      $gunk = '/#~:.?+=&%@!\-';
 491      $punc = '.:?\-';
 492      $any = $ltrs . $gunk . $punc;
 493  
 494      preg_match_all( "{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp );
 495  
 496      debug_fwrite( $log, 'Post contents:' );
 497      debug_fwrite( $log, $content . "\n" );
 498  
 499      foreach ( $pung as $link_test ) {
 500          if ( !in_array( $link_test, $post_links_temp[0] ) ) { // link no longer in post
 501              $mid = $wpdb->get_col( $wpdb->prepare("SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $link_test ) . '%') );
 502              do_action( 'delete_postmeta', $mid );
 503              $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id IN(%s)", implode( ',', $mid ) ) );
 504              do_action( 'deleted_postmeta', $mid );
 505          }
 506      }
 507  
 508      foreach ( (array) $post_links_temp[0] as $link_test ) {
 509          if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
 510              $test = @parse_url( $link_test );
 511              if ( false === $test )
 512                  continue;
 513              if ( isset( $test['query'] ) )
 514                  $post_links[] = $link_test;
 515              elseif ( isset($test['path']) && ( $test['path'] != '/' ) &&  ($test['path'] != '' ) )
 516                  $post_links[] = $link_test;
 517          }
 518      }
 519  
 520      foreach ( (array) $post_links as $url ) {
 521          if ( $url != '' && !$wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = 'enclosure' AND meta_value LIKE (%s)", $post_ID, like_escape( $url ) . '%' ) ) ) {
 522  
 523              if ( $headers = wp_get_http_headers( $url) ) {
 524                  $len = (int) $headers['content-length'];
 525                  $type = $headers['content-type'];
 526                  $allowed_types = array( 'video', 'audio' );
 527  
 528                  // Check to see if we can figure out the mime type from
 529                  // the extension
 530                  $url_parts = @parse_url( $url );
 531                  if ( false !== $url_parts ) {
 532                      $extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );
 533                      if ( !empty( $extension ) ) {
 534                          foreach ( get_allowed_mime_types( ) as $exts => $mime ) {
 535                              if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
 536                                  $type = $mime;
 537                                  break;
 538                              }
 539                          }
 540                      }
 541                  }
 542  
 543                  if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
 544                      $meta_value = "$url\n$len\n$type\n";
 545                      $wpdb->insert($wpdb->postmeta, array('post_id' => $post_ID, 'meta_key' => 'enclosure', 'meta_value' => $meta_value) );
 546                      do_action( 'added_postmeta', $wpdb->insert_id, $post_ID, 'enclosure', $meta_value );
 547                  }
 548              }
 549          }
 550      }
 551  }
 552  
 553  /**
 554   * Perform a HTTP HEAD or GET request.
 555   *
 556   * If $file_path is a writable filename, this will do a GET request and write
 557   * the file to that path.
 558   *
 559   * @since 2.5.0
 560   *
 561   * @param string $url URL to fetch.
 562   * @param string|bool $file_path Optional. File path to write request to.
 563   * @param int $red (private) The number of Redirects followed, Upon 5 being hit, returns false.
 564   * @return bool|string False on failure and string of headers if HEAD request.
 565   */
 566  function wp_get_http( $url, $file_path = false, $red = 1 ) {
 567      @set_time_limit( 60 );
 568  
 569      if ( $red > 5 )
 570          return false;
 571  
 572      $options = array();
 573      $options['redirection'] = 5;
 574  
 575      if ( false == $file_path )
 576          $options['method'] = 'HEAD';
 577      else
 578          $options['method'] = 'GET';
 579  
 580      $response = wp_remote_request($url, $options);
 581  
 582      if ( is_wp_error( $response ) )
 583          return false;
 584  
 585      $headers = wp_remote_retrieve_headers( $response );
 586      $headers['response'] = wp_remote_retrieve_response_code( $response );
 587  
 588      // WP_HTTP no longer follows redirects for HEAD requests.
 589      if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
 590          return wp_get_http( $headers['location'], $file_path, ++$red );
 591      }
 592  
 593      if ( false == $file_path )
 594          return $headers;
 595  
 596      // GET request - write it to the supplied filename
 597      $out_fp = fopen($file_path, 'w');
 598      if ( !$out_fp )
 599          return $headers;
 600  
 601      fwrite( $out_fp,  wp_remote_retrieve_body( $response ) );
 602      fclose($out_fp);
 603      clearstatcache();
 604  
 605      return $headers;
 606  }
 607  
 608  /**
 609   * Retrieve HTTP Headers from URL.
 610   *
 611   * @since 1.5.1
 612   *
 613   * @param string $url
 614   * @param bool $deprecated Not Used.
 615   * @return bool|string False on failure, headers on success.
 616   */
 617  function wp_get_http_headers( $url, $deprecated = false ) {
 618      if ( !empty( $deprecated ) )
 619          _deprecated_argument( __FUNCTION__, '2.7' );
 620  
 621      $response = wp_remote_head( $url );
 622  
 623      if ( is_wp_error( $response ) )
 624          return false;
 625  
 626      return wp_remote_retrieve_headers( $response );
 627  }
 628  
 629  /**
 630   * Whether today is a new day.
 631   *
 632   * @since 0.71
 633   * @uses $day Today
 634   * @uses $previousday Previous day
 635   *
 636   * @return int 1 when new day, 0 if not a new day.
 637   */
 638  function is_new_day() {
 639      global $currentday, $previousday;
 640      if ( $currentday != $previousday )
 641          return 1;
 642      else
 643          return 0;
 644  }
 645  
 646  /**
 647   * Build URL query based on an associative and, or indexed array.
 648   *
 649   * This is a convenient function for easily building url queries. It sets the
 650   * separator to '&' and uses _http_build_query() function.
 651   *
 652   * @see _http_build_query() Used to build the query
 653   * @link http://us2.php.net/manual/en/function.http-build-query.php more on what
 654   *        http_build_query() does.
 655   *
 656   * @since 2.3.0
 657   *
 658   * @param array $data URL-encode key/value pairs.
 659   * @return string URL encoded string
 660   */
 661  function build_query( $data ) {
 662      return _http_build_query( $data, null, '&', '', false );
 663  }
 664  
 665  // from php.net (modified by Mark Jaquith to behave like the native PHP5 function)
 666  function _http_build_query($data, $prefix=null, $sep=null, $key='', $urlencode=true) {
 667      $ret = array();
 668  
 669      foreach ( (array) $data as $k => $v ) {
 670          if ( $urlencode)
 671              $k = urlencode($k);
 672          if ( is_int($k) && $prefix != null )
 673              $k = $prefix.$k;
 674          if ( !empty($key) )
 675              $k = $key . '%5B' . $k . '%5D';
 676          if ( $v === null )
 677              continue;
 678          elseif ( $v === FALSE )
 679              $v = '0';
 680  
 681          if ( is_array($v) || is_object($v) )
 682              array_push($ret,_http_build_query($v, '', $sep, $k, $urlencode));
 683          elseif ( $urlencode )
 684              array_push($ret, $k.'='.urlencode($v));
 685          else
 686              array_push($ret, $k.'='.$v);
 687      }
 688  
 689      if ( null === $sep )
 690          $sep = ini_get('arg_separator.output');
 691  
 692      return implode($sep, $ret);
 693  }
 694  
 695  /**
 696   * Retrieve a modified URL query string.
 697   *
 698   * You can rebuild the URL and append a new query variable to the URL query by
 699   * using this function. You can also retrieve the full URL with query data.
 700   *
 701   * Adding a single key & value or an associative array. Setting a key value to
 702   * an empty string removes the key. Omitting oldquery_or_uri uses the $_SERVER
 703   * value. Additional values provided are expected to be encoded appropriately
 704   * with urlencode() or rawurlencode().
 705   *
 706   * @since 1.5.0
 707   *
 708   * @param mixed $param1 Either newkey or an associative_array
 709   * @param mixed $param2 Either newvalue or oldquery or uri
 710   * @param mixed $param3 Optional. Old query or uri
 711   * @return string New URL query string.
 712   */
 713  function add_query_arg() {
 714      $ret = '';
 715      if ( is_array( func_get_arg(0) ) ) {
 716          if ( @func_num_args() < 2 || false === @func_get_arg( 1 ) )
 717              $uri = $_SERVER['REQUEST_URI'];
 718          else
 719              $uri = @func_get_arg( 1 );
 720      } else {
 721          if ( @func_num_args() < 3 || false === @func_get_arg( 2 ) )
 722              $uri = $_SERVER['REQUEST_URI'];
 723          else
 724              $uri = @func_get_arg( 2 );
 725      }
 726  
 727      if ( $frag = strstr( $uri, '#' ) )
 728          $uri = substr( $uri, 0, -strlen( $frag ) );
 729      else
 730          $frag = '';
 731  
 732      if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
 733          $protocol = $matches[0];
 734          $uri = substr( $uri, strlen( $protocol ) );
 735      } else {
 736          $protocol = '';
 737      }
 738  
 739      if ( strpos( $uri, '?' ) !== false ) {
 740          $parts = explode( '?', $uri, 2 );
 741          if ( 1 == count( $parts ) ) {
 742              $base = '?';
 743              $query = $parts[0];
 744          } else {
 745              $base = $parts[0] . '?';
 746              $query = $parts[1];
 747          }
 748      } elseif ( !empty( $protocol ) || strpos( $uri, '=' ) === false ) {
 749          $base = $uri . '?';
 750          $query = '';
 751      } else {
 752          $base = '';
 753          $query = $uri;
 754      }
 755  
 756      wp_parse_str( $query, $qs );
 757      $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
 758      if ( is_array( func_get_arg( 0 ) ) ) {
 759          $kayvees = func_get_arg( 0 );
 760          $qs = array_merge( $qs, $kayvees );
 761      } else {
 762          $qs[func_get_arg( 0 )] = func_get_arg( 1 );
 763      }
 764  
 765      foreach ( (array) $qs as $k => $v ) {
 766          if ( $v === false )
 767              unset( $qs[$k] );
 768      }
 769  
 770      $ret = build_query( $qs );
 771      $ret = trim( $ret, '?' );
 772      $ret = preg_replace( '#=(&|$)#', '$1', $ret );
 773      $ret = $protocol . $base . $ret . $frag;
 774      $ret = rtrim( $ret, '?' );
 775      return $ret;
 776  }
 777  
 778  /**
 779   * Removes an item or list from the query string.
 780   *
 781   * @since 1.5.0
 782   *
 783   * @param string|array $key Query key or keys to remove.
 784   * @param bool $query When false uses the $_SERVER value.
 785   * @return string New URL query string.
 786   */
 787  function remove_query_arg( $key, $query=false ) {
 788      if ( is_array( $key ) ) { // removing multiple keys
 789          foreach ( $key as $k )
 790              $query = add_query_arg( $k, false, $query );
 791          return $query;
 792      }
 793      return add_query_arg( $key, false, $query );
 794  }
 795  
 796  /**
 797   * Walks the array while sanitizing the contents.
 798   *
 799   * @since 0.71
 800   *
 801   * @param array $array Array to used to walk while sanitizing contents.
 802   * @return array Sanitized $array.
 803   */
 804  function add_magic_quotes( $array ) {
 805      foreach ( (array) $array as $k => $v ) {
 806          if ( is_array( $v ) ) {
 807              $array[$k] = add_magic_quotes( $v );
 808          } else {
 809              $array[$k] = addslashes( $v );
 810          }
 811      }
 812      return $array;
 813  }
 814  
 815  /**
 816   * HTTP request for URI to retrieve content.
 817   *
 818   * @since 1.5.1
 819   * @uses wp_remote_get()
 820   *
 821   * @param string $uri URI/URL of web page to retrieve.
 822   * @return bool|string HTTP content. False on failure.
 823   */
 824  function wp_remote_fopen( $uri ) {
 825      $parsed_url = @parse_url( $uri );
 826  
 827      if ( !$parsed_url || !is_array( $parsed_url ) )
 828          return false;
 829  
 830      $options = array();
 831      $options['timeout'] = 10;
 832  
 833      $response = wp_remote_get( $uri, $options );
 834  
 835      if ( is_wp_error( $response ) )
 836          return false;
 837  
 838      return wp_remote_retrieve_body( $response );
 839  }
 840  
 841  /**
 842   * Set up the WordPress query.
 843   *
 844   * @since 2.0.0
 845   *
 846   * @param string $query_vars Default WP_Query arguments.
 847   */
 848  function wp( $query_vars = '' ) {
 849      global $wp, $wp_query, $wp_the_query;
 850      $wp->main( $query_vars );
 851  
 852      if ( !isset($wp_the_query) )
 853          $wp_the_query = $wp_query;
 854  }
 855  
 856  /**
 857   * Retrieve the description for the HTTP status.
 858   *
 859   * @since 2.3.0
 860   *
 861   * @param int $code HTTP status code.
 862   * @return string Empty string if not found, or description if found.
 863   */
 864  function get_status_header_desc( $code ) {
 865      global $wp_header_to_desc;
 866  
 867      $code = absint( $code );
 868  
 869      if ( !isset( $wp_header_to_desc ) ) {
 870          $wp_header_to_desc = array(
 871              100 => 'Continue',
 872              101 => 'Switching Protocols',
 873              102 => 'Processing',
 874  
 875              200 => 'OK',
 876              201 => 'Created',
 877              202 => 'Accepted',
 878              203 => 'Non-Authoritative Information',
 879              204 => 'No Content',
 880              205 => 'Reset Content',
 881              206 => 'Partial Content',
 882              207 => 'Multi-Status',
 883              226 => 'IM Used',
 884  
 885              300 => 'Multiple Choices',
 886              301 => 'Moved Permanently',
 887              302 => 'Found',
 888              303 => 'See Other',
 889              304 => 'Not Modified',
 890              305 => 'Use Proxy',
 891              306 => 'Reserved',
 892              307 => 'Temporary Redirect',
 893  
 894              400 => 'Bad Request',
 895              401 => 'Unauthorized',
 896              402 => 'Payment Required',
 897              403 => 'Forbidden',
 898              404 => 'Not Found',
 899              405 => 'Method Not Allowed',
 900              406 => 'Not Acceptable',
 901              407 => 'Proxy Authentication Required',
 902              408 => 'Request Timeout',
 903              409 => 'Conflict',
 904              410 => 'Gone',
 905              411 => 'Length Required',
 906              412 => 'Precondition Failed',
 907              413 => 'Request Entity Too Large',
 908              414 => 'Request-URI Too Long',
 909              415 => 'Unsupported Media Type',
 910              416 => 'Requested Range Not Satisfiable',
 911              417 => 'Expectation Failed',
 912              422 => 'Unprocessable Entity',
 913              423 => 'Locked',
 914              424 => 'Failed Dependency',
 915              426 => 'Upgrade Required',
 916  
 917              500 => 'Internal Server Error',
 918              501 => 'Not Implemented',
 919              502 => 'Bad Gateway',
 920              503 => 'Service Unavailable',
 921              504 => 'Gateway Timeout',
 922              505 => 'HTTP Version Not Supported',
 923              506 => 'Variant Also Negotiates',
 924              507 => 'Insufficient Storage',
 925              510 => 'Not Extended'
 926          );
 927      }
 928  
 929      if ( isset( $wp_header_to_desc[$code] ) )
 930          return $wp_header_to_desc[$code];
 931      else
 932          return '';
 933  }
 934  
 935  /**
 936   * Set HTTP status header.
 937   *
 938   * @since 2.0.0
 939   * @uses apply_filters() Calls 'status_header' on status header string, HTTP
 940   *        HTTP code, HTTP code description, and protocol string as separate
 941   *        parameters.
 942   *
 943   * @param int $header HTTP status code
 944   * @return unknown
 945   */
 946  function status_header( $header ) {
 947      $text = get_status_header_desc( $header );
 948  
 949      if ( empty( $text ) )
 950          return false;
 951  
 952      $protocol = $_SERVER["SERVER_PROTOCOL"];
 953      if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
 954          $protocol = 'HTTP/1.0';
 955      $status_header = "$protocol $header $text";
 956      if ( function_exists( 'apply_filters' ) )
 957          $status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );
 958  
 959      return @header( $status_header, true, $header );
 960  }
 961  
 962  /**
 963   * Gets the header information to prevent caching.
 964   *
 965   * The several different headers cover the different ways cache prevention is handled
 966   * by different browsers
 967   *
 968   * @since 2.8.0
 969   *
 970   * @uses apply_filters()
 971   * @return array The associative array of header names and field values.
 972   */
 973  function wp_get_nocache_headers() {
 974      $headers = array(
 975          'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
 976          'Last-Modified' => gmdate( 'D, d M Y H:i:s' ) . ' GMT',
 977          'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
 978          'Pragma' => 'no-cache',
 979      );
 980  
 981      if ( function_exists('apply_filters') ) {
 982          $headers = (array) apply_filters('nocache_headers', $headers);
 983      }
 984      return $headers;
 985  }
 986  
 987  /**
 988   * Sets the headers to prevent caching for the different browsers.
 989   *
 990   * Different browsers support different nocache headers, so several headers must
 991   * be sent so that all of them get the point that no caching should occur.
 992   *
 993   * @since 2.0.0
 994   * @uses wp_get_nocache_headers()
 995   */
 996  function nocache_headers() {
 997      $headers = wp_get_nocache_headers();
 998      foreach( $headers as $name => $field_value )
 999          @header("{$name}: {$field_value}");
1000  }
1001  
1002  /**
1003   * Set the headers for caching for 10 days with JavaScript content type.
1004   *
1005   * @since 2.1.0
1006   */
1007  function cache_javascript_headers() {
1008      $expiresOffset = 864000; // 10 days
1009      header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
1010      header( "Vary: Accept-Encoding" ); // Handle proxies
1011      header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
1012  }
1013  
1014  /**
1015   * Retrieve the number of database queries during the WordPress execution.
1016   *
1017   * @since 2.0.0
1018   *
1019   * @return int Number of database queries
1020   */
1021  function get_num_queries() {
1022      global $wpdb;
1023      return $wpdb->num_queries;
1024  }
1025  
1026  /**
1027   * Whether input is yes or no. Must be 'y' to be true.
1028   *
1029   * @since 1.0.0
1030   *
1031   * @param string $yn Character string containing either 'y' or 'n'
1032   * @return bool True if yes, false on anything else
1033   */
1034  function bool_from_yn( $yn ) {
1035      return ( strtolower( $yn ) == 'y' );
1036  }
1037  
1038  /**
1039   * Loads the feed template from the use of an action hook.
1040   *
1041   * If the feed action does not have a hook, then the function will die with a
1042   * message telling the visitor that the feed is not valid.
1043   *
1044   * It is better to only have one hook for each feed.
1045   *
1046   * @since 2.1.0
1047   * @uses $wp_query Used to tell if the use a comment feed.
1048   * @uses do_action() Calls 'do_feed_$feed' hook, if a hook exists for the feed.
1049   */
1050  function do_feed() {
1051      global $wp_query;
1052  
1053      $feed = get_query_var( 'feed' );
1054  
1055      // Remove the pad, if present.
1056      $feed = preg_replace( '/^_+/', '', $feed );
1057  
1058      if ( $feed == '' || $feed == 'feed' )
1059          $feed = get_default_feed();
1060  
1061      $hook = 'do_feed_' . $feed;
1062      if ( !has_action($hook) ) {
1063          $message = sprintf( __( 'ERROR: %s is not a valid feed template.' ), esc_html($feed));
1064          wp_die( $message, '', array( 'response' => 404 ) );
1065      }
1066  
1067      do_action( $hook, $wp_query->is_comment_feed );
1068  }
1069  
1070  /**
1071   * Load the RDF RSS 0.91 Feed template.
1072   *
1073   * @since 2.1.0
1074   */
1075  function do_feed_rdf() {
1076      load_template( ABSPATH . WPINC . '/feed-rdf.php' );
1077  }
1078  
1079  /**
1080   * Load the RSS 1.0 Feed Template.
1081   *
1082   * @since 2.1.0
1083   */
1084  function do_feed_rss() {
1085      load_template( ABSPATH . WPINC . '/feed-rss.php' );
1086  }
1087  
1088  /**
1089   * Load either the RSS2 comment feed or the RSS2 posts feed.
1090   *
1091   * @since 2.1.0
1092   *
1093   * @param bool $for_comments True for the comment feed, false for normal feed.
1094   */
1095  function do_feed_rss2( $for_comments ) {
1096      if ( $for_comments )
1097          load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
1098      else
1099          load_template( ABSPATH . WPINC . '/feed-rss2.php' );
1100  }
1101  
1102  /**
1103   * Load either Atom comment feed or Atom posts feed.
1104   *
1105   * @since 2.1.0
1106   *
1107   * @param bool $for_comments True for the comment feed, false for normal feed.
1108   */
1109  function do_feed_atom( $for_comments ) {
1110      if ($for_comments)
1111          load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
1112      else
1113          load_template( ABSPATH . WPINC . '/feed-atom.php' );
1114  }
1115  
1116  /**
1117   * Display the robots.txt file content.
1118   *
1119   * The echo content should be with usage of the permalinks or for creating the
1120   * robots.txt file.
1121   *
1122   * @since 2.1.0
1123   * @uses do_action() Calls 'do_robotstxt' hook for displaying robots.txt rules.
1124   */
1125  function do_robots() {
1126      header( 'Content-Type: text/plain; charset=utf-8' );
1127  
1128      do_action( 'do_robotstxt' );
1129  
1130      $output = "User-agent: *\n";
1131      $public = get_option( 'blog_public' );
1132      if ( '0' == $public ) {
1133          $output .= "Disallow: /\n";
1134      } else {
1135          $site_url = parse_url( site_url() );
1136          $path = ( !empty( $site_url['path'] ) ) ? $site_url['path'] : '';
1137          $output .= "Disallow: $path/wp-admin/\n";
1138          $output .= "Disallow: $path/wp-includes/\n";
1139      }
1140  
1141      echo apply_filters('robots_txt', $output, $public);
1142  }
1143  
1144  /**
1145   * Test whether blog is already installed.
1146   *
1147   * The cache will be checked first. If you have a cache plugin, which saves the
1148   * cache values, then this will work. If you use the default WordPress cache,
1149   * and the database goes away, then you might have problems.
1150   *
1151   * Checks for the option siteurl for whether WordPress is installed.
1152   *
1153   * @since 2.1.0
1154   * @uses $wpdb
1155   *
1156   * @return bool Whether blog is already installed.
1157   */
1158  function is_blog_installed() {
1159      global $wpdb;
1160  
1161      // Check cache first. If options table goes away and we have true cached, oh well.
1162      if ( wp_cache_get( 'is_blog_installed' ) )
1163          return true;
1164  
1165      $suppress = $wpdb->suppress_errors();
1166      if ( ! defined( 'WP_INSTALLING' ) ) {
1167          $alloptions = wp_load_alloptions();
1168      }
1169      // If siteurl is not set to autoload, check it specifically
1170      if ( !isset( $alloptions['siteurl'] ) )
1171          $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
1172      else
1173          $installed = $alloptions['siteurl'];
1174      $wpdb->suppress_errors( $suppress );
1175  
1176      $installed = !empty( $installed );
1177      wp_cache_set( 'is_blog_installed', $installed );
1178  
1179      if ( $installed )
1180          return true;
1181  
1182      // If visiting repair.php, return true and let it take over.
1183      if ( defined( 'WP_REPAIRING' ) )
1184          return true;
1185  
1186      $suppress = $wpdb->suppress_errors();
1187  
1188      // Loop over the WP tables. If none exist, then scratch install is allowed.
1189      // If one or more exist, suggest table repair since we got here because the options
1190      // table could not be accessed.
1191      $wp_tables = $wpdb->tables();
1192      foreach ( $wp_tables as $table ) {
1193          // The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
1194          if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
1195              continue;
1196          if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
1197              continue;
1198  
1199          if ( ! $wpdb->get_results( "DESCRIBE $table;" ) )
1200              continue;
1201  
1202          // One or more tables exist. We are insane.
1203  
1204          wp_load_translations_early();
1205  
1206          // Die with a DB error.
1207          $wpdb->error = sprintf( __( 'One or more database tables are unavailable. The database may need to be <a href="%s">repaired</a>.' ), 'maint/repair.php?referrer=is_blog_installed' );
1208          dead_db();
1209      }
1210  
1211      $wpdb->suppress_errors( $suppress );
1212  
1213      wp_cache_set( 'is_blog_installed', false );
1214  
1215      return false;
1216  }
1217  
1218  /**
1219   * Retrieve URL with nonce added to URL query.
1220   *
1221   * @package WordPress
1222   * @subpackage Security
1223   * @since 2.0.4
1224   *
1225   * @param string $actionurl URL to add nonce action
1226   * @param string $action Optional. Nonce action name
1227   * @return string URL with nonce action added.
1228   */
1229  function wp_nonce_url( $actionurl, $action = -1 ) {
1230      $actionurl = str_replace( '&amp;', '&', $actionurl );
1231      return esc_html( add_query_arg( '_wpnonce', wp_create_nonce( $action ), $actionurl ) );
1232  }
1233  
1234  /**
1235   * Retrieve or display nonce hidden field for forms.
1236   *
1237   * The nonce field is used to validate that the contents of the form came from
1238   * the location on the current site and not somewhere else. The nonce does not
1239   * offer absolute protection, but should protect against most cases. It is very
1240   * important to use nonce field in forms.
1241   *
1242   * The $action and $name are optional, but if you want to have better security,
1243   * it is strongly suggested to set those two parameters. It is easier to just
1244   * call the function without any parameters, because validation of the nonce
1245   * doesn't require any parameters, but since crackers know what the default is
1246   * it won't be difficult for them to find a way around your nonce and cause
1247   * damage.
1248   *
1249   * The input name will be whatever $name value you gave. The input value will be
1250   * the nonce creation value.
1251   *
1252   * @package WordPress
1253   * @subpackage Security
1254   * @since 2.0.4
1255   *
1256   * @param string $action Optional. Action name.
1257   * @param string $name Optional. Nonce name.
1258   * @param bool $referer Optional, default true. Whether to set the referer field for validation.
1259   * @param bool $echo Optional, default true. Whether to display or return hidden form field.
1260   * @return string Nonce field.
1261   */
1262  function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1263      $name = esc_attr( $name );
1264      $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
1265  
1266      if ( $referer )
1267          $nonce_field .= wp_referer_field( false );
1268  
1269      if ( $echo )
1270          echo $nonce_field;
1271  
1272      return $nonce_field;
1273  }
1274  
1275  /**
1276   * Retrieve or display referer hidden field for forms.
1277   *
1278   * The referer link is the current Request URI from the server super global. The
1279   * input name is '_wp_http_referer', in case you wanted to check manually.
1280   *
1281   * @package WordPress
1282   * @subpackage Security
1283   * @since 2.0.4
1284   *
1285   * @param bool $echo Whether to echo or return the referer field.
1286   * @return string Referer field.
1287   */
1288  function wp_referer_field( $echo = true ) {
1289      $ref = esc_attr( $_SERVER['REQUEST_URI'] );
1290      $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. $ref . '" />';
1291  
1292      if ( $echo )
1293          echo $referer_field;
1294      return $referer_field;
1295  }
1296  
1297  /**
1298   * Retrieve or display original referer hidden field for forms.
1299   *
1300   * The input name is '_wp_original_http_referer' and will be either the same
1301   * value of {@link wp_referer_field()}, if that was posted already or it will
1302   * be the current page, if it doesn't exist.
1303   *
1304   * @package WordPress
1305   * @subpackage Security
1306   * @since 2.0.4
1307   *
1308   * @param bool $echo Whether to echo the original http referer
1309   * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to.
1310   * @return string Original referer field.
1311   */
1312  function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
1313      $jump_back_to = ( 'previous' == $jump_back_to ) ? wp_get_referer() : $_SERVER['REQUEST_URI'];
1314      $ref = ( wp_get_original_referer() ) ? wp_get_original_referer() : $jump_back_to;
1315      $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( stripslashes( $ref ) ) . '" />';
1316      if ( $echo )
1317          echo $orig_referer_field;
1318      return $orig_referer_field;
1319  }
1320  
1321  /**
1322   * Retrieve referer from '_wp_http_referer' or HTTP referer. If it's the same
1323   * as the current request URL, will return false.
1324   *
1325   * @package WordPress
1326   * @subpackage Security
1327   * @since 2.0.4
1328   *
1329   * @return string|bool False on failure. Referer URL on success.
1330   */
1331  function wp_get_referer() {
1332      $ref = false;
1333      if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
1334          $ref = $_REQUEST['_wp_http_referer'];
1335      else if ( ! empty( $_SERVER['HTTP_REFERER'] ) )
1336          $ref = $_SERVER['HTTP_REFERER'];
1337  
1338      if ( $ref && $ref !== $_SERVER['REQUEST_URI'] )
1339          return $ref;
1340      return false;
1341  }
1342  
1343  /**
1344   * Retrieve original referer that was posted, if it exists.
1345   *
1346   * @package WordPress
1347   * @subpackage Security
1348   * @since 2.0.4
1349   *
1350   * @return string|bool False if no original referer or original referer if set.
1351   */
1352  function wp_get_original_referer() {
1353      if ( !empty( $_REQUEST['_wp_original_http_referer'] ) )
1354          return $_REQUEST['_wp_original_http_referer'];
1355      return false;
1356  }
1357  
1358  /**
1359   * Recursive directory creation based on full path.
1360   *
1361   * Will attempt to set permissions on folders.
1362   *
1363   * @since 2.0.1
1364   *
1365   * @param string $target Full path to attempt to create.
1366   * @return bool Whether the path was created. True if path already exists.
1367   */
1368  function wp_mkdir_p( $target ) {
1369      // from php.net/mkdir user contributed notes
1370      $target = str_replace( '//', '/', $target );
1371  
1372      // safe mode fails with a trailing slash under certain PHP versions.
1373      $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
1374      if ( empty($target) )
1375          $target = '/';
1376  
1377      if ( file_exists( $target ) )
1378          return @is_dir( $target );
1379  
1380      // Attempting to create the directory may clutter up our display.
1381      if ( @mkdir( $target ) ) {
1382          $stat = @stat( dirname( $target ) );
1383          $dir_perms = $stat['mode'] & 0007777;  // Get the permission bits.
1384          @chmod( $target, $dir_perms );
1385          return true;
1386      } elseif ( is_dir( dirname( $target ) ) ) {
1387              return false;
1388      }
1389  
1390      // If the above failed, attempt to create the parent node, then try again.
1391      if ( ( $target != '/' ) && ( wp_mkdir_p( dirname( $target ) ) ) )
1392          return wp_mkdir_p( $target );
1393  
1394      return false;
1395  }
1396  
1397  /**
1398   * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
1399   *
1400   * @since 2.5.0
1401   *
1402   * @param string $path File path
1403   * @return bool True if path is absolute, false is not absolute.
1404   */
1405  function path_is_absolute( $path ) {
1406      // this is definitive if true but fails if $path does not exist or contains a symbolic link
1407      if ( realpath($path) == $path )
1408          return true;
1409  
1410      if ( strlen($path) == 0 || $path[0] == '.' )
1411          return false;
1412  
1413      // windows allows absolute paths like this
1414      if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
1415          return true;
1416  
1417      // a path starting with / or \ is absolute; anything else is relative
1418      return ( $path[0] == '/' || $path[0] == '\\' );
1419  }
1420  
1421  /**
1422   * Join two filesystem paths together (e.g. 'give me $path relative to $base').
1423   *
1424   * If the $path is absolute, then it the full path is returned.
1425   *
1426   * @since 2.5.0
1427   *
1428   * @param string $base
1429   * @param string $path
1430   * @return string The path with the base or absolute path.
1431   */
1432  function path_join( $base, $path ) {
1433      if ( path_is_absolute($path) )
1434          return $path;
1435  
1436      return rtrim($base, '/') . '/' . ltrim($path, '/');
1437  }
1438  
1439  /**
1440   * Determines a writable directory for temporary files.
1441   * Function's preference is to WP_CONTENT_DIR followed by the return value of <code>sys_get_temp_dir()</code>, before finally defaulting to /tmp/
1442   *
1443   * In the event that this function does not find a writable location, It may be overridden by the <code>WP_TEMP_DIR</code> constant in your <code>wp-config.php</code> file.
1444   *
1445   * @since 2.5.0
1446   *
1447   * @return string Writable temporary directory
1448   */
1449  function get_temp_dir() {
1450      static $temp;
1451      if ( defined('WP_TEMP_DIR') )
1452          return trailingslashit(WP_TEMP_DIR);
1453  
1454      if ( $temp )
1455          return trailingslashit($temp);
1456  
1457      $temp = WP_CONTENT_DIR . '/';
1458      if ( is_dir($temp) && @is_writable($temp) )
1459          return $temp;
1460  
1461      if  ( function_exists('sys_get_temp_dir') ) {
1462          $temp = sys_get_temp_dir();
1463          if ( @is_writable($temp) )
1464              return trailingslashit($temp);
1465      }
1466  
1467      $temp = ini_get('upload_tmp_dir');
1468      if ( is_dir($temp) && @is_writable($temp) )
1469          return trailingslashit($temp);
1470  
1471      $temp = '/tmp/';
1472      return $temp;
1473  }
1474  
1475  /**
1476   * Get an array containing the current upload directory's path and url.
1477   *
1478   * Checks the 'upload_path' option, which should be from the web root folder,
1479   * and if it isn't empty it will be used. If it is empty, then the path will be
1480   * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
1481   * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
1482   *
1483   * The upload URL path is set either by the 'upload_url_path' option or by using
1484   * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
1485   *
1486   * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
1487   * the administration settings panel), then the time will be used. The format
1488   * will be year first and then month.
1489   *
1490   * If the path couldn't be created, then an error will be returned with the key
1491   * 'error' containing the error message. The error suggests that the parent
1492   * directory is not writable by the server.
1493   *
1494   * On success, the returned array will have many indices:
1495   * 'path' - base directory and sub directory or full path to upload directory.
1496   * 'url' - base url and sub directory or absolute URL to upload directory.
1497   * 'subdir' - sub directory if uploads use year/month folders option is on.
1498   * 'basedir' - path without subdir.
1499   * 'baseurl' - URL path without subdir.
1500   * 'error' - set to false.
1501   *
1502   * @since 2.0.0
1503   * @uses apply_filters() Calls 'upload_dir' on returned array.
1504   *
1505   * @param string $time Optional. Time formatted in 'yyyy/mm'.
1506   * @return array See above for description.
1507   */
1508  function wp_upload_dir( $time = null ) {
1509      global $switched;
1510      $siteurl = get_option( 'siteurl' );
1511      $upload_path = get_option( 'upload_path' );
1512      $upload_path = trim($upload_path);
1513      $main_override = is_multisite() && defined( 'MULTISITE' ) && is_main_site();
1514      if ( empty($upload_path) ) {
1515          $dir = WP_CONTENT_DIR . '/uploads';
1516      } else {
1517          $dir = $upload_path;
1518          if ( 'wp-content/uploads' == $upload_path ) {
1519              $dir = WP_CONTENT_DIR . '/uploads';
1520          } elseif ( 0 !== strpos($dir, ABSPATH) ) {
1521              // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
1522              $dir = path_join( ABSPATH, $dir );
1523          }
1524      }
1525  
1526      if ( !$url = get_option( 'upload_url_path' ) ) {
1527          if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) )
1528              $url = WP_CONTENT_URL . '/uploads';
1529          else
1530              $url = trailingslashit( $siteurl ) . $upload_path;
1531      }
1532  
1533      if ( defined('UPLOADS') && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
1534          $dir = ABSPATH . UPLOADS;
1535          $url = trailingslashit( $siteurl ) . UPLOADS;
1536      }
1537  
1538      if ( is_multisite() && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
1539          if ( defined( 'BLOGUPLOADDIR' ) )
1540              $dir = untrailingslashit(BLOGUPLOADDIR);
1541          $url = str_replace( UPLOADS, 'files', $url );
1542      }
1543  
1544      $bdir = $dir;
1545      $burl = $url;
1546  
1547      $subdir = '';
1548      if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
1549          // Generate the yearly and monthly dirs
1550          if ( !$time )
1551              $time = current_time( 'mysql' );
1552          $y = substr( $time, 0, 4 );
1553          $m = substr( $time, 5, 2 );
1554          $subdir = "/$y/$m";
1555      }
1556  
1557      $dir .= $subdir;
1558      $url .= $subdir;
1559  
1560      $uploads = apply_filters( 'upload_dir', array( 'path' => $dir, 'url' => $url, 'subdir' => $subdir, 'basedir' => $bdir, 'baseurl' => $burl, 'error' => false ) );
1561  
1562      // Make sure we have an uploads dir
1563      if ( ! wp_mkdir_p( $uploads['path'] ) ) {
1564          $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $uploads['path'] );
1565          return array( 'error' => $message );
1566      }
1567  
1568      return $uploads;
1569  }
1570  
1571  /**
1572   * Get a filename that is sanitized and unique for the given directory.
1573   *
1574   * If the filename is not unique, then a number will be added to the filename
1575   * before the extension, and will continue adding numbers until the filename is
1576   * unique.
1577   *
1578   * The callback is passed three parameters, the first one is the directory, the
1579   * second is the filename, and the third is the extension.
1580   *
1581   * @since 2.5.0
1582   *
1583   * @param string $dir
1584   * @param string $filename
1585   * @param mixed $unique_filename_callback Callback.
1586   * @return string New filename, if given wasn't unique.
1587   */
1588  function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
1589      // sanitize the file name before we begin processing
1590      $filename = sanitize_file_name($filename);
1591  
1592      // separate the filename into a name and extension
1593      $info = pathinfo($filename);
1594      $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
1595      $name = basename($filename, $ext);
1596  
1597      // edge case: if file is named '.ext', treat as an empty name
1598      if ( $name === $ext )
1599          $name = '';
1600  
1601      // Increment the file number until we have a unique file to save in $dir. Use callback if supplied.
1602      if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
1603          $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext );
1604      } else {
1605          $number = '';
1606  
1607          // change '.ext' to lower case
1608          if ( $ext && strtolower($ext) != $ext ) {
1609              $ext2 = strtolower($ext);
1610              $filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
1611  
1612              // check for both lower and upper case extension or image sub-sizes may be overwritten
1613              while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
1614                  $new_number = $number + 1;
1615                  $filename = str_replace( "$number$ext", "$new_number$ext", $filename );
1616                  $filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
1617                  $number = $new_number;
1618              }
1619              return $filename2;
1620          }
1621  
1622          while ( file_exists( $dir . "/$filename" ) ) {
1623              if ( '' == "$number$ext" )
1624                  $filename = $filename . ++$number . $ext;
1625              else
1626                  $filename = str_replace( "$number$ext", ++$number . $ext, $filename );
1627          }
1628      }
1629  
1630      return $filename;
1631  }
1632  
1633  /**
1634   * Create a file in the upload folder with given content.
1635   *
1636   * If there is an error, then the key 'error' will exist with the error message.
1637   * If success, then the key 'file' will have the unique file path, the 'url' key
1638   * will have the link to the new file. and the 'error' key will be set to false.
1639   *
1640   * This function will not move an uploaded file to the upload folder. It will
1641   * create a new file with the content in $bits parameter. If you move the upload
1642   * file, read the content of the uploaded file, and then you can give the
1643   * filename and content to this function, which will add it to the upload
1644   * folder.
1645   *
1646   * The permissions will be set on the new file automatically by this function.
1647   *
1648   * @since 2.0.0
1649   *
1650   * @param string $name
1651   * @param null $deprecated Never used. Set to null.
1652   * @param mixed $bits File content
1653   * @param string $time Optional. Time formatted in 'yyyy/mm'.
1654   * @return array
1655   */
1656  function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
1657      if ( !empty( $deprecated ) )
1658          _deprecated_argument( __FUNCTION__, '2.0' );
1659  
1660      if ( empty( $name ) )
1661          return array( 'error' => __( 'Empty filename' ) );
1662  
1663      $wp_filetype = wp_check_filetype( $name );
1664      if ( !$wp_filetype['ext'] )
1665          return array( 'error' => __( 'Invalid file type' ) );
1666  
1667      $upload = wp_upload_dir( $time );
1668  
1669      if ( $upload['error'] !== false )
1670          return $upload;
1671  
1672      $upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) );
1673      if ( !is_array( $upload_bits_error ) ) {
1674          $upload[ 'error' ] = $upload_bits_error;
1675          return $upload;
1676      }
1677  
1678      $filename = wp_unique_filename( $upload['path'], $name );
1679  
1680      $new_file = $upload['path'] . "/$filename";
1681      if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
1682          $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), dirname( $new_file ) );
1683          return array( 'error' => $message );
1684      }
1685  
1686      $ifp = @ fopen( $new_file, 'wb' );
1687      if ( ! $ifp )
1688          return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
1689  
1690      @fwrite( $ifp, $bits );
1691      fclose( $ifp );
1692      clearstatcache();
1693  
1694      // Set correct file permissions
1695      $stat = @ stat( dirname( $new_file ) );
1696      $perms = $stat['mode'] & 0007777;
1697      $perms = $perms & 0000666;
1698      @ chmod( $new_file, $perms );
1699      clearstatcache();
1700  
1701      // Compute the URL
1702      $url = $upload['url'] . "/$filename";
1703  
1704      return array( 'file' => $new_file, 'url' => $url, 'error' => false );
1705  }
1706  
1707  /**
1708   * Retrieve the file type based on the extension name.
1709   *
1710   * @package WordPress
1711   * @since 2.5.0
1712   * @uses apply_filters() Calls 'ext2type' hook on default supported types.
1713   *
1714   * @param string $ext The extension to search.
1715   * @return string|null The file type, example: audio, video, document, spreadsheet, etc. Null if not found.
1716   */
1717  function wp_ext2type( $ext ) {
1718      $ext2type = apply_filters( 'ext2type', array(
1719          'audio'       => array( 'aac', 'ac3',  'aif',  'aiff', 'm3a',  'm4a',   'm4b', 'mka', 'mp1', 'mp2',  'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
1720          'video'       => array( 'asf', 'avi',  'divx', 'dv',   'flv',  'm4v',   'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt',  'rm', 'vob', 'wmv' ),
1721          'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt',  'pages', 'pdf', 'rtf', 'wp',  'wpd' ),
1722          'spreadsheet' => array( 'numbers',     'ods',  'xls',  'xlsx', 'xlsb',  'xlsm' ),
1723          'interactive' => array( 'key', 'ppt',  'pptx', 'pptm', 'odp',  'swf' ),
1724          'text'        => array( 'asc', 'csv',  'tsv',  'txt' ),
1725          'archive'     => array( 'bz2', 'cab',  'dmg',  'gz',   'rar',  'sea',   'sit', 'sqx', 'tar', 'tgz',  'zip', '7z' ),
1726          'code'        => array( 'css', 'htm',  'html', 'php',  'js' ),
1727      ));
1728      foreach ( $ext2type as $type => $exts )
1729          if ( in_array( $ext, $exts ) )
1730              return $type;
1731  }
1732  
1733  /**
1734   * Retrieve the file type from the file name.
1735   *
1736   * You can optionally define the mime array, if needed.
1737   *
1738   * @since 2.0.4
1739   *
1740   * @param string $filename File name or path.
1741   * @param array $mimes Optional. Key is the file extension with value as the mime type.
1742   * @return array Values with extension first and mime type.
1743   */
1744  function wp_check_filetype( $filename, $mimes = null ) {
1745      if ( empty($mimes) )
1746          $mimes = get_allowed_mime_types();
1747      $type = false;
1748      $ext = false;
1749  
1750      foreach ( $mimes as $ext_preg => $mime_match ) {
1751          $ext_preg = '!\.(' . $ext_preg . ')$!i';
1752          if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
1753              $type = $mime_match;
1754              $ext = $ext_matches[1];
1755              break;
1756          }
1757      }
1758  
1759      return compact( 'ext', 'type' );
1760  }
1761  
1762  /**
1763   * Attempt to determine the real file type of a file.
1764   * If unable to, the file name extension will be used to determine type.
1765   *
1766   * If it's determined that the extension does not match the file's real type,
1767   * then the "proper_filename" value will be set with a proper filename and extension.
1768   *
1769   * Currently this function only supports validating images known to getimagesize().
1770   *
1771   * @since 3.0.0
1772   *
1773   * @param string $file Full path to the image.
1774   * @param string $filename The filename of the image (may differ from $file due to $file being in a tmp directory)
1775   * @param array $mimes Optional. Key is the file extension with value as the mime type.
1776   * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
1777   */
1778  function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
1779  
1780      $proper_filename = false;
1781  
1782      // Do basic extension validation and MIME mapping
1783      $wp_filetype = wp_check_filetype( $filename, $mimes );
1784      extract( $wp_filetype );
1785  
1786      // We can't do any further validation without a file to work with
1787      if ( ! file_exists( $file ) )
1788          return compact( 'ext', 'type', 'proper_filename' );
1789  
1790      // We're able to validate images using GD
1791      if ( $type && 0 === strpos( $type, 'image/' ) && function_exists('getimagesize') ) {
1792  
1793          // Attempt to figure out what type of image it actually is
1794          $imgstats = @getimagesize( $file );
1795  
1796          // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
1797          if ( !empty($imgstats['mime']) && $imgstats['mime'] != $type ) {
1798              // This is a simplified array of MIMEs that getimagesize() can detect and their extensions
1799              // You shouldn't need to use this filter, but it's here just in case
1800              $mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array(
1801                  'image/jpeg' => 'jpg',
1802                  'image/png'  => 'png',
1803                  'image/gif'  => 'gif',
1804                  'image/bmp'  => 'bmp',
1805                  'image/tiff' => 'tif',
1806              ) );
1807  
1808              // Replace whatever is after the last period in the filename with the correct extension
1809              if ( ! empty( $mime_to_ext[ $imgstats['mime'] ] ) ) {
1810                  $filename_parts = explode( '.', $filename );
1811                  array_pop( $filename_parts );
1812                  $filename_parts[] = $mime_to_ext[ $imgstats['mime'] ];
1813                  $new_filename = implode( '.', $filename_parts );
1814  
1815                  if ( $new_filename != $filename )
1816                      $proper_filename = $new_filename; // Mark that it changed
1817  
1818                  // Redefine the extension / MIME
1819                  $wp_filetype = wp_check_filetype( $new_filename, $mimes );
1820                  extract( $wp_filetype );
1821              }
1822          }
1823      }
1824  
1825      // Let plugins try and validate other types of files
1826      // Should return an array in the style of array( 'ext' => $ext, 'type' => $type, 'proper_filename' => $proper_filename )
1827      return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes );
1828  }
1829  
1830  /**
1831   * Retrieve list of allowed mime types and file extensions.
1832   *
1833   * @since 2.8.6
1834   *
1835   * @return array Array of mime types keyed by the file extension regex corresponding to those types.
1836   */
1837  function get_allowed_mime_types() {
1838      static $mimes = false;
1839  
1840      if ( !$mimes ) {
1841          // Accepted MIME types are set here as PCRE unless provided.
1842          $mimes = apply_filters( 'upload_mimes', array(
1843          'jpg|jpeg|jpe' => 'image/jpeg',
1844          'gif' => 'image/gif',
1845          'png' => 'image/png',
1846          'bmp' => 'image/bmp',
1847          'tif|tiff' => 'image/tiff',
1848          'ico' => 'image/x-icon',
1849          'asf|asx|wax|wmv|wmx' => 'video/asf',
1850          'avi' => 'video/avi',
1851          'divx' => 'video/divx',
1852          'flv' => 'video/x-flv',
1853          'mov|qt' => 'video/quicktime',
1854          'mpeg|mpg|mpe' => 'video/mpeg',
1855          'txt|asc|c|cc|h' => 'text/plain',
1856          'csv' => 'text/csv',
1857          'tsv' => 'text/tab-separated-values',
1858          'ics' => 'text/calendar',
1859          'rtx' => 'text/richtext',
1860          'css' => 'text/css',
1861          'htm|html' => 'text/html',
1862          'mp3|m4a|m4b' => 'audio/mpeg',
1863          'mp4|m4v' => 'video/mp4',
1864          'ra|ram' => 'audio/x-realaudio',
1865          'wav' => 'audio/wav',
1866          'ogg|oga' => 'audio/ogg',
1867          'ogv' => 'video/ogg',
1868          'mid|midi' => 'audio/midi',
1869          'wma' => 'audio/wma',
1870          'mka' => 'audio/x-matroska',
1871          'mkv' => 'video/x-matroska',
1872          'rtf' => 'application/rtf',
1873          'js' => 'application/javascript',
1874          'pdf' => 'application/pdf',
1875          'doc|docx' => 'application/msword',
1876          'pot|pps|ppt|pptx|ppam|pptm|sldm|ppsm|potm' => 'application/vnd.ms-powerpoint',
1877          'wri' => 'application/vnd.ms-write',
1878          'xla|xls|xlsx|xlt|xlw|xlam|xlsb|xlsm|xltm' => 'application/vnd.ms-excel',
1879          'mdb' => 'application/vnd.ms-access',
1880          'mpp' => 'application/vnd.ms-project',
1881          'docm|dotm' => 'application/vnd.ms-word',
1882          'pptx|sldx|ppsx|potx' => 'application/vnd.openxmlformats-officedocument.presentationml',
1883          'xlsx|xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml',
1884          'docx|dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml',
1885          'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
1886          'swf' => 'application/x-shockwave-flash',
1887          'class' => 'application/java',
1888          'tar' => 'application/x-tar',
1889          'zip' => 'application/zip',
1890          'gz|gzip' => 'application/x-gzip',
1891          'rar' => 'application/rar',
1892          '7z' => 'application/x-7z-compressed',
1893          'exe' => 'application/x-msdownload',
1894          // openoffice formats
1895          'odt' => 'application/vnd.oasis.opendocument.text',
1896          'odp' => 'application/vnd.oasis.opendocument.presentation',
1897          'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
1898          'odg' => 'application/vnd.oasis.opendocument.graphics',
1899          'odc' => 'application/vnd.oasis.opendocument.chart',
1900          'odb' => 'application/vnd.oasis.opendocument.database',
1901          'odf' => 'application/vnd.oasis.opendocument.formula',
1902          // wordperfect formats
1903          'wp|wpd' => 'application/wordperfect',
1904          ) );
1905      }
1906  
1907      return $mimes;
1908  }
1909  
1910  /**
1911   * Retrieve nonce action "Are you sure" message.
1912   *
1913   * The action is split by verb and noun. The action format is as follows:
1914   * verb-action_extra. The verb is before the first dash and has the format of
1915   * letters and no spaces and numbers. The noun is after the dash and before the
1916   * underscore, if an underscore exists. The noun is also only letters.
1917   *
1918   * The filter will be called for any action, which is not defined by WordPress.
1919   * You may use the filter for your plugin to explain nonce actions to the user,
1920   * when they get the "Are you sure?" message. The filter is in the format of
1921   * 'explain_nonce_$verb-$noun' with the $verb replaced by the found verb and the
1922   * $noun replaced by the found noun. The two parameters that are given to the
1923   * hook are the localized "Are you sure you want to do this?" message with the
1924   * extra text (the text after the underscore).
1925   *
1926   * @package WordPress
1927   * @subpackage Security
1928   * @since 2.0.4
1929   *
1930   * @param string $action Nonce action.
1931   * @return string Are you sure message.
1932   */
1933  function wp_explain_nonce( $action ) {
1934      if ( $action !== -1 && preg_match( '/([a-z]+)-([a-z]+)(_(.+))?/', $action, $matches ) ) {
1935          $verb = $matches[1];
1936          $noun = $matches[2];
1937  
1938          $trans = array();
1939          $trans['update']['attachment'] = array( __( 'Your attempt to edit this attachment: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
1940  
1941          $trans['add']['category']      = array( __( 'Your attempt to add this category has failed.' ), false );
1942          $trans['delete']['category']   = array( __( 'Your attempt to delete this category: &#8220;%s&#8221; has failed.' ), 'get_cat_name' );
1943          $trans['update']['category']   = array( __( 'Your attempt to edit this category: &#8220;%s&#8221; has failed.' ), 'get_cat_name' );
1944  
1945          $trans['delete']['comment']    = array( __( 'Your attempt to delete this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
1946          $trans['unapprove']['comment'] = array( __( 'Your attempt to unapprove this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
1947          $trans['approve']['comment']   = array( __( 'Your attempt to approve this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
1948          $trans['update']['comment']    = array( __( 'Your attempt to edit this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
1949          $trans['bulk']['comments']     = array( __( 'Your attempt to bulk modify comments has failed.' ), false );
1950          $trans['moderate']['comments'] = array( __( 'Your attempt to moderate comments has failed.' ), false );
1951  
1952          $trans['add']['bookmark']      = array( __( 'Your attempt to add this link has failed.' ), false );
1953          $trans['delete']['bookmark']   = array( __( 'Your attempt to delete this link: &#8220;%s&#8221; has failed.' ), 'use_id' );
1954          $trans['update']['bookmark']   = array( __( 'Your attempt to edit this link: &#8220;%s&#8221; has failed.' ), 'use_id' );
1955          $trans['bulk']['bookmarks']    = array( __( 'Your attempt to bulk modify links has failed.' ), false );
1956  
1957          $trans['add']['page']          = array( __( 'Your attempt to add this page has failed.' ), false );
1958          $trans['delete']['page']       = array( __( 'Your attempt to delete this page: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
1959          $trans['update']['page']       = array( __( 'Your attempt to edit this page: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
1960  
1961          $trans['edit']['plugin']       = array( __( 'Your attempt to edit this plugin file: &#8220;%s&#8221; has failed.' ), 'use_id' );
1962          $trans['activate']['plugin']   = array( __( 'Your attempt to activate this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
1963          $trans['deactivate']['plugin'] = array( __( 'Your attempt to deactivate this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
1964          $trans['upgrade']['plugin']    = array( __( 'Your attempt to update this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
1965  
1966          $trans['add']['post']          = array( __( 'Your attempt to add this post has failed.' ), false );
1967          $trans['delete']['post']       = array( __( 'Your attempt to delete this post: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
1968          $trans['update']['post']       = array( __( 'Your attempt to edit this post: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
1969  
1970          $trans['add']['user']          = array( __( 'Your attempt to add this user has failed.' ), false );
1971          $trans['delete']['users']      = array( __( 'Your attempt to delete users has failed.' ), false );
1972          $trans['bulk']['users']        = array( __( 'Your attempt to bulk modify users has failed.' ), false );
1973          $trans['update']['user']       = array( __( 'Your attempt to edit this user: &#8220;%s&#8221; has failed.' ), 'get_the_author_meta', 'display_name' );
1974          $trans['update']['profile']    = array( __( 'Your attempt to modify the profile for: &#8220;%s&#8221; has failed.' ), 'get_the_author_meta', 'display_name' );
1975  
1976          $trans['update']['options']    = array( __( 'Your attempt to edit your settings has failed.' ), false );
1977          $trans['update']['permalink']  = array( __( 'Your attempt to change your permalink structure to: %s has failed.' ), 'use_id' );
1978          $trans['edit']['file']         = array( __( 'Your attempt to edit this file: &#8220;%s&#8221; has failed.' ), 'use_id' );
1979          $trans['edit']['theme']        = array( __( 'Your attempt to edit this theme file: &#8220;%s&#8221; has failed.' ), 'use_id' );
1980          $trans['switch']['theme']      = array( __( 'Your attempt to switch to this theme: &#8220;%s&#8221; has failed.' ), 'use_id' );
1981  
1982          $trans['log']['out']           = array( sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'sitename' ) ), false );
1983  
1984          if ( isset( $trans[$verb][$noun] ) ) {
1985              if ( !empty( $trans[$verb][$noun][1] ) ) {
1986                  $lookup = $trans[$verb][$noun][1];
1987                  if ( isset($trans[$verb][$noun][2]) )
1988                      $lookup_value = $trans[$verb][$noun][2];
1989                  $object = $matches[4];
1990                  if ( 'use_id' != $lookup ) {
1991                      if ( isset( $lookup_value ) )
1992                          $object = call_user_func( $lookup, $lookup_value, $object );
1993                      else
1994                          $object = call_user_func( $lookup, $object );
1995                  }
1996                  return sprintf( $trans[$verb][$noun][0], esc_html($object) );
1997              } else {
1998                  return $trans[$verb][$noun][0];
1999              }
2000          }
2001  
2002          return apply_filters( 'explain_nonce_' . $verb . '-' . $noun, __( 'Are you sure you want to do this?' ), isset($matches[4]) ? $matches[4] : '' );
2003      } else {
2004          return apply_filters( 'explain_nonce_' . $action, __( 'Are you sure you want to do this?' ) );
2005      }
2006  }
2007  
2008  /**
2009   * Display "Are You Sure" message to confirm the action being taken.
2010   *
2011   * If the action has the nonce explain message, then it will be displayed along
2012   * with the "Are you sure?" message.
2013   *
2014   * @package WordPress
2015   * @subpackage Security
2016   * @since 2.0.4
2017   *
2018   * @param string $action The nonce action.
2019   */
2020  function wp_nonce_ays( $action ) {
2021      $title = __( 'WordPress Failure Notice' );
2022      $html = esc_html( wp_explain_nonce( $action ) );
2023      if ( 'log-out' == $action )
2024          $html .= "</p><p>" . sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url() );
2025      elseif ( wp_get_referer() )
2026          $html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
2027  
2028      wp_die( $html, $title, array('response' => 403) );
2029  }
2030  
2031  /**
2032   * Kill WordPress execution and display HTML message with error message.
2033   *
2034   * This function complements the die() PHP function. The difference is that
2035   * HTML will be displayed to the user. It is recommended to use this function
2036   * only, when the execution should not continue any further. It is not
2037   * recommended to call this function very often and try to handle as many errors
2038   * as possible silently.
2039   *
2040   * @since 2.0.4
2041   *
2042   * @param string $message Error message.
2043   * @param string $title Error title.
2044   * @param string|array $args Optional arguments to control behavior.
2045   */
2046  function wp_die( $message = '', $title = '', $args = array() ) {
2047      if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
2048          $function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
2049      elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST )
2050          $function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
2051      else
2052          $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
2053  
2054      call_user_func( $function, $message, $title, $args );
2055  }
2056  
2057  /**
2058   * Kill WordPress execution and display HTML message with error message.
2059   *
2060   * This is the default handler for wp_die if you want a custom one for your
2061   * site then you can overload using the wp_die_handler filter in wp_die
2062   *
2063   * @since 3.0.0
2064   * @access private
2065   *
2066   * @param string $message Error message.
2067   * @param string $title Error title.
2068   * @param string|array $args Optional arguments to control behavior.
2069   */
2070  function _default_wp_die_handler( $message, $title = '', $args = array() ) {
2071      $defaults = array( 'response' => 500 );
2072      $r = wp_parse_args($args, $defaults);
2073  
2074      $have_gettext = function_exists('__');
2075  
2076      if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
2077          if ( empty( $title ) ) {
2078              $error_data = $message->get_error_data();
2079              if ( is_array( $error_data ) && isset( $error_data['title'] ) )
2080                  $title = $error_data['title'];
2081          }
2082          $errors = $message->get_error_messages();
2083          switch ( count( $errors ) ) :
2084          case 0 :
2085              $message = '';
2086              break;
2087          case 1 :
2088              $message = "<p>{$errors[0]}</p>";
2089              break;
2090          default :
2091              $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
2092              break;
2093          endswitch;
2094      } elseif ( is_string( $message ) ) {
2095          $message = "<p>$message</p>";
2096      }
2097  
2098      if ( isset( $r['back_link'] ) && $r['back_link'] ) {
2099          $back_text = $have_gettext? __('&laquo; Back') : '&laquo; Back';
2100          $message .= "\n<p><a href='javascript:history.back()'>$back_text</a></p>";
2101      }
2102  
2103      if ( ! did_action( 'admin_head' ) ) :
2104          if ( !headers_sent() ) {
2105              status_header( $r['response'] );
2106              nocache_headers();
2107              header( 'Content-Type: text/html; charset=utf-8' );
2108          }
2109  
2110          if ( empty($title) )
2111              $title = $have_gettext ? __('WordPress &rsaquo; Error') : 'WordPress &rsaquo; Error';
2112  
2113          $text_direction = 'ltr';
2114          if ( isset($r['text_direction']) && 'rtl' == $r['text_direction'] )
2115              $text_direction = 'rtl';
2116          elseif ( function_exists( 'is_rtl' ) && is_rtl() )
2117              $text_direction = 'rtl';
2118  ?>
2119  <!DOCTYPE html>
2120  <!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono
2121  -->
2122  <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) && function_exists( 'is_rtl' ) ) language_attributes(); else echo "dir='$text_direction'"; ?>>
2123  <head>
2124      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2125      <title><?php echo $title ?></title>
2126      <style type="text/css">
2127          html {
2128              background: #f9f9f9;
2129          }
2130          body {
2131              background: #fff;
2132              color: #333;
2133              font-family: sans-serif;
2134              margin: 2em auto;
2135              padding: 1em 2em;
2136              -webkit-border-radius: 3px;
2137              border-radius: 3px;
2138              border: 1px solid #dfdfdf;
2139              max-width: 700px;
2140          }
2141          #error-page {
2142              margin-top: 50px;
2143          }
2144          #error-page p {
2145              font-size: 14px;
2146              line-height: 1.5;
2147              margin: 25px 0 20px;
2148          }
2149          #error-page code {
2150              font-family: Consolas, Monaco, monospace;
2151          }
2152          ul li {
2153              margin-bottom: 10px;
2154              font-size: 14px ;
2155          }
2156          a {
2157              color: #21759B;
2158              text-decoration: none;
2159          }
2160          a:hover {
2161              color: #D54E21;
2162          }
2163  
2164          .button {
2165              font-family: sans-serif;
2166              text-decoration: none;
2167              font-size: 14px !important;
2168              line-height: 16px;
2169              padding: 6px 12px;
2170              cursor: pointer;
2171              border: 1px solid #bbb;
2172              color: #464646;
2173              -webkit-border-radius: 15px;
2174              border-radius: 15px;
2175              -moz-box-sizing: content-box;
2176              -webkit-box-sizing: content-box;
2177              box-sizing: content-box;
2178              background-color: #f5f5f5;
2179              background-image: -ms-linear-gradient(top, #ffffff, #f2f2f2);
2180              background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
2181              background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
2182              background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f2f2f2));
2183              background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
2184              background-image: linear-gradient(top, #ffffff, #f2f2f2);
2185          }
2186  
2187          .button:hover {
2188              color: #000;
2189              border-color: #666;
2190          }
2191  
2192          .button:active {
2193              background-image: -ms-linear-gradient(top, #f2f2f2, #ffffff);
2194              background-image: -moz-linear-gradient(top, #f2f2f2, #ffffff);
2195              background-image: -o-linear-gradient(top, #f2f2f2, #ffffff);
2196              background-image: -webkit-gradient(linear, left top, left bottom, from(#f2f2f2), to(#ffffff));
2197              background-image: -webkit-linear-gradient(top, #f2f2f2, #ffffff);
2198              background-image: linear-gradient(top, #f2f2f2, #ffffff);
2199          }
2200  
2201          <?php if ( 'rtl' == $text_direction ) : ?>
2202          body { font-family: Tahoma, Arial; }
2203          <?php endif; ?>
2204      </style>
2205  </head>
2206  <body id="error-page">
2207  <?php endif; // ! did_action( 'admin_head' ) ?>
2208      <?php echo $message; ?>
2209  </body>
2210  </html>
2211  <?php
2212      die();
2213  }
2214  
2215  /**
2216   * Kill WordPress execution and display XML message with error message.
2217   *
2218   * This is the handler for wp_die when processing XMLRPC requests.
2219   *
2220   * @since 3.2.0
2221   * @access private
2222   *
2223   * @param string $message Error message.
2224   * @param string $title Error title.
2225   * @param string|array $args Optional arguments to control behavior.
2226   */
2227  function _xmlrpc_wp_die_handler( $message, $title = '', $args = array() ) {
2228      global $wp_xmlrpc_server;
2229      $defaults = array( 'response' => 500 );
2230  
2231      $r = wp_parse_args($args, $defaults);
2232  
2233      if ( $wp_xmlrpc_server ) {
2234          $error = new IXR_Error( $r['response'] , $message);
2235          $wp_xmlrpc_server->output( $error->getXml() );
2236      }
2237      die();
2238  }
2239  
2240  /**
2241   * Kill WordPress ajax execution.
2242   *
2243   * This is the handler for wp_die when processing Ajax requests.
2244   *
2245   * @since 3.4.0
2246   * @access private
2247   *
2248   * @param string $message Optional. Response to print.
2249   */
2250  function _ajax_wp_die_handler( $message = '' ) {
2251      if ( is_scalar( $message ) )
2252          die( (string) $message );
2253      die( '0' );
2254  }
2255  
2256  /**
2257   * Retrieve the WordPress home page URL.
2258   *
2259   * If the constant named 'WP_HOME' exists, then it will be used and returned by
2260   * the function. This can be used to counter the redirection on your local
2261   * development environment.
2262   *
2263   * @access private
2264   * @package WordPress
2265   * @since 2.2.0
2266   *
2267   * @param string $url URL for the home location
2268   * @return string Homepage location.
2269   */
2270  function _config_wp_home( $url = '' ) {
2271      if ( defined( 'WP_HOME' ) )
2272          return untrailingslashit( WP_HOME );
2273      return $url;
2274  }
2275  
2276  /**
2277   * Retrieve the WordPress site URL.
2278   *
2279   * If the constant named 'WP_SITEURL' is defined, then the value in that
2280   * constant will always be returned. This can be used for debugging a site on
2281   * your localhost while not having to change the database to your URL.
2282   *
2283   * @access private
2284   * @package WordPress
2285   * @since 2.2.0
2286   *
2287   * @param string $url URL to set the WordPress site location.
2288   * @return string The WordPress Site URL
2289   */
2290  function _config_wp_siteurl( $url = '' ) {
2291      if ( defined( 'WP_SITEURL' ) )
2292          return untrailingslashit( WP_SITEURL );
2293      return $url;
2294  }
2295  
2296  /**
2297   * Set the localized direction for MCE plugin.
2298   *
2299   * Will only set the direction to 'rtl', if the WordPress locale has the text
2300   * direction set to 'rtl'.
2301   *
2302   * Fills in the 'directionality', 'plugins', and 'theme_advanced_button1' array
2303   * keys. These keys are then returned in the $input array.
2304   *
2305   * @access private
2306   * @package WordPress
2307   * @subpackage MCE
2308   * @since 2.1.0
2309   *
2310   * @param array $input MCE plugin array.
2311   * @return array Direction set for 'rtl', if needed by locale.
2312   */
2313  function _mce_set_direction( $input ) {
2314      if ( is_rtl() ) {
2315          $input['directionality'] = 'rtl';
2316          $input['plugins'] .= ',directionality';
2317          $input['theme_advanced_buttons1'] .= ',ltr';
2318      }
2319  
2320      return $input;
2321  }
2322  
2323  /**
2324   * Convert smiley code to the icon graphic file equivalent.
2325   *
2326   * You can turn off smilies, by going to the write setting screen and unchecking
2327   * the box, or by setting 'use_smilies' option to false or removing the option.
2328   *
2329   * Plugins may override the default smiley list by setting the $wpsmiliestrans
2330   * to an array, with the key the code the blogger types in and the value the
2331   * image file.
2332   *
2333   * The $wp_smiliessearch global is for the regular expression and is set each
2334   * time the function is called.
2335   *
2336   * The full list of smilies can be found in the function and won't be listed in
2337   * the description. Probably should create a Codex page for it, so that it is
2338   * available.
2339   *
2340   * @global array $wpsmiliestrans
2341   * @global array $wp_smiliessearch
2342   * @since 2.2.0
2343   */
2344  function smilies_init() {
2345      global $wpsmiliestrans, $wp_smiliessearch;
2346  
2347      // don't bother setting up smilies if they are disabled
2348      if ( !get_option( 'use_smilies' ) )
2349          return;
2350  
2351      if ( !isset( $wpsmiliestrans ) ) {
2352          $wpsmiliestrans = array(
2353          ':mrgreen:' => 'icon_mrgreen.gif',
2354          ':neutral:' => 'icon_neutral.gif',
2355          ':twisted:' => 'icon_twisted.gif',
2356            ':arrow:' => 'icon_arrow.gif',
2357            ':shock:' => 'icon_eek.gif',
2358            ':smile:' => 'icon_smile.gif',
2359              ':???:' => 'icon_confused.gif',
2360             ':cool:' => 'icon_cool.gif',
2361             ':evil:' => 'icon_evil.gif',
2362             ':grin:' => 'icon_biggrin.gif',
2363             ':idea:' => 'icon_idea.gif',
2364             ':oops:' => 'icon_redface.gif',
2365             ':razz:' => 'icon_razz.gif',
2366             ':roll:' => 'icon_rolleyes.gif',
2367             ':wink:' => 'icon_wink.gif',
2368              ':cry:' => 'icon_cry.gif',
2369              ':eek:' => 'icon_surprised.gif',
2370              ':lol:' => 'icon_lol.gif',
2371              ':mad:' => 'icon_mad.gif',
2372              ':sad:' => 'icon_sad.gif',
2373                '8-)' => 'icon_cool.gif',
2374                '8-O' => 'icon_eek.gif',
2375                ':-(' => 'icon_sad.gif',
2376                ':-)' => 'icon_smile.gif',
2377                ':-?' => 'icon_confused.gif',
2378                ':-D' => 'icon_biggrin.gif',
2379                ':-P' => 'icon_razz.gif',
2380                ':-o' => 'icon_surprised.gif',
2381                ':-x' => 'icon_mad.gif',
2382                ':-|' => 'icon_neutral.gif',
2383                ';-)' => 'icon_wink.gif',
2384          // This one transformation breaks regular text with frequency.
2385          //     '8)' => 'icon_cool.gif',
2386                 '8O' => 'icon_eek.gif',
2387                 ':(' => 'icon_sad.gif',
2388                 ':)' => 'icon_smile.gif',
2389                 ':?' => 'icon_confused.gif',
2390                 ':D' => 'icon_biggrin.gif',
2391                 ':P' => 'icon_razz.gif',
2392                 ':o' => 'icon_surprised.gif',
2393                 ':x' => 'icon_mad.gif',
2394                 ':|' => 'icon_neutral.gif',
2395                 ';)' => 'icon_wink.gif',
2396                ':!:' => 'icon_exclaim.gif',
2397                ':?:' => 'icon_question.gif',
2398          );
2399      }
2400  
2401      if (count($wpsmiliestrans) == 0) {
2402          return;
2403      }
2404  
2405      /*
2406       * NOTE: we sort the smilies in reverse key order. This is to make sure
2407       * we match the longest possible smilie (:???: vs :?) as the regular
2408       * expression used below is first-match
2409       */
2410      krsort($wpsmiliestrans);
2411  
2412      $wp_smiliessearch = '/(?:\s|^)';
2413  
2414      $subchar = '';
2415      foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
2416          $firstchar = substr($smiley, 0, 1);
2417          $rest = substr($smiley, 1);
2418  
2419          // new subpattern?
2420          if ($firstchar != $subchar) {
2421              if ($subchar != '') {
2422                  $wp_smiliessearch .= ')|(?:\s|^)';
2423              }
2424              $subchar = $firstchar;
2425              $wp_smiliessearch .= preg_quote($firstchar, '/') . '(?:';
2426          } else {
2427              $wp_smiliessearch .= '|';
2428          }
2429          $wp_smiliessearch .= preg_quote($rest, '/');
2430      }
2431  
2432      $wp_smiliessearch .= ')(?:\s|$)/m';
2433  }
2434  
2435  /**
2436   * Merge user defined arguments into defaults array.
2437   *
2438   * This function is used throughout WordPress to allow for both string or array
2439   * to be merged into another array.
2440   *
2441   * @since 2.2.0
2442   *
2443   * @param string|array $args Value to merge with $defaults
2444   * @param array $defaults Array that serves as the defaults.
2445   * @return array Merged user defined values with defaults.
2446   */
2447  function wp_parse_args( $args, $defaults = '' ) {
2448      if ( is_object( $args ) )
2449          $r = get_object_vars( $args );
2450      elseif ( is_array( $args ) )
2451          $r =& $args;
2452      else
2453          wp_parse_str( $args, $r );
2454  
2455      if ( is_array( $defaults ) )
2456          return array_merge( $defaults, $r );
2457      return $r;
2458  }
2459  
2460  /**
2461   * Clean up an array, comma- or space-separated list of IDs.
2462   *
2463   * @since 3.0.0
2464   *
2465   * @param array|string $list
2466   * @return array Sanitized array of IDs
2467   */
2468  function wp_parse_id_list( $list ) {
2469      if ( !is_array($list) )
2470          $list = preg_split('/[\s,]+/', $list);
2471  
2472      return array_unique(array_map('absint', $list));
2473  }
2474  
2475  /**
2476   * Extract a slice of an array, given a list of keys.
2477   *
2478   * @since 3.1.0
2479   *
2480   * @param array $array The original array
2481   * @param array $keys The list of keys
2482   * @return array The array slice
2483   */
2484  function wp_array_slice_assoc( $array, $keys ) {
2485      $slice = array();
2486      foreach ( $keys as $key )
2487          if ( isset( $array[ $key ] ) )
2488              $slice[ $key ] = $array[ $key ];
2489  
2490      return $slice;
2491  }
2492  
2493  /**
2494   * Filters a list of objects, based on a set of key => value arguments.
2495   *
2496   * @since 3.0.0
2497   *
2498   * @param array $list An array of objects to filter
2499   * @param array $args An array of key => value arguments to match against each object
2500   * @param string $operator The logical operation to perform. 'or' means only one element
2501   *    from the array needs to match; 'and' means all elements must match. The default is 'and'.
2502   * @param bool|string $field A field from the object to place instead of the entire object
2503   * @return array A list of objects or object fields
2504   */
2505  function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
2506      if ( ! is_array( $list ) )
2507          return array();
2508  
2509      $list = wp_list_filter( $list,