[ Index ]

PHP Cross Reference of WordPress 3.0 beta 1

[ Index ]     [ Variables ]     [ Functions ]     [ Classes ]     [ Constants ]     [ Statistics ]

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  
  34      $i = strtotime( $m );
  35  
  36      if ( 'U' == $dateformatstring )
  37          return $i;
  38  
  39      if ( $translate)
  40          return date_i18n( $dateformatstring, $i );
  41      else
  42          return date( $dateformatstring, $i );
  43  }
  44  
  45  /**
  46   * Retrieve the current time based on specified type.
  47   *
  48   * The 'mysql' type will return the time in the format for MySQL DATETIME field.
  49   * The 'timestamp' type will return the current timestamp.
  50   *
  51   * If $gmt is set to either '1' or 'true', then both types will use GMT time.
  52   * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
  53   *
  54   * @since 1.0.0
  55   *
  56   * @param string $type Either 'mysql' or 'timestamp'.
  57   * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false.
  58   * @return int|string String if $type is 'gmt', int if $type is 'timestamp'.
  59   */
  60  function current_time( $type, $gmt = 0 ) {
  61      switch ( $type ) {
  62          case 'mysql':
  63              return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * 3600 ) ) );
  64              break;
  65          case 'timestamp':
  66              return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * 3600 );
  67              break;
  68      }
  69  }
  70  
  71  /**
  72   * Retrieve the date in localized format, based on timestamp.
  73   *
  74   * If the locale specifies the locale month and weekday, then the locale will
  75   * take over the format for the date. If it isn't, then the date format string
  76   * will be used instead.
  77   *
  78   * @since 0.71
  79   *
  80   * @param string $dateformatstring Format to display the date.
  81   * @param int $unixtimestamp Optional. Unix timestamp.
  82   * @param bool $gmt Optional, default is false. Whether to convert to GMT for time.
  83   * @return string The date, translated if locale specifies it.
  84   */
  85  function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
  86      global $wp_locale;
  87      $i = $unixtimestamp;
  88      // Sanity check for PHP 5.1.0-
  89      if ( false === $i || intval($i) < 0 ) {
  90          if ( ! $gmt )
  91              $i = current_time( 'timestamp' );
  92          else
  93              $i = time();
  94          // we should not let date() interfere with our
  95          // specially computed timestamp
  96          $gmt = true;
  97      }
  98  
  99      // store original value for language with untypical grammars
 100      // see http://core.trac.wordpress.org/ticket/9396
 101      $req_format = $dateformatstring;
 102  
 103      $datefunc = $gmt? 'gmdate' : 'date';
 104  
 105      if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
 106          $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
 107          $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
 108          $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
 109          $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
 110          $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
 111          $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
 112          $dateformatstring = ' '.$dateformatstring;
 113          $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
 114          $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
 115          $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
 116          $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
 117          $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
 118          $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
 119  
 120          $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
 121      }
 122      $j = @$datefunc( $dateformatstring, $i );
 123      // allow plugins to redo this entirely for languages with untypical grammars
 124      $j = apply_filters('date_i18n', $j, $req_format, $i, $gmt);
 125      return $j;
 126  }
 127  
 128  /**
 129   * Convert number to format based on the locale.
 130   *
 131   * @since 2.3.0
 132   *
 133   * @param mixed $number The number to convert based on locale.
 134   * @param int $decimals Precision of the number of decimal places.
 135   * @return string Converted number in string format.
 136   */
 137  function number_format_i18n( $number, $decimals = null ) {
 138      global $wp_locale;
 139      // let the user override the precision only
 140      $decimals = ( is_null( $decimals ) ) ? $wp_locale->number_format['decimals'] : intval( $decimals );
 141  
 142      $num = number_format( $number, $decimals, $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
 143  
 144      // let the user translate digits from latin to localized language
 145      return apply_filters( 'number_format_i18n', $num );
 146  }
 147  
 148  /**
 149   * Convert number of bytes largest unit bytes will fit into.
 150   *
 151   * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts
 152   * number of bytes to human readable number by taking the number of that unit
 153   * that the bytes will go into it. Supports TB value.
 154   *
 155   * Please note that integers in PHP are limited to 32 bits, unless they are on
 156   * 64 bit architecture, then they have 64 bit size. If you need to place the
 157   * larger size then what PHP integer type will hold, then use a string. It will
 158   * be converted to a double, which should always have 64 bit length.
 159   *
 160   * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
 161   * @link http://en.wikipedia.org/wiki/Byte
 162   *
 163   * @since 2.3.0
 164   *
 165   * @param int|string $bytes Number of bytes. Note max integer size for integers.
 166   * @param int $decimals Precision of number of decimal places.
 167   * @return bool|string False on failure. Number string on success.
 168   */
 169  function size_format( $bytes, $decimals = null ) {
 170      $quant = array(
 171          // ========================= Origin ====
 172          'TB' => 1099511627776,  // pow( 1024, 4)
 173          'GB' => 1073741824,     // pow( 1024, 3)
 174          'MB' => 1048576,        // pow( 1024, 2)
 175          'kB' => 1024,           // pow( 1024, 1)
 176          'B ' => 1,              // pow( 1024, 0)
 177      );
 178  
 179      foreach ( $quant as $unit => $mag )
 180          if ( doubleval($bytes) >= $mag )
 181              return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
 182  
 183      return false;
 184  }
 185  
 186  /**
 187   * Get the week start and end from the datetime or date string from mysql.
 188   *
 189   * @since 0.71
 190   *
 191   * @param string $mysqlstring Date or datetime field type from mysql.
 192   * @param int $start_of_week Optional. Start of the week as an integer.
 193   * @return array Keys are 'start' and 'end'.
 194   */
 195  function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
 196      $my = substr( $mysqlstring, 0, 4 ); // Mysql string Year
 197      $mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month
 198      $md = substr( $mysqlstring, 5, 2 ); // Mysql string day
 199      $day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day.
 200      $weekday = date( 'w', $day ); // The day of the week from the timestamp
 201      $i = 86400; // One day
 202      if ( !is_numeric($start_of_week) )
 203          $start_of_week = get_option( 'start_of_week' );
 204  
 205      if ( $weekday < $start_of_week )
 206          $weekday = 7 - $start_of_week - $weekday;
 207  
 208      while ( $weekday > $start_of_week ) {
 209          $weekday = date( 'w', $day );
 210          if ( $weekday < $start_of_week )
 211              $weekday = 7 - $start_of_week - $weekday;
 212  
 213          $day -= 86400;
 214          $i = 0;
 215      }
 216      $week['start'] = $day + 86400 - $i;
 217      $week['end'] = $week['start'] + 604799;
 218      return $week;
 219  }
 220  
 221  /**
 222   * Unserialize value only if it was serialized.
 223   *
 224   * @since 2.0.0
 225   *
 226   * @param string $original Maybe unserialized original, if is needed.
 227   * @return mixed Unserialized data can be any type.
 228   */
 229  function maybe_unserialize( $original ) {
 230      if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
 231          return @unserialize( $original );
 232      return $original;
 233  }
 234  
 235  /**
 236   * Check value to find if it was serialized.
 237   *
 238   * If $data is not an string, then returned value will always be false.
 239   * Serialized data is always a string.
 240   *
 241   * @since 2.0.5
 242   *
 243   * @param mixed $data Value to check to see if was serialized.
 244   * @return bool False if not serialized and true if it was.
 245   */
 246  function is_serialized( $data ) {
 247      // if it isn't a string, it isn't serialized
 248      if ( !is_string( $data ) )
 249          return false;
 250      $data = trim( $data );
 251      if ( 'N;' == $data )
 252          return true;
 253      if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
 254          return false;
 255      switch ( $badions[1] ) {
 256          case 'a' :
 257          case 'O' :
 258          case 's' :
 259              if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
 260                  return true;
 261              break;
 262          case 'b' :
 263          case 'i' :
 264          case 'd' :
 265              if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
 266                  return true;
 267              break;
 268      }
 269      return false;
 270  }
 271  
 272  /**
 273   * Check whether serialized data is of string type.
 274   *
 275   * @since 2.0.5
 276   *
 277   * @param mixed $data Serialized data
 278   * @return bool False if not a serialized string, true if it is.
 279   */
 280  function is_serialized_string( $data ) {
 281      // if it isn't a string, it isn't a serialized string
 282      if ( !is_string( $data ) )
 283          return false;
 284      $data = trim( $data );
 285      if ( preg_match( '/^s:[0-9]+:.*;$/s', $data ) ) // this should fetch all serialized strings
 286          return true;
 287      return false;
 288  }
 289  
 290  /**
 291   * Retrieve option value based on name of option.
 292   *
 293   * If the option does not exist or does not have a value, then the return value
 294   * will be false. This is useful to check whether you need to install an option
 295   * and is commonly used during installation of plugin options and to test
 296   * whether upgrading is required.
 297   *
 298   * If the option was serialized then it will be unserialized when it is returned.
 299   *
 300   * @since 1.5.0
 301   * @package WordPress
 302   * @subpackage Option
 303   * @uses apply_filters() Calls 'pre_option_$option' before checking the option.
 304   *     Any value other than false will "short-circuit" the retrieval of the option
 305   *    and return the returned value. You should not try to override special options,
 306   *     but you will not be prevented from doing so.
 307   * @uses apply_filters() Calls 'option_$option', after checking the option, with
 308   *     the option value.
 309   *
 310   * @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
 311   * @return mixed Value set for the option.
 312   */
 313  function get_option( $option, $default = false ) {
 314      global $wpdb;
 315  
 316      // Allow plugins to short-circuit options.
 317      $pre = apply_filters( 'pre_option_' . $option, false );
 318      if ( false !== $pre )
 319          return $pre;
 320  
 321      $option = trim($option);
 322      if ( empty($option) )
 323          return false;
 324  
 325      // prevent non-existent options from triggering multiple queries
 326      if ( defined( 'WP_INSTALLING' ) && is_multisite() ) {
 327          $notoptions = array();
 328      } else {
 329          $notoptions = wp_cache_get( 'notoptions', 'options' );
 330          if ( isset( $notoptions[$option] ) )
 331              return $default;
 332      }
 333  
 334      if ( ! defined( 'WP_INSTALLING' ) ) {
 335          $alloptions = wp_load_alloptions();
 336      }
 337  
 338      if ( isset( $alloptions[$option] ) ) {
 339          $value = $alloptions[$option];
 340      } else {
 341          $value = wp_cache_get( $option, 'options' );
 342  
 343          if ( false === $value ) {
 344              if ( defined( 'WP_INSTALLING' ) )
 345                  $suppress = $wpdb->suppress_errors();
 346              $row = $wpdb->get_row( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = '%s' LIMIT 1", $option ) );
 347              if ( defined( 'WP_INSTALLING' ) )
 348                  $wpdb->suppress_errors( $suppress );
 349  
 350              // Has to be get_row instead of get_var because of funkiness with 0, false, null values
 351              if ( is_object( $row ) ) {
 352                  $value = $row->option_value;
 353                  wp_cache_add( $option, $value, 'options' );
 354              } else { // option does not exist, so we must cache its non-existence
 355                  $notoptions[$option] = true;
 356                  wp_cache_set( 'notoptions', $notoptions, 'options' );
 357                  return $default;
 358              }
 359          }
 360      }
 361  
 362      // If home is not set use siteurl.
 363      if ( 'home' == $option && '' == $value )
 364          return get_option( 'siteurl' );
 365  
 366      if ( in_array( $option, array('siteurl', 'home', 'category_base', 'tag_base') ) )
 367          $value = untrailingslashit( $value );
 368  
 369      return apply_filters( 'option_' . $option, maybe_unserialize( $value ) );
 370  }
 371  
 372  /**
 373   * Protect WordPress special option from being modified.
 374   *
 375   * Will die if $option is in protected list. Protected options are 'alloptions'
 376   * and 'notoptions' options.
 377   *
 378   * @since 2.2.0
 379   * @package WordPress
 380   * @subpackage Option
 381   *
 382   * @param string $option Option name.
 383   */
 384  function wp_protect_special_option( $option ) {
 385      $protected = array( 'alloptions', 'notoptions' );
 386      if ( in_array( $option, $protected ) )
 387          wp_die( sprintf( __( '%s is a protected WP option and may not be modified' ), esc_html( $option ) ) );
 388  }
 389  
 390  /**
 391   * Print option value after sanitizing for forms.
 392   *
 393   * @uses attr Sanitizes value.
 394   * @since 1.5.0
 395   * @package WordPress
 396   * @subpackage Option
 397   *
 398   * @param string $option Option name.
 399   */
 400  function form_option( $option ) {
 401      echo esc_attr( get_option( $option ) );
 402  }
 403  
 404  /**
 405   * Loads and caches all autoloaded options, if available or all options.
 406   *
 407   * @since 2.2.0
 408   * @package WordPress
 409   * @subpackage Option
 410   *
 411   * @return array List of all options.
 412   */
 413  function wp_load_alloptions() {
 414      global $wpdb;
 415  
 416      if ( !defined( 'WP_INSTALLING' ) || !is_multisite() )
 417          $alloptions = wp_cache_get( 'alloptions', 'options' );
 418      else
 419          $alloptions = false;
 420  
 421      if ( !$alloptions ) {
 422          $suppress = $wpdb->suppress_errors();
 423          if ( !$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) )
 424              $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
 425          $wpdb->suppress_errors($suppress);
 426          $alloptions = array();
 427          foreach ( (array) $alloptions_db as $o )
 428              $alloptions[$o->option_name] = $o->option_value;
 429              if ( !defined( 'WP_INSTALLING' ) || !is_multisite() )
 430                  wp_cache_add( 'alloptions', $alloptions, 'options' );
 431      }
 432  
 433      return $alloptions;
 434  }
 435  
 436  /**
 437   * Loads and caches certain often requested site options if is_multisite() and a peristent cache is not being used.
 438   *
 439   * @since 3.0.0
 440   * @package WordPress
 441   * @subpackage Option
 442   *
 443   * @param int $site_id Optional site ID for which to query the options. Defaults to the current site.
 444   */
 445  function wp_load_core_site_options( $site_id = null ) {
 446      global $wpdb, $_wp_using_ext_object_cache;
 447  
 448      if ( !is_multisite() || $_wp_using_ext_object_cache || defined( 'WP_INSTALLING' ) )
 449          return;
 450  
 451      if ( empty($site_id) )
 452          $site_id = $wpdb->siteid;
 453  
 454      $core_options = array('site_name', 'siteurl', 'active_sitewide_plugins', '_site_transient_timeout_theme_roots', '_site_transient_theme_roots', 'site_admins', 'dashboard_blog', 'can_compress_scripts', 'global_terms_enabled' );
 455  
 456      $core_options_in = "'" . implode("', '", $core_options) . "'";
 457      $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) );
 458  
 459      foreach ( $options as $option ) {
 460          $key = $option->meta_key;
 461          $cache_key = "{$site_id}:$key";
 462          $option->meta_value = maybe_unserialize( $option->meta_value );
 463  
 464          wp_cache_set( $cache_key, $option->meta_value, 'site-options' );
 465      }
 466  }
 467  
 468  /**
 469   * Update the value of an option that was already added.
 470   *
 471   * You do not need to serialize values. If the value needs to be serialized, then
 472   * it will be serialized before it is inserted into the database. Remember,
 473   * resources can not be serialized or added as an option.
 474   *
 475   * If the option does not exist, then the option will be added with the option
 476   * value, but you will not be able to set whether it is autoloaded. If you want
 477   * to set whether an option is autoloaded, then you need to use the add_option().
 478   *
 479   * @since 1.0.0
 480   * @package WordPress
 481   * @subpackage Option
 482   *
 483   * @uses apply_filters() Calls 'pre_update_option_$option' hook to allow overwriting the
 484   *     option value to be stored.
 485   * @uses do_action() Calls 'update_option' hook before updating the option.
 486   * @uses do_action() Calls 'update_option_$option' and 'updated_option' hooks on success.
 487   *
 488   * @param string $option Option name. Expected to not be SQL-escaped.
 489   * @param mixed $newvalue Option value. Expected to not be SQL-escaped.
 490   * @return bool False if value was not updated and true if value was updated.
 491   */
 492  function update_option( $option, $newvalue ) {
 493      global $wpdb;
 494  
 495      $option = trim($option);
 496      if ( empty($option) )
 497          return false;
 498  
 499      wp_protect_special_option( $option );
 500  
 501      $newvalue = sanitize_option( $option, $newvalue );
 502      $oldvalue = get_option( $option );
 503      $newvalue = apply_filters( 'pre_update_option_' . $option, $newvalue, $oldvalue );
 504  
 505      // If the new and old values are the same, no need to update.
 506      if ( $newvalue === $oldvalue )
 507          return false;
 508  
 509      if ( false === $oldvalue )
 510          return add_option( $option, $newvalue );
 511  
 512      $notoptions = wp_cache_get( 'notoptions', 'options' );
 513      if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
 514          unset( $notoptions[$option] );
 515          wp_cache_set( 'notoptions', $notoptions, 'options' );
 516      }
 517  
 518      $_newvalue = $newvalue;
 519      $newvalue = maybe_serialize( $newvalue );
 520  
 521      do_action( 'update_option', $option, $oldvalue, $_newvalue );
 522      if ( ! defined( 'WP_INSTALLING' ) ) {
 523          $alloptions = wp_load_alloptions();
 524          if ( isset( $alloptions[$option] ) ) {
 525              $alloptions[$option] = $_newvalue;
 526              wp_cache_set( 'alloptions', $alloptions, 'options' );
 527          } else {
 528              wp_cache_set( $option, $_newvalue, 'options' );
 529          }
 530      }
 531  
 532      $result = $wpdb->update( $wpdb->options, array( 'option_value' => $newvalue ), array( 'option_name' => $option ) );
 533  
 534      if ( $result ) {
 535          do_action( "update_option_{$option}", $oldvalue, $_newvalue );
 536          do_action( 'updated_option', $option, $oldvalue, $_newvalue );
 537          return true;
 538      }
 539      return false;
 540  }
 541  
 542  /**
 543   * Add a new option.
 544   *
 545   * You do not need to serialize values. If the value needs to be serialized, then
 546   * it will be serialized before it is inserted into the database. Remember,
 547   * resources can not be serialized or added as an option.
 548   *
 549   * You can create options without values and then add values later. Does not
 550   * check whether the option has already been added, but does check that you
 551   * aren't adding a protected WordPress option. Care should be taken to not name
 552   * options the same as the ones which are protected and to not add options
 553   * that were already added.
 554   *
 555   * @package WordPress
 556   * @subpackage Option
 557   * @since 1.0.0
 558   * @link http://alex.vort-x.net/blog/ Thanks Alex Stapleton
 559   *
 560   * @uses do_action() Calls 'add_option' hook before adding the option.
 561   * @uses do_action() Calls 'add_option_$option' and 'added_option' hooks on success.
 562   *
 563   * @param string $option Name of option to add. Expected to not be SQL-escaped.
 564   * @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped.
 565   * @param mixed $deprecated Optional. Description. Not used anymore.
 566   * @param bool $autoload Optional. Default is enabled. Whether to load the option when WordPress starts up.
 567   * @return null returns when finished.
 568   */
 569  function add_option( $option, $value = '', $deprecated = '', $autoload = 'yes' ) {
 570      global $wpdb;
 571  
 572      if ( !empty( $deprecated ) )
 573          _deprecated_argument( __FUNCTION__, '2.3' );
 574  
 575      $option = trim($option);
 576      if ( empty($option) )
 577          return false;
 578  
 579      wp_protect_special_option( $option );
 580      $value = sanitize_option( $option, $value );
 581  
 582      // Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
 583      $notoptions = wp_cache_get( 'notoptions', 'options' );
 584      if ( !is_array( $notoptions ) || !isset( $notoptions[$option] ) )
 585          if ( false !== get_option( $option ) )
 586              return;
 587  
 588      $_value = $value;
 589      $value = maybe_serialize( $value );
 590      $autoload = ( 'no' === $autoload ) ? 'no' : 'yes';
 591      do_action( 'add_option', $option, $_value );
 592      if ( ! defined( 'WP_INSTALLING' ) ) {
 593          if ( 'yes' == $autoload ) {
 594              $alloptions = wp_load_alloptions();
 595              $alloptions[$option] = $value;
 596              wp_cache_set( 'alloptions', $alloptions, 'options' );
 597          } else {
 598              wp_cache_set( $option, $value, 'options' );
 599          }
 600      }
 601  
 602      // This option exists now
 603      $notoptions = wp_cache_get( 'notoptions', 'options' ); // yes, again... we need it to be fresh
 604      if ( is_array( $notoptions ) && isset( $notoptions[$option] ) ) {
 605          unset( $notoptions[$option] );
 606          wp_cache_set( 'notoptions', $notoptions, 'options' );
 607      }
 608  
 609      $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 ) );
 610  
 611      if ( $result ) {
 612          do_action( "add_option_{$option}", $option, $_value );
 613          do_action( 'added_option', $option, $_value );
 614          return true;
 615      }
 616      return false;
 617  }
 618  
 619  /**
 620   * Removes option by name. Prevents removal of protected WordPress options.
 621   *
 622   * @package WordPress
 623   * @subpackage Option
 624   * @since 1.2.0
 625   *
 626   * @uses do_action() Calls 'delete_option' hook before option is deleted.
 627   * @uses do_action() Calls 'deleted_option' and 'delete_option_$option' hooks on success.
 628   *
 629   * @param string $option Name of option to remove. Expected to not be SQL-escaped.
 630   * @return bool True, if option is successfully deleted. False on failure.
 631   */
 632  function delete_option( $option ) {
 633      global $wpdb;
 634  
 635      wp_protect_special_option( $option );
 636  
 637      // Get the ID, if no ID then return
 638      $row = $wpdb->get_row( $wpdb->prepare( "SELECT autoload FROM $wpdb->options WHERE option_name = '%s'", $option ) );
 639      if ( is_null( $row ) )
 640          return false;
 641      do_action( 'delete_option', $option );
 642      $result = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name = '%s'", $option) );
 643      if ( ! defined( 'WP_INSTALLING' ) ) {
 644          if ( 'yes' == $row->autoload ) {
 645              $alloptions = wp_load_alloptions();
 646              if ( isset( $alloptions[$option] ) ) {
 647                  unset( $alloptions[$option] );
 648                  wp_cache_set( 'alloptions', $alloptions, 'options' );
 649              }
 650          } else {
 651              wp_cache_delete( $option, 'options' );
 652          }
 653      }
 654      if ( $result ) {
 655          do_action( "delete_option_$option", $option );
 656          do_action( 'deleted_option', $option );
 657          return true;
 658      }
 659      return false;
 660  }
 661  
 662  /**
 663   * Delete a transient
 664   *
 665   * @since 2.8.0
 666   * @package WordPress
 667   * @subpackage Transient
 668   *
 669   * @uses do_action() Calls 'delete_transient_$transient' hook before transient is deleted.
 670   * @uses do_action() Calls 'deleted_transient' hook on success.
 671   *
 672   * @param string $transient Transient name. Expected to not be SQL-escaped.
 673   * @return bool true if successful, false otherwise
 674   */
 675  function delete_transient( $transient ) {
 676      global $_wp_using_ext_object_cache;
 677  
 678      do_action( 'delete_transient_' . $transient, $transient );
 679  
 680      if ( $_wp_using_ext_object_cache ) {
 681          $result = wp_cache_delete( $transient, 'transient' );
 682      } else {
 683          $option_timeout = '_transient_timeout_' . $transient;
 684          $option = '_transient_' . $transient;
 685          $result = delete_option( $option );
 686          if ( $result )
 687              delete_option( $option_timeout );
 688      }
 689  
 690      if ( $result )
 691          do_action( 'deleted_transient', $transient );
 692      return $result;
 693  }
 694  
 695  /**
 696   * Get the value of a transient
 697   *
 698   * If the transient does not exist or does not have a value, then the return value
 699   * will be false.
 700   *
 701   * @uses apply_filters() Calls 'pre_transient_$transient' hook before checking the transient.
 702   *     Any value other than false will "short-circuit" the retrieval of the transient
 703   *    and return the returned value.
 704   * @uses apply_filters() Calls 'transient_$option' hook, after checking the transient, with
 705   *     the transient value.
 706   *
 707   * @since 2.8.0
 708   * @package WordPress
 709   * @subpackage Transient
 710   *
 711   * @param string $transient Transient name. Expected to not be SQL-escaped
 712   * @return mixed Value of transient
 713   */
 714  function get_transient( $transient ) {
 715      global $_wp_using_ext_object_cache;
 716  
 717      $pre = apply_filters( 'pre_transient_' . $transient, false );
 718      if ( false !== $pre )
 719          return $pre;
 720  
 721      if ( $_wp_using_ext_object_cache ) {
 722          $value = wp_cache_get( $transient, 'transient' );
 723      } else {
 724          $transient_option = '_transient_' . $transient;
 725          if ( ! defined( 'WP_INSTALLING' ) ) {
 726              // If option is not in alloptions, it is not autoloaded and thus has a timeout
 727              $alloptions = wp_load_alloptions();
 728              if ( !isset( $alloptions[$transient_option] ) ) {
 729                  $transient_timeout = '_transient_timeout_' . $transient;
 730                  if ( get_option( $transient_timeout ) < time() ) {
 731                      delete_option( $transient_option  );
 732                      delete_option( $transient_timeout );
 733                      return false;
 734                  }
 735              }
 736          }
 737  
 738          $value = get_option( $transient_option );
 739      }
 740  
 741      return apply_filters( 'transient_' . $transient, $value );
 742  }
 743  
 744  /**
 745   * Set/update the value of a transient
 746   *
 747   * You do not need to serialize values. If the value needs to be serialized, then
 748   * it will be serialized before it is set.
 749   *
 750   * @since 2.8.0
 751   * @package WordPress
 752   * @subpackage Transient
 753   *
 754   * @uses apply_filters() Calls 'pre_set_transient_$transient' hook to allow overwriting the
 755   *     transient value to be stored.
 756   * @uses do_action() Calls 'set_transient_$transient' and 'setted_transient' hooks on success.
 757   *
 758   * @param string $transient Transient name. Expected to not be SQL-escaped.
 759   * @param mixed $value Transient value. Expected to not be SQL-escaped.
 760   * @param int $expiration Time until expiration in seconds, default 0
 761   * @return bool False if value was not set and true if value was set.
 762   */
 763  function set_transient( $transient, $value, $expiration = 0 ) {
 764      global $_wp_using_ext_object_cache;
 765  
 766      $value = apply_filters( 'pre_set_transient_' . $transient, $value );
 767  
 768      if ( $_wp_using_ext_object_cache ) {
 769          $result = wp_cache_set( $transient, $value, 'transient', $expiration );
 770      } else {
 771          $transient_timeout = '_transient_timeout_' . $transient;
 772          $transient = '_transient_' . $transient;
 773          if ( false === get_option( $transient ) ) {
 774              $autoload = 'yes';
 775              if ( $expiration ) {
 776                  $autoload = 'no';
 777                  add_option( $transient_timeout, time() + $expiration, '', 'no' );
 778              }
 779              $result = add_option( $transient, $value, '', $autoload );
 780          } else {
 781              if ( $expiration )
 782                  update_option( $transient_timeout, time() + $expiration );
 783              $result = update_option( $transient, $value );
 784          }
 785      }
 786      if ( $result ) {
 787          do_action( 'set_transient_' . $transient );
 788          do_action( 'setted_transient', $transient );
 789      }
 790      return $result;
 791  }
 792  
 793  /**
 794   * Saves and restores user interface settings stored in a cookie.
 795   *
 796   * Checks if the current user-settings cookie is updated and stores it. When no
 797   * cookie exists (different browser used), adds the last saved cookie restoring
 798   * the settings.
 799   *
 800   * @package WordPress
 801   * @subpackage Option
 802   * @since 2.7.0
 803   */
 804  function wp_user_settings() {
 805  
 806      if ( ! is_admin() )
 807          return;
 808  
 809      if ( defined('DOING_AJAX') )
 810          return;
 811  
 812      if ( ! $user = wp_get_current_user() )
 813          return;
 814  
 815      $settings = get_user_option( 'user-settings', $user->ID );
 816  
 817      if ( isset( $_COOKIE['wp-settings-' . $user->ID] ) ) {
 818          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] );
 819  
 820          if ( ! empty( $cookie ) && strpos( $cookie, '=' ) ) {
 821              if ( $cookie == $settings )
 822                  return;
 823  
 824              $last_time = (int) get_user_option( 'user-settings-time', $user->ID );
 825              $saved = isset( $_COOKIE['wp-settings-time-' . $user->ID]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user->ID] ) : 0;
 826  
 827              if ( $saved > $last_time ) {
 828                  update_user_option( $user->ID, 'user-settings', $cookie, false );
 829                  update_user_option( $user->ID, 'user-settings-time', time() - 5, false );
 830                  return;
 831              }
 832          }
 833      }
 834  
 835      setcookie( 'wp-settings-' . $user->ID, $settings, time() + 31536000, SITECOOKIEPATH );
 836      setcookie( 'wp-settings-time-' . $user->ID, time(), time() + 31536000, SITECOOKIEPATH );
 837      $_COOKIE['wp-settings-' . $user->ID] = $settings;
 838  }
 839  
 840  /**
 841   * Retrieve user interface setting value based on setting name.
 842   *
 843   * @package WordPress
 844   * @subpackage Option
 845   * @since 2.7.0
 846   *
 847   * @param string $name The name of the setting.
 848   * @param string $default Optional default value to return when $name is not set.
 849   * @return mixed the last saved user setting or the default value/false if it doesn't exist.
 850   */
 851  function get_user_setting( $name, $default = false ) {
 852  
 853      $all = get_all_user_settings();
 854  
 855      return isset($all[$name]) ? $all[$name] : $default;
 856  }
 857  
 858  /**
 859   * Add or update user interface setting.
 860   *
 861   * Both $name and $value can contain only ASCII letters, numbers and underscores.
 862   * This function has to be used before any output has started as it calls setcookie().
 863   *
 864   * @package WordPress
 865   * @subpackage Option
 866   * @since 2.8.0
 867   *
 868   * @param string $name The name of the setting.
 869   * @param string $value The value for the setting.
 870   * @return bool true if set successfully/false if not.
 871   */
 872  function set_user_setting( $name, $value ) {
 873  
 874      if ( headers_sent() )
 875          return false;
 876  
 877      $all = get_all_user_settings();
 878      $name = preg_replace( '/[^A-Za-z0-9_]+/', '', $name );
 879  
 880      if ( empty($name) )
 881          return false;
 882  
 883      $all[$name] = $value;
 884  
 885      return wp_set_all_user_settings($all);
 886  }
 887  
 888  /**
 889   * Delete user interface settings.
 890   *
 891   * Deleting settings would reset them to the defaults.
 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.7.0
 897   *
 898   * @param mixed $names The name or array of names of the setting to be deleted.
 899   * @return bool true if deleted successfully/false if not.
 900   */
 901  function delete_user_setting( $names ) {
 902  
 903      if ( headers_sent() )
 904          return false;
 905  
 906      $all = get_all_user_settings();
 907      $names = (array) $names;
 908  
 909      foreach ( $names as $name ) {
 910          if ( isset($all[$name]) ) {
 911              unset($all[$name]);
 912              $deleted = true;
 913          }
 914      }
 915  
 916      if ( isset($deleted) )
 917          return wp_set_all_user_settings($all);
 918  
 919      return false;
 920  }
 921  
 922  /**
 923   * Retrieve all user interface settings.
 924   *
 925   * @package WordPress
 926   * @subpackage Option
 927   * @since 2.7.0
 928   *
 929   * @return array the last saved user settings or empty array.
 930   */
 931  function get_all_user_settings() {
 932      global $_updated_user_settings;
 933  
 934      if ( ! $user = wp_get_current_user() )
 935          return array();
 936  
 937      if ( isset($_updated_user_settings) && is_array($_updated_user_settings) )
 938          return $_updated_user_settings;
 939  
 940      $all = array();
 941      if ( isset($_COOKIE['wp-settings-' . $user->ID]) ) {
 942          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] );
 943  
 944          if ( $cookie && strpos($cookie, '=') ) // the '=' cannot be 1st char
 945              parse_str($cookie, $all);
 946  
 947      } else {
 948          $option = get_user_option('user-settings', $user->ID);
 949          if ( $option && is_string($option) )
 950              parse_str( $option, $all );
 951      }
 952  
 953      return $all;
 954  }
 955  
 956  /**
 957   * Private. Set all user interface settings.
 958   *
 959   * @package WordPress
 960   * @subpackage Option
 961   * @since 2.8.0
 962   *
 963   * @param unknown $all
 964   * @return bool
 965   */
 966  function wp_set_all_user_settings($all) {
 967      global $_updated_user_settings;
 968  
 969      if ( ! $user = wp_get_current_user() )
 970          return false;
 971  
 972      $_updated_user_settings = $all;
 973      $settings = '';
 974      foreach ( $all as $k => $v ) {
 975          $v = preg_replace( '/[^A-Za-z0-9_]+/', '', $v );
 976          $settings .= $k . '=' . $v . '&';
 977      }
 978  
 979      $settings = rtrim($settings, '&');
 980  
 981      update_user_option( $user->ID, 'user-settings', $settings, false );
 982      update_user_option( $user->ID, 'user-settings-time', time(), false );
 983  
 984      return true;
 985  }
 986  
 987  /**
 988   * Delete the user settings of the current user.
 989   *
 990   * @package WordPress
 991   * @subpackage Option
 992   * @since 2.7.0
 993   */
 994  function delete_all_user_settings() {
 995      if ( ! $user = wp_get_current_user() )
 996          return;
 997  
 998      update_user_option( $user->ID, 'user-settings', '', false );
 999      setcookie('wp-settings-' . $user->ID, ' ', time() - 31536000, SITECOOKIEPATH);
1000  }
1001  
1002  /**
1003   * Serialize data, if needed.
1004   *
1005   * @since 2.0.5
1006   *
1007   * @param mixed $data Data that might be serialized.
1008   * @return mixed A scalar data
1009   */
1010  function maybe_serialize( $data ) {
1011      if ( !is_scalar( $data ) )
1012          return serialize( $data );
1013  
1014      return $data;
1015  }
1016  
1017  /**
1018   * Retrieve post title from XMLRPC XML.
1019   *
1020   * If the title element is not part of the XML, then the default post title from
1021   * the $post_default_title will be used instead.
1022   *
1023   * @package WordPress
1024   * @subpackage XMLRPC
1025   * @since 0.71
1026   *
1027   * @global string $post_default_title Default XMLRPC post title.
1028   *
1029   * @param string $content XMLRPC XML Request content
1030   * @return string Post title
1031   */
1032  function xmlrpc_getposttitle( $content ) {
1033      global $post_default_title;
1034      if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
1035          $post_title = $matchtitle[1];
1036      } else {
1037          $post_title = $post_default_title;
1038      }
1039      return $post_title;
1040  }
1041  
1042  /**
1043   * Retrieve the post category or categories from XMLRPC XML.
1044   *
1045   * If the category element is not found, then the default post category will be
1046   * used. The return type then would be what $post_default_category. If the
1047   * category is found, then it will always be an array.
1048   *
1049   * @package WordPress
1050   * @subpackage XMLRPC
1051   * @since 0.71
1052   *
1053   * @global string $post_default_category Default XMLRPC post category.
1054   *
1055   * @param string $content XMLRPC XML Request content
1056   * @return string|array List of categories or category name.
1057   */
1058  function xmlrpc_getpostcategory( $content ) {
1059      global $post_default_category;
1060      if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
1061          $post_category = trim( $matchcat[1], ',' );
1062          $post_category = explode( ',', $post_category );
1063      } else {
1064          $post_category = $post_default_category;
1065      }
1066      return $post_category;
1067  }
1068  
1069  /**
1070   * XMLRPC XML content without title and category elements.
1071   *
1072   * @package WordPress
1073   * @subpackage XMLRPC
1074   * @since 0.71
1075   *
1076   * @param string $content XMLRPC XML Request content
1077   * @return string XMLRPC XML Request content without title and category elements.
1078   */
1079  function xmlrpc_removepostdata( $content ) {
1080      $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
1081      $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
1082      $content = trim( $content );
1083      return $content;
1084  }
1085  
1086  /**
1087   * Open the file handle for debugging.
1088   *
1089   * This function is used for XMLRPC feature, but it is general purpose enough
1090   * to be used in anywhere.
1091   *
1092   * @see fopen() for mode options.
1093   * @package WordPress
1094   * @subpackage Debug
1095   * @since 0.71
1096   * @uses $debug Used for whether debugging is enabled.
1097   *
1098   * @param string $filename File path to debug file.
1099   * @param string $mode Same as fopen() mode parameter.
1100   * @return bool|resource File handle. False on failure.
1101   */
1102  function debug_fopen( $filename, $mode ) {
1103      global $debug;
1104      if ( 1 == $debug ) {
1105          $fp = fopen( $filename, $mode );
1106          return $fp;
1107      } else {
1108          return false;
1109      }
1110  }
1111  
1112  /**
1113   * Write contents to the file used for debugging.
1114   *
1115   * Technically, this can be used to write to any file handle when the global
1116   * $debug is set to 1 or true.
1117   *
1118   * @package WordPress
1119   * @subpackage Debug
1120   * @since 0.71
1121   * @uses $debug Used for whether debugging is enabled.
1122   *
1123   * @param resource $fp File handle for debugging file.
1124   * @param string $string Content to write to debug file.
1125   */
1126  function debug_fwrite( $fp, $string ) {
1127      global $debug;
1128      if ( 1 == $debug )
1129          fwrite( $fp, $string );
1130  }
1131  
1132  /**
1133   * Close the debugging file handle.
1134   *
1135   * Technically, this can be used to close any file handle when the global $debug
1136   * is set to 1 or true.
1137   *
1138   * @package WordPress
1139   * @subpackage Debug
1140   * @since 0.71
1141   * @uses $debug Used for whether debugging is enabled.
1142   *
1143   * @param resource $fp Debug File handle.
1144   */
1145  function debug_fclose( $fp ) {
1146      global $debug;
1147      if ( 1 == $debug )
1148          fclose( $fp );
1149  }
1150  
1151  /**
1152   * Check content for video and audio links to add as enclosures.
1153   *
1154   * Will not add enclosures that have already been added and will
1155   * remove enclosures that are no longer in the post. This is called as
1156   * pingbacks and trackbacks.
1157   *
1158   * @package WordPress
1159   * @since 1.5.0
1160   *
1161   * @uses $wpdb
1162   *
1163   * @param string $content Post Content
1164   * @param int $post_ID Post ID
1165   */
1166  function do_enclose( $content, $post_ID ) {
1167      global $wpdb;
1168      include_once ( ABSPATH . WPINC . '/class-IXR.php' );
1169  
1170      $log = debug_fopen( ABSPATH . 'enclosures.log', 'a' );
1171      $post_links = array();
1172      debug_fwrite( $log, 'BEGIN ' . date( 'YmdHis', time() ) . "\n" );
1173  
1174      $pung = get_enclosed( $post_ID );
1175  
1176      $ltrs = '\w';
1177      $gunk = '/#~:.?+=&%@!\-';
1178      $punc = '.:?\-';
1179      $any = $ltrs . $gunk . $punc;
1180  
1181      preg_match_all( "{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp );
1182  
1183      debug_fwrite( $log, 'Post contents:' );
1184      debug_fwrite( $log, $content . "\n" );
1185  
1186      foreach ( $pung as $link_test ) {
1187          if ( !in_array( $link_test, $post_links_temp[0] ) ) { // link no longer in post
1188              $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, $link_test . '%') );
1189              do_action( 'delete_postmeta', $mid );
1190              $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE post_id IN(%s)", implode( ',', $mid ) ) );
1191              do_action( 'deleted_postmeta', $mid );
1192          }
1193      }
1194  
1195      foreach ( (array) $post_links_temp[0] as $link_test ) {
1196          if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
1197              $test = parse_url( $link_test );
1198              if ( isset( $test['query'] ) )
1199                  $post_links[] = $link_test;
1200              elseif ( $test['path'] != '/' && $test['path'] != '' )
1201                  $post_links[] = $link_test;
1202          }
1203      }
1204  
1205      foreach ( (array) $post_links as $url ) {
1206          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, $url . '%' ) ) ) {
1207  
1208              if ( $headers = wp_get_http_headers( $url) ) {
1209                  $len = (int) $headers['content-length'];
1210                  $type = $headers['content-type'];
1211                  $allowed_types = array( 'video', 'audio' );
1212  
1213                  // Check to see if we can figure out the mime type from
1214                  // the extension
1215                  $url_parts = parse_url( $url );
1216                  $extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );
1217                  if ( !empty( $extension ) ) {
1218                      foreach ( get_allowed_mime_types( ) as $exts => $mime ) {
1219                          if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
1220                              $type = $mime;
1221                              break;
1222                          }
1223                      }
1224                  }
1225  
1226                  if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
1227                      $meta_value = "$url\n$len\n$type\n";
1228                      $wpdb->insert($wpdb->postmeta, array('post_id' => $post_ID, 'meta_key' => 'enclosure', 'meta_value' => $meta_value) );
1229                      do_action( 'added_postmeta', $wpdb->insert_id, $post_ID, 'enclosure', $meta_value );
1230                  }
1231              }
1232          }
1233      }
1234  }
1235  
1236  /**
1237   * Perform a HTTP HEAD or GET request.
1238   *
1239   * If $file_path is a writable filename, this will do a GET request and write
1240   * the file to that path.
1241   *
1242   * @since 2.5.0
1243   *
1244   * @param string $url URL to fetch.
1245   * @param string|bool $file_path Optional. File path to write request to.
1246   * @param int $red (private) The number of Redirects followed, Upon 5 being hit, returns false.
1247   * @return bool|string False on failure and string of headers if HEAD request.
1248   */
1249  function wp_get_http( $url, $file_path = false, $red = 1 ) {
1250      @set_time_limit( 60 );
1251  
1252      if ( $red > 5 )
1253          return false;
1254  
1255      $options = array();
1256      $options['redirection'] = 5;
1257  
1258      if ( false == $file_path )
1259          $options['method'] = 'HEAD';
1260      else
1261          $options['method'] = 'GET';
1262  
1263      $response = wp_remote_request($url, $options);
1264  
1265      if ( is_wp_error( $response ) )
1266          return false;
1267  
1268      $headers = wp_remote_retrieve_headers( $response );
1269      $headers['response'] = $response['response']['code'];
1270  
1271      // WP_HTTP no longer follows redirects for HEAD requests.
1272      if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
1273          return wp_get_http( $headers['location'], $file_path, ++$red );
1274      }
1275  
1276      if ( false == $file_path )
1277          return $headers;
1278  
1279      // GET request - write it to the supplied filename
1280      $out_fp = fopen($file_path, 'w');
1281      if ( !$out_fp )
1282          return $headers;
1283  
1284      fwrite( $out_fp,  $response['body']);
1285      fclose($out_fp);
1286  
1287      return $headers;
1288  }
1289  
1290  /**
1291   * Retrieve HTTP Headers from URL.
1292   *
1293   * @since 1.5.1
1294   *
1295   * @param string $url
1296   * @param bool $deprecated Not Used.
1297   * @return bool|string False on failure, headers on success.
1298   */
1299  function wp_get_http_headers( $url, $deprecated = false ) {
1300      if ( !empty( $deprecated ) )
1301          _deprecated_argument( __FUNCTION__, '2.7' );
1302  
1303      $response = wp_remote_head( $url );
1304  
1305      if ( is_wp_error( $response ) )
1306          return false;
1307  
1308      return wp_remote_retrieve_headers( $response );
1309  }
1310  
1311  /**
1312   * Whether today is a new day.
1313   *
1314   * @since 0.71
1315   * @uses $day Today
1316   * @uses $previousday Previous day
1317   *
1318   * @return int 1 when new day, 0 if not a new day.
1319   */
1320  function is_new_day() {
1321      global $day, $previousday;
1322      if ( $day != $previousday )
1323          return 1;
1324      else
1325          return 0;
1326  }
1327  
1328  /**
1329   * Build URL query based on an associative and, or indexed array.
1330   *
1331   * This is a convenient function for easily building url queries. It sets the
1332   * separator to '&' and uses _http_build_query() function.
1333   *
1334   * @see _http_build_query() Used to build the query
1335   * @link http://us2.php.net/manual/en/function.http-build-query.php more on what
1336   *        http_build_query() does.
1337   *
1338   * @since 2.3.0
1339   *
1340   * @param array $data URL-encode key/value pairs.
1341   * @return string URL encoded string
1342   */
1343  function build_query( $data ) {
1344      return _http_build_query( $data, null, '&', '', false );
1345  }
1346  
1347  /**
1348   * Retrieve a modified URL query string.
1349   *
1350   * You can rebuild the URL and append a new query variable to the URL query by
1351   * using this function. You can also retrieve the full URL with query data.
1352   *
1353   * Adding a single key & value or an associative array. Setting a key value to
1354   * emptystring removes the key. Omitting oldquery_or_uri uses the $_SERVER
1355   * value.
1356   *
1357   * @since 1.5.0
1358   *
1359   * @param mixed $param1 Either newkey or an associative_array
1360   * @param mixed $param2 Either newvalue or oldquery or uri
1361   * @param mixed $param3 Optional. Old query or uri
1362   * @return string New URL query string.
1363   */
1364  function add_query_arg() {
1365      $ret = '';
1366      if ( is_array( func_get_arg(0) ) ) {
1367          if ( @func_num_args() < 2 || false === @func_get_arg( 1 ) )
1368              $uri = $_SERVER['REQUEST_URI'];
1369          else
1370              $uri = @func_get_arg( 1 );
1371      } else {
1372          if ( @func_num_args() < 3 || false === @func_get_arg( 2 ) )
1373              $uri = $_SERVER['REQUEST_URI'];
1374          else
1375              $uri = @func_get_arg( 2 );
1376      }
1377  
1378      if ( $frag = strstr( $uri, '#' ) )
1379          $uri = substr( $uri, 0, -strlen( $frag ) );
1380      else
1381          $frag = '';
1382  
1383      if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
1384          $protocol = $matches[0];
1385          $uri = substr( $uri, strlen( $protocol ) );
1386      } else {
1387          $protocol = '';
1388      }
1389  
1390      if ( strpos( $uri, '?' ) !== false ) {
1391          $parts = explode( '?', $uri, 2 );
1392          if ( 1 == count( $parts ) ) {
1393              $base = '?';
1394              $query = $parts[0];
1395          } else {
1396              $base = $parts[0] . '?';
1397              $query = $parts[1];
1398          }
1399      } elseif ( !empty( $protocol ) || strpos( $uri, '=' ) === false ) {
1400          $base = $uri . '?';
1401          $query = '';
1402      } else {
1403          $base = '';
1404          $query = $uri;
1405      }
1406  
1407      wp_parse_str( $query, $qs );
1408      $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
1409      if ( is_array( func_get_arg( 0 ) ) ) {
1410          $kayvees = func_get_arg( 0 );
1411          $qs = array_merge( $qs, $kayvees );
1412      } else {
1413          $qs[func_get_arg( 0 )] = func_get_arg( 1 );
1414      }
1415  
1416      foreach ( (array) $qs as $k => $v ) {
1417          if ( $v === false )
1418              unset( $qs[$k] );
1419      }
1420  
1421      $ret = build_query( $qs );
1422      $ret = trim( $ret, '?' );
1423      $ret = preg_replace( '#=(&|$)#', '$1', $ret );
1424      $ret = $protocol . $base . $ret . $frag;
1425      $ret = rtrim( $ret, '?' );
1426      return $ret;
1427  }
1428  
1429  /**
1430   * Removes an item or list from the query string.
1431   *
1432   * @since 1.5.0
1433   *
1434   * @param string|array $key Query key or keys to remove.
1435   * @param bool $query When false uses the $_SERVER value.
1436   * @return string New URL query string.
1437   */
1438  function remove_query_arg( $key, $query=false ) {
1439      if ( is_array( $key ) ) { // removing multiple keys
1440          foreach ( $key as $k )
1441              $query = add_query_arg( $k, false, $query );
1442          return $query;
1443      }
1444      return add_query_arg( $key, false, $query );
1445  }
1446  
1447  /**
1448   * Walks the array while sanitizing the contents.
1449   *
1450   * @since 0.71
1451   *
1452   * @param array $array Array to used to walk while sanitizing contents.
1453   * @return array Sanitized $array.
1454   */
1455  function add_magic_quotes( $array ) {
1456      foreach ( (array) $array as $k => $v ) {
1457          if ( is_array( $v ) ) {
1458              $array[$k] = add_magic_quotes( $v );
1459          } else {
1460              $array[$k] = addslashes( $v );
1461          }
1462      }
1463      return $array;
1464  }
1465  
1466  /**
1467   * HTTP request for URI to retrieve content.
1468   *
1469   * @since 1.5.1
1470   * @uses wp_remote_get()
1471   *
1472   * @param string $uri URI/URL of web page to retrieve.
1473   * @return bool|string HTTP content. False on failure.
1474   */
1475  function wp_remote_fopen( $uri ) {
1476      $parsed_url = @parse_url( $uri );
1477  
1478      if ( !$parsed_url || !is_array( $parsed_url ) )
1479          return false;
1480  
1481      $options = array();
1482      $options['timeout'] = 10;
1483  
1484      $response = wp_remote_get( $uri, $options );
1485  
1486      if ( is_wp_error( $response ) )
1487          return false;
1488  
1489      return $response['body'];
1490  }
1491  
1492  /**
1493   * Set up the WordPress query.
1494   *
1495   * @since 2.0.0
1496   *
1497   * @param string $query_vars Default WP_Query arguments.
1498   */
1499  function wp( $query_vars = '' ) {
1500      global $wp, $wp_query, $wp_the_query;
1501      $wp->main( $query_vars );
1502  
1503      if ( !isset($wp_the_query) )
1504          $wp_the_query = $wp_query;
1505  }
1506  
1507  /**
1508   * Retrieve the description for the HTTP status.
1509   *
1510   * @since 2.3.0
1511   *
1512   * @param int $code HTTP status code.
1513   * @return string Empty string if not found, or description if found.
1514   */
1515  function get_status_header_desc( $code ) {
1516      global $wp_header_to_desc;
1517  
1518      $code = absint( $code );
1519  
1520      if ( !isset( $wp_header_to_desc ) ) {
1521          $wp_header_to_desc = array(
1522              100 => 'Continue',
1523              101 => 'Switching Protocols',
1524              102 => 'Processing',
1525  
1526              200 => 'OK',
1527              201 => 'Created',
1528              202 => 'Accepted',
1529              203 => 'Non-Authoritative Information',
1530              204 => 'No Content',
1531              205 => 'Reset Content',
1532              206 => 'Partial Content',
1533              207 => 'Multi-Status',
1534              226 => 'IM Used',
1535  
1536              300 => 'Multiple Choices',
1537              301 => 'Moved Permanently',
1538              302 => 'Found',
1539              303 => 'See Other',
1540              304 => 'Not Modified',
1541              305 => 'Use Proxy',
1542              306 => 'Reserved',
1543              307 => 'Temporary Redirect',
1544  
1545              400 => 'Bad Request',
1546              401 => 'Unauthorized',
1547              402 => 'Payment Required',
1548              403 => 'Forbidden',
1549              404 => 'Not Found',
1550              405 => 'Method Not Allowed',
1551              406 => 'Not Acceptable',
1552              407 => 'Proxy Authentication Required',
1553              408 => 'Request Timeout',
1554              409 => 'Conflict',
1555              410 => 'Gone',
1556              411 => 'Length Required',
1557              412 => 'Precondition Failed',
1558              413 => 'Request Entity Too Large',
1559              414 => 'Request-URI Too Long',
1560              415 => 'Unsupported Media Type',
1561              416 => 'Requested Range Not Satisfiable',
1562              417 => 'Expectation Failed',
1563              422 => 'Unprocessable Entity',
1564              423 => 'Locked',
1565              424 => 'Failed Dependency',
1566              426 => 'Upgrade Required',
1567  
1568              500 => 'Internal Server Error',
1569              501 => 'Not Implemented',
1570              502 => 'Bad Gateway',
1571              503 => 'Service Unavailable',
1572              504 => 'Gateway Timeout',
1573              505 => 'HTTP Version Not Supported',
1574              506 => 'Variant Also Negotiates',
1575              507 => 'Insufficient Storage',
1576              510 => 'Not Extended'
1577          );
1578      }
1579  
1580      if ( isset( $wp_header_to_desc[$code] ) )
1581          return $wp_header_to_desc[$code];
1582      else
1583          return '';
1584  }
1585  
1586  /**
1587   * Set HTTP status header.
1588   *
1589   * @since 2.0.0
1590   * @uses apply_filters() Calls 'status_header' on status header string, HTTP
1591   *        HTTP code, HTTP code description, and protocol string as separate
1592   *        parameters.
1593   *
1594   * @param int $header HTTP status code
1595   * @return unknown
1596   */
1597  function status_header( $header ) {
1598      $text = get_status_header_desc( $header );
1599  
1600      if ( empty( $text ) )
1601          return false;
1602  
1603      $protocol = $_SERVER["SERVER_PROTOCOL"];
1604      if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
1605          $protocol = 'HTTP/1.0';
1606      $status_header = "$protocol $header $text";
1607      if ( function_exists( 'apply_filters' ) )
1608          $status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );
1609  
1610      return @header( $status_header, true, $header );
1611  }
1612  
1613  /**
1614   * Gets the header information to prevent caching.
1615   *
1616   * The several different headers cover the different ways cache prevention is handled
1617   * by different browsers
1618   *
1619   * @since 2.8
1620   *
1621   * @uses apply_filters()
1622   * @return array The associative array of header names and field values.
1623   */
1624  function wp_get_nocache_headers() {
1625      $headers = array(
1626          'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
1627          'Last-Modified' => gmdate( 'D, d M Y H:i:s' ) . ' GMT',
1628          'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
1629          'Pragma' => 'no-cache',
1630      );
1631  
1632      if ( function_exists('apply_filters') ) {
1633          $headers = apply_filters('nocache_headers', $headers);
1634      }
1635      return $headers;
1636  }
1637  
1638  /**
1639   * Sets the headers to prevent caching for the different browsers.
1640   *
1641   * Different browsers support different nocache headers, so several headers must
1642   * be sent so that all of them get the point that no caching should occur.
1643   *
1644   * @since 2.0.0
1645   * @uses wp_get_nocache_headers()
1646   */
1647  function nocache_headers() {
1648      $headers = wp_get_nocache_headers();
1649      foreach( (array) $headers as $name => $field_value )
1650          @header("{$name}: {$field_value}");
1651  }
1652  
1653  /**
1654   * Set the headers for caching for 10 days with JavaScript content type.
1655   *
1656   * @since 2.1.0
1657   */
1658  function cache_javascript_headers() {
1659      $expiresOffset = 864000; // 10 days
1660      header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
1661      header( "Vary: Accept-Encoding" ); // Handle proxies
1662      header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
1663  }
1664  
1665  /**
1666   * Retrieve the number of database queries during the WordPress execution.
1667   *
1668   * @since 2.0.0
1669   *
1670   * @return int Number of database queries
1671   */
1672  function get_num_queries() {
1673      global $wpdb;
1674      return $wpdb->num_queries;
1675  }
1676  
1677  /**
1678   * Whether input is yes or no. Must be 'y' to be true.
1679   *
1680   * @since 1.0.0
1681   *
1682   * @param string $yn Character string containing either 'y' or 'n'
1683   * @return bool True if yes, false on anything else
1684   */
1685  function bool_from_yn( $yn ) {
1686      return ( strtolower( $yn ) == 'y' );
1687  }
1688  
1689  /**
1690   * Loads the feed template from the use of an action hook.
1691   *
1692   * If the feed action does not have a hook, then the function will die with a
1693   * message telling the visitor that the feed is not valid.
1694   *
1695   * It is better to only have one hook for each feed.
1696   *
1697   * @since 2.1.0
1698   * @uses $wp_query Used to tell if the use a comment feed.
1699   * @uses do_action() Calls 'do_feed_$feed' hook, if a hook exists for the feed.
1700   */
1701  function do_feed() {
1702      global $wp_query;
1703  
1704      $feed = get_query_var( 'feed' );
1705  
1706      // Remove the pad, if present.
1707      $feed = preg_replace( '/^_+/', '', $feed );
1708  
1709      if ( $feed == '' || $feed == 'feed' )
1710          $feed = get_default_feed();
1711  
1712      $hook = 'do_feed_' . $feed;
1713      if ( !has_action($hook) ) {
1714          $message = sprintf( __( 'ERROR: %s is not a valid feed template.' ), esc_html($feed));
1715          wp_die( $message, '', array( 'response' => 404 ) );
1716      }
1717  
1718      do_action( $hook, $wp_query->is_comment_feed );
1719  }
1720  
1721  /**
1722   * Load the RDF RSS 0.91 Feed template.
1723   *
1724   * @since 2.1.0
1725   */
1726  function do_feed_rdf() {
1727      load_template( ABSPATH . WPINC . '/feed-rdf.php' );
1728  }
1729  
1730  /**
1731   * Load the RSS 1.0 Feed Template
1732   *
1733   * @since 2.1.0
1734   */
1735  function do_feed_rss() {
1736      load_template( ABSPATH . WPINC . '/feed-rss.php' );
1737  }
1738  
1739  /**
1740   * Load either the RSS2 comment feed or the RSS2 posts feed.
1741   *
1742   * @since 2.1.0
1743   *
1744   * @param bool $for_comments True for the comment feed, false for normal feed.
1745   */
1746  function do_feed_rss2( $for_comments ) {
1747      if ( $for_comments )
1748          load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
1749      else
1750          load_template( ABSPATH . WPINC . '/feed-rss2.php' );
1751  }
1752  
1753  /**
1754   * Load either Atom comment feed or Atom posts feed.
1755   *
1756   * @since 2.1.0
1757   *
1758   * @param bool $for_comments True for the comment feed, false for normal feed.
1759   */
1760  function do_feed_atom( $for_comments ) {
1761      if ($for_comments)
1762          load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
1763      else
1764          load_template( ABSPATH . WPINC . '/feed-atom.php' );
1765  }
1766  
1767  /**
1768   * Display the robot.txt file content.
1769   *
1770   * The echo content should be with usage of the permalinks or for creating the
1771   * robot.txt file.
1772   *
1773   * @since 2.1.0
1774   * @uses do_action() Calls 'do_robotstxt' hook for displaying robot.txt rules.
1775   */
1776  function do_robots() {
1777      header( 'Content-Type: text/plain; charset=utf-8' );
1778  
1779      do_action( 'do_robotstxt' );
1780  
1781      $output = '';
1782      $public = get_option( 'blog_public' );
1783      if ( '0' ==  $public ) {
1784          $output .= "User-agent: *\n";
1785          $output .= "Disallow: /\n";
1786      } else {
1787          $output .= "User-agent: *\n";
1788          $output .= "Disallow:\n";
1789      }
1790  
1791      echo apply_filters('robots_txt', $output, $public);
1792  }
1793  
1794  /**
1795   * Test whether blog is already installed.
1796   *
1797   * The cache will be checked first. If you have a cache plugin, which saves the
1798   * cache values, then this will work. If you use the default WordPress cache,
1799   * and the database goes away, then you might have problems.
1800   *
1801   * Checks for the option siteurl for whether WordPress is installed.
1802   *
1803   * @since 2.1.0
1804   * @uses $wpdb
1805   *
1806   * @return bool Whether blog is already installed.
1807   */
1808  function is_blog_installed() {
1809      global $wpdb;
1810  
1811      // Check cache first. If options table goes away and we have true cached, oh well.
1812      if ( wp_cache_get( 'is_blog_installed' ) )
1813          return true;
1814  
1815      $suppress = $wpdb->suppress_errors();
1816      if ( ! defined( 'WP_INSTALLING' ) ) {
1817          $alloptions = wp_load_alloptions();
1818      }
1819      // If siteurl is not set to autoload, check it specifically
1820      if ( !isset( $alloptions['siteurl'] ) )
1821          $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
1822      else
1823          $installed = $alloptions['siteurl'];
1824      $wpdb->suppress_errors( $suppress );
1825  
1826      $installed = !empty( $installed );
1827      wp_cache_set( 'is_blog_installed', $installed );
1828  
1829      if ( $installed )
1830          return true;
1831  
1832      $suppress = $wpdb->suppress_errors();
1833      $tables = $wpdb->get_col('SHOW TABLES');
1834      $wpdb->suppress_errors( $suppress );
1835  
1836      $wp_tables = $wpdb->tables();
1837      // Loop over the WP tables.  If none exist, then scratch install is allowed.
1838      // If one or more exist, suggest table repair since we got here because the options
1839      // table could not be accessed.
1840      foreach ( $wp_tables as $table ) {
1841          // If one of the WP tables exist, then we are in an insane state.
1842          if ( in_array( $table, $tables ) ) {
1843              // The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
1844              if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
1845                  continue;
1846              if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
1847                  continue;
1848  
1849              // If visiting repair.php, return true and let it take over.
1850              if ( defined('WP_REPAIRING') )
1851                  return true;
1852              // Die with a DB error.
1853              $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' );
1854              dead_db();
1855          }
1856      }
1857  
1858      wp_cache_set( 'is_blog_installed', false );
1859  
1860      return false;
1861  }
1862  
1863  /**
1864   * Retrieve URL with nonce added to URL query.
1865   *
1866   * @package WordPress
1867   * @subpackage Security
1868   * @since 2.0.4
1869   *
1870   * @param string $actionurl URL to add nonce action
1871   * @param string $action Optional. Nonce action name
1872   * @return string URL with nonce action added.
1873   */
1874  function wp_nonce_url( $actionurl, $action = -1 ) {
1875      $actionurl = str_replace( '&amp;', '&', $actionurl );
1876      return esc_html( add_query_arg( '_wpnonce', wp_create_nonce( $action ), $actionurl ) );
1877  }
1878  
1879  /**
1880   * Retrieve or display nonce hidden field for forms.
1881   *
1882   * The nonce field is used to validate that the contents of the form came from
1883   * the location on the current site and not somewhere else. The nonce does not
1884   * offer absolute protection, but should protect against most cases. It is very
1885   * important to use nonce field in forms.
1886   *
1887   * If you set $echo to true and set $referer to true, then you will need to
1888   * retrieve the {@link wp_referer_field() wp referer field}. If you have the
1889   * $referer set to true and are echoing the nonce field, it will also echo the
1890   * referer field.
1891   *
1892   * The $action and $name are optional, but if you want to have better security,
1893   * it is strongly suggested to set those two parameters. It is easier to just
1894   * call the function without any parameters, because validation of the nonce
1895   * doesn't require any parameters, but since crackers know what the default is
1896   * it won't be difficult for them to find a way around your nonce and cause
1897   * damage.
1898   *
1899   * The input name will be whatever $name value you gave. The input value will be
1900   * the nonce creation value.
1901   *
1902   * @package WordPress
1903   * @subpackage Security
1904   * @since 2.0.4
1905   *
1906   * @param string $action Optional. Action name.
1907   * @param string $name Optional. Nonce name.
1908   * @param bool $referer Optional, default true. Whether to set the referer field for validation.
1909   * @param bool $echo Optional, default true. Whether to display or return hidden form field.
1910   * @return string Nonce field.
1911   */
1912  function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1913      $name = esc_attr( $name );
1914      $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
1915      if ( $echo )
1916          echo $nonce_field;
1917  
1918      if ( $referer )
1919          wp_referer_field( $echo, 'previous' );
1920  
1921      return $nonce_field;
1922  }
1923  
1924  /**
1925   * Retrieve or display referer hidden field for forms.
1926   *
1927   * The referer link is the current Request URI from the server super global. The
1928   * input name is '_wp_http_referer', in case you wanted to check manually.
1929   *
1930   * @package WordPress
1931   * @subpackage Security
1932   * @since 2.0.4
1933   *
1934   * @param bool $echo Whether to echo or return the referer field.
1935   * @return string Referer field.
1936   */
1937  function wp_referer_field( $echo = true) {
1938      $ref = esc_attr( $_SERVER['REQUEST_URI'] );
1939      $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. $ref . '" />';
1940  
1941      if ( $echo )
1942          echo $referer_field;
1943      return $referer_field;
1944  }
1945  
1946  /**
1947   * Retrieve or display original referer hidden field for forms.
1948   *
1949   * The input name is '_wp_original_http_referer' and will be either the same
1950   * value of {@link wp_referer_field()}, if that was posted already or it will
1951   * be the current page, if it doesn't exist.
1952   *
1953   * @package WordPress
1954   * @subpackage Security
1955   * @since 2.0.4
1956   *
1957   * @param bool $echo Whether to echo the original http referer
1958   * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to.
1959   * @return string Original referer field.
1960   */
1961  function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
1962      $jump_back_to = ( 'previous' == $jump_back_to ) ? wp_get_referer() : $_SERVER['REQUEST_URI'];
1963      $ref = ( wp_get_original_referer() ) ? wp_get_original_referer() : $jump_back_to;
1964      $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( stripslashes( $ref ) ) . '" />';
1965      if ( $echo )
1966          echo $orig_referer_field;
1967      return $orig_referer_field;
1968  }
1969  
1970  /**
1971   * Retrieve referer from '_wp_http_referer', HTTP referer, or current page respectively.
1972   *
1973   * @package WordPress
1974   * @subpackage Security
1975   * @since 2.0.4
1976   *
1977   * @return string|bool False on failure. Referer URL on success.
1978   */
1979  function wp_get_referer() {
1980      $ref = '';
1981      if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
1982          $ref = $_REQUEST['_wp_http_referer'];
1983      else if ( ! empty( $_SERVER['HTTP_REFERER'] ) )
1984          $ref = $_SERVER['HTTP_REFERER'];
1985  
1986      if ( $ref !== $_SERVER['REQUEST_URI'] )
1987          return $ref;
1988      return false;
1989  }
1990  
1991  /**
1992   * Retrieve original referer that was posted, if it exists.
1993   *
1994   * @package WordPress
1995   * @subpackage Security
1996   * @since 2.0.4
1997   *
1998   * @return string|bool False if no original referer or original referer if set.
1999   */
2000  function wp_get_original_referer() {
2001      if ( !empty( $_REQUEST['_wp_original_http_referer'] ) )
2002          return $_REQUEST['_wp_original_http_referer'];
2003      return false;
2004  }
2005  
2006  /**
2007   * Recursive directory creation based on full path.
2008   *
2009   * Will attempt to set permissions on folders.
2010   *
2011   * @since 2.0.1
2012   *
2013   * @param string $target Full path to attempt to create.
2014   * @return bool Whether the path was created. True if path already exists.
2015   */
2016  function wp_mkdir_p( $target ) {
2017      // from php.net/mkdir user contributed notes
2018      $target = str_replace( '//', '/', $target );
2019  
2020      // safe mode fails with a trailing slash under certain PHP versions.
2021      $target = untrailingslashit($target);
2022      if ( empty($target) )
2023          $target = '/';
2024  
2025      if ( file_exists( $target ) )
2026          return @is_dir( $target );
2027  
2028      // Attempting to create the directory may clutter up our display.
2029      if ( @mkdir( $target ) ) {
2030          $stat = @stat( dirname( $target ) );
2031          $dir_perms = $stat['mode'] & 0007777;  // Get the permission bits.
2032          @chmod( $target, $dir_perms );
2033          return true;
2034      } elseif ( is_dir( dirname( $target ) ) ) {
2035              return false;
2036      }
2037  
2038      // If the above failed, attempt to create the parent node, then try again.
2039      if ( ( $target != '/' ) && ( wp_mkdir_p( dirname( $target ) ) ) )
2040          return wp_mkdir_p( $target );
2041  
2042      return false;
2043  }
2044  
2045  /**
2046   * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
2047   *
2048   * @since 2.5.0
2049   *
2050   * @param string $path File path
2051   * @return bool True if path is absolute, false is not absolute.
2052   */
2053  function path_is_absolute( $path ) {
2054      // this is definitive if true but fails if $path does not exist or contains a symbolic link
2055      if ( realpath($path) == $path )
2056          return true;
2057  
2058      if ( strlen($path) == 0 || $path{0} == '.' )
2059          return false;
2060  
2061      // windows allows absolute paths like this
2062      if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
2063          return true;
2064  
2065      // a path starting with / or \ is absolute; anything else is relative
2066      return (bool) preg_match('#^[/\\\\]#', $path);
2067  }
2068  
2069  /**
2070   * Join two filesystem paths together (e.g. 'give me $path relative to $base').
2071   *
2072   * If the $path is absolute, then it the full path is returned.
2073   *
2074   * @since 2.5.0
2075   *
2076   * @param string $base
2077   * @param string $path
2078   * @return string The path with the base or absolute path.
2079   */
2080  function path_join( $base, $path ) {
2081      if ( path_is_absolute($path) )
2082          return $path;
2083  
2084      return rtrim($base, '/') . '/' . ltrim($path, '/');
2085  }
2086  
2087  /**
2088   * Get an array containing the current upload directory's path and url.
2089   *
2090   * Checks the 'upload_path' option, which should be from the web root folder,
2091   * and if it isn't empty it will be used. If it is empty, then the path will be
2092   * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
2093   * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
2094   *
2095   * The upload URL path is set either by the 'upload_url_path' option or by using
2096   * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
2097   *
2098   * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
2099   * the administration settings panel), then the time will be used. The format
2100   * will be year first and then month.
2101   *
2102   * If the path couldn't be created, then an error will be returned with the key
2103   * 'error' containing the error message. The error suggests that the parent
2104   * directory is not writable by the server.
2105   *
2106   * On success, the returned array will have many indices:
2107   * 'path' - base directory and sub directory or full path to upload directory.
2108   * 'url' - base url and sub directory or absolute URL to upload directory.
2109   * 'subdir' - sub directory if uploads use year/month folders option is on.
2110   * 'basedir' - path without subdir.
2111   * 'baseurl' - URL path without subdir.
2112   * 'error' - set to false.
2113   *
2114   * @since 2.0.0
2115   * @uses apply_filters() Calls 'upload_dir' on returned array.
2116   *
2117   * @param string $time Optional. Time formatted in 'yyyy/mm'.
2118   * @return array See above for description.
2119   */
2120  function wp_upload_dir( $time = null ) {
2121      $siteurl = get_option( 'siteurl' );
2122      $upload_path = get_option( 'upload_path' );
2123      $upload_path = trim($upload_path);
2124      if ( empty($upload_path) ) {
2125          $dir = WP_CONTENT_DIR . '/uploads';
2126      } else {
2127          $dir = $upload_path;
2128          if ( 'wp-content/uploads' == $upload_path ) {
2129              $dir = WP_CONTENT_DIR . '/uploads';
2130          } elseif ( 0 !== strpos($dir, ABSPATH) ) {
2131              // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
2132              $dir = path_join( ABSPATH, $dir );
2133          }
2134      }
2135  
2136      if ( !$url = get_option( 'upload_url_path' ) ) {
2137          if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) )
2138              $url = WP_CONTENT_URL . '/uploads';
2139          else
2140              $url = trailingslashit( $siteurl ) . $upload_path;
2141      }
2142  
2143      if ( defined('UPLOADS') && ( WP_CONTENT_DIR . '/uploads' != ABSPATH . $upload_path ) ) {
2144          $dir = ABSPATH . UPLOADS;
2145          $url = trailingslashit( $siteurl ) . UPLOADS;
2146      }
2147  
2148      if ( is_multisite() && ( WP_CONTENT_DIR . '/uploads' != ABSPATH . $upload_path ) ) {
2149          if ( defined( 'BLOGUPLOADDIR' ) )
2150              $dir = untrailingslashit(BLOGUPLOADDIR);
2151          $url = str_replace( UPLOADS, 'files', $url );
2152      }
2153  
2154      $bdir = $dir;
2155      $burl = $url;
2156  
2157      $subdir = '';
2158      if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
2159          // Generate the yearly and monthly dirs
2160          if ( !$time )
2161              $time = current_time( 'mysql' );
2162          $y = substr( $time, 0, 4 );
2163          $m = substr( $time, 5, 2 );
2164          $subdir = "/$y/$m";
2165      }
2166  
2167      $dir .= $subdir;
2168      $url .= $subdir;
2169  
2170      $uploads = apply_filters( 'upload_dir', array( 'path' => $dir, 'url' => $url, 'subdir' => $subdir, 'basedir' => $bdir, 'baseurl' => $burl, 'error' => false ) );
2171  
2172      // Make sure we have an uploads dir
2173      if ( ! wp_mkdir_p( $uploads['path'] ) ) {
2174          $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $uploads['path'] );
2175          return array( 'error' => $message );
2176      }
2177  
2178      return $uploads;
2179  }
2180  
2181  /**
2182   * Get a filename that is sanitized and unique for the given directory.
2183   *
2184   * If the filename is not unique, then a number will be added to the filename
2185   * before the extension, and will continue adding numbers until the filename is
2186   * unique.
2187   *
2188   * The callback must accept two parameters, the first one is the directory and
2189   * the second is the filename. The callback must be a function.
2190   *
2191   * @since 2.5
2192   *
2193   * @param string $dir
2194   * @param string $filename
2195   * @param string $unique_filename_callback Function name, must be a function.
2196   * @return string New filename, if given wasn't unique.
2197   */
2198  function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
2199      // sanitize the file name before we begin processing
2200      $filename = sanitize_file_name($filename);
2201  
2202      // separate the filename into a name and extension
2203      $info = pathinfo($filename);
2204      $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
2205      $name = basename($filename, $ext);
2206  
2207      // edge case: if file is named '.ext', treat as an empty name
2208      if ( $name === $ext )
2209          $name = '';
2210  
2211      // Increment the file number until we have a unique file to save in $dir. Use $override['unique_filename_callback'] if supplied.
2212      if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
2213          $filename = $unique_filename_callback( $dir, $name );
2214      } else {
2215          $number = '';
2216  
2217          // change '.ext' to lower case
2218          if ( $ext && strtolower($ext) != $ext ) {
2219              $ext2 = strtolower($ext);
2220              $filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
2221  
2222              // check for both lower and upper case extension or image sub-sizes may be overwritten
2223              while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
2224                  $new_number = $number + 1;
2225                  $filename = str_replace( "$number$ext", "$new_number$ext", $filename );
2226                  $filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
2227                  $number = $new_number;
2228              }
2229              return $filename2;
2230          }
2231  
2232          while ( file_exists( $dir . "/$filename" ) ) {
2233              if ( '' == "$number$ext" )
2234                  $filename = $filename . ++$number . $ext;
2235              else
2236                  $filename = str_replace( "$number$ext", ++$number . $ext, $filename );
2237          }
2238      }
2239  
2240      return $filename;
2241  }
2242  
2243  /**
2244   * Create a file in the upload folder with given content.
2245   *
2246   * If there is an error, then the key 'error' will exist with the error message.
2247   * If success, then the key 'file' will have the unique file path, the 'url' key
2248   * will have the link to the new file. and the 'error' key will be set to false.
2249   *
2250   * This function will not move an uploaded file to the upload folder. It will
2251   * create a new file with the content in $bits parameter. If you move the upload
2252   * file, read the content of the uploaded file, and then you can give the
2253   * filename and content to this function, which will add it to the upload
2254   * folder.
2255   *
2256   * The permissions will be set on the new file automatically by this function.
2257   *
2258   * @since 2.0.0
2259   *
2260   * @param string $name
2261   * @param null $deprecated Never used. Set to null.
2262   * @param mixed $bits File content
2263   * @param string $time Optional. Time formatted in 'yyyy/mm'.
2264   * @return array
2265   */
2266  function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
2267      if ( !empty( $deprecated ) )
2268          _deprecated_argument( __FUNCTION__, '2.0' );
2269  
2270      if ( empty( $name ) )
2271          return array( 'error' => __( 'Empty filename' ) );
2272  
2273      $wp_filetype = wp_check_filetype( $name );
2274      if ( !$wp_filetype['ext'] )
2275          return array( 'error' => __( 'Invalid file type' ) );
2276  
2277      $upload = wp_upload_dir( $time );
2278  
2279      if ( $upload['error'] !== false )
2280          return $upload;
2281  
2282      $upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) );
2283      if ( !is_array( $upload_bits_error ) ) {
2284          $upload[ 'error' ] = $upload_bits_error;
2285          return $upload;
2286      }
2287  
2288      $filename = wp_unique_filename( $upload['path'], $name );
2289  
2290      $new_file = $upload['path'] . "/$filename";
2291      if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
2292          $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), dirname( $new_file ) );
2293          return array( 'error' => $message );
2294      }
2295  
2296      $ifp = @ fopen( $new_file, 'wb' );
2297      if ( ! $ifp )
2298          return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
2299  
2300      @fwrite( $ifp, $bits );
2301      fclose( $ifp );
2302      // Set correct file permissions
2303      $stat = @ stat( dirname( $new_file ) );
2304      $perms = $stat['mode'] & 0007777;
2305      $perms = $perms & 0000666;
2306      @ chmod( $new_file, $perms );
2307  
2308      // Compute the URL
2309      $url = $upload['url'] . "/$filename";
2310  
2311      return array( 'file' => $new_file, 'url' => $url, 'error' => false );
2312  }
2313  
2314  /**
2315   * Retrieve the file type based on the extension name.
2316   *
2317   * @package WordPress
2318   * @since 2.5.0
2319   * @uses apply_filters() Calls 'ext2type' hook on default supported types.
2320   *
2321   * @param string $ext The extension to search.
2322   * @return string|null The file type, example: audio, video, document, spreadsheet, etc. Null if not found.
2323   */
2324  function wp_ext2type( $ext ) {
2325      $ext2type = apply_filters( 'ext2type', array(
2326          'audio'       => array( 'aac', 'ac3',  'aif',  'aiff', 'm3a',  'm4a',   'm4b', 'mka', 'mp1', 'mp2',  'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
2327          'video'       => array( 'asf', 'avi',  'divx', 'dv',   'flv',  'm4v',   'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt',  'rm', 'vob', 'wmv' ),
2328          'document'    => array( 'doc', 'docx', 'docm', 'dotm', 'odt',  'pages', 'pdf', 'rtf' ),
2329          'spreadsheet' => array( 'numbers',     'ods',  'xls',  'xlsx', 'xlsb',  'xlsm' ),
2330          'interactive' => array( 'key', 'ppt',  'pptx', 'pptm', 'odp',  'swf' ),
2331          'text'        => array( 'asc', 'txt' ),
2332          'archive'     => array( 'bz2', 'cab',  'dmg',  'gz',   'rar',  'sea',   'sit', 'sqx', 'tar', 'tgz',  'zip' ),
2333          'code'        => array( 'css', 'html', 'php',  'js' ),
2334      ));
2335      foreach ( $ext2type as $type => $exts )
2336          if ( in_array( $ext, $exts ) )
2337              return $type;
2338  }
2339  
2340  /**
2341   * Retrieve the file type from the file name.
2342   *
2343   * You can optionally define the mime array, if needed.
2344   *
2345   * @since 2.0.4
2346   *
2347   * @param string $filename File name or path.
2348   * @param array $mimes Optional. Key is the file extension with value as the mime type.
2349   * @return array Values with extension first and mime type.
2350   */
2351  function wp_check_filetype( $filename, $mimes = null ) {
2352      if ( empty($mimes) )
2353          $mimes = get_allowed_mime_types();
2354      $type = false;
2355      $ext = false;
2356  
2357      foreach ( $mimes as $ext_preg => $mime_match ) {
2358          $ext_preg = '!\.(' . $ext_preg . ')$!i';
2359          if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
2360              $type = $mime_match;
2361              $ext = $ext_matches[1];
2362              break;
2363          }
2364      }
2365  
2366      return compact( 'ext', 'type' );
2367  }
2368  
2369  /**
2370   * Retrieve list of allowed mime types and file extensions.
2371   *
2372   * @since 2.8.6
2373   *
2374   * @return array Array of mime types keyed by the file extension regex corresponding to those types.
2375   */
2376  function get_allowed_mime_types() {
2377      static $mimes = false;
2378  
2379      if ( !$mimes ) {
2380          // Accepted MIME types are set here as PCRE unless provided.
2381          $mimes = apply_filters( 'upload_mimes', array(
2382          'jpg|jpeg|jpe' => 'image/jpeg',
2383          'gif' => 'image/gif',
2384          'png' => 'image/png',
2385          'bmp' => 'image/bmp',
2386          'tif|tiff' => 'image/tiff',
2387          'ico' => 'image/x-icon',
2388          'asf|asx|wax|wmv|wmx' => 'video/asf',
2389          'avi' => 'video/avi',
2390          'divx' => 'video/divx',
2391          'flv' => 'video/x-flv',
2392          'mov|qt' => 'video/quicktime',
2393          'mpeg|mpg|mpe' => 'video/mpeg',
2394          'txt|asc|c|cc|h' => 'text/plain',
2395          'rtx' => 'text/richtext',
2396          'css' => 'text/css',
2397          'htm|html' => 'text/html',
2398          'mp3|m4a|m4b' => 'audio/mpeg',
2399          'mp4|m4v' => 'video/mp4',
2400          'ra|ram' => 'audio/x-realaudio',
2401          'wav' => 'audio/wav',
2402          'ogg|oga' => 'audio/ogg',
2403          'ogv' => 'video/ogg',
2404          'mid|midi' => 'audio/midi',
2405          'wma' => 'audio/wma',
2406          'mka' => 'audio/x-matroska',
2407          'mkv' => 'video/x-matroska',
2408          'rtf' => 'application/rtf',
2409          'js' => 'application/javascript',
2410          'pdf' => 'application/pdf',
2411          'doc|docx' => 'application/msword',
2412          'pot|pps|ppt|pptx|ppam|pptm|sldm|ppsm|potm' => 'application/vnd.ms-powerpoint',
2413          'wri' => 'application/vnd.ms-write',
2414          'xla|xls|xlsx|xlt|xlw|xlam|xlsb|xlsm|xltm' => 'application/vnd.ms-excel',
2415          'mdb' => 'application/vnd.ms-access',
2416          'mpp' => 'application/vnd.ms-project',
2417          'docm|dotm' => 'application/vnd.ms-word',
2418          'pptx|sldx|ppsx|potx' => 'application/vnd.openxmlformats-officedocument.presentationml',
2419          'xlsx|xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml',
2420          'docx|dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml',
2421          'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
2422          'swf' => 'application/x-shockwave-flash',
2423          'class' => 'application/java',
2424          'tar' => 'application/x-tar',
2425          'zip' => 'application/zip',
2426          'gz|gzip' => 'application/x-gzip',
2427          'exe' => 'application/x-msdownload',
2428          // openoffice formats
2429          'odt' => 'application/vnd.oasis.opendocument.text',
2430          'odp' => 'application/vnd.oasis.opendocument.presentation',
2431          'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
2432          'odg' => 'application/vnd.oasis.opendocument.graphics',
2433          'odc' => 'application/vnd.oasis.opendocument.chart',
2434          'odb' => 'application/vnd.oasis.opendocument.database',
2435          'odf' => 'application/vnd.oasis.opendocument.formula',
2436          ) );
2437      }
2438  
2439      return $mimes;
2440  }
2441  
2442  /**
2443   * Retrieve nonce action "Are you sure" message.
2444   *
2445   * The action is split by verb and noun. The action format is as follows:
2446   * verb-action_extra. The verb is before the first dash and has the format of
2447   * letters and no spaces and numbers. The noun is after the dash and before the
2448   * underscore, if an underscore exists. The noun is also only letters.
2449   *
2450   * The filter will be called for any action, which is not defined by WordPress.
2451   * You may use the filter for your plugin to explain nonce actions to the user,
2452   * when they get the "Are you sure?" message. The filter is in the format of
2453   * 'explain_nonce_$verb-$noun' with the $verb replaced by the found verb and the
2454   * $noun replaced by the found noun. The two parameters that are given to the
2455   * hook are the localized "Are you sure you want to do this?" message with the
2456   * extra text (the text after the underscore).
2457   *
2458   * @package WordPress
2459   * @subpackage Security
2460   * @since 2.0.4
2461   *
2462   * @param string $action Nonce action.
2463   * @return string Are you sure message.
2464   */
2465  function wp_explain_nonce( $action ) {
2466      if ( $action !== -1 && preg_match( '/([a-z]+)-([a-z]+)(_(.+))?/', $action, $matches ) ) {
2467          $verb = $matches[1];
2468          $noun = $matches[2];
2469  
2470          $trans = array();
2471          $trans['update']['attachment'] = array( __( 'Your attempt to edit this attachment: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2472  
2473          $trans['add']['category']      = array( __( 'Your attempt to add this category has failed.' ), false );
2474          $trans['delete']['category']   = array( __( 'Your attempt to delete this category: &#8220;%s&#8221; has failed.' ), 'get_cat_name' );
2475          $trans['update']['category']   = array( __( 'Your attempt to edit this category: &#8220;%s&#8221; has failed.' ), 'get_cat_name' );
2476  
2477          $trans['delete']['comment']    = array( __( 'Your attempt to delete this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2478          $trans['unapprove']['comment'] = array( __( 'Your attempt to unapprove this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2479          $trans['approve']['comment']   = array( __( 'Your attempt to approve this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2480          $trans['update']['comment']    = array( __( 'Your attempt to edit this comment: &#8220;%s&#8221; has failed.' ), 'use_id' );
2481          $trans['bulk']['comments']     = array( __( 'Your attempt to bulk modify comments has failed.' ), false );
2482          $trans['moderate']['comments'] = array( __( 'Your attempt to moderate comments has failed.' ), false );
2483  
2484          $trans['add']['bookmark']      = array( __( 'Your attempt to add this link has failed.' ), false );
2485          $trans['delete']['bookmark']   = array( __( 'Your attempt to delete this link: &#8220;%s&#8221; has failed.' ), 'use_id' );
2486          $trans['update']['bookmark']   = array( __( 'Your attempt to edit this link: &#8220;%s&#8221; has failed.' ), 'use_id' );
2487          $trans['bulk']['bookmarks']    = array( __( 'Your attempt to bulk modify links has failed.' ), false );
2488  
2489          $trans['add']['page']          = array( __( 'Your attempt to add this page has failed.' ), false );
2490          $trans['delete']['page']       = array( __( 'Your attempt to delete this page: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2491          $trans['update']['page']       = array( __( 'Your attempt to edit this page: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2492  
2493          $trans['edit']['plugin']       = array( __( 'Your attempt to edit this plugin file: &#8220;%s&#8221; has failed.' ), 'use_id' );
2494          $trans['activate']['plugin']   = array( __( 'Your attempt to activate this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
2495          $trans['deactivate']['plugin'] = array( __( 'Your attempt to deactivate this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
2496          $trans['upgrade']['plugin']    = array( __( 'Your attempt to upgrade this plugin: &#8220;%s&#8221; has failed.' ), 'use_id' );
2497  
2498          $trans['add']['post']          = array( __( 'Your attempt to add this post has failed.' ), false );
2499          $trans['delete']['post']       = array( __( 'Your attempt to delete this post: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2500          $trans['update']['post']       = array( __( 'Your attempt to edit this post: &#8220;%s&#8221; has failed.' ), 'get_the_title' );
2501  
2502          $trans['add']['user']          = array( __( 'Your attempt to add this user has failed.' ), false );
2503          $trans['delete']['users']      = array( __( 'Your attempt to delete users has failed.' ), false );
2504          $trans['bulk']['users']        = array( __( 'Your attempt to bulk modify users has failed.' ), false );
2505          $trans['update']['user']       = array( __( 'Your attempt to edit this user: &#8220;%s&#8221; has failed.' ), 'get_the_author_meta', 'display_name' );
2506          $trans['update']['profile']    = array( __( 'Your attempt to modify the profile for: &#8220;%s&#8221; has failed.' ), 'get_the_author_meta', 'display_name' );
2507  
2508          $trans['update']['options']    = array( __( 'Your attempt to edit your settings has failed.' ), false );
2509          $trans['update']['permalink']  = array( __( 'Your attempt to change your permalink structure to: %s has failed.' ), 'use_id' );
2510          $trans['edit']['file']         = array( __( 'Your attempt to edit this file: &#8220;%s&#8221; has failed.' ), 'use_id' );
2511          $trans['edit']['theme']        = array( __( 'Your attempt to edit this theme file: &#8220;%s&#8221; has failed.' ), 'use_id' );
2512          $trans['switch']['theme']      = array( __( 'Your attempt to switch to this theme: &#8220;%s&#8221; has failed.' ), 'use_id' );
2513  
2514          $trans['log']['out']           = array( sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'sitename' ) ), false );
2515  
2516          if ( isset( $trans[$verb][$noun] ) ) {
2517              if ( !empty( $trans[$verb][$noun][1] ) ) {
2518                  $lookup = $trans[$verb][$noun][1];
2519                  if ( isset($trans[$verb][$noun][2]) )
2520                      $lookup_value = $trans[$verb][$noun][2];
2521                  $object = $matches[4];
2522                  if ( 'use_id' != $lookup ) {
2523                      if ( isset( $lookup_value ) )
2524                          $object = call_user_func( $lookup, $lookup_value, $object );
2525                      else
2526                          $object = call_user_func( $lookup, $object );
2527                  }
2528                  return sprintf( $trans[$verb][$noun][0], esc_html($object) );
2529              } else {
2530                  return $trans[$verb][$noun][0];
2531              }
2532          }
2533  
2534          return apply_filters( 'explain_nonce_' . $verb . '-' . $noun, __( 'Are you sure you want to do this?' ), isset($matches[4]) ? $matches[4] : '' );
2535      } else {
2536          return apply_filters( 'explain_nonce_' . $action, __( 'Are you sure you want to do this?' ) );
2537      }
2538  }
2539  
2540  /**
2541   * Display "Are You Sure" message to confirm the action being taken.
2542   *
2543   * If the action has the nonce explain message, then it will be displayed along
2544   * with the "Are you sure?" message.
2545   *
2546   * @package WordPress
2547   * @subpackage Security
2548   * @since 2.0.4
2549   *
2550   * @param string $action The nonce action.
2551   */
2552  function wp_nonce_ays( $action ) {
2553      $title = __( 'WordPress Failure Notice' );
2554      $html = esc_html( wp_explain_nonce( $action ) );
2555      if ( 'log-out' == $action )
2556          $html .= "</p><p>" . sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url() );
2557      elseif ( wp_get_referer() )
2558          $html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
2559  
2560      wp_die( $html, $title, array('response' => 403) );
2561  }
2562  
2563  
2564  /**
2565   * Kill WordPress execution and display HTML message with error message.
2566   *
2567   * This function complements the die() PHP function. The difference is that
2568   * HTML will be displayed to the user. It is recommended to use this function
2569   * only, when the execution should not continue any further. It is not
2570   * recommended to call this function very often and try to handle as many errors
2571   * as possible siliently.
2572   *
2573   * @since 2.0.4
2574   *
2575   * @param string $message Error message.
2576   * @param string $title Error title.
2577   * @param string|array $args Optional arguements to control behaviour.
2578   */
2579  function wp_die( $message, $title = '', $args = array() ) {
2580      if ( function_exists( 'apply_filters' ) ) {
2581          $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler');
2582      }else {
2583          $function = '_default_wp_die_handler';
2584      }
2585  
2586      call_user_func( $function, $message, $title, $args );
2587  }
2588  
2589  /**
2590   * Kill WordPress execution and display HTML message with error message.
2591   *
2592   * This is the default handler for wp_die if you want a custom one for your
2593   * site then you can overload using the wp_die_handler filter in wp_die
2594   *
2595   * @since 3.0.0
2596   * @private
2597   *
2598   * @param string $message Error message.
2599   * @param string $title Error title.
2600   * @param string|array $args Optional arguements to control behaviour.
2601   */
2602  function _default_wp_die_handler( $message, $title = '', $args = array() ) {
2603      global $wp_locale;
2604  
2605      $defaults = array( 'response' => 500 );
2606      $r = wp_parse_args($args, $defaults);
2607  
2608      $have_gettext = function_exists('__');
2609  
2610      if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
2611          if ( empty( $title ) ) {
2612              $error_data = $message->get_error_data();
2613              if ( is_array( $error_data ) && isset( $error_data['title'] ) )
2614                  $title = $error_data['title'];
2615          }
2616          $errors = $message->get_error_messages();
2617          switch ( count( $errors ) ) :
2618          case 0 :
2619              $message = '';
2620              break;
2621          case 1 :
2622              $message = "<p>{$errors[0]}</p>";
2623              break;
2624          default :
2625              $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
2626              break;
2627          endswitch;
2628      } elseif ( is_string( $message ) ) {
2629          $message = "<p>$message</p>";
2630      }
2631  
2632      if ( isset( $r['back_link'] ) && $r['back_link'] ) {
2633          $back_text = $have_gettext? __('&laquo; Back') : '&laquo; Back';
2634          $message .= "\n<p><a href='javascript:history.back()'>$back_text</p>";
2635      }
2636  
2637      if ( defined( 'WP_SITEURL' ) && '' != WP_SITEURL )
2638          $admin_dir = WP_SITEURL . '/wp-admin/';
2639      elseif ( function_exists( 'get_bloginfo' ) && '' != get_bloginfo( 'wpurl' ) )
2640          $admin_dir = get_bloginfo( 'wpurl' ) . '/wp-admin/';
2641      elseif ( strpos( $_SERVER['PHP_SELF'], 'wp-admin' ) !== false )
2642          $admin_dir = '';
2643      else
2644          $admin_dir = 'wp-admin/';
2645  
2646      if ( !function_exists( 'did_action' ) || !did_action( 'admin_head' ) ) :
2647      if ( !headers_sent() ) {
2648          status_header( $r['response'] );
2649          nocache_headers();
2650          header( 'Content-Type: text/html; charset=utf-8' );
2651      }
2652  
2653      if ( empty($title) )
2654          $title = $have_gettext ? __('WordPress &rsaquo; Error') : 'WordPress &rsaquo; Error';
2655  
2656      $text_direction = 'ltr';
2657      if ( isset($r['text_direction']) && 'rtl' == $r['text_direction'] )
2658          $text_direction = 'rtl';
2659      elseif ( isset($wp_locale ) && 'rtl' == $wp_locale->text_direction )
2660          $text_direction = 'rtl';
2661  ?>
2662  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2663  <!-- 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 -->
2664  <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) ) language_attributes(); ?>>
2665  <head>
2666      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2667      <title><?php echo $title ?></title>
2668      <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install.css" type="text/css" />
2669  <?php
2670  if ( 'rtl' == $text_direction ) : ?>
2671      <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install-rtl.css" type="text/css" />
2672  <?php endif; ?>
2673  </head>
2674  <body id="error-page">
2675  <?php endif; ?>
2676      <?php echo $message; ?>
2677  </body>
2678  </html>
2679  <?php
2680      die();
2681  }
2682  
2683  /**
2684   * Retrieve the WordPress home page URL.
2685   *
2686   * If the constant named 'WP_HOME' exists, then it willl be used and returned by
2687   * the function. This can be used to counter the redirection on your local
2688   * development environment.
2689   *
2690   * @access private
2691   * @package WordPress
2692   * @since 2.2.0
2693   *
2694   * @param string $url URL for the home location
2695   * @return string Homepage location.
2696   */
2697  function _config_wp_home( $url = '' ) {
2698      if ( defined( 'WP_HOME' ) )
2699          return WP_HOME;
2700      return $url;
2701  }
2702  
2703  /**
2704   * Retrieve the WordPress site URL.
2705   *
2706   * If the constant named 'WP_SITEURL' is defined, then the value in that
2707   * constant will always be returned. This can be used for debugging a site on
2708   * your localhost while not having to change the database to your URL.
2709   *
2710   * @access private
2711   * @package WordPress
2712   * @since 2.2.0
2713   *
2714   * @param string $url URL to set the WordPress site location.
2715   * @return string The WordPress Site URL
2716   */
2717  function _config_wp_siteurl( $url = '' ) {
2718      if ( defined( 'WP_SITEURL' ) )
2719          return WP_SITEURL;
2720      return $url;
2721  }
2722  
2723  /**
2724   * Set the localized direction for MCE plugin.
2725   *
2726   * Will only set the direction to 'rtl', if the WordPress locale has the text
2727   * direction set to 'rtl'.
2728   *
2729   * Fills in the 'directionality', 'plugins', and 'theme_advanced_button1' array
2730   * keys. These keys are then returned in the $input array.
2731   *
2732   * @access private
2733   * @package WordPress
2734   * @subpackage MCE
2735   * @since 2.1.0
2736   *
2737   * @param array $input MCE plugin array.
2738   * @return array Direction set for 'rtl', if needed by locale.
2739   */
2740  function _mce_set_direction( $input ) {
2741      global $wp_locale;
2742  
2743      if ( 'rtl' == $wp_locale->text_direction ) {
2744          $input['directionality'] = 'rtl';
2745          $input['plugins'] .= ',directionality';
2746          $input['theme_advanced_buttons1'] .= ',ltr';
2747      }
2748  
2749      return $input;
2750  }
2751  
2752  
2753  /**
2754   * Convert smiley code to the icon graphic file equivalent.
2755   *
2756   * You can turn off smilies, by going to the write setting screen and unchecking
2757   * the box, or by setting 'use_smilies' option to false or removing the option.
2758   *
2759   * Plugins may override the default smiley list by setting the $wpsmiliestrans
2760   * to an array, with the key the code the blogger types in and the value the
2761   * image file.
2762   *
2763   * The $wp_smiliessearch global is for the regular expression and is set each
2764   * time the function is called.
2765   *
2766   * The full list of smilies can be found in the function and won't be listed in
2767   * the description. Probably should create a Codex page for it, so that it is
2768   * available.
2769   *
2770   * @global array $wpsmiliestrans
2771   * @global array $wp_smiliessearch
2772   * @since 2.2.0
2773   */
2774  function smilies_init() {
2775      global $wpsmiliestrans, $wp_smiliessearch;
2776  
2777      // don't bother setting up smilies if they are disabled
2778      if ( !get_option( 'use_smilies' ) )
2779          return;
2780  
2781      if ( !isset( $wpsmiliestrans ) ) {
2782          $wpsmiliestrans = array(
2783          ':mrgreen:' => 'icon_mrgreen.gif',
2784          ':neutral:' => 'icon_neutral.gif',
2785          ':twisted:' => 'icon_twisted.gif',
2786            ':arrow:' => 'icon_arrow.gif',
2787            ':shock:' => 'icon_eek.gif',
2788            ':smile:' => 'icon_smile.gif',
2789              ':???:' => 'icon_confused.gif',
2790             ':cool:' => 'icon_cool.gif',
2791             ':evil:' => 'icon_evil.gif',
2792             ':grin:' => 'icon_biggrin.gif',
2793             ':idea:' => 'icon_idea.gif',
2794             ':oops:' => 'icon_redface.gif',
2795             ':razz:' => 'icon_razz.gif',
2796             ':roll:' => 'icon_rolleyes.gif',
2797             ':wink:' => 'icon_wink.gif',
2798              ':cry:' => 'icon_cry.gif',
2799              ':eek:' => 'icon_surprised.gif',
2800              ':lol:' => 'icon_lol.gif',
2801              ':mad:' => 'icon_mad.gif',
2802              ':sad:' => 'icon_sad.gif',
2803                '8-)' => 'icon_cool.gif',
2804                '8-O' => 'icon_eek.gif',
2805                ':-(' => 'icon_sad.gif',
2806                ':-)' => 'icon_smile.gif',
2807                ':-?' => 'icon_confused.gif',
2808                ':-D' => 'icon_biggrin.gif',
2809                ':-P' => 'icon_razz.gif',
2810                ':-o' => 'icon_surprised.gif',
2811                ':-x' => 'icon_mad.gif',
2812                ':-|' => 'icon_neutral.gif',
2813                ';-)' => 'icon_wink.gif',
2814                 '8)' => 'icon_cool.gif',
2815                 '8O' => 'icon_eek.gif',
2816                 ':(' => 'icon_sad.gif',
2817                 ':)' => 'icon_smile.gif',
2818                 ':?' => 'icon_confused.gif',
2819                 ':D' => 'icon_biggrin.gif',
2820                 ':P' => 'icon_razz.gif',
2821                 ':o' => 'icon_surprised.gif',
2822                 ':x' => 'icon_mad.gif',
2823                 ':|' => 'icon_neutral.gif',
2824                 ';)' => 'icon_wink.gif',
2825                ':!:' => 'icon_exclaim.gif',
2826                ':?:' => 'icon_question.gif',
2827          );
2828      }
2829  
2830      if (count($wpsmiliestrans) == 0) {
2831          return;
2832      }
2833  
2834      /*
2835       * NOTE: we sort the smilies in reverse key order. This is to make sure
2836       * we match the longest possible smilie (:???: vs :?) as the regular
2837       * expression used below is first-match
2838       */
2839      krsort($wpsmiliestrans);
2840  
2841      $wp_smiliessearch = '/(?:\s|^)';
2842  
2843      $subchar = '';
2844      foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
2845          $firstchar = substr($smiley, 0, 1);
2846          $rest = substr($smiley, 1);
2847  
2848          // new subpattern?
2849          if ($firstchar != $subchar) {
2850              if ($subchar != '') {
2851                  $wp_smiliessearch .= ')|(?:\s|^)';
2852              }
2853              $subchar = $firstchar;
2854              $wp_smiliessearch .= preg_quote($firstchar, '/') . '(?:';
2855          } else {
2856              $wp_smiliessearch .= '|';
2857          }
2858          $wp_smiliessearch .= preg_quote($rest, '/');
2859      }
2860  
2861      $wp_smiliessearch .= ')(?:\s|$)/m';
2862  }
2863  
2864  /**
2865   * Merge user defined arguments into defaults array.
2866   *
2867   * This function is used throughout WordPress to allow for both string or array
2868   * to be merged into another array.
2869   *
2870   * @since 2.2.0
2871   *
2872   * @param string|array $args Value to merge with $defaults
2873   * @param array $defaults Array that serves as the defaults.
2874   * @return array Merged user defined values with defaults.
2875   */
2876  function wp_parse_args( $args, $defaults = '' ) {
2877      if ( is_object( $args ) )
2878          $r = get_object_vars( $args );
2879      elseif ( is_array( $args ) )
2880          $r =& $args;
2881      else
2882          wp_parse_str( $args, $r );
2883  
2884      if ( is_array( $defaults ) )
2885          return array_merge( $defaults, $r );
2886      return $r;
2887  }
2888  
2889  /**
2890   * Clean up an array, comma- or space-separated list of IDs
2891   *
2892   * @since 3.0.0
2893   *
2894   * @param array|string $list
2895   * @return array Sanitized array of IDs
2896   */
2897  function wp_parse_id_list($list) {
2898      if ( !is_array($list) )
2899          $list = preg_split('/[\s,]+/', $list);
2900  
2901      return array_unique(array_map('absint', $list));
2902  }
2903  
2904  /**
2905   * Determines if default embed handlers should be loaded.
2906   *
2907   * Checks to make sure that the embeds library hasn't already been loaded. If
2908   * it hasn't, then it will load the embeds library.
2909   *
2910   * @since 2.9.0
2911   */
2912  function wp_maybe_load_embeds() {
2913      if ( ! apply_filters('load_default_embeds', true) )
2914          return;
2915      require_once( ABSPATH . WPINC . '/default-embeds.php' );
2916  }
2917  
2918  /**
2919   * Determines if Widgets library should be loaded.
2920   *
2921   * Checks to make sure that the widgets library hasn't already been loaded. If
2922   * it hasn't, then it will load the widgets library and run an action hook.
2923   *
2924   * @since 2.2.0
2925   * @uses add_action() Calls '_admin_menu' hook with 'wp_widgets_add_menu' value.
2926   */
2927  function wp_maybe_load_widgets() {
2928      if ( ! apply_filters('load_default_widgets', true) )
2929          return;
2930      require_once( ABSPATH . WPINC . '/default-widgets.php' );
2931      add_action( '_admin_menu', 'wp_widgets_add_menu' );
2932  }
2933  
2934  /**
2935   * Append the Widgets menu to the themes main menu.
2936   *
2937   * @since 2.2.0
2938   * @uses $submenu The administration submenu list.
2939   */
2940  function wp_widgets_add_menu() {
2941      global $submenu;
2942      $submenu['themes.php'][7] = array( __( 'Widgets' ), 'switch_themes', 'widgets.php' );
2943      ksort( $submenu['themes.php'], SORT_NUMERIC );
2944  }
2945  
2946  /**
2947   * Flush all output buffers for PHP 5.2.
2948   *
2949   * Make sure all output buffers are flushed before our singletons our destroyed.
2950   *
2951   * @since 2.2.0
2952   */
2953  function wp_ob_end_flush_all() {
2954      $levels = ob_get_level();
2955      for ($i=0; $i<$levels; $i++)
2956          ob_end_flush();
2957  }
2958  
2959  /**
2960   * Load the correct database class file.
2961   *
2962   * This function is used to load the database class file either at runtime or by
2963   * wp-admin/setup-config.php We must globalise $wpdb to ensure that it is
2964   * defined globally by the inline code in wp-db.php.
2965   *
2966   * @since 2.5.0
2967   * @global $wpdb WordPress Database Object
2968   */
2969  function require_wp_db() {
2970      global $wpdb;
2971      if ( file_exists( WP_CONTENT_DIR . '/db.php' ) )
2972          require_once( WP_CONTENT_DIR . '/db.php' );
2973      else
2974          require_once( ABSPATH . WPINC . '/wp-db.php' );
2975  }
2976  
2977  /**
2978   * Load custom DB error or display WordPress DB error.
2979   *
2980   * If a file exists in the wp-content directory named db-error.php, then it will
2981   * be loaded instead of displaying the WordPress DB error. If it is not found,
2982   * then the WordPress DB error will be displayed instead.
2983   *
2984   * The WordPress DB error sets the HTTP status header to 500 to try to prevent
2985   * search engines from caching the message. Custom DB messages should do the
2986   * same.
2987   *
2988   * This function was backported to the the WordPress 2.3.2, but originally was
2989   * added in WordPress 2.5.0.
2990   *
2991   * @since 2.3.2
2992   * @uses $wpdb
2993   */
2994  function dead_db() {
2995      global $wpdb;
2996  
2997      // Load custom DB error template, if present.
2998      if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
2999          require_once( WP_CONTENT_DIR . '/db-error.php' );
3000          die();
3001      }
3002  
3003      // If installing or in the admin, provide the verbose message.
3004      if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
3005          wp_die($wpdb->error);
3006  
3007      // Otherwise, be terse.
3008      status_header( 500 );
3009      nocache_headers();
3010      header( 'Content-Type: text/html; charset=utf-8' );
3011  ?>
3012  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3013  <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) ) language_attributes(); ?>>
3014  <head>
3015  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
3016      <title>Database Error</title>
3017  
3018  </head>
3019  <body>
3020      <h1>Error establishing a database connection</h1>
3021  </body>
3022  </html>
3023  <?php
3024      die();
3025  }
3026  
3027  /**
3028   * Converts value to nonnegative integer.
3029   *
3030   * @since 2.5.0
3031   *
3032   * @param mixed $maybeint Data you wish to have convered to an nonnegative integer
3033   * @return int An nonnegative integer
3034   */
3035  function absint( $maybeint ) {
3036      return abs( intval( $maybeint ) );
3037  }
3038  
3039  /**
3040   * Determines if the blog can be accessed over SSL.
3041   *
3042   * Determines if blog can be accessed over SSL by using cURL to access the site
3043   * using the https in the siteurl. Requires cURL extension to work correctly.
3044   *
3045   * @since 2.5.0
3046   *
3047   * @param string $url
3048   * @return bool Whether SSL access is available
3049   */
3050  function url_is_accessable_via_ssl($url)
3051  {
3052      if (in_array('curl', get_loaded_extensions())) {
3053          $ssl = preg_replace( '/^http:\/\//', 'https://',  $url );
3054  
3055          $ch = curl_init();
3056          curl_setopt($ch, CURLOPT_URL, $ssl);
3057          curl_setopt($ch, CURLOPT_FAILONERROR, true);
3058          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
3059          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
3060          curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
3061  
3062          curl_exec($ch);
3063  
3064          $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
3065          curl_close ($ch);
3066  
3067          if ($status == 200 || $status == 401) {
3068              return true;
3069          }
3070      }
3071      return false;
3072  }
3073  
3074  /**
3075   * Secure URL, if available or the given URL.
3076   *
3077   * @since 2.5.0
3078   *
3079   * @param string $url Complete URL path with transport.
3080   * @return string Secure or regular URL path.
3081   */
3082  function atom_service_url_filter($url)
3083  {
3084      if ( url_is_accessable_via_ssl($url) )
3085          return preg_replace( '/^http:\/\//', 'https://',  $url );
3086      else
3087          return $url;
3088  }
3089  
3090  /**
3091   * Marks a function as deprecated and informs when it has been used.
3092   *
3093   * There is a hook deprecated_function_run that will be called that can be used
3094   * to get the backtrace up to what file and function called the deprecated
3095   * function.
3096   *
3097   * The current behavior is to trigger an user error if WP_DEBUG is true.
3098   *
3099   * This function is to be used in every function in depreceated.php
3100   *
3101   * @package WordPress
3102   * @subpackage Debug
3103   * @since 2.5.0
3104   * @access private
3105   *
3106   * @uses do_action() Calls 'deprecated_function_run' and passes the function name, what to use instead,
3107   *   and the version the function was deprecated in.
3108   * @uses apply_filters() Calls 'deprecated_function_trigger_error' and expects boolean value of true to do
3109   *   trigger or false to not trigger error.
3110   *
3111   * @param string $function The function that was called
3112   * @param string $version The version of WordPress that deprecated the function
3113   * @param string $replacement Optional. The function that should have been called
3114   */
3115  function _deprecated_function( $function, $version, $replacement=null ) {
3116  
3117      do_action( 'deprecated_function_run', $function, $replacement, $version );
3118  
3119      // Allow plugin to filter the output error trigger
3120      if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
3121          if ( ! is_null($replacement) )
3122              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
3123          else
3124              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
3125      }
3126  }
3127  
3128  /**
3129   * Marks a file as deprecated and informs when it has been used.
3130   *
3131   * There is a hook deprecated_file_included that will be called that can be used
3132   * to get the backtrace up to what file and function included the deprecated
3133   * file.
3134   *
3135   * The current behavior is to trigger an user error if WP_DEBUG is true.
3136   *
3137   * This function is to be used in every file that is depreceated
3138   *
3139   * @package WordPress
3140   * @subpackage Debug
3141   * @since 2.5.0
3142   * @access private
3143   *
3144   * @uses do_action() Calls 'deprecated_file_included' and passes the file name, what to use instead,
3145   *   the version in which the file was deprecated, and any message regarding the change.
3146   * @uses apply_filters() Calls 'deprecated_file_trigger_error' and expects boolean value of true to do
3147   *   trigger or false to not trigger error.
3148   *
3149   * @param string $file The file that was included
3150   * @param string $version The version of WordPress that deprecated the file
3151   * @param string $replacement Optional. The file that should have been included based on ABSPATH
3152   * @param string $message Optional. A message regarding the change
3153   */
3154  function _deprecated_file( $file, $version, $replacement = null, $message = '' ) {
3155  
3156      do_action( 'deprecated_file_included', $file, $replacement, $version, $message );
3157  
3158      // Allow plugin to filter the output error trigger
3159      if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) {
3160          $message = empty( $message ) ? '' : ' ' . $message;
3161          if ( ! is_null( $replacement ) )
3162              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message );
3163          else
3164              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) . $message );
3165      }
3166  }
3167  /**
3168   * Marks a function argument as deprecated and informs when it has been used.
3169   *
3170   * This function is to be used whenever a deprecated function argument is used.
3171   * Before this function is called, the argument must be checked for whether it was
3172   * used by comparing it to its default value or evaluating whether it is empty.
3173   * For example:
3174   * <code>
3175   * if ( !empty($deprecated) )
3176   *     _deprecated_argument( __FUNCTION__, '3.0' );
3177   * </code>
3178   *
3179   * There is a hook deprecated_argument_run that will be called that can be used
3180   * to get the backtrace up to what file and function used the deprecated
3181   * argument.
3182   *
3183   * The current behavior is to trigger an user error if WP_DEBUG is true.
3184   *
3185   * @package WordPress
3186   * @subpackage Debug
3187   * @since 3.0.0
3188   * @access private
3189   *
3190   * @uses do_action() Calls 'deprecated_argument_run' and passes the function name, a message on the change,
3191   *   and the version in which the argument was deprecated.
3192   * @uses apply_filters() Calls 'deprecated_argument_trigger_error' and expects boolean value of true to do
3193   *   trigger or false to not trigger error.
3194   *
3195   * @param string $function The function that was called
3196   * @param string $version The version of WordPress that deprecated the argument used
3197   * @param string $message Optional. A message regarding the change.
3198   */
3199  function _deprecated_argument( $function, $version, $message = null ) {
3200  
3201      do_action( 'deprecated_argument_run', $function, $message, $version );
3202  
3203      // Allow plugin to filter the output error trigger
3204      if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
3205          if ( ! is_null( $message ) )
3206              trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s'), $function, $version, $message ) );
3207          else
3208              trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
3209      }
3210  }
3211  
3212  /**
3213   * Is the server running earlier than 1.5.0 version of lighttpd
3214   *
3215   * @since 2.5.0
3216   *
3217   * @return bool Whether the server is running lighttpd < 1.5.0
3218   */
3219  function is_lighttpd_before_150() {
3220      $server_parts = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] )? $_SERVER['SERVER_SOFTWARE'] : '' );
3221      $server_parts[1] = isset( $server_parts[1] )? $server_parts[1] : '';
3222      return  'lighttpd' == $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' );
3223  }
3224  
3225  /**
3226   * Does the specified module exist in the apache config?
3227   *
3228   * @since 2.5.0
3229   *
3230   * @param string $mod e.g. mod_rewrite
3231   * @param bool $default The default return value if the module is not found
3232   * @return bool
3233   */
3234  function apache_mod_loaded($mod, $default = false) {
3235      global $is_apache;
3236  
3237      if ( !$is_apache )
3238          return false;
3239  
3240      if ( function_exists('apache_get_modules') ) {
3241          $mods = apache_get_modules();
3242          if ( in_array($mod, $mods) )
3243              return true;
3244      } elseif ( function_exists('phpinfo') ) {
3245              ob_start();
3246              phpinfo(8);
3247              $phpinfo = ob_get_clean();
3248              if ( false !== strpos($phpinfo, $mod) )
3249                  return true;
3250      }
3251      return $default;
3252  }
3253  
3254  /**
3255   * File validates against allowed set of defined rules.
3256   *
3257   * A return value of '1' means that the $file contains either '..' or './'. A
3258   * return value of '2' means that the $file contains ':' after the first
3259   * character. A return value of '3' means that the file is not in the allowed
3260   * files list.
3261   *
3262   * @since 1.2.0
3263   *
3264   * @param string $file File path.
3265   * @param array $allowed_files List of allowed files.
3266   * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
3267   */
3268  function validate_file( $file, $allowed_files = '' ) {
3269      if ( false !== strpos( $file, '..' ))
3270          return 1;
3271  
3272      if ( false !== strpos( $file, './' ))
3273          return 1;
3274  
3275      if (!empty ( $allowed_files ) && (!in_array( $file, $allowed_files ) ) )
3276          return 3;
3277  
3278      if (':' == substr( $file, 1, 1 ))
3279          return 2;
3280  
3281      return 0;
3282  }
3283  
3284  /**
3285   * Determine if SSL is used.
3286   *
3287   * @since 2.6.0
3288   *
3289   * @return bool True if SSL, false if not used.
3290   */
3291  function is_ssl() {
3292      if ( isset($_SERVER['HTTPS']) ) {
3293          if ( 'on' == strtolower($_SERVER['HTTPS']) )
3294              return true;
3295          if ( '1' == $_SERVER['HTTPS'] )
3296              return true;
3297      } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
3298          return true;
3299      }
3300      return false;
3301  }
3302  
3303  /**
3304   * Whether SSL login should be forced.
3305   *
3306   * @since 2.6.0
3307   *
3308   * @param string|bool $force Optional.
3309   * @return bool True if forced, false if not forced.
3310   */
3311  function force_ssl_login( $force = null ) {
3312      static $forced = false;
3313  
3314      if ( !is_null( $force ) ) {
3315          $old_forced = $forced;
3316          $forced = $force;
3317          return $old_forced;
3318      }
3319  
3320      return $forced;
3321  }
3322  
3323  /**
3324   * Whether to force SSL used for the Administration Panels.
3325   *
3326   * @since 2.6.0
3327   *
3328   * @param string|bool $force
3329   * @return bool True if forced, false if not forced.
3330   */
3331  function force_ssl_admin( $force = null ) {
3332      static $forced = false;
3333  
3334      if ( !is_null( $force ) ) {
3335          $old_forced = $forced;
3336          $forced = $force;
3337          return $old_forced;
3338      }
3339  
3340      return $forced;
3341  }
3342  
3343  /**
3344   * Guess the URL for the site.
3345   *
3346   * Will remove wp-admin links to retrieve only return URLs not in the wp-admin
3347   * directory.
3348   *
3349   * @since 2.6.0
3350   *
3351   * @return string
3352   */
3353  function wp_guess_url() {
3354      if ( defined('WP_SITEURL') && '' != WP_SITEURL ) {
3355          $url = WP_SITEURL;
3356      } else {
3357          $schema = is_ssl() ? 'https://' : 'http://';
3358          $url = preg_replace('|/wp-admin/.*|i', '', $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
3359      }
3360      return $url;
3361  }
3362  
3363  /**
3364   * Suspend cache invalidation.
3365   *
3366   * Turns cache invalidation on and off.  Useful during imports where you don't wont to do invalidations
3367   * every time a post is inserted.  Callers must be sure that what they are doing won't lead to an inconsistent
3368   * cache when invalidation is suspended.
3369   *
3370   * @since 2.7.0
3371   *
3372   * @param bool $suspend Whether to suspend or enable cache invalidation
3373   * @return bool The current suspend setting
3374   */
3375  function wp_suspend_cache_invalidation($suspend = true) {
3376      global $_wp_suspend_cache_invalidation;
3377  
3378      $current_suspend = $_wp_suspend_cache_invalidation;
3379      $_wp_suspend_cache_invalidation = $suspend;
3380      return $current_suspend;
3381  }
3382  
3383  /**
3384   * Retrieve site option value based on name of option.
3385   *
3386   * @see get_option()
3387   * @package WordPress
3388   * @subpackage Option
3389   * @since 2.8.0
3390   *
3391   * @uses apply_filters() Calls 'pre_site_option_$option' before checking the option.
3392   *     Any value other than false will "short-circuit" the retrieval of the option
3393   *    and return the returned value.
3394   * @uses apply_filters() Calls 'site_option_$option', after checking the  option, with
3395   *     the option value.
3396   *
3397   * @param string $option Name of option to retrieve. Expected to not be SQL-escaped.
3398   * @param mixed $default Optional value to return if option doesn't exist. Default false.
3399   * @param bool $use_cache Whether to use cache. Multisite only. Default true.
3400   * @return mixed Value set for the option.
3401   */
3402  function get_site_option( $option, $default = false, $use_cache = true ) {
3403      global $wpdb;
3404  
3405      // Allow plugins to short-circuit site options.
3406       $pre = apply_filters( 'pre_site_option_' . $option, false );
3407       if ( false !== $pre )
3408           return $pre;
3409  
3410      if ( !is_multisite() ) {
3411          $value = get_option($option, $default);
3412      } else {
3413          $cache_key = "{$wpdb->siteid}:$option";
3414          if ( $use_cache )
3415              $value = wp_cache_get($cache_key, 'site-options');
3416  
3417          if ( false === $value ) {
3418              $value = $wpdb->get_var( $wpdb->prepare("SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) );
3419  
3420              if ( is_null($value) )
3421                  $value = $default;
3422  
3423              $value = maybe_unserialize( $value );
3424  
3425              wp_cache_set( $cache_key, $value, 'site-options' );
3426          }
3427      }
3428  
3429       return apply_filters( 'site_option_' . $option, $value );
3430  }
3431  
3432  /**
3433   * Add a new site option.
3434   *
3435   * @see add_option()
3436   * @package WordPress
3437   * @subpackage Option
3438   * @since 2.8.0
3439   *
3440   * @uses apply_filters() Calls 'pre_add_site_option_$option' hook to allow overwriting the
3441   *     option value to be stored.
3442   * @uses do_action() Calls 'add_site_option_$option' and 'add_site_option' hooks on success.
3443   *
3444   * @param string $option Name of option to add. Expected to not be SQL-escaped.
3445   * @param mixed $value Optional. Option value, can be anything. Expected to not be SQL-escaped.
3446   * @return bool False if option was not added and true if option was added.
3447   */
3448  function add_site_option( $option, $value ) {
3449      global $wpdb;
3450  
3451      $value = apply_filters( 'pre_add_site_option_' . $option, $value );
3452  
3453      if ( !is_multisite() ) {
3454          $result = add_option( $option, $value );
3455      } else {
3456          $cache_key = "{$wpdb->siteid}:$option";
3457  
3458          if ( $wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) ) )
3459              return update_site_option( $option, $value );
3460  
3461          $value = sanitize_option( $option, $value );
3462          wp_cache_set( $cache_key, $value, 'site-options' );
3463  
3464          $_value = $value;
3465          $value = maybe_serialize($value);
3466          $result = $wpdb->insert( $wpdb->sitemeta, array('site_id' => $wpdb->siteid, 'meta_key' => $option, 'meta_value' => $value ) );
3467          $value = $_value;
3468      }
3469  
3470      do_action( "add_site_option_{$option}", $option, $value );
3471      do_action( "add_site_option", $option, $value );
3472  
3473      return $result;
3474  }
3475  
3476  /**
3477   * Removes site option by name.
3478   *
3479   * @see delete_option()
3480   * @package WordPress
3481   * @subpackage Option
3482   * @since 2.8.0
3483   *
3484   * @uses do_action() Calls 'pre_delete_site_option_$option' hook before option is deleted.
3485   * @uses do_action() Calls 'delete_site_option' and 'delete_site_option_$option'
3486   *     hooks on success.
3487   *
3488   * @param string $option Name of option to remove. Expected to not be SQL-escaped.
3489   * @return bool True, if succeed. False, if failure.
3490   */
3491  function delete_site_option( $option ) {
3492      global $wpdb;
3493  
3494      // ms_protect_special_option( $option ); @todo
3495  
3496      do_action( 'pre_delete_site_option_' . $option );
3497  
3498      if ( !is_multisite() ) {
3499          $result = delete_option( $option );
3500      } else {
3501          $row = $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) );
3502          if ( is_null( $row ) || !$row->meta_id )
3503              return false;
3504          $cache_key = "{$wpdb->siteid}:$option";
3505          wp_cache_delete( $cache_key, 'site-options' );
3506  
3507          $result = $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->sitemeta} WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) );
3508      }
3509  
3510      if ( $result ) {
3511          do_action( "delete_site_option_{$option}", $option );
3512          do_action( "delete_site_option", $option );
3513          return true;
3514      }
3515      return false;
3516  }
3517  
3518  /**
3519   * Update the value of a site option that was already added.
3520   *
3521   * @see update_option()
3522   * @since 2.8.0
3523   * @package WordPress
3524   * @subpackage Option
3525   *
3526   * @uses apply_filters() Calls 'pre_update_site_option_$option' hook to allow overwriting the
3527   *     option value to be stored.
3528   * @uses do_action() Calls 'update_site_option_$option' and 'update_site_option' hooks on success.
3529   *
3530   * @param string $option Name of option. Expected to not be SQL-escaped.
3531   * @param mixed $value Option value. Expected to not be SQL-escaped.
3532   * @return bool False if value was not updated and true if value was updated.
3533   */
3534  function update_site_option( $option, $value ) {
3535      global $wpdb;
3536  
3537      $oldvalue = get_site_option( $option );
3538      $value = apply_filters( 'pre_update_site_option_' . $option, $value, $oldvalue );
3539  
3540      if ( $value === $oldvalue )
3541          return false;
3542  
3543      if ( !is_multisite() ) {
3544          $result = update_option( $option, $value );
3545      } else {
3546          $cache_key = "{$wpdb->siteid}:$option";
3547  
3548          if ( $value && !$wpdb->get_row( $wpdb->prepare( "SELECT meta_value FROM $wpdb->sitemeta WHERE meta_key = %s AND site_id = %d", $option, $wpdb->siteid ) ) )
3549              return add_site_option( $option, $value );
3550          $value = sanitize_option( $option, $value );
3551          wp_cache_set( $cache_key, $value, 'site-options' );
3552  
3553          $_value = $value;
3554          $value = maybe_serialize( $value );
3555          $result = $wpdb->update( $wpdb->sitemeta, array( 'meta_value' => $value ), array( 'site_id' => $wpdb->siteid, 'meta_key' => $option ) );
3556          $value = $_value;
3557      }
3558  
3559      if ( $result ) {
3560          do_action( "update_site_option_{$option}", $option, $value );
3561          do_action( "update_site_option", $option, $value );
3562          return true;
3563      }
3564      return false;
3565  }
3566  
3567  /**
3568   * Delete a site transient
3569   *
3570   * @since 2.9.0
3571   * @package WordPress
3572   * @subpackage Transient
3573   *
3574   * @uses do_action() Calls 'delete_site_transient_$transient' hook before transient is deleted.
3575   * @uses do_action() Calls 'deleted_site_transient' hook on success.
3576   *
3577   * @param string $transient Transient name. Expected to not be SQL-escaped.
3578   * @return bool True if successful, false otherwise
3579   */
3580  function delete_site_transient( $transient ) {
3581      global $_wp_using_ext_object_cache;
3582  
3583      do_action( 'delete_site_transient_' . $transient, $transient );
3584      if ( $_wp_using_ext_object_cache ) {
3585          $result = wp_cache_delete( $transient, 'site-transient' );
3586      } else {
3587          $option_timeout = '_site_transient_timeout_' . $transient;
3588          $option = '_site_transient_' . $transient;
3589          $result = delete_site_option( $option );
3590          if ( $result )
3591              delete_site_option( $option_timeout );
3592      }
3593      if ( $result )
3594          do_action( 'deleted_site_transient', $transient );
3595      return $result;
3596  }
3597  
3598  /**
3599   * Get the value of a site transient
3600   *
3601   * If the transient does not exist or does not have a value, then the return value
3602   * will be false.
3603   *
3604   * @see get_transient()
3605   * @since 2.9.0
3606   * @package WordPress
3607   * @subpackage Transient
3608   *
3609   * @uses apply_filters() Calls 'pre_site_transient_$transient' hook before checking the transient.
3610   *     Any value other than false will "short-circuit" the retrieval of the transient
3611   *    and return the returned value.
3612   * @uses apply_filters() Calls 'site_transient_$option' hook, after checking the transient, with
3613   *     the transient value.
3614   *
3615   * @param string $transient Transient name. Expected to not be SQL-escaped.
3616   * @return mixed Value of transient
3617   */
3618  function get_site_transient( $transient ) {
3619      global $_wp_using_ext_object_cache;
3620  
3621      $pre = apply_filters( 'pre_site_transient_' . $transient, false );
3622      if ( false !== $pre )
3623          return $pre;
3624  
3625      if ( $_wp_using_ext_object_cache ) {
3626          $value = wp_cache_get( $transient, 'site-transient' );
3627      } else {
3628          // Core transients that do not have a timeout. Listed here so querying timeouts can be avoided.
3629          $no_timeout = array('update_core', 'update_plugins', 'update_themes');
3630          $transient_option = '_site_transient_' . $transient;
3631          if ( ! in_array( $transient, $no_timeout ) ) {
3632              $transient_timeout = '_site_transient_timeout_' . $transient;
3633              $timeout = get_site_option( $transient_timeout );
3634              if ( false !== $timeout && $timeout < time() ) {
3635                  delete_site_option( $transient_option  );
3636                  delete_site_option( $transient_timeout );
3637                  return false;
3638              }
3639          }
3640  
3641          $value = get_site_option( $transient_option );
3642      }
3643  
3644      return apply_filters( 'site_transient_' . $transient, $value );
3645  }
3646  
3647  /**
3648   * Set/update the value of a site transient
3649   *
3650   * You do not need to serialize values, if the value needs to be serialize, then
3651   * it will be serialized before it is set.
3652   *
3653   * @see set_transient()
3654   * @since 2.9.0
3655   * @package WordPress
3656   * @subpackage Transient
3657   *
3658   * @uses apply_filters() Calls 'pre_set_site_transient_$transient' hook to allow overwriting the
3659   *     transient value to be stored.
3660   * @uses do_action() Calls 'set_site_transient_$transient' and 'setted_site_transient' hooks on success.
3661   *
3662   * @param string $transient Transient name. Expected to not be SQL-escaped.
3663   * @param mixed $value Transient value. Expected to not be SQL-escaped.
3664   * @param int $expiration Time until expiration in seconds, default 0
3665   * @return bool False if value was not set and true if value was set.
3666   */
3667  function set_site_transient( $transient, $value, $expiration = 0 ) {
3668      global $_wp_using_ext_object_cache;
3669  
3670      $value = apply_filters( 'pre_set_site_transient_' . $transient, $value );
3671  
3672      if ( $_wp_using_ext_object_cache ) {
3673          $result = wp_cache_set( $transient, $value, 'site-transient', $expiration );
3674      } else {
3675          $transient_timeout = '_site_transient_timeout_' . $transient;
3676          $transient = '_site_transient_' . $transient;
3677          if ( false === get_site_option( $transient ) ) {
3678              if ( $expiration )
3679                  add_site_option( $transient_timeout, time() + $expiration );
3680              $result = add_site_option( $transient, $value );
3681          } else {
3682              if ( $expiration )
3683                  update_site_option( $transient_timeout, time() + $expiration );
3684              $result = update_site_option( $transient, $value );
3685          }
3686      }
3687      if ( $result ) {
3688          do_action( 'set_site_transient_' . $transient );
3689          do_action( 'setted_site_transient', $transient );
3690      }
3691      return $result;
3692  }
3693  
3694  /**
3695   * is main site
3696   *
3697   *
3698   * @since 3.0.0
3699   * @package WordPress
3700   *
3701   * @param int $blog_id optional blog id to test (default current blog)
3702   * @return bool True if not multisite or $blog_id is main site
3703   */
3704  function is_main_site( $blog_id = '' ) {
3705      global $current_site, $current_blog;
3706  
3707      if ( !is_multisite() )
3708          return true;
3709  
3710      if ( !$blog_id )
3711          $blog_id = $current_blog->blog_id;
3712  
3713      return $blog_id == $current_site->blog_id;
3714  }
3715  
3716  /**
3717   * are global terms enabled
3718   *
3719   *
3720   * @since 3.0.0
3721   * @package WordPress
3722   *
3723   * @return bool True if multisite and global terms enabled
3724   */
3725  function global_terms_enabled() {
3726      if ( is_multisite() && '1' == get_site_option( 'global_terms_enabled' ) )
3727          return true;
3728  
3729      return false;
3730  }
3731  
3732  /**
3733   * gmt_offset modification for smart timezone handling
3734   *
3735   * Overrides the gmt_offset option if we have a timezone_string available
3736   *
3737   * @since 2.8.0
3738   *
3739   * @return float|bool
3740   */
3741  function wp_timezone_override_offset() {
3742      if ( !wp_timezone_supported() ) {
3743          return false;
3744      }
3745      if ( !$timezone_string = get_option( 'timezone_string' ) ) {
3746          return false;
3747      }
3748  
3749      $timezone_object = timezone_open( $timezone_string );
3750      $datetime_object = date_create();
3751      if ( false === $timezone_object || false === $datetime_object ) {
3752          return false;
3753      }
3754      return round( timezone_offset_get( $timezone_object, $datetime_object ) / 3600, 2 );
3755  }
3756  
3757  /**
3758   * Check for PHP timezone support
3759   *
3760   * @since 2.9.0
3761   *
3762   * @return bool
3763   */
3764  function wp_timezone_supported() {
3765      $support = false;
3766      if (
3767          function_exists( 'date_create' ) &&
3768          function_exists( 'date_default_timezone_set' ) &&
3769          function_exists( 'timezone_identifiers_list' ) &&
3770          function_exists( 'timezone_open' ) &&
3771          function_exists( 'timezone_offset_get' )
3772      ) {
3773          $support = true;
3774      }
3775      return apply_filters( 'timezone_support', $support );
3776  }
3777  
3778  /**
3779   * {@internal Missing Short Description}}
3780   *
3781   * @since 2.9.0
3782   *
3783   * @param unknown_type $a
3784   * @param unknown_type $b
3785   * @return int
3786   */
3787  function _wp_timezone_choice_usort_callback( $a, $b ) {
3788      // Don't use translated versions of Etc
3789      if ( 'Etc' === $a['continent'] && 'Etc' === $b['continent'] ) {
3790          // Make the order of these more like the old dropdown
3791          if ( 'GMT+' === substr( $a['city'], 0, 4 ) && 'GMT+' === substr( $b['city'], 0, 4 ) ) {
3792              return -1 * ( strnatcasecmp( $a['city'], $b['city'] ) );
3793          }
3794          if ( 'UTC' === $a['city'] ) {
3795              if ( 'GMT+' === substr( $b['city'], 0, 4 ) ) {
3796                  return 1;
3797              }
3798              return -1;
3799          }
3800          if ( 'UTC' === $b['city'] ) {
3801              if ( 'GMT+' === substr( $a['city'], 0, 4 ) ) {
3802                  return -1;
3803              }
3804              return 1;
3805          }
3806          return strnatcasecmp( $a['city'], $b['city'] );
3807      }
3808      if ( $a['t_continent'] == $b['t_continent'] ) {
3809          if ( $a['t_city'] == $b['t_city'] ) {
3810              return strnatcasecmp( $a['t_subcity'], $b['t_subcity'] );
3811          }
3812          return strnatcasecmp( $a['t_city'], $b['t_city'] );
3813      } else {
3814          // Force Etc to the bottom of the list
3815          if ( 'Etc' === $a['continent'] ) {
3816              return 1;
3817          }
3818          if ( 'Etc' === $b['continent'] ) {
3819              return -1;
3820          }
3821          return strnatcasecmp( $a['t_continent'], $b['t_continent'] );
3822      }
3823  }
3824  
3825  /**
3826   * Gives a nicely formatted list of timezone strings // temporary! Not in final
3827   *
3828   * @since 2.9.0
3829   *
3830   * @param string $selected_zone Selected Zone
3831   * @return string
3832   */
3833  function wp_timezone_choice( $selected_zone ) {
3834      static $mo_loaded = false;
3835  
3836      $continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
3837  
3838      // Load translations for continents and cities
3839      if ( !$mo_loaded ) {
3840          $locale = get_locale();
3841          $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
3842          load_textdomain( 'continents-cities', $mofile );
3843          $mo_loaded = true;
3844      }
3845  
3846      $zonen = array();
3847      foreach ( timezone_identifiers_list() as $zone ) {
3848          $zone = explode( '/', $zone );
3849          if ( !in_array( $zone[0], $continents ) ) {
3850              continue;
3851          }
3852  
3853          // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
3854          $exists = array(
3855              0 => ( isset( $zone[0] ) && $zone[0] ),
3856              1 => ( isset( $zone[1] ) && $zone[1] ),
3857              2 => ( isset( $zone[2] ) && $zone[2] ),
3858          );
3859          $exists[3] = ( $exists[0] && 'Etc' !== $zone[0] );
3860          $exists[4] = ( $exists[1] && $exists[3] );
3861          $exists[5] = ( $exists[2] && $exists[3] );
3862  
3863          $zonen[] = array(
3864              'continent'   => ( $exists[0] ? $zone[0] : '' ),
3865              'city'        => ( $exists[1] ? $zone[1] : '' ),
3866              'subcity'     => ( $exists[2] ? $zone[2] : '' ),
3867              't_continent' => ( $exists[3] ? translate( str_replace( '_', ' ', $zone[0] ), 'continents-cities' ) : '' ),
3868              't_city'      => ( $exists[4] ? translate( str_replace( '_', ' ', $zone[1] ), 'continents-cities' ) : '' ),
3869              't_subcity'   => ( $exists[5] ? translate( str_replace( '_', ' ', $zone[2] ), 'continents-cities' ) : '' )
3870          );
3871      }
3872      usort( $zonen, '_wp_timezone_choice_usort_callback' );
3873  
3874      $structure = array();
3875  
3876      if ( empty( $selected_zone ) ) {
3877          $structure[] = '<option selected="selected" value="">' . __( 'Select a city' ) . '</option>';
3878      }
3879  
3880      foreach ( $zonen as $key => $zone ) {
3881          // Build value in an array to join later
3882          $value = array( $zone['continent'] );
3883  
3884          if ( empty( $zone['city'] ) ) {
3885              // It's at the continent level (generally won't happen)
3886              $display = $zone['t_continent'];
3887          } else {
3888              // It's inside a continent group
3889  
3890              // Continent optgroup
3891              if ( !isset( $zonen[$key - 1] ) || $zonen[$key - 1]['continent'] !== $zone['continent'] ) {
3892                  $label = $zone['t_continent'];
3893                  $structure[] = '<optgroup label="'. esc_attr( $label ) .'">';
3894              }
3895  
3896              // Add the city to the value
3897              $value[] = $zone['city'];
3898  
3899              $display = $zone['t_city'];
3900              if ( !empty( $zone['subcity'] ) ) {
3901                  // Add the subcity to the value
3902                  $value[] = $zone['subcity'];
3903                  $display .= ' - ' . $zone['t_subcity'];
3904              }
3905          }
3906  
3907          // Build the value
3908          $value = join( '/', $value );
3909          $selected = '';
3910          if ( $value === $selected_zone ) {
3911              $selected = 'selected="selected" ';
3912          }
3913          $structure[] = '<option ' . $selected . 'value="' . esc_attr( $value ) . '">' . esc_html( $display ) . "</option>";
3914  
3915          // Close continent optgroup
3916          if ( !empty( $zone['city'] ) && ( !isset($zonen[$key + 1]) || (isset( $zonen[$key + 1] ) && $zonen[$key + 1]['continent'] !== $zone['continent']) ) ) {
3917              $structure[] = '</optgroup>';
3918          }
3919      }
3920  
3921      // Do UTC
3922      $structure[] = '<optgroup label="'. esc_attr__( 'UTC' ) .'">';
3923      $selected = '';
3924      if ( 'UTC' === $selected_zone )
3925          $selected = 'selected="selected" ';
3926      $structure[] = '<option ' . $selected . 'value="' . esc_attr( 'UTC' ) . '">' . __('UTC') . '</option>';
3927      $structure[] = '</optgroup>';
3928  
3929      // Do manual UTC offsets
3930      $structure[] = '<optgroup label="'. esc_attr__( 'Manual Offsets' ) .'">';
3931      $offset_range = array (-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5,
3932          0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
3933      foreach ( $offset_range as $offset ) {
3934          if ( 0 <= $offset )
3935              $offset_name = '+' . $offset;
3936          else
3937              $offset_name = (string) $offset;
3938  
3939          $offset_value = $offset_name;
3940          $offset_name = str_replace(array('.25','.5','.75'), array(':15',':30',':45'), $offset_name);
3941          $offset_name = 'UTC' . $offset_name;
3942          $offset_value = 'UTC' . $offset_value;
3943          $selected = '';
3944          if ( $offset_value === $selected_zone )
3945              $selected = 'selected="selected" ';
3946          $structure[] = '<option ' . $selected . 'value="' . esc_attr( $offset_value ) . '">' . esc_html( $offset_name ) . "</option>";
3947  
3948      }
3949      $structure[] = '</optgroup>';
3950  
3951      return join( "\n", $structure );
3952  }
3953  
3954  /**
3955   * Strip close comment and close php tags from file headers used by WP
3956   * See http://core.trac.wordpress.org/ticket/8497
3957   *
3958   * @since 2.8.0
3959   *
3960   * @param string $str
3961   * @return string
3962   */
3963  function _cleanup_header_comment($str) {
3964      return trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $str));
3965  }
3966  
3967  /**
3968   * Permanently deletes posts, pages, attachments, and comments which have been in the trash for EMPTY_TRASH_DAYS.
3969   *
3970   * @since 2.9.0
3971   */
3972  function wp_scheduled_delete() {
3973      global $wpdb;
3974  
3975      $delete_timestamp = time() - (60*60*24*EMPTY_TRASH_DAYS);
3976  
3977      $posts_to_delete = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);
3978  
3979      foreach ( (array) $posts_to_delete as $post ) {
3980          $post_id = (int) $post['post_id'];
3981          if ( !$post_id )
3982              continue;
3983  
3984          $del_post = get_post($post_id);
3985  
3986          if ( !$del_post || 'trash' != $del_post->post_status ) {
3987              delete_post_meta($post_id, '_wp_trash_meta_status');
3988              delete_post_meta($post_id, '_wp_trash_meta_time');
3989          } else {
3990              wp_delete_post($post_id);
3991          }
3992      }
3993  
3994      $comments_to_delete = $wpdb->get_results($wpdb->prepare("SELECT comment_id FROM $wpdb->commentmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);
3995  
3996      foreach ( (array) $comments_to_delete as $comment ) {
3997          $comment_id = (int) $comment['comment_id'];
3998          if ( !$comment_id )
3999              continue;
4000  
4001          $del_comment = get_comment($comment_id);
4002  
4003          if ( !$del_comment || 'trash' != $del_comment->comment_approved ) {
4004              delete_comment_meta($comment_id, '_wp_trash_meta_time');
4005              delete_comment_meta($comment_id, '_wp_trash_meta_status');
4006          } else {
4007              wp_delete_comment($comment_id);
4008          }
4009      }
4010  }
4011  
4012  /**
4013   * Parse the file contents to retrieve its metadata.
4014   *
4015   * Searches for metadata for a file, such as a plugin or theme.  Each piece of
4016   * metadata must be on its own line. For a field spanning multple lines, it
4017   * must not have any newlines or only parts of it will be displayed.
4018   *
4019   * Some users have issues with opening large files and manipulating the contents
4020   * for want is usually the first 1kiB or 2kiB. This function stops pulling in
4021   * the file contents when it has all of the required data.
4022   *
4023   * The first 8kiB of the file will be pulled in and if the file data is not
4024   * within that first 8kiB, then the author should correct their plugin file
4025   * and move the data headers to the top.
4026   *
4027   * The file is assumed to have permissions to allow for scripts to read
4028   * the file. This is not checked however and the file is only opened for
4029   * reading.
4030   *
4031   * @since 2.9.0
4032   *
4033   * @param string $file Path to the file
4034   * @param bool $markup If the returned data should have HTML markup applied
4035   * @param string $context If specified adds filter hook "extra_<$context>_headers"
4036   */
4037  function get_file_data( $file, $default_headers, $context = '' ) {
4038      // We don't need to write to the file, so just open for reading.
4039      $fp = fopen( $file, 'r' );
4040  
4041      // Pull only the first 8kiB of the file in.
4042      $file_data = fread( $fp, 8192 );
4043  
4044      // PHP will close file handle, but we are good citizens.
4045      fclose( $fp );
4046  
4047      if ( $context != '' ) {
4048          $extra_headers = apply_filters( "extra_$context".'_headers', array() );
4049  
4050          $extra_headers = array_flip( $extra_headers );
4051          foreach( $extra_headers as $key=>$value ) {
4052              $extra_headers[$key] = $key;
4053          }
4054          $all_headers = array_merge($extra_headers, $default_headers);
4055      } else {
4056          $all_headers = $default_headers;
4057      }
4058  
4059  
4060      foreach ( $all_headers as $field => $regex ) {
4061          preg_match( '/' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, ${$field});
4062          if ( !empty( ${$field} ) )
4063              ${$field} = _cleanup_header_comment( ${$field}[1] );
4064          else
4065              ${$field} = '';
4066      }
4067  
4068      $file_data = compact( array_keys( $all_headers ) );
4069  
4070      return $file_data;
4071  }
4072  /*
4073   * Used internally to tidy up the search terms
4074   *
4075   * @private
4076   * @since 2.9.0
4077   *
4078   * @param string $t
4079   * @return string
4080   */
4081  function _search_terms_tidy($t) {
4082      return trim($t, "\"'\n\r ");
4083  }
4084  
4085  /**
4086   * Returns true
4087   *
4088   * Useful for returning true to filters easily
4089   *
4090   * @see __return_false()
4091   * @return bool true
4092   */
4093  function __return_true() {
4094      return true;
4095  }
4096  
4097  /**
4098   * Returns false
4099   *
4100   * Useful for returning false to filters easily
4101   *
4102   * @see __return_true()
4103   * @return bool false
4104   */
4105  function __return_false() {
4106      return false;
4107  }
4108  
4109  /**
4110   * Send a HTTP header to disable content type sniffing in browsers which support it.
4111   *
4112   * @link http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
4113   * @link http://src.chromium.org/viewvc/chrome?view=rev&revision=6985
4114   *
4115   * @since 3.0.0
4116   * @return none
4117   */
4118  function send_nosniff_header() {
4119      @header( 'X-Content-Type-Options: nosniff' );
4120  }
4121  
4122  ?>


Generated: Mon Apr 5 14:26:09 2010 Cross-referenced by PHPXref 0.7