[ XREF Home ] [ Index ]

PHP Cross Reference of WordPress Trunk

Provided by Yoast

title

Body

[close]

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

   1  <?php
   2  /**
   3   * Main WordPress API
   4   *
   5   * @package WordPress
   6   */
   7  
   8  /**
   9   * Converts MySQL DATETIME field to user specified date format.
  10   *
  11   * If $dateformatstring has 'G' value, then gmmktime() function will be used to
  12   * make the time. If $dateformatstring is set to 'U', then mktime() function
  13   * will be used to make the time.
  14   *
  15   * The $translate will only be used, if it is set to true and it is by default
  16   * and if the $wp_locale object has the month and weekday set.
  17   *
  18   * @since 0.71
  19   *
  20   * @param string $dateformatstring Either 'G', 'U', or php date format.
  21   * @param string $mysqlstring Time from mysql DATETIME field.
  22   * @param bool $translate Optional. Default is true. Will switch format to locale.
  23   * @return string Date formated by $dateformatstring or locale (if available).
  24   */
  25  function mysql2date( $dateformatstring, $mysqlstring, $translate = true ) {
  26      $m = $mysqlstring;
  27      if ( empty( $m ) )
  28          return false;
  29  
  30      if ( 'G' == $dateformatstring )
  31          return strtotime( $m . ' +0000' );
  32  
  33      $i = strtotime( $m );
  34  
  35      if ( 'U' == $dateformatstring )
  36          return $i;
  37  
  38      if ( $translate )
  39          return date_i18n( $dateformatstring, $i );
  40      else
  41          return date( $dateformatstring, $i );
  42  }
  43  
  44  /**
  45   * Retrieve the current time based on specified type.
  46   *
  47   * The 'mysql' type will return the time in the format for MySQL DATETIME field.
  48   * The 'timestamp' type will return the current timestamp.
  49   *
  50   * If $gmt is set to either '1' or 'true', then both types will use GMT time.
  51   * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
  52   *
  53   * @since 1.0.0
  54   *
  55   * @param string $type Either 'mysql' or 'timestamp'.
  56   * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false.
  57   * @return int|string String if $type is 'gmt', int if $type is 'timestamp'.
  58   */
  59  function current_time( $type, $gmt = 0 ) {
  60      switch ( $type ) {
  61          case 'mysql':
  62              return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * 3600 ) ) );
  63              break;
  64          case 'timestamp':
  65              return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * 3600 );
  66              break;
  67      }
  68  }
  69  
  70  /**
  71   * Retrieve the date in localized format, based on timestamp.
  72   *
  73   * If the locale specifies the locale month and weekday, then the locale will
  74   * take over the format for the date. If it isn't, then the date format string
  75   * will be used instead.
  76   *
  77   * @since 0.71
  78   *
  79   * @param string $dateformatstring Format to display the date.
  80   * @param int $unixtimestamp Optional. Unix timestamp.
  81   * @param bool $gmt Optional, default is false. Whether to convert to GMT for time.
  82   * @return string The date, translated if locale specifies it.
  83   */
  84  function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
  85      global $wp_locale;
  86      $i = $unixtimestamp;
  87  
  88      if ( false === $i ) {
  89          if ( ! $gmt )
  90              $i = current_time( 'timestamp' );
  91          else
  92              $i = time();
  93          // we should not let date() interfere with our
  94          // specially computed timestamp
  95          $gmt = true;
  96      }
  97  
  98      // store original value for language with untypical grammars
  99      // see http://core.trac.wordpress.org/ticket/9396
 100      $req_format = $dateformatstring;
 101  
 102      $datefunc = $gmt? 'gmdate' : 'date';
 103  
 104      if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
 105          $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
 106          $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
 107          $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
 108          $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
 109          $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
 110          $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
 111          $dateformatstring = ' '.$dateformatstring;
 112          $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
 113          $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
 114          $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
 115          $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
 116          $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
 117          $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
 118  
 119          $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
 120      }
 121      $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
 122      $timezone_formats_re = implode( '|', $timezone_formats );
 123      if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
 124          $timezone_string = get_option( 'timezone_string' );
 125          if ( $timezone_string ) {
 126              $timezone_object = timezone_open( $timezone_string );
 127              $date_object = date_create( null, $timezone_object );
 128              foreach( $timezone_formats as $timezone_format ) {
 129                  if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
 130                      $formatted = date_format( $date_object, $timezone_format );
 131                      $dateformatstring = ' '.$dateformatstring;
 132                      $dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
 133                      $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
 134                  }
 135              }
 136          }
 137      }
 138      $j = @$datefunc( $dateformatstring, $i );
 139      // allow plugins to redo this entirely for languages with untypical grammars
 140      $j = apply_filters('date_i18n', $j, $req_format, $i, $gmt);
 141      return $j;
 142  }
 143  
 144  /**
 145   * Convert integer number to format based on the locale.
 146   *
 147   * @since 2.3.0
 148   *
 149   * @param int $number The number to convert based on locale.
 150   * @param int $decimals Precision of the number of decimal places.
 151   * @return string Converted number in string format.
 152   */
 153  function number_format_i18n( $number, $decimals = 0 ) {
 154      global $wp_locale;
 155      $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
 156      return apply_filters( 'number_format_i18n', $formatted );
 157  }
 158  
 159  /**
 160   * Convert number of bytes largest unit bytes will fit into.
 161   *
 162   * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts
 163   * number of bytes to human readable number by taking the number of that unit
 164   * that the bytes will go into it. Supports TB value.
 165   *
 166   * Please note that integers in PHP are limited to 32 bits, unless they are on
 167   * 64 bit architecture, then they have 64 bit size. If you need to place the
 168   * larger size then what PHP integer type will hold, then use a string. It will
 169   * be converted to a double, which should always have 64 bit length.
 170   *
 171   * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
 172   * @link http://en.wikipedia.org/wiki/Byte
 173   *
 174   * @since 2.3.0
 175   *
 176   * @param int|string $bytes Number of bytes. Note max integer size for integers.
 177   * @param int $decimals Precision of number of decimal places. Deprecated.
 178   * @return bool|string False on failure. Number string on success.
 179   */
 180  function size_format( $bytes, $decimals = 0 ) {
 181      $quant = array(
 182          // ========================= Origin ====
 183          'TB' => 1099511627776,  // pow( 1024, 4)
 184          'GB' => 1073741824,     // pow( 1024, 3)
 185          'MB' => 1048576,        // pow( 1024, 2)
 186          'kB' => 1024,           // pow( 1024, 1)
 187          'B ' => 1,              // pow( 1024, 0)
 188      );
 189      foreach ( $quant as $unit => $mag )
 190          if ( doubleval($bytes) >= $mag )
 191              return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
 192  
 193      return false;
 194  }
 195  
 196  /**
 197   * Get the week start and end from the datetime or date string from mysql.
 198   *
 199   * @since 0.71
 200   *
 201   * @param string $mysqlstring Date or datetime field type from mysql.
 202   * @param int $start_of_week Optional. Start of the week as an integer.
 203   * @return array Keys are 'start' and 'end'.
 204   */
 205  function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
 206      $my = substr( $mysqlstring, 0, 4 ); // Mysql string Year
 207      $mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month
 208      $md = substr( $mysqlstring, 5, 2 ); // Mysql string day
 209      $day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day.
 210      $weekday = date( 'w', $day ); // The day of the week from the timestamp
 211      if ( !is_numeric($start_of_week) )
 212          $start_of_week = get_option( 'start_of_week' );
 213  
 214      if ( $weekday < $start_of_week )
 215          $weekday += 7;
 216  
 217      $start = $day - 86400 * ( $weekday - $start_of_week ); // The most recent week start day on or before $day
 218      $end = $start + 604799; // $start + 7 days - 1 second
 219      return compact( 'start', 'end' );
 220  }
 221  
 222  /**
 223   * Unserialize value only if it was serialized.
 224   *
 225   * @since 2.0.0
 226   *
 227   * @param string $original Maybe unserialized original, if is needed.
 228   * @return mixed Unserialized data can be any type.
 229   */
 230  function maybe_unserialize( $original ) {
 231      if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
 232          return @unserialize( $original );
 233      return $original;
 234  }
 235  
 236  /**
 237   * Check value to find if it was serialized.
 238   *
 239   * If $data is not an string, then returned value will always be false.
 240   * Serialized data is always a string.
 241   *
 242   * @since 2.0.5
 243   *
 244   * @param mixed $data Value to check to see if was serialized.
 245   * @return bool False if not serialized and true if it was.
 246   */
 247  function is_serialized( $data ) {
 248      // if it isn't a string, it isn't serialized
 249      if ( ! is_string( $data ) )
 250          return false;
 251      $data = trim( $data );
 252       if ( 'N;' == $data )
 253          return true;
 254      $length = strlen( $data );
 255      if ( $length < 4 )
 256          return false;
 257      if ( ':' !== $data[1] )
 258          return false;
 259      $lastc = $data[$length-1];
 260      if ( ';' !== $lastc && '}' !== $lastc )
 261          return false;
 262      $token = $data[0];
 263      switch ( $token ) {
 264          case 's' :
 265              if ( '"' !== $data[$length-2] )
 266                  return false;
 267          case 'a' :
 268          case 'O' :
 269              return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
 270          case 'b' :
 271          case 'i' :
 272          case 'd' :
 273              return (bool) preg_match( "/^{$token}:[0-9.E-]+;\$/", $data );
 274      }
 275      return false;
 276  }
 277  
 278  /**
 279   * Check whether serialized data is of string type.
 280   *
 281   * @since 2.0.5
 282   *
 283   * @param mixed $data Serialized data
 284   * @return bool False if not a serialized string, true if it is.
 285   */
 286  function is_serialized_string( $data ) {
 287      // if it isn't a string, it isn't a serialized string
 288      if ( !is_string( $data ) )
 289          return false;
 290      $data = trim( $data );
 291      $length = strlen( $data );
 292      if ( $length < 4 )
 293          return false;
 294      elseif ( ':' !== $data[1] )
 295          return false;
 296      elseif ( ';' !== $data[$length-1] )
 297          return false;
 298      elseif ( $data[0] !== 's' )
 299          return false;
 300      elseif ( '"' !== $data[$length-2] )
 301          return false;
 302      else
 303          return true;
 304  }
 305  
 306  /**
 307   * Retrieve option value based on name of option.
 308   *
 309   * If the option does not exist or does not have a value, then the return value
 310   * will be false. This is useful to check whether you need to install an option
 311   * and is commonly used during installation of plugin options and to test
 312   * whether upgrading is required.
 313   *
 314   * If the option was serialized then it will be unserialized when it is returned.
 315   *
 316   * @since 1.5.0
 317   * @package WordPress
 318   * @subpackage Option
 319   * @uses apply_filters() Calls 'pre_option_$option' before checking the option.
 320   *     Any value other than false will "short-circuit" the retrieval of the option
 321   *    and return the returned value. You should not try to override special options,
 322   *     but you will not be prevented from doing so.
 323   * @uses apply_filters() Calls 'option_$option', after checking the option, with
 324   *     the option value.
 325   *
 326   * @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
 327   * @return mixed Value set for the option.
 328   */
 329  function get_option( $option, $default = false ) {
 330      global $wpdb;
 331  
 332      // Allow plugins to short-circuit options.
 333      $pre = apply_filters( 'pre_option_' . $option, false );
 334      if ( false !== $pre )
 335          return $pre;
 336  
 337      $option = trim($option);
 338      if ( empty($option) )
 339          return false;
 340  
 341      if ( defined( 'WP_SETUP_CONFIG' ) )
 342          return false;
 343  
 344      if ( ! defined( 'WP_INSTALLING' ) ) {
 345          // prevent non-existent options from triggering multiple queries
 346          $notoptions = wp_cache_get( 'notoptions', 'options' );
 347          if ( isset( $notoptions[$option] ) )
 348              return $default;
 349  
 350          $alloptions = wp_load_alloptions();
 351  
 352          if ( isset( $alloptions[$option] ) ) {
 353              $value = $alloptions[$option];
 354          } else {
 355              $value = wp_cache_get( $option, 'options' );
 356  
 357              if ( false === $value ) {
 358                  $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 359  
 360                  // Has to be get_row instead of get_var because of funkiness with 0, false, null values
 361                  if ( is_object( $row ) ) {
 362                      $value = $row->option_value;
 363                      wp_cache_add( $option, $value, 'options' );
 364                  } else { // option does not exist, so we must cache its non-existence
 365                      $notoptions[$option] = true;
 366                      wp_cache_set( 'notoptions', $notoptions, 'options' );
 367                      return $default;
 368                  }
 369              }
 370          }
 371      } else {
 372          $suppress = $wpdb->suppress_errors();
 373          $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s LIMIT 1", $option ) );
 374          $wpdb->suppress_errors( $suppress );
 375          if ( is_object( $row ) )
 376              $value = $row->option_value;
 377          else
 378              return $default;
 379      }
 380  
 381      // If home is not set use siteurl.
 382      if ( 'home' == $option && '' == $value )
 383          return get_option( 'siteurl' );
 384  
 385      if ( in_array( $option, array('siteurl', 'home', 'category_base', 'tag_base') ) )
 386          $value = untrailingslashit( $value );
 387  
 388      return apply_filters( 'option_' . $option, maybe_unserialize( $value ) );
 389  }
 390  
 391  /**
 392   * Protect WordPress special option from being modified.
 393   *
 394   * Will die if $option is in protected list. Protected options are 'alloptions'
 395   * and 'notoptions' options.
 396   *
 397   * @since 2.2.0
 398   * @package WordPress
 399   * @subpackage Option
 400   *
 401   * @param string $option Option name.
 402   */
 403  function wp_protect_special_option( $option ) {
 404      $protected = array( 'alloptions', 'notoptions' );
 405      if ( in_array( $option, $protected ) )
 406          wp_die( sprintf( __( '%s is a protected WP option and may not be modified' ), esc_html( $option ) ) );
 407  }
 408  
 409  /**
 410   * Print option value after sanitizing for forms.
 411   *
 412   * @uses attr Sanitizes value.
 413   * @since 1.5.0
 414   * @package WordPress
 415   * @subpackage Option
 416   *
 417   * @param string $option Option name.
 418   */
 419  function form_option( $option ) {
 420      echo esc_attr( get_option( $option ) );
 421  }
 422  
 423  /**
 424   * Loads and caches all autoloaded options, if available or all options.
 425   *
 426   * @since 2.2.0
 427   * @package WordPress
 428   * @subpackage Option
 429   *
 430   * @return array List of all options.
 431   */
 432  function wp_load_alloptions() {
 433      global $wpdb;
 434  
 435      if ( !defined( 'WP_INSTALLING' ) || !is_multisite() )
 436          $alloptions = wp_cache_get( 'alloptions', 'options' );
 437      else
 438          $alloptions = false;
 439  
 440      if ( !$alloptions ) {
 441          $suppress = $wpdb->suppress_errors();
 442          if ( !$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) )
 443              $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
 444          $wpdb->suppress_errors($suppress);
 445          $alloptions = array();
 446          foreach ( (array) $alloptions_db as $o ) {
 447              $alloptions[$o->option_name] = $o->option_value;
 448          }
 449          if ( !defined( 'WP_INSTALLING' ) || !is_multisite() )
 450              wp_cache_add( 'alloptions', $alloptions, 'options' );
 451      }
 452  
 453      return $alloptions;
 454  }
 455  
 456  /**
 457   * Loads and caches certain often requested site options if is_multisite() and a peristent cache is not being used.
 458   *
 459   * @since 3.0.0
 460   * @package WordPress
 461   * @subpackage Option
 462   *
 463   * @param int $site_id Optional site ID for which to query the options. Defaults to the current site.
 464   */
 465  function wp_load_core_site_options( $site_id = null ) {
 466      global $wpdb, $_wp_using_ext_object_cache;
 467  
 468      if ( !is_multisite() || $_wp_using_ext_object_cache || defined( 'WP_INSTALLING' ) )
 469          return;
 470  
 471      if ( empty($site_id) )
 472          $site_id = $wpdb->siteid;
 473  
 474      $core_options = array('site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'can_compress_scripts', 'global_terms_enabled' );
 475  
 476      $core_options_in = "'" . implode("', '", $core_options) . "'";
 477      $options = $wpdb->get_results( $wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->sitemeta WHERE meta_key IN ($core_options_in) AND site_id = %d", $site_id) );
 478  
 479      foreach ( $options as $option ) {
 480          $key = $option->meta_key;
 481          $cache_key = "{$site_id}:$key";
 482          $option->meta_value = maybe_unserialize( $option->meta_value );
 483  
 484          wp_cache_set( $cache_key, $option->meta_value, 'site-options' );
 485      }
 486  }
 487  
 488  /**
 489   * Update the value of an option that was already added.
 490   *
 491   * You do not need to serialize values. If the value needs to be serialized, then
 492   * it will be serialized before it is inserted into the database. Remember,
 493   * resources can not be serialized or added as an option.
 494   *
 495   * If the option does not exist, then the option will be added with the option
 496   * value, but you will not be able to set whether it is autoloaded. If you want
 497   * to set whether an option is autoloaded, then you need to use the add_option().
 498   *
 499   * @since 1.0.0
 500   * @package WordPress
 501   * @subpackage Option
 502   *
 503   * @uses apply_filters() Calls 'pre_update_option_$option' hook to allow overwriting the
 504   *     option value to be stored.
 505   * @uses do_action() Calls 'update_option' hook before updating the option.
 506   * @uses do_action() Calls 'update_option_$option' and 'updated_option' hooks on success.
 507   *
 508   * @param string $option Option name. Expected to not be SQL-escaped.
 509   * @param mixed $newvalue Option value. Expected to not be SQL-escaped.
 510   * @return bool False if value was not updated and true if value was updated.
 511   */
 512  function update_option( $option, $newvalue ) {
 513      global $wpdb;
 514  
 515      $option = trim($option);
 516      if ( empty($option) )
 517          return false;
 518  
 519      wp_protect_special_option( $option );
 520  
 521      if ( is_object($newvalue) )
 522          $newvalue = clone $newvalue;
 523  
 524      $newvalue = sanitize_option( $option, $newvalue );
 525      $oldvalue = get_option( $option );
 526      $newvalue = apply_filters( 'pre_update_option_' . $option, $newvalue, $oldvalue );
 527  
 528      // If the new and old values are the same, no need to update.
 529      if ( $newvalue === $oldvalue )
 530          return false;
 531  
 532      if ( false === $oldvalue )
 533          return add_option( $option, $newvalue );
 534  
 535      $notoptions = wp_cache_get( 'notoptions', 'options' );
 536      if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
 537          unset( $notoptions[$option] );
 538          wp_cache_set( 'notoptions', $notoptions, 'options' );
 539      }
 540  
 541      $_newvalue = $newvalue;
 542      $newvalue = maybe_serialize( $newvalue );
 543  
 544      do_action( 'update_option', $option, $oldvalue, $_newvalue );
 545      if ( ! defined( 'WP_INSTALLING' ) ) {
 546          $alloptions = wp_load_alloptions();
 547          if ( isset( $alloptions[$option] ) ) {
 548              $alloptions[$option] = $_newvalue;
 549              wp_cache_set( 'alloptions', $alloptions, 'options' );
 550          } else {
 551              wp_cache_set( $option, $_newvalue, 'options' );
 552          }
 553      }
 554  
 555      $result = $wpdb->update( $wpdb->options, array( 'option_value' => $newvalue ), array( 'option_name' => $option ) );
 556  
 557      if ( $result ) {
 558          do_action( "update_option_{$option}", $oldvalue, $_newvalue );
 559          do_action( 'updated_option', $option, $oldvalue, $_newvalue );
 560          return true;
 561      }
 562      return false;
 563  }
 564  
 565  /**
 566   * Add a new option.
 567   *
 568   * You do not need to serialize values. If the value needs to be serialized, then
 569   * it will be serialized before it is inserted into the database. Remember,
 570   * resources can not be serialized or added as an option.
 571   *
 572   * You can create options without values and then add values later. Does not
 573   * check whether the option has already been added, but does check that you
 574   * aren't adding a protected WordPress option. Care should be taken to not name
 575   * options the same as the ones which are protected and to not add options
 576   * that were already added.
 577   *
 578   * @package WordPress
 579   * @subpackage Option
 580   * @since 1.0.0
 581   *
 582   * @uses do_action() Calls 'add_option' hook before adding the option.
 583   * @uses do_action() Calls 'add_option_$option' and 'added_option' hooks on success.
 584   *
 585   * @param string $option Name of option to add. Expected to not be SQL-escaped.
 586   * @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped.
 587   * @param mixed $deprecated Optional. Description. Not used anymore.
 588   * @param bool $autoload Optional. Default is enabled. Whether to load the option when WordPress starts up.
 589   * @return null returns when finished.
 590   */
 591  function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
 592      global $wpdb;
 593  
 594      if ( !empty( $deprecated ) )
 595          _deprecated_argument( __FUNCTION__, '2.3' );
 596  
 597      $option = trim($option);
 598      if ( empty($option) )
 599          return false;
 600  
 601      wp_protect_special_option( $option );
 602  
 603      /*
 604       * FIXME the next two lines of code are not necessary and should be removed.
 605       * @see http://core.trac.wordpress.org/ticket/13480
 606       */
 607      if ( is_object($value) )
 608          $value = clone $value;
 609  
 610      $value = sanitize_option( $option, $value );
 611  
 612      // Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
 613      $notoptions = wp_cache_get( 'notoptions', 'options' );
 614      if ( !is_array( $notoptions ) || !isset( $notoptions[$option] ) )
 615          if ( false !== get_option( $option ) )
 616              return;
 617  
 618      $_value = $value;
 619      $value = maybe_serialize( $value );
 620      $autoload = ( 'no' === $autoload ) ? 'no' : 'yes';
 621      do_action( 'add_option', $option, $_value );
 622      if ( ! defined( 'WP_INSTALLING' ) ) {
 623          if ( 'yes' == $autoload ) {
 624              $alloptions = wp_load_alloptions();
 625              $alloptions[$option] = $value;
 626              wp_cache_set( 'alloptions', $alloptions, 'options' );
 627          } else {
 628              wp_cache_set( $option, $value, 'options' );
 629          }
 630      }
 631  
 632      // This option exists now
 633      $notoptions = wp_cache_get( 'notoptions', 'options' ); // yes, again... we need it to be fresh
 634      if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
 635          unset( $notoptions[$option] );
 636          wp_cache_set( 'notoptions', $notoptions, 'options' );
 637      }
 638  
 639      $result = $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)", $option, $value, $autoload ) );
 640  
 641      if ( $result ) {
 642          do_action( "add_option_{$option}", $option, $_value );
 643          do_action( 'added_option', $option, $_value );
 644          return true;
 645      }
 646      return false;
 647  }
 648  
 649  /**
 650   * Removes option by name. Prevents removal of protected WordPress options.
 651   *
 652   * @package WordPress
 653   * @subpackage Option
 654   * @since 1.2.0
 655   *
 656   * @uses do_action() Calls 'delete_option' hook before option is deleted.
 657   * @uses do_action() Calls 'deleted_option' and 'delete_option_$option' hooks on success.
 658   *
 659   * @param string $option Name of option to remove. Expected to not be SQL-escaped.
 660   * @return bool True, if option is successfully deleted. False on failure.
 661   */
 662  function delete_option( $option ) {
 663      global $wpdb;
 664  
 665      wp_protect_special_option( $option );
 666  
 667      // Get the ID, if no ID then return
 668      $row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = %s", $option ) );
 669      if ( is_null( $row ) )
 670          return false;
 671      do_action( 'delete_option', $option );
 672      $result = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name = %s", $option) );
 673      if ( ! defined( 'WP_INSTALLING' ) ) {
 674          if ( 'yes' == $row->autoload ) {
 675              $alloptions = wp_load_alloptions();
 676              if ( is_array( $alloptions ) && isset( $alloptions[$option] ) ) {
 677                  unset( $alloptions[$option] );
 678                  wp_cache_set( 'alloptions', $alloptions, 'options' );
 679              }
 680          } else {
 681              wp_cache_delete( $option, 'options' );
 682          }
 683      }
 684      if ( $result ) {
 685          do_action( "delete_option_$option", $option );
 686          do_action( 'deleted_option', $option );
 687          return true;
 688      }
 689      return false;
 690  }
 691  
 692  /**
 693   * Delete a transient
 694   *
 695   * @since 2.8.0
 696   * @package WordPress
 697   * @subpackage Transient
 698   *
 699   * @uses do_action() Calls 'delete_transient_$transient' hook before transient is deleted.
 700   * @uses do_action() Calls 'deleted_transient' hook on success.
 701   *
 702   * @param string $transient Transient name. Expected to not be SQL-escaped.
 703   * @return bool true if successful, false otherwise
 704   */
 705  function delete_transient( $transient ) {
 706      global $_wp_using_ext_object_cache;
 707  
 708      do_action( 'delete_transient_' . $transient, $transient );
 709  
 710      if ( $_wp_using_ext_object_cache ) {
 711          $result = wp_cache_delete( $transient, 'transient' );
 712      } else {
 713          $option_timeout = '_transient_timeout_' . $transient;
 714          $option = '_transient_' . $transient;
 715          $result = delete_option( $option );
 716          if ( $result )
 717              delete_option( $option_timeout );
 718      }
 719  
 720      if ( $result )
 721          do_action( 'deleted_transient', $transient );
 722      return $result;
 723  }
 724  
 725  /**
 726   * Get the value of a transient
 727   *
 728   * If the transient does not exist or does not have a value, then the return value
 729   * will be false.
 730   *
 731   * @uses apply_filters() Calls 'pre_transient_$transient' hook before checking the transient.
 732   *     Any value other than false will "short-circuit" the retrieval of the transient
 733   *    and return the returned value.
 734   * @uses apply_filters() Calls 'transient_$option' hook, after checking the transient, with
 735   *     the transient value.
 736   *
 737   * @since 2.8.0
 738   * @package WordPress
 739   * @subpackage Transient
 740   *
 741   * @param string $transient Transient name. Expected to not be SQL-escaped
 742   * @return mixed Value of transient
 743   */
 744  function get_transient( $transient ) {
 745      global $_wp_using_ext_object_cache;
 746  
 747      $pre = apply_filters( 'pre_transient_' . $transient, false );
 748      if ( false !== $pre )
 749          return $pre;
 750  
 751      if ( $_wp_using_ext_object_cache ) {
 752          $value = wp_cache_get( $transient, 'transient' );
 753      } else {
 754          $transient_option = '_transient_' . $transient;
 755          if ( ! defined( 'WP_INSTALLING' ) ) {
 756              // If option is not in alloptions, it is not autoloaded and thus has a timeout
 757              $alloptions = wp_load_alloptions();
 758              if ( !isset( $alloptions[$transient_option] ) ) {
 759                  $transient_timeout = '_transient_timeout_' . $transient;
 760                  if ( get_option( $transient_timeout ) < time() ) {
 761                      delete_option( $transient_option  );
 762                      delete_option( $transient_timeout );
 763                      return false;
 764                  }
 765              }
 766          }
 767  
 768          $value = get_option( $transient_option );
 769      }
 770  
 771      return apply_filters( 'transient_' . $transient, $value );
 772  }
 773  
 774  /**
 775   * Set/update the value of a transient
 776   *
 777   * You do not need to serialize values. If the value needs to be serialized, then
 778   * it will be serialized before it is set.
 779   *
 780   * @since 2.8.0
 781   * @package WordPress
 782   * @subpackage Transient
 783   *
 784   * @uses apply_filters() Calls 'pre_set_transient_$transient' hook to allow overwriting the
 785   *     transient value to be stored.
 786   * @uses do_action() Calls 'set_transient_$transient' and 'setted_transient' hooks on success.
 787   *
 788   * @param string $transient Transient name. Expected to not be SQL-escaped.
 789   * @param mixed $value Transient value. Expected to not be SQL-escaped.
 790   * @param int $expiration Time until expiration in seconds, default 0
 791   * @return bool False if value was not set and true if value was set.
 792   */
 793  function set_transient( $transient, $value, $expiration = 0 ) {
 794      global $_wp_using_ext_object_cache;
 795  
 796      $value = apply_filters( 'pre_set_transient_' . $transient, $value );
 797  
 798      if ( $_wp_using_ext_object_cache ) {
 799          $result = wp_cache_set( $transient, $value, 'transient', $expiration );
 800      } else {
 801          $transient_timeout = '_transient_timeout_' . $transient;
 802          $transient = '_transient_' . $transient;
 803          if ( false === get_option( $transient ) ) {
 804              $autoload = 'yes';
 805              if ( $expiration ) {
 806                  $autoload = 'no';
 807                  add_option( $transient_timeout, time() + $expiration, '', 'no' );
 808              }
 809              $result = add_option( $transient, $value, '', $autoload );
 810          } else {
 811              if ( $expiration )
 812                  update_option( $transient_timeout, time() + $expiration );
 813              $result = update_option( $transient, $value );
 814          }
 815      }
 816      if ( $result ) {
 817          do_action( 'set_transient_' . $transient );
 818          do_action( 'setted_transient', $transient );
 819      }
 820      return $result;
 821  }
 822  
 823  /**
 824   * Saves and restores user interface settings stored in a cookie.
 825   *
 826   * Checks if the current user-settings cookie is updated and stores it. When no
 827   * cookie exists (different browser used), adds the last saved cookie restoring
 828   * the settings.
 829   *
 830   * @package WordPress
 831   * @subpackage Option
 832   * @since 2.7.0
 833   */
 834  function wp_user_settings() {
 835  
 836      if ( ! is_admin() )
 837          return;
 838  
 839      if ( defined('DOING_AJAX') )
 840          return;
 841  
 842      if ( ! $user = wp_get_current_user() )
 843          return;
 844  
 845      $settings = get_user_option( 'user-settings', $user->ID );
 846  
 847      if ( isset( $_COOKIE['wp-settings-' . $user->ID] ) ) {
 848          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] );
 849  
 850          if ( ! empty( $cookie ) && strpos( $cookie, '=' ) ) {
 851              if ( $cookie == $settings )
 852                  return;
 853  
 854              $last_time = (int) get_user_option( 'user-settings-time', $user->ID );
 855              $saved = isset( $_COOKIE['wp-settings-time-' . $user->ID]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user->ID] ) : 0;
 856  
 857              if ( $saved > $last_time ) {
 858                  update_user_option( $user->ID, 'user-settings', $cookie, false );
 859                  update_user_option( $user->ID, 'user-settings-time', time() - 5, false );
 860                  return;
 861              }
 862          }
 863      }
 864  
 865      setcookie( 'wp-settings-' . $user->ID, $settings, time() + 31536000, SITECOOKIEPATH );
 866      setcookie( 'wp-settings-time-' . $user->ID, time(), time() + 31536000, SITECOOKIEPATH );
 867      $_COOKIE['wp-settings-' . $user->ID] = $settings;
 868  }
 869  
 870  /**
 871   * Retrieve user interface setting value based on setting name.
 872   *
 873   * @package WordPress
 874   * @subpackage Option
 875   * @since 2.7.0
 876   *
 877   * @param string $name The name of the setting.
 878   * @param string $default Optional default value to return when $name is not set.
 879   * @return mixed the last saved user setting or the default value/false if it doesn't exist.
 880   */
 881  function get_user_setting( $name, $default = false ) {
 882  
 883      $all = get_all_user_settings();
 884  
 885      return isset($all[$name]) ? $all[$name] : $default;
 886  }
 887  
 888  /**
 889   * Add or update user interface setting.
 890   *
 891   * Both $name and $value can contain only ASCII letters, numbers and underscores.
 892   * This function has to be used before any output has started as it calls setcookie().
 893   *
 894   * @package WordPress
 895   * @subpackage Option
 896   * @since 2.8.0
 897   *
 898   * @param string $name The name of the setting.
 899   * @param string $value The value for the setting.
 900   * @return bool true if set successfully/false if not.
 901   */
 902  function set_user_setting( $name, $value ) {
 903  
 904      if ( headers_sent() )
 905          return false;
 906  
 907      $all = get_all_user_settings();
 908      $name = preg_replace( '/[^A-Za-z0-9_]+/', '', $name );
 909  
 910      if ( empty($name) )
 911          return false;
 912  
 913      $all[$name] = $value;
 914  
 915      return wp_set_all_user_settings($all);
 916  }
 917  
 918  /**
 919   * Delete user interface settings.
 920   *
 921   * Deleting settings would reset them to the defaults.
 922   * This function has to be used before any output has started as it calls setcookie().
 923   *
 924   * @package WordPress
 925   * @subpackage Option
 926   * @since 2.7.0
 927   *
 928   * @param mixed $names The name or array of names of the setting to be deleted.
 929   * @return bool true if deleted successfully/false if not.
 930   */
 931  function delete_user_setting( $names ) {
 932  
 933      if ( headers_sent() )
 934          return false;
 935  
 936      $all = get_all_user_settings();
 937      $names = (array) $names;
 938  
 939      foreach ( $names as $name ) {
 940          if ( isset($all[$name]) ) {
 941              unset($all[$name]);
 942              $deleted = true;
 943          }
 944      }
 945  
 946      if ( isset($deleted) )
 947          return wp_set_all_user_settings($all);
 948  
 949      return false;
 950  }
 951  
 952  /**
 953   * Retrieve all user interface settings.
 954   *
 955   * @package WordPress
 956   * @subpackage Option
 957   * @since 2.7.0
 958   *
 959   * @return array the last saved user settings or empty array.
 960   */
 961  function get_all_user_settings() {
 962      global $_updated_user_settings;
 963  
 964      if ( ! $user = wp_get_current_user() )
 965          return array();
 966  
 967      if ( isset($_updated_user_settings) && is_array($_updated_user_settings) )
 968          return $_updated_user_settings;
 969  
 970      $all = array();
 971      if ( isset($_COOKIE['wp-settings-' . $user->ID]) ) {
 972          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] );
 973  
 974          if ( $cookie && strpos($cookie, '=') ) // the '=' cannot be 1st char
 975              parse_str($cookie, $all);
 976  
 977      } else {
 978          $option = get_user_option('user-settings', $user->ID);
 979          if ( $option && is_string($option) )
 980              parse_str( $option, $all );
 981      }
 982  
 983      return $all;
 984  }
 985  
 986  /**
 987   * Private. Set all user interface settings.
 988   *
 989   * @package WordPress
 990   * @subpackage Option
 991   * @since 2.8.0
 992   *
 993   * @param unknown $all
 994   * @return bool
 995   */
 996  function wp_set_all_user_settings($all) {
 997      global $_updated_user_settings;
 998  
 999      if ( ! $user = wp_get_current_user() )
1000          return false;
1001  
1002      $_updated_user_settings = $all;
1003      $settings = '';
1004      foreach ( $all as $k => $v ) {
1005          $v = preg_replace( '/[^A-Za-z0-9_]+/', '', $v );
1006          $settings .= $k . '=' . $v . '&';
1007      }
1008  
1009      $settings = rtrim($settings, '&');
1010  
1011      update_user_option( $user->ID, 'user-settings', $settings, false );
1012      update_user_option( $user->ID, 'user-settings-time', time(), false );
1013  
1014      return true;
1015  }
1016  
1017  /**
1018   * Delete the user settings of the current user.
1019   *
1020   * @package WordPress
1021   * @subpackage Option
1022   * @since 2.7.0
1023   */
1024  function delete_all_user_settings() {
1025      if ( ! $user = wp_get_current_user() )
1026          return;
1027  
1028      update_user_option( $user->ID, 'user-settings', '', false );
1029      setcookie('wp-settings-' . $user->ID, ' ', time() - 31536000, SITECOOKIEPATH);
1030  }
1031  
1032  /**
1033   * Serialize data, if needed.
1034   *
1035   * @since 2.0.5
1036   *
1037   * @param mixed $data Data that might be serialized.
1038   * @return mixed A scalar data
1039   */
1040  function maybe_serialize( $data ) {
1041      if ( is_array( $data ) || is_object( $data ) )
1042          return serialize( $data );
1043  
1044      if ( is_serialized( $data ) )
1045          return serialize( $data );
1046  
1047      return $data;
1048  }
1049  
1050  /**
1051   * Retrieve post title from XMLRPC XML.
1052   *
1053   * If the title element is not part of the XML, then the default post title from
1054   * the $post_default_title will be used instead.
1055   *
1056   * @package WordPress
1057   * @subpackage XMLRPC
1058   * @since 0.71
1059   *
1060   * @global string $post_default_title Default XMLRPC post title.
1061   *
1062   * @param string $content XMLRPC XML Request content
1063   * @return string Post title
1064   */
1065  function xmlrpc_getposttitle( $content ) {
1066      global $post_default_title;
1067      if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
1068          $post_title = $matchtitle[1];
1069      } else {
1070          $post_title = $post_default_title;
1071      }
1072      return $post_title;
1073  }
1074  
1075  /**
1076   * Retrieve the post category or categories from XMLRPC XML.
1077   *
1078   * If the category element is not found, then the default post category will be
1079   * used. The return type then would be what $post_default_category. If the
1080   * category is found, then it will always be an array.
1081   *
1082   * @package WordPress
1083   * @subpackage XMLRPC
1084   * @since 0.71
1085   *
1086   * @global string $post_default_category Default XMLRPC post category.
1087   *
1088   * @param string $content XMLRPC XML Request content
1089   * @return string|array List of categories or category name.
1090   */
1091  function xmlrpc_getpostcategory( $content ) {
1092      global $post_default_category;
1093      if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
1094          $post_category = trim( $matchcat[1], ',' );
1095          $post_category = explode( ',', $post_category );
1096      } else {
1097          $post_category = $post_default_category;
1098      }
1099      return $post_category;
1100  }
1101  
1102  /**
1103   * XMLRPC XML content without title and category elements.
1104   *
1105   * @package WordPress
1106   * @subpackage XMLRPC
1107   * @since 0.71
1108   *
1109   * @param string $content XMLRPC XML Request content
1110   * @return string XMLRPC XML Request content without title and category elements.
1111   */
1112  function xmlrpc_removepostdata( $content ) {
1113      $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
1114      $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
1115      $content = trim( $content );
1116      return $content;
1117  }
1118  
1119  /**
1120   * Open the file handle for debugging.
1121   *
1122   * This function is used for XMLRPC feature, but it is general purpose enough
1123   * to be used in anywhere.
1124   *
1125   * @see fopen() for mode options.
1126   * @package WordPress
1127   * @subpackage Debug
1128   * @since 0.71
1129   * @uses $debug Used for whether debugging is enabled.
1130   *
1131   * @param string $filename File path to debug file.
1132   * @param string $mode Same as fopen() mode parameter.
1133   * @return bool|resource File handle. False on failure.
1134   */
1135  function debug_fopen( $filename, $mode ) {
1136      global $debug;
1137      if ( 1 == $debug ) {
1138          $fp = fopen( $filename, $mode );
1139          return $fp;
1140      } else {
1141          return false;
1142      }
1143  }
1144  
1145  /**
1146   * Write contents to the file used for debugging.
1147   *
1148   * Technically, this can be used to write to any file handle when the global
1149   * $debug is set to 1 or true.
1150   *
1151   * @package WordPress
1152   * @subpackage Debug
1153   * @since 0.71
1154   * @uses $debug Used for whether debugging is enabled.
1155   *
1156   * @param resource $fp File handle for debugging file.
1157   * @param string $string Content to write to debug file.
1158   */
1159  function debug_fwrite( $fp, $string ) {
1160      global $debug;
1161      if ( 1 == $debug )
1162          fwrite( $fp, $string );
1163  }
1164  
1165  /**
1166   * Close the debugging file handle.
1167   *
1168   * Technically, this can be used to close any file handle when the global $debug
1169   * is set to 1 or true.
1170   *
1171   * @package WordPress
1172   * @subpackage Debug
1173   * @since 0.71
1174   * @uses $debug Used for whether debugging is enabled.
1175   *
1176   * @param resource $fp Debug File handle.
1177   */
1178  function debug_fclose( $fp ) {
1179      global $debug;
1180      if ( 1 == $debug )
1181          fclose( $fp );
1182  }
1183  
1184  /**
1185   * Check content for video and audio links to add as enclosures.
1186   *
1187   * Will not add enclosures that have already been added and will
1188   * remove enclosures that are no longer in the post. This is called as
1189   * pingbacks and trackbacks.
1190   *
1191   * @package WordPress
1192   * @since 1.5.0
1193   *
1194   * @uses $wpdb
1195   *
1196   * @param string $content Post Content
1197   * @param int $post_ID Post ID
1198   */
1199  function do_enclose( $content, $post_ID ) {
1200      global $wpdb;
1201  
1202      //TODO: Tidy this ghetto code up and make the debug code optional
1203      include_once( ABSPATH . WPINC . '/class-IXR.php' );
1204  
1205      $log = debug_fopen( ABSPATH . 'enclosures.log', 'a' );
1206      $post_links = array();
1207      debug_fwrite( $log, 'BEGIN ' . date( 'YmdHis', time() ) . "\n" );
1208  
1209      $pung = get_enclosed( $post_ID );
1210  
1211      $ltrs = '\w';
1212      $gunk = '/#~:.?+=&%@!\-';
1213      $punc = '.:?\-';
1214      $any = $ltrs . $gunk . $punc;
1215  
1216      preg_match_all( "{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp );
1217  
1218      debug_fwrite( $log, 'Post contents:' );
1219      debug_fwrite( $log, $content . "\n" );
1220  
1221      foreach ( $pung as $link_test ) {
1222          if ( !in_array( $link_test, $post_links_temp[0] ) ) { // link no longer in post
1223              $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 ) . '%') );
1224              do_action( 'delete_postmeta', $mid );
1225              $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id IN(%s)", implode( ',', $mid ) ) );
1226              do_action( 'deleted_postmeta', $mid );
1227          }
1228      }
1229  
1230      foreach ( (array) $post_links_temp[0] as $link_test ) {
1231          if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
1232              $test = @parse_url( $link_test );
1233              if ( false === $test )
1234                  continue;
1235              if ( isset( $test['query'] ) )
1236                  $post_links[] = $link_test;
1237              elseif ( isset($test['path']) && ( $test['path'] != '/' ) &&  ($test['path'] != '' ) )
1238                  $post_links[] = $link_test;
1239          }
1240      }
1241  
1242      foreach ( (array) $post_links as $url ) {
1243          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 ) . '%' ) ) ) {
1244  
1245              if ( $headers = wp_get_http_headers( $url) ) {
1246                  $len = (int) $headers['content-length'];
1247                  $type = $headers['content-type'];
1248                  $allowed_types = array( 'video', 'audio' );
1249  
1250                  // Check to see if we can figure out the mime type from
1251                  // the extension
1252                  $url_parts = @parse_url( $url );
1253                  if ( false !== $url_parts ) {
1254                      $extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );
1255                      if ( !empty( $extension ) ) {
1256                          foreach ( get_allowed_mime_types( ) as $exts => $mime ) {
1257                              if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
1258                                  $type = $mime;
1259                                  break;
1260                              }
1261                          }
1262                      }
1263                  }
1264  
1265                  if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
1266                      $meta_value = "$url\n$len\n$type\n";
1267                      $wpdb->insert($wpdb->postmeta, array('post_id' => $post_ID, 'meta_key' => 'enclosure', 'meta_value' => $meta_value) );
1268                      do_action( 'added_postmeta', $wpdb->insert_id, $post_ID, 'enclosure', $meta_value );
1269                  }
1270              }
1271          }
1272      }
1273  }
1274  
1275  /**
1276   * Perform a HTTP HEAD or GET request.
1277   *
1278   * If $file_path is a writable filename, this will do a GET request and write
1279   * the file to that path.
1280   *
1281   * @since 2.5.0
1282   *
1283   * @param string $url URL to fetch.
1284   * @param string|bool $file_path Optional. File path to write request to.
1285   * @param int $red (private) The number of Redirects followed, Upon 5 being hit, returns false.
1286   * @return bool|string False on failure and string of headers if HEAD request.
1287   */
1288  function wp_get_http( $url, $file_path = false, $red = 1 ) {
1289      @set_time_limit( 60 );
1290  
1291      if ( $red > 5 )
1292          return false;
1293  
1294      $options = array();
1295      $options['redirection'] = 5;
1296  
1297      if ( false == $file_path )
1298          $options['method'] = 'HEAD';
1299      else
1300          $options['method'] = 'GET';
1301  
1302      $response = wp_remote_request($url, $options);
1303  
1304      if ( is_wp_error( $response ) )
1305          return false;
1306  
1307      $headers = wp_remote_retrieve_headers( $response );
1308      $headers['response'] = wp_remote_retrieve_response_code( $response );
1309  
1310      // WP_HTTP no longer follows redirects for HEAD requests.
1311      if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
1312          return wp_get_http( $headers['location'], $file_path, ++$red );
1313      }
1314  
1315      if ( false == $file_path )
1316          return $headers;
1317  
1318      // GET request - write it to the supplied filename
1319      $out_fp = fopen($file_path, 'w');
1320      if ( !$out_fp )
1321          return $headers;
1322  
1323      fwrite( $out_fp,  wp_remote_retrieve_body( $response ) );
1324      fclose($out_fp);
1325      clearstatcache();
1326  
1327      return $headers;
1328  }
1329  
1330  /**
1331   * Retrieve HTTP Headers from URL.
1332   *
1333   * @since 1.5.1
1334   *
1335   * @param string $url
1336   * @param bool $deprecated Not Used.
1337   * @return bool|string False on failure, headers on success.
1338   */
1339  function wp_get_http_headers( $url, $deprecated = false ) {
1340      if ( !empty( $deprecated ) )
1341          _deprecated_argument( __FUNCTION__, '2.7' );
1342  
1343      $response = wp_remote_head( $url );
1344  
1345      if ( is_wp_error( $response ) )
1346          return false;
1347  
1348      return wp_remote_retrieve_headers( $response );
1349  }
1350  
1351  /**
1352   * Whether today is a new day.
1353   *
1354   * @since 0.71
1355   * @uses $day Today
1356   * @uses $previousday Previous day
1357   *
1358   * @return int 1 when new day, 0 if not a new day.
1359   */
1360  function is_new_day() {
1361      global $currentday, $previousday;
1362      if ( $currentday != $previousday )
1363          return 1;
1364      else
1365          return 0;
1366  }
1367  
1368  /**
1369   * Build URL query based on an associative and, or indexed array.
1370   *
1371   * This is a convenient function for easily building url queries. It sets the
1372   * separator to '&' and uses _http_build_query() function.
1373   *
1374   * @see _http_build_query() Used to build the query
1375   * @link http://us2.php.net/manual/en/function.http-build-query.php more on what
1376   *        http_build_query() does.
1377   *
1378   * @since 2.3.0
1379   *
1380   * @param array $data URL-encode key/value pairs.
1381   * @return string URL encoded string
1382   */
1383  function build_query( $data ) {
1384      return _http_build_query( $data, null, '&', '', false );
1385  }
1386  
1387  // from php.net (modified by Mark Jaquith to behave like the native PHP5 function)
1388  function _http_build_query($data, $prefix=null, $sep=null, $key='', $urlencode=true) {
1389      $ret = array();
1390  
1391      foreach ( (array) $data as $k => $v ) {
1392          if ( $urlencode)
1393              $k = urlencode($k);
1394          if ( is_int($k) && $prefix != null )
1395              $k = $prefix.$k;
1396          if ( !empty($key) )
1397              $k = $key . '%5B' . $k . '%5D';
1398          if ( $v === NULL )
1399              continue;
1400          elseif ( $v === FALSE )
1401              $v = '0';
1402  
1403          if ( is_array($v) || is_object($v) )
1404              array_push($ret,_http_build_query($v, '', $sep, $k, $urlencode));
1405          elseif ( $urlencode )
1406              array_push($ret, $k.'='.urlencode($v));
1407          else
1408              array_push($ret, $k.'='.$v);
1409      }
1410  
1411      if ( NULL === $sep )
1412          $sep = ini_get('arg_separator.output');
1413  
1414      return implode($sep, $ret);
1415  }
1416  
1417  /**
1418   * Retrieve a modified URL query string.
1419   *
1420   * You can rebuild the URL and append a new query variable to the URL query by
1421   * using this function. You can also retrieve the full URL with query data.
1422   *
1423   * Adding a single key & value or an associative array. Setting a key value to
1424   * emptystring removes the key. Omitting oldquery_or_uri uses the $_SERVER
1425   * value.
1426   *
1427   * @since 1.5.0
1428   *
1429   * @param mixed $param1 Either newkey or an associative_array
1430   * @param mixed $param2 Either newvalue or oldquery or uri
1431   * @param mixed $param3 Optional. Old query or uri
1432   * @return string New URL query string.
1433   */
1434  function add_query_arg() {
1435      $ret = '';
1436      if ( is_array( func_get_arg(0) ) ) {
1437          if ( @func_num_args() < 2 || false === @func_get_arg( 1 ) )
1438              $uri = $_SERVER['REQUEST_URI'];
1439          else
1440              $uri = @func_get_arg( 1 );
1441      } else {
1442          if ( @func_num_args() < 3 || false === @func_get_arg( 2 ) )
1443              $uri = $_SERVER['REQUEST_URI'];
1444          else
1445              $uri = @func_get_arg( 2 );
1446      }
1447  
1448      if ( $frag = strstr( $uri, '#' ) )
1449          $uri = substr( $uri, 0, -strlen( $frag ) );
1450      else
1451          $frag = '';
1452  
1453      if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
1454          $protocol = $matches[0];
1455          $uri = substr( $uri, strlen( $protocol ) );
1456      } else {
1457          $protocol = '';
1458      }
1459  
1460      if ( strpos( $uri, '?' ) !== false ) {
1461          $parts = explode( '?', $uri, 2 );
1462          if ( 1 == count( $parts ) ) {
1463              $base = '?';
1464              $query = $parts[0];
1465          } else {
1466              $base = $parts[0] . '?';
1467              $query = $parts[1];
1468          }
1469      } elseif ( !empty( $protocol ) || strpos( $uri, '=' ) === false ) {
1470          $base = $uri . '?';
1471          $query = '';
1472      } else {
1473          $base = '';
1474          $query = $uri;
1475      }
1476  
1477      wp_parse_str( $query, $qs );
1478      $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
1479      if ( is_array( func_get_arg( 0 ) ) ) {
1480          $kayvees = func_get_arg( 0 );
1481          $qs = array_merge( $qs, $kayvees );
1482      } else {
1483          $qs[func_get_arg( 0 )] = func_get_arg( 1 );
1484      }
1485  
1486      foreach ( (array) $qs as $k => $v ) {
1487          if ( $v === false )
1488              unset( $qs[$k] );
1489      }
1490  
1491      $ret = build_query( $qs );
1492      $ret = trim( $ret, '?' );
1493      $ret = preg_replace( '#=(&|$)#', '$1', $ret );
1494      $ret = $protocol . $base . $ret . $frag;
1495      $ret = rtrim( $ret, '?' );
1496      return $ret;
1497  }
1498  
1499  /**
1500   * Removes an item or list from the query string.
1501   *
1502   * @since 1.5.0
1503   *
1504   * @param string|array $key Query key or keys to remove.
1505   * @param bool $query When false uses the $_SERVER value.
1506   * @return string New URL query string.
1507   */
1508  function remove_query_arg( $key, $query=false ) {
1509      if ( is_array( $key ) ) { // removing multiple keys
1510          foreach ( $key as $k )
1511              $query = add_query_arg( $k, false, $query );
1512          return $query;
1513      }
1514      return add_query_arg( $key, false, $query );
1515  }
1516  
1517  /**
1518   * Walks the array while sanitizing the contents.
1519   *
1520   * @since 0.71
1521   *
1522   * @param array $array Array to used to walk while sanitizing contents.
1523   * @return array Sanitized $array.
1524   */
1525  function add_magic_quotes( $array ) {
1526      foreach ( (array) $array as $k => $v ) {
1527          if ( is_array( $v ) ) {
1528              $array[$k] = add_magic_quotes( $v );
1529          } else {
1530              $array[$k] = addslashes( $v );
1531          }
1532      }
1533      return $array;
1534  }
1535  
1536  /**
1537   * HTTP request for URI to retrieve content.
1538   *
1539   * @since 1.5.1
1540   * @uses wp_remote_get()
1541   *
1542   * @param string $uri URI/URL of web page to retrieve.
1543   * @return bool|string HTTP content. False on failure.
1544   */
1545  function wp_remote_fopen( $uri ) {
1546      $parsed_url = @parse_url( $uri );
1547  
1548      if ( !$parsed_url || !is_array( $parsed_url ) )
1549          return false;
1550  
1551      $options = array();
1552      $options['timeout'] = 10;
1553  
1554      $response = wp_remote_get( $uri, $options );
1555  
1556      if ( is_wp_error( $response ) )
1557          return false;
1558  
1559      return wp_remote_retrieve_body( $response );
1560  }
1561  
1562  /**
1563   * Set up the WordPress query.
1564   *
1565   * @since 2.0.0
1566   *
1567   * @param string $query_vars Default WP_Query arguments.
1568   */
1569  function wp( $query_vars = '' ) {
1570      global $wp, $wp_query, $wp_the_query;
1571      $wp->main( $query_vars );
1572  
1573      if ( !isset($wp_the_query) )
1574          $wp_the_query = $wp_query;
1575  }
1576  
1577  /**
1578   * Retrieve the description for the HTTP status.
1579   *
1580   * @since 2.3.0
1581   *
1582   * @param int $code HTTP status code.
1583   * @return string Empty string if not found, or description if found.
1584   */
1585  function get_status_header_desc( $code ) {
1586      global $wp_header_to_desc;
1587  
1588      $code = absint( $code );
1589  
1590      if ( !isset( $wp_header_to_desc ) ) {
1591          $wp_header_to_desc = array(
1592              100 => 'Continue',
1593              101 => 'Switching Protocols',
1594              102 => 'Processing',
1595  
1596              200 => 'OK',
1597              201 => 'Created',
1598              202 => 'Accepted',
1599              203 => 'Non-Authoritative Information',
1600              204 => 'No Content',
1601              205 => 'Reset Content',
1602              206 => 'Partial Content',
1603              207 => 'Multi-Status',
1604              226 => 'IM Used',
1605  
1606              300 => 'Multiple Choices',
1607              301 => 'Moved Permanently',
1608              302 => 'Found',
1609              303 => 'See Other',
1610              304 => 'Not Modified',
1611              305 => 'Use Proxy',
1612              306 => 'Reserved',
1613              307 => 'Temporary Redirect',
1614  
1615              400 => 'Bad Request',
1616              401 => 'Unauthorized',
1617              402 => 'Payment Required',
1618              403 => 'Forbidden',
1619              404 => 'Not Found',
1620              405 => 'Method Not Allowed',
1621              406 => 'Not Acceptable',
1622              407 => 'Proxy Authentication Required',
1623              408 => 'Request Timeout',
1624              409 => 'Conflict',
1625              410 => 'Gone',
1626              411 => 'Length Required',
1627              412 => 'Precondition Failed',
1628              413 => 'Request Entity Too Large',
1629              414 => 'Request-URI Too Long',
1630              415 => 'Unsupported Media Type',
1631              416 => 'Requested Range Not Satisfiable',
1632              417 => 'Expectation Failed',
1633              422 => 'Unprocessable Entity',
1634              423 => 'Locked',
1635              424 => 'Failed Dependency',
1636              426 => 'Upgrade Required',
1637  
1638              500 => 'Internal Server Error',
1639              501 => 'Not Implemented',
1640              502 => 'Bad Gateway',
1641              503 => 'Service Unavailable',
1642              504 => 'Gateway Timeout',
1643              505 => 'HTTP Version Not Supported',
1644              506 => 'Variant Also Negotiates',
1645              507 => 'Insufficient Storage',
1646              510 => 'Not Extended'
1647          );
1648      }
1649  
1650      if ( isset( $wp_header_to_desc[$code] ) )
1651          return $wp_header_to_desc[$code];
1652      else
1653          return '';
1654  }
1655  
1656  /**
1657   * Set HTTP status header.
1658   *
1659   * @since 2.0.0
1660   * @uses apply_filters() Calls 'status_header' on status header string, HTTP
1661   *        HTTP code, HTTP code description, and protocol string as separate
1662   *        parameters.
1663   *
1664   * @param int $header HTTP status code
1665   * @return unknown
1666   */
1667  function status_header( $header ) {
1668      $text = get_status_header_desc( $header );
1669  
1670      if ( empty( $text ) )
1671          return false;
1672  
1673      $protocol = $_SERVER["SERVER_PROTOCOL"];
1674      if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
1675          $protocol = 'HTTP/1.0';
1676      $status_header = "$protocol $header $text";
1677      if ( function_exists( 'apply_filters' ) )
1678          $status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );
1679  
1680      return @header( $status_header, true, $header );
1681  }
1682  
1683  /**
1684   * Gets the header information to prevent caching.
1685   *
1686   * The several different headers cover the different ways cache prevention is handled
1687   * by different browsers
1688   *
1689   * @since 2.8.0
1690   *
1691   * @uses apply_filters()
1692   * @return array The associative array of header names and field values.
1693   */
1694  function wp_get_nocache_headers() {
1695      $headers = array(
1696          'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
1697          'Last-Modified' => gmdate( 'D, d M Y H:i:s' ) . ' GMT',
1698          'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
1699          'Pragma' => 'no-cache',
1700      );
1701  
1702      if ( function_exists('apply_filters') ) {
1703          $headers = (array) apply_filters('nocache_headers', $headers);
1704      }
1705      return $headers;
1706  }
1707  
1708  /**
1709   * Sets the headers to prevent caching for the different browsers.
1710   *
1711   * Different browsers support different nocache headers, so several headers must
1712   * be sent so that all of them get the point that no caching should occur.
1713   *
1714   * @since 2.0.0
1715   * @uses wp_get_nocache_headers()
1716   */
1717  function nocache_headers() {
1718      $headers = wp_get_nocache_headers();
1719      foreach( $headers as $name => $field_value )
1720          @header("{$name}: {$field_value}");
1721  }
1722  
1723  /**
1724   * Set the headers for caching for 10 days with JavaScript content type.
1725   *
1726   * @since 2.1.0
1727   */
1728  function cache_javascript_headers() {
1729      $expiresOffset = 864000; // 10 days
1730      header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
1731      header( "Vary: Accept-Encoding" ); // Handle proxies
1732      header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
1733  }
1734  
1735  /**
1736   * Retrieve the number of database queries during the WordPress execution.
1737   *
1738   * @since 2.0.0
1739   *
1740   * @return int Number of database queries
1741   */
1742  function get_num_queries() {
1743      global $wpdb;
1744      return $wpdb->num_queries;
1745  }
1746  
1747  /**
1748   * Whether input is yes or no. Must be 'y' to be true.
1749   *
1750   * @since 1.0.0
1751   *
1752   * @param string $yn Character string containing either 'y' or 'n'
1753   * @return bool True if yes, false on anything else
1754   */
1755  function bool_from_yn( $yn ) {
1756      return ( strtolower( $yn ) == 'y' );
1757  }
1758  
1759  /**
1760   * Loads the feed template from the use of an action hook.
1761   *
1762   * If the feed action does not have a hook, then the function will die with a
1763   * message telling the visitor that the feed is not valid.
1764   *
1765   * It is better to only have one hook for each feed.
1766   *
1767   * @since 2.1.0
1768   * @uses $wp_query Used to tell if the use a comment feed.
1769   * @uses do_action() Calls 'do_feed_$feed' hook, if a hook exists for the feed.
1770   */
1771  function do_feed() {
1772      global $wp_query;
1773  
1774      $feed = get_query_var( 'feed' );
1775  
1776      // Remove the pad, if present.
1777      $feed = preg_replace( '/^_+/', '', $feed );
1778  
1779      if ( $feed == '' || $feed == 'feed' )
1780          $feed = get_default_feed();
1781  
1782      $hook = 'do_feed_' . $feed;
1783      if ( !has_action($hook) ) {
1784          $message = sprintf( __( 'ERROR: %s is not a valid feed template.' ), esc_html($feed));
1785          wp_die( $message, '', array( 'response' => 404 ) );
1786      }
1787  
1788      do_action( $hook, $wp_query->is_comment_feed );
1789  }
1790  
1791  /**
1792   * Load the RDF RSS 0.91 Feed template.
1793   *
1794   * @since 2.1.0
1795   */
1796  function do_feed_rdf() {
1797      load_template( ABSPATH . WPINC . '/feed-rdf.php' );
1798  }
1799  
1800  /**
1801   * Load the RSS 1.0 Feed Template
1802   *
1803   * @since 2.1.0
1804   */
1805  function do_feed_rss() {
1806      load_template( ABSPATH . WPINC . '/feed-rss.php' );
1807  }
1808  
1809  /**
1810   * Load either the RSS2 comment feed or the RSS2 posts feed.
1811   *
1812   * @since 2.1.0
1813   *
1814   * @param bool $for_comments True for the comment feed, false for normal feed.
1815   */
1816  function do_feed_rss2( $for_comments ) {
1817      if ( $for_comments )
1818          load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
1819      else
1820          load_template( ABSPATH . WPINC . '/feed-rss2.php' );
1821  }
1822  
1823  /**
1824   * Load either Atom comment feed or Atom posts feed.
1825   *
1826   * @since 2.1.0
1827   *
1828   * @param bool $for_comments True for the comment feed, false for normal feed.
1829   */
1830  function do_feed_atom( $for_comments ) {
1831      if ($for_comments)
1832          load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
1833      else
1834          load_template( ABSPATH . WPINC . '/feed-atom.php' );
1835  }
1836  
1837  /**
1838   * Display the robot.txt file content.
1839   *
1840   * The echo content should be with usage of the permalinks or for creating the
1841   * robot.txt file.
1842   *
1843   * @since 2.1.0
1844   * @uses do_action() Calls 'do_robotstxt' hook for displaying robot.txt rules.
1845   */
1846  function do_robots() {
1847      header( 'Content-Type: text/plain; charset=utf-8' );
1848  
1849      do_action( 'do_robotstxt' );
1850  
1851      $output = '';
1852      $public = get_option( 'blog_public' );
1853      if ( '0' ==  $public ) {
1854          $output .= "User-agent: *\n";
1855          $output .= "Disallow: /\n";
1856      } else {
1857          $output .= "User-agent: *\n";
1858          $output .= "Disallow:\n";
1859      }
1860  
1861      echo apply_filters('robots_txt', $output, $public);
1862  }
1863  
1864  /**
1865   * Test whether blog is already installed.
1866   *
1867   * The cache will be checked first. If you have a cache plugin, which saves the
1868   * cache values, then this will work. If you use the default WordPress cache,
1869   * and the database goes away, then you might have problems.
1870   *
1871   * Checks for the option siteurl for whether WordPress is installed.
1872   *
1873   * @since 2.1.0
1874   * @uses $wpdb
1875   *
1876   * @return bool Whether blog is already installed.
1877   */
1878  function is_blog_installed() {
1879      global $wpdb;
1880  
1881      // Check cache first. If options table goes away and we have true cached, oh well.
1882      if ( wp_cache_get( 'is_blog_installed' ) )
1883          return true;
1884  
1885      $suppress = $wpdb->suppress_errors();
1886      if ( ! defined( 'WP_INSTALLING' ) ) {
1887          $alloptions = wp_load_alloptions();
1888      }
1889      // If siteurl is not set to autoload, check it specifically
1890      if ( !isset( $alloptions['siteurl'] ) )
1891          $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
1892      else
1893          $installed = $alloptions['siteurl'];
1894      $wpdb->suppress_errors( $suppress );
1895  
1896      $installed = !empty( $installed );
1897      wp_cache_set( 'is_blog_installed', $installed );
1898  
1899      if ( $installed )
1900          return true;
1901  
1902      $suppress = $wpdb->suppress_errors();
1903      $tables = $wpdb->get_col('SHOW TABLES');
1904      $wpdb->suppress_errors( $suppress );
1905  
1906      $wp_tables = $wpdb->tables();
1907      // Loop over the WP tables.  If none exist, then scratch install is allowed.
1908      // If one or more exist, suggest table repair since we got here because the options
1909      // table could not be accessed.
1910      foreach ( $wp_tables as $table ) {
1911          // If one of the WP tables exist, then we are in an insane state.
1912          if ( in_array( $table, $tables ) ) {
1913              // The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
1914              if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
1915                  continue;
1916              if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
1917                  continue;
1918  
1919              // If visiting repair.php, return true and let it take over.
1920              if ( defined('WP_REPAIRING') )
1921                  return true;
1922              // Die with a DB error.
1923              $wpdb->error = sprintf( /*WP_I18N_NO_TABLES*/'One or more database tables are unavailable.  The database may need to be <a href="%s">repaired</a>.'/*/WP_I18N_NO_TABLES*/, 'maint/repair.php?referrer=is_blog_installed' );
1924              dead_db();
1925          }
1926      }
1927  
1928      wp_cache_set( 'is_blog_installed', false );
1929  
1930      return false;
1931  }
1932  
1933  /**
1934   * Retrieve URL with nonce added to URL query.
1935   *
1936   * @package WordPress
1937   * @subpackage Security
1938   * @since 2.0.4
1939   *
1940   * @param string $actionurl URL to add nonce action
1941   * @param string $action Optional. Nonce action name
1942   * @return string URL with nonce action added.
1943   */
1944  function wp_nonce_url( $actionurl, $action = -1 ) {
1945      $actionurl = str_replace( '&amp;', '&', $actionurl );
1946      return esc_html( add_query_arg( '_wpnonce', wp_create_nonce( $action ), $actionurl ) );
1947  }
1948  
1949  /**
1950   * Retrieve or display nonce hidden field for forms.
1951   *
1952   * The nonce field is used to validate that the contents of the form came from
1953   * the location on the current site and not somewhere else. The nonce does not
1954   * offer absolute protection, but should protect against most cases. It is very
1955   * important to use nonce field in forms.
1956   *
1957   * If you set $echo to true and set $referer to true, then you will need to
1958   * retrieve the {@link wp_referer_field() wp referer field}. If you have the
1959   * $referer set to true and are echoing the nonce field, it will also echo the
1960   * referer field.
1961   *
1962   * The $action and $name are optional, but if you want to have better security,
1963   * it is strongly suggested to set those two parameters. It is easier to just
1964   * call the function without any parameters, because validation of the nonce
1965   * doesn't require any parameters, but since crackers know what the default is
1966   * it won't be difficult for them to find a way around your nonce and cause
1967   * damage.
1968   *
1969   * The input name will be whatever $name value you gave. The input value will be
1970   * the nonce creation value.
1971   *
1972   * @package WordPress
1973   * @subpackage Security
1974   * @since 2.0.4
1975   *
1976   * @param string $action Optional. Action name.
1977   * @param string $name Optional. Nonce name.
1978   * @param bool $referer Optional, default true. Whether to set the referer field for validation.
1979   * @param bool $echo Optional, default true. Whether to display or return hidden form field.
1980   * @return string Nonce field.
1981   */
1982  function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1983      $name = esc_attr( $name );
1984      $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
1985      if ( $echo )
1986          echo $nonce_field;
1987  
1988      if ( $referer )
1989          wp_referer_field( $echo );
1990  
1991      return $nonce_field;
1992  }
1993  
1994  /**
1995   * Retrieve or display referer hidden field for forms.
1996   *
1997   * The referer link is the current Request URI from the server super global. The
1998   * input name is '_wp_http_referer', in case you wanted to check manually.
1999   *
2000   * @package WordPress
2001   * @subpackage Security
2002   * @since 2.0.4
2003   *
2004   * @param bool $echo Whether to echo or return the referer field.
2005   * @return string Referer field.
2006   */
2007  function wp_referer_field( $echo = true ) {
2008      $ref = esc_attr( $_SERVER['REQUEST_URI'] );
2009      $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. $ref . '" />';
2010  
2011      if ( $echo )
2012          echo $referer_field;
2013      return $referer_field;
2014  }
2015  
2016  /**
2017   * Retrieve or display original referer hidden field for forms.
2018   *
2019   * The input name is '_wp_original_http_referer' and will be either the same
2020   * value of {@link wp_referer_field()}, if that was posted already or it will
2021   * be the current page, if it doesn't exist.
2022   *
2023   * @package WordPress
2024   * @subpackage Security
2025   * @since 2.0.4
2026   *
2027   * @param bool $echo Whether to echo the original http referer
2028   * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to.
2029   * @return string Original referer field.
2030   */
2031  function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
2032      $jump_back_to = ( 'previous' == $jump_back_to ) ? wp_get_referer() : $_SERVER['REQUEST_URI'];
2033      $ref = ( wp_get_original_referer() ) ? wp_get_original_referer() : $jump_back_to;
2034      $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( stripslashes( $ref ) ) . '" />';
2035      if ( $echo )
2036          echo $orig_referer_field;
2037      return $orig_referer_field;
2038  }
2039  
2040  /**
2041   * Retrieve referer from '_wp_http_referer', HTTP referer, or current page respectively.
2042   *
2043   * @package WordPress
2044   * @subpackage Security
2045   * @since 2.0.4
2046   *
2047   * @return string|bool False on failure. Referer URL on success.
2048   */
2049  function wp_get_referer() {
2050      $ref = '';
2051      if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
2052          $ref = $_REQUEST['_wp_http_referer'];
2053      else if ( ! empty( $_SERVER['HTTP_REFERER'] ) )
2054          $ref = $_SERVER['HTTP_REFERER'];
2055  
2056      if ( $ref !== $_SERVER['REQUEST_URI'] )
2057          return $ref;
2058      return false;
2059  }
2060  
2061  /**
2062   * Retrieve original referer that was posted, if it exists.
2063   *
2064   * @package WordPress
2065   * @subpackage Security
2066   * @since 2.0.4
2067   *
2068   * @return string|bool False if no original referer or original referer if set.
2069   */
2070  function wp_get_original_referer() {
2071      if ( !empty( $_REQUEST['_wp_original_http_referer'] ) )
2072          return $_REQUEST['_wp_original_http_referer'];
2073      return false;
2074  }
2075  
2076  /**
2077   * Recursive directory creation based on full path.
2078   *
2079   * Will attempt to set permissions on folders.
2080   *
2081   * @since 2.0.1
2082   *
2083   * @param string $target Full path to attempt to create.
2084   * @return bool Whether the path was created. True if path already exists.
2085   */
2086  function wp_mkdir_p( $target ) {
2087      // from php.net/mkdir user contributed notes
2088      $target = str_replace( '//', '/', $target );
2089  
2090      // safe mode fails with a trailing slash under certain PHP versions.
2091      $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
2092      if ( empty($target) )
2093          $target = '/';
2094  
2095      if ( file_exists( $target ) )
2096          return @is_dir( $target );
2097  
2098      // Attempting to create the directory may clutter up our display.
2099      if ( @mkdir( $target ) ) {
2100          $stat = @stat( dirname( $target ) );
2101          $dir_perms = $stat['mode'] & 0007777;  // Get the permission bits.
2102          @chmod( $target, $dir_perms );
2103          return true;
2104      } elseif ( is_dir( dirname( $target ) ) ) {
2105              return false;
2106      }
2107  
2108      // If the above failed, attempt to create the parent node, then try again.
2109      if ( ( $target != '/' ) && ( wp_mkdir_p( dirname( $target ) ) ) )
2110          return wp_mkdir_p( $target );
2111  
2112      return false;
2113  }
2114  
2115  /**
2116   * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
2117   *
2118   * @since 2.5.0
2119   *
2120   * @param string $path File path
2121   * @return bool True if path is absolute, false is not absolute.
2122   */
2123  function path_is_absolute( $path ) {
2124      // this is definitive if true but fails if $path does not exist or contains a symbolic link
2125      if ( realpath($path) == $path )
2126          return true;
2127  
2128      if ( strlen($path) == 0 || $path[0] == '.' )
2129          return false;
2130  
2131      // windows allows absolute paths like this
2132      if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
2133          return true;
2134  
2135      // a path starting with / or \ is absolute; anything else is relative
2136      return (bool) preg_match('#^[/\\\\]#', $path);
2137  }
2138  
2139  /**
2140   * Join two filesystem paths together (e.g. 'give me $path relative to $base').
2141   *
2142   * If the $path is absolute, then it the full path is returned.
2143   *
2144   * @since 2.5.0
2145   *
2146   * @param string $base
2147   * @param string $path
2148   * @return string The path with the base or absolute path.
2149   */
2150  function path_join( $base, $path ) {
2151      if ( path_is_absolute($path) )
2152          return $path;
2153  
2154      return rtrim($base, '/') . '/' . ltrim($path, '/');
2155  }
2156  
2157  /**
2158   * Determines a writable directory for temporary files.
2159   * 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/
2160   *
2161   * 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.
2162   *
2163   * @since 2.5.0
2164   *
2165   * @return string Writable temporary directory
2166   */
2167  function get_temp_dir() {
2168      static $temp;
2169      if ( defined('WP_TEMP_DIR') )
2170          return trailingslashit(WP_TEMP_DIR);
2171  
2172      if ( $temp )
2173          return trailingslashit($temp);
2174  
2175      $temp = WP_CONTENT_DIR . '/';
2176      if ( is_dir($temp) && @is_writable($temp) )
2177          return $temp;
2178  
2179      if  ( function_exists('sys_get_temp_dir') ) {
2180          $temp = sys_get_temp_dir();
2181          if ( @is_writable($temp) )
2182              return trailingslashit($temp);
2183      }
2184  
2185      $temp = ini_get('upload_tmp_dir');
2186      if ( is_dir($temp) && @is_writable($temp) )
2187          return trailingslashit($temp);
2188  
2189      $temp = '/tmp/';
2190      return $temp;
2191  }
2192  
2193  /**
2194   * Get an array containing the current upload directory's path and url.
2195   *
2196   * Checks the 'upload_path' option, which should be from the web root folder,
2197   * and if it isn't empty it will be used. If it is empty, then the path will be
2198   * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
2199   * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
2200   *
2201   * The upload URL path is set either by the 'upload_url_path' option or by using
2202   * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
2203   *
2204   * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
2205   * the administration settings panel), then the time will be used. The format
2206   * will be year first and then month.
2207   *
2208   * If the path couldn't be created, then an error will be returned with the key
2209   * 'error' containing the error message. The error suggests that the parent
2210   * directory is not writable by the server.
2211   *
2212   * On success, the returned array will have many indices:
2213   * 'path' - base directory and sub directory or full path to upload directory.
2214   * 'url' - base url and sub directory or absolute URL to upload directory.
2215   * 'subdir' - sub directory if uploads use year/month folders option is on.
2216   * 'basedir' - path without subdir.
2217   * 'baseurl' - URL path without subdir.
2218   * 'error' - set to false.
2219   *
2220   * @since 2.0.0
2221   * @uses apply_filters() Calls 'upload_dir' on returned array.
2222   *
2223   * @param string $time Optional. Time formatted in 'yyyy/mm'.
2224   * @return array See above for description.
2225   */
2226  function wp_upload_dir( $time = null ) {
2227      global $switched;
2228      $siteurl = get_option( 'siteurl' );
2229      $upload_path = get_option( 'upload_path' );
2230      $upload_path = trim($upload_path);
2231      $main_override = is_multisite() && defined( 'MULTISITE' ) && is_main_site();
2232      if ( empty($upload_path) ) {
2233          $dir = WP_CONTENT_DIR . '/uploads';
2234      } else {
2235          $dir = $upload_path;
2236          if ( 'wp-content/uploads' == $upload_path ) {
2237              $dir = WP_CONTENT_DIR . '/uploads';
2238          } elseif ( 0 !== strpos($dir, ABSPATH) ) {
2239              // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
2240              $dir = path_join( ABSPATH, $dir );
2241          }
2242      }
2243  
2244      if ( !$url = get_option( 'upload_url_path' ) ) {
2245          if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) )
2246              $url = WP_CONTENT_URL . '/uploads';
2247          else
2248              $url = trailingslashit( $siteurl ) . $upload_path;
2249      }
2250  
2251      if ( defined('UPLOADS') && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
2252          $dir = ABSPATH . UPLOADS;
2253          $url = trailingslashit( $siteurl ) . UPLOADS;
2254      }
2255  
2256      if ( is_multisite() && !$main_override && ( !isset( $switched ) || $switched === false ) ) {
2257          if ( defined( 'BLOGUPLOADDIR' ) )
2258              $dir = untrailingslashit(BLOGUPLOADDIR);
2259          $url = str_replace( UPLOADS, 'files', $url );
2260      }
2261  
2262      $bdir = $dir;
2263      $burl = $url;
2264  
2265      $subdir = '';
2266      if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
2267          // Generate the yearly and monthly dirs
2268          if ( !$time )
2269              $time = current_time( 'mysql' );
2270          $y = substr( $time, 0, 4 );
2271          $m = substr( $time, 5, 2 );
2272          $subdir = "/$y/$m";
2273      }
2274  
2275      $dir .= $subdir;
2276      $url .= $subdir;
2277  
2278      $uploads = apply_filters( 'upload_dir', array( 'path' => $dir, 'url' => $url, 'subdir' => $subdir, 'basedir' => $bdir, 'baseurl' => $burl, 'error' => false ) );
2279  
2280      // Make sure we have an uploads dir
2281      if ( ! wp_mkdir_p( $uploads['path'] ) ) {
2282          $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $uploads['path'] );
2283          return array( 'error' => $message );
2284      }
2285  
2286      return $uploads;
2287  }
2288  
2289  /**
2290   * Get a filename that is sanitized and unique for the given directory.
2291   *
2292   * If the filename is not unique, then a number will be added to the filename
2293   * before the extension, and will continue adding numbers until the filename is
2294   * unique.
2295   *
2296   * The callback is passed three parameters, the first one is the directory, the
2297   * second is the filename, and the third is the extension.
2298   *
2299   * @since 2.5.0
2300   *
2301   * @param string $dir
2302   * @param string $filename
2303   * @param mixed $unique_filename_callback Callback.
2304   * @return string New filename, if given wasn't unique.
2305   */
2306  function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
2307      // sanitize the file name before we begin processing
2308      $filename = sanitize_file_name($filename);
2309  
2310      // separate the filename into a name and extension
2311      $info = pathinfo($filename);
2312      $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
2313      $name = basename($filename, $ext);
2314  
2315      // edge case: if file is named '.ext', treat as an empty name
2316      if ( $name === $ext )
2317          $name = '';
2318  
2319      // Increment the file number until we have a unique file to save in $dir. Use callback if supplied.
2320      if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
2321          $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext );
2322      } else {
2323          $number = '';
2324  
2325          // change '.ext' to lower case
2326          if ( $ext && strtolower($ext) != $ext ) {
2327              $ext2 = strtolower($ext);
2328              $filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
2329  
2330              // check for both lower and upper case extension or image sub-sizes may be overwritten
2331              while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
2332                  $new_number = $number + 1;
2333                  $filename = str_replace( "$number$ext", "$new_number$ext", $filename );
2334                  $filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
2335                  $number = $new_number;
2336              }
2337              return $filename2;
2338          }
2339  
2340          while ( file_exists( $dir . "/$filename" ) ) {
2341              if ( '' == "$number$ext" )
2342                  $filename = $filename . ++$number . $ext;
2343              else
2344                  $filename = str_replace( "$number$ext", ++$number . $ext, $filename );
2345          }
2346      }
2347  
2348      return $filename;
2349  }
2350