[ Index ]

PHP Cross Reference of Wordpress 2.7.1

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      global $wp_locale;
  27      $m = $mysqlstring;
  28      if ( empty( $m ) )
  29          return false;
  30  
  31      if( 'G' == $dateformatstring ) {
  32          return gmmktime(
  33              (int) substr( $m, 11, 2 ), (int) substr( $m, 14, 2 ), (int) substr( $m, 17, 2 ),
  34              (int) substr( $m, 5, 2 ), (int) substr( $m, 8, 2 ), (int) substr( $m, 0, 4 )
  35          );
  36      }
  37  
  38      $i = mktime(
  39          (int) substr( $m, 11, 2 ), (int) substr( $m, 14, 2 ), (int) substr( $m, 17, 2 ),
  40          (int) substr( $m, 5, 2 ), (int) substr( $m, 8, 2 ), (int) substr( $m, 0, 4 )
  41      );
  42  
  43      if( 'U' == $dateformatstring )
  44          return $i;
  45  
  46      if ( -1 == $i || false == $i )
  47          $i = 0;
  48  
  49      if ( !empty( $wp_locale->month ) && !empty( $wp_locale->weekday ) && $translate ) {
  50          $datemonth = $wp_locale->get_month( date( 'm', $i ) );
  51          $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
  52          $dateweekday = $wp_locale->get_weekday( date( 'w', $i ) );
  53          $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
  54          $datemeridiem = $wp_locale->get_meridiem( date( 'a', $i ) );
  55          $datemeridiem_capital = $wp_locale->get_meridiem( date( 'A', $i ) );
  56          $dateformatstring = ' ' . $dateformatstring;
  57          $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
  58          $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
  59          $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
  60          $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
  61          $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
  62          $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
  63  
  64          $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
  65      }
  66      $j = @date( $dateformatstring, $i );
  67  
  68      /*
  69      if ( !$j ) // for debug purposes
  70          echo $i." ".$mysqlstring;
  71      */
  72  
  73      return $j;
  74  }
  75  
  76  /**
  77   * Retrieve the current time based on specified type.
  78   *
  79   * The 'mysql' type will return the time in the format for MySQL DATETIME field.
  80   * The 'timestamp' type will return the current timestamp.
  81   *
  82   * If $gmt is set to either '1' or 'true', then both types will use GMT time.
  83   * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
  84   *
  85   * @since 1.0.0
  86   *
  87   * @param string $type Either 'mysql' or 'timestamp'.
  88   * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false.
  89   * @return int|string String if $type is 'gmt', int if $type is 'timestamp'.
  90   */
  91  function current_time( $type, $gmt = 0 ) {
  92      switch ( $type ) {
  93          case 'mysql':
  94              return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * 3600 ) ) );
  95              break;
  96          case 'timestamp':
  97              return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * 3600 );
  98              break;
  99      }
 100  }
 101  
 102  /**
 103   * Retrieve the date in localized format, based on timestamp.
 104   *
 105   * If the locale specifies the locale month and weekday, then the locale will
 106   * take over the format for the date. If it isn't, then the date format string
 107   * will be used instead.
 108   *
 109   * @since 0.71
 110   *
 111   * @param string $dateformatstring Format to display the date
 112   * @param int $unixtimestamp Unix timestamp
 113   * @return string The date, translated if locale specifies it.
 114   */
 115  function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
 116      global $wp_locale;
 117      $i = $unixtimestamp;
 118      // Sanity check for PHP 5.1.0-
 119      if ( false === $i || intval($i) < 0 ) {
 120          if ( ! $gmt )
 121              $i = current_time( 'timestamp' );
 122          else
 123              $i = time();
 124          // we should not let date() interfere with our
 125          // specially computed timestamp
 126          $gmt = true;
 127      }
 128  
 129      $datefunc = $gmt? 'gmdate' : 'date';
 130  
 131      if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
 132          $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
 133          $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
 134          $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
 135          $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
 136          $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
 137          $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
 138          $dateformatstring = ' '.$dateformatstring;
 139          $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
 140          $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
 141          $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
 142          $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
 143          $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
 144          $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
 145  
 146          $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
 147      }
 148      $j = @$datefunc( $dateformatstring, $i );
 149      return $j;
 150  }
 151  
 152  /**
 153   * Convert number to format based on the locale.
 154   *
 155   * @since 2.3.0
 156   *
 157   * @param mixed $number The number to convert based on locale.
 158   * @param int $decimals Precision of the number of decimal places.
 159   * @return string Converted number in string format.
 160   */
 161  function number_format_i18n( $number, $decimals = null ) {
 162      global $wp_locale;
 163      // let the user override the precision only
 164      $decimals = ( is_null( $decimals ) ) ? $wp_locale->number_format['decimals'] : intval( $decimals );
 165  
 166      return number_format( $number, $decimals, $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
 167  }
 168  
 169  /**
 170   * Convert number of bytes largest unit bytes will fit into.
 171   *
 172   * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts
 173   * number of bytes to human readable number by taking the number of that unit
 174   * that the bytes will go into it. Supports TB value.
 175   *
 176   * Please note that integers in PHP are limited to 32 bits, unless they are on
 177   * 64 bit architecture, then they have 64 bit size. If you need to place the
 178   * larger size then what PHP integer type will hold, then use a string. It will
 179   * be converted to a double, which should always have 64 bit length.
 180   *
 181   * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
 182   * @link http://en.wikipedia.org/wiki/Byte
 183   *
 184   * @since 2.3.0
 185   *
 186   * @param int|string $bytes Number of bytes. Note max integer size for integers.
 187   * @param int $decimals Precision of number of decimal places.
 188   * @return bool|string False on failure. Number string on success.
 189   */
 190  function size_format( $bytes, $decimals = null ) {
 191      $quant = array(
 192          // ========================= Origin ====
 193          'TB' => 1099511627776,  // pow( 1024, 4)
 194          'GB' => 1073741824,     // pow( 1024, 3)
 195          'MB' => 1048576,        // pow( 1024, 2)
 196          'kB' => 1024,           // pow( 1024, 1)
 197          'B ' => 1,              // pow( 1024, 0)
 198      );
 199  
 200      foreach ( $quant as $unit => $mag )
 201          if ( doubleval($bytes) >= $mag )
 202              return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
 203  
 204      return false;
 205  }
 206  
 207  /**
 208   * Get the week start and end from the datetime or date string from mysql.
 209   *
 210   * @since 0.71
 211   *
 212   * @param string $mysqlstring Date or datetime field type from mysql.
 213   * @param int $start_of_week Optional. Start of the week as an integer.
 214   * @return array Keys are 'start' and 'end'.
 215   */
 216  function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
 217      $my = substr( $mysqlstring, 0, 4 ); // Mysql string Year
 218      $mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month
 219      $md = substr( $mysqlstring, 5, 2 ); // Mysql string day
 220      $day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day.
 221      $weekday = date( 'w', $day ); // The day of the week from the timestamp
 222      $i = 86400; // One day
 223      if( !is_numeric($start_of_week) )
 224          $start_of_week = get_option( 'start_of_week' );
 225  
 226      if ( $weekday < $start_of_week )
 227          $weekday = 7 - $start_of_week - $weekday;
 228  
 229      while ( $weekday > $start_of_week ) {
 230          $weekday = date( 'w', $day );
 231          if ( $weekday < $start_of_week )
 232              $weekday = 7 - $start_of_week - $weekday;
 233  
 234          $day -= 86400;
 235          $i = 0;
 236      }
 237      $week['start'] = $day + 86400 - $i;
 238      $week['end'] = $week['start'] + 604799;
 239      return $week;
 240  }
 241  
 242  /**
 243   * Unserialize value only if it was serialized.
 244   *
 245   * @since 2.0.0
 246   *
 247   * @param string $original Maybe unserialized original, if is needed.
 248   * @return mixed Unserialized data can be any type.
 249   */
 250  function maybe_unserialize( $original ) {
 251      if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
 252          if ( false !== $gm = @unserialize( $original ) )
 253              return $gm;
 254      return $original;
 255  }
 256  
 257  /**
 258   * Check value to find if it was serialized.
 259   *
 260   * If $data is not an string, then returned value will always be false.
 261   * Serialized data is always a string.
 262   *
 263   * @since 2.0.5
 264   *
 265   * @param mixed $data Value to check to see if was serialized.
 266   * @return bool False if not serialized and true if it was.
 267   */
 268  function is_serialized( $data ) {
 269      // if it isn't a string, it isn't serialized
 270      if ( !is_string( $data ) )
 271          return false;
 272      $data = trim( $data );
 273      if ( 'N;' == $data )
 274          return true;
 275      if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
 276          return false;
 277      switch ( $badions[1] ) {
 278          case 'a' :
 279          case 'O' :
 280          case 's' :
 281              if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
 282                  return true;
 283              break;
 284          case 'b' :
 285          case 'i' :
 286          case 'd' :
 287              if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
 288                  return true;
 289              break;
 290      }
 291      return false;
 292  }
 293  
 294  /**
 295   * Check whether serialized data is of string type.
 296   *
 297   * @since 2.0.5
 298   *
 299   * @param mixed $data Serialized data
 300   * @return bool False if not a serialized string, true if it is.
 301   */
 302  function is_serialized_string( $data ) {
 303      // if it isn't a string, it isn't a serialized string
 304      if ( !is_string( $data ) )
 305          return false;
 306      $data = trim( $data );
 307      if ( preg_match( '/^s:[0-9]+:.*;$/s', $data ) ) // this should fetch all serialized strings
 308          return true;
 309      return false;
 310  }
 311  
 312  /**
 313   * Retrieve option value based on setting name.
 314   *
 315   * If the option does not exist or does not have a value, then the return value
 316   * will be false. This is useful to check whether you need to install an option
 317   * and is commonly used during installation of plugin options and to test
 318   * whether upgrading is required.
 319   *
 320   * You can "short-circuit" the retrieval of the option from the database for
 321   * your plugin or core options that aren't protected. You can do so by hooking
 322   * into the 'pre_option_$option' with the $option being replaced by the option
 323   * name. You should not try to override special options, but you will not be
 324   * prevented from doing so.
 325   *
 326   * There is a second filter called 'option_$option' with the $option being
 327   * replaced with the option name. This gives the value as the only parameter.
 328   *
 329   * If the option was serialized, when the option was added and, or updated, then
 330   * it will be unserialized, when it is returned.
 331   *
 332   * @since 1.5.0
 333   * @package WordPress
 334   * @subpackage Option
 335   * @uses apply_filters() Calls 'pre_option_$optionname' false to allow
 336   *        overwriting the option value in a plugin.
 337   * @uses apply_filters() Calls 'option_$optionname' with the option name value.
 338   *
 339   * @param string $setting Name of option to retrieve. Should already be SQL-escaped
 340   * @return mixed Value set for the option.
 341   */
 342  function get_option( $setting, $default = false ) {
 343      global $wpdb;
 344  
 345      // Allow plugins to short-circuit options.
 346      $pre = apply_filters( 'pre_option_' . $setting, false );
 347      if ( false !== $pre )
 348          return $pre;
 349  
 350      // prevent non-existent options from triggering multiple queries
 351      $notoptions = wp_cache_get( 'notoptions', 'options' );
 352      if ( isset( $notoptions[$setting] ) )
 353          return $default;
 354  
 355      $alloptions = wp_load_alloptions();
 356  
 357      if ( isset( $alloptions[$setting] ) ) {
 358          $value = $alloptions[$setting];
 359      } else {
 360          $value = wp_cache_get( $setting, 'options' );
 361  
 362          if ( false === $value ) {
 363              if ( defined( 'WP_INSTALLING' ) )
 364                  $suppress = $wpdb->suppress_errors();
 365              // expected_slashed ($setting)
 366              $row = $wpdb->get_row( "SELECT option_value FROM $wpdb->options WHERE option_name = '$setting' LIMIT 1" );
 367              if ( defined( 'WP_INSTALLING' ) )
 368                  $wpdb->suppress_errors($suppress);
 369  
 370              if ( is_object( $row) ) { // Has to be get_row instead of get_var because of funkiness with 0, false, null values
 371                  $value = $row->option_value;
 372                  wp_cache_add( $setting, $value, 'options' );
 373              } else { // option does not exist, so we must cache its non-existence
 374                  $notoptions[$setting] = true;
 375                  wp_cache_set( 'notoptions', $notoptions, 'options' );
 376                  return $default;
 377              }
 378          }
 379      }
 380  
 381      // If home is not set use siteurl.
 382      if ( 'home' == $setting && '' == $value )
 383          return get_option( 'siteurl' );
 384  
 385      if ( in_array( $setting, array('siteurl', 'home', 'category_base', 'tag_base') ) )
 386          $value = untrailingslashit( $value );
 387  
 388      return apply_filters( 'option_' . $setting, maybe_unserialize( $value ) );
 389  }
 390  
 391  /**
 392   * Protect WordPress special option from being modified.
 393   *
 394   * Will die if $option is in protected list. Protected options are 'alloptions'
 395   * and 'notoptions' options.
 396   *
 397   * @since 2.2.0
 398   * @package WordPress
 399   * @subpackage Option
 400   *
 401   * @param string $option Option name.
 402   */
 403  function wp_protect_special_option( $option ) {
 404      $protected = array( 'alloptions', 'notoptions' );
 405      if ( in_array( $option, $protected ) )
 406          die( sprintf( __( '%s is a protected WP option and may not be modified' ), wp_specialchars( $option ) ) );
 407  }
 408  
 409  /**
 410   * Print option value after sanitizing for forms.
 411   *
 412   * @uses attribute_escape Sanitizes value.
 413   * @since 1.5.0
 414   * @package WordPress
 415   * @subpackage Option
 416   *
 417   * @param string $option Option name.
 418   */
 419  function form_option( $option ) {
 420      echo attribute_escape (get_option( $option ) );
 421  }
 422  
 423  /**
 424   * Retrieve all autoload options or all options, if no autoloaded ones exist.
 425   *
 426   * This is different from wp_load_alloptions() in that this function does not
 427   * cache its results and will retrieve all options from the database every time
 428   *
 429   * it is called.
 430   *
 431   * @since 1.0.0
 432   * @package WordPress
 433   * @subpackage Option
 434   * @uses apply_filters() Calls 'pre_option_$optionname' hook with option value as parameter.
 435   * @uses apply_filters() Calls 'all_options' on options list.
 436   *
 437   * @return array List of all options.
 438   */
 439  function get_alloptions() {
 440      global $wpdb;
 441      $show = $wpdb->hide_errors();
 442      if ( !$options = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) )
 443          $options = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
 444      $wpdb->show_errors($show);
 445  
 446      foreach ( (array) $options as $option ) {
 447          // "When trying to design a foolproof system,
 448          //  never underestimate the ingenuity of the fools :)" -- Dougal
 449          if ( in_array( $option->option_name, array( 'siteurl', 'home', 'category_base', 'tag_base' ) ) )
 450              $option->option_value = untrailingslashit( $option->option_value );
 451          $value = maybe_unserialize( $option->option_value );
 452          $all_options->{$option->option_name} = apply_filters( 'pre_option_' . $option->option_name, $value );
 453      }
 454      return apply_filters( 'all_options', $all_options );
 455  }
 456  
 457  /**
 458   * Loads and caches all autoloaded options, if available or all options.
 459   *
 460   * This is different from get_alloptions(), in that this function will cache the
 461   * options and will return the cached options when called again.
 462   *
 463   * @since 2.2.0
 464   * @package WordPress
 465   * @subpackage Option
 466   *
 467   * @return array List all options.
 468   */
 469  function wp_load_alloptions() {
 470      global $wpdb;
 471  
 472      $alloptions = wp_cache_get( 'alloptions', 'options' );
 473  
 474      if ( !$alloptions ) {
 475          $suppress = $wpdb->suppress_errors();
 476          if ( !$alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'" ) )
 477              $alloptions_db = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
 478          $wpdb->suppress_errors($suppress);
 479          $alloptions = array();
 480          foreach ( (array) $alloptions_db as $o )
 481              $alloptions[$o->option_name] = $o->option_value;
 482          wp_cache_add( 'alloptions', $alloptions, 'options' );
 483      }
 484      return $alloptions;
 485  }
 486  
 487  /**
 488   * Update the value of an option that was already added.
 489   *
 490   * You do not need to serialize values, if the value needs to be serialize, then
 491   * it will be serialized before it is inserted into the database. Remember,
 492   * resources can not be serialized or added as an option.
 493   *
 494   * If the option does not exist, then the option will be added with the option
 495   * value, but you will not be able to set whether it is autoloaded. If you want
 496   * to set whether an option autoloaded, then you need to use the add_option().
 497   *
 498   * When the option is updated, then the filter named
 499   * 'update_option_$option_name', with the $option_name as the $option_name
 500   * parameter value, will be called. The hook should accept two parameters, the
 501   * first is the old parameter and the second is the new parameter.
 502   *
 503   * @since 1.0.0
 504   * @package WordPress
 505   * @subpackage Option
 506   *
 507   * @param string $option_name Option name. Expected to not be SQL-escaped
 508   * @param mixed $newvalue Option value.
 509   * @return bool False if value was not updated and true if value was updated.
 510   */
 511  function update_option( $option_name, $newvalue ) {
 512      global $wpdb;
 513  
 514      wp_protect_special_option( $option_name );
 515  
 516      $safe_option_name = $wpdb->escape( $option_name );
 517      $newvalue = sanitize_option( $option_name, $newvalue );
 518  
 519      $oldvalue = get_option( $safe_option_name );
 520  
 521      $newvalue = apply_filters( 'pre_update_option_' . $option_name, $newvalue, $oldvalue );
 522  
 523      // If the new and old values are the same, no need to update.
 524      if ( $newvalue === $oldvalue )
 525          return false;
 526  
 527      if ( false === $oldvalue ) {
 528          add_option( $option_name, $newvalue );
 529          return true;
 530      }
 531  
 532      $notoptions = wp_cache_get( 'notoptions', 'options' );
 533      if ( is_array( $notoptions ) && isset( $notoptions[$option_name] ) ) {
 534          unset( $notoptions[$option_name] );
 535          wp_cache_set( 'notoptions', $notoptions, 'options' );
 536      }
 537  
 538      $_newvalue = $newvalue;
 539      $newvalue = maybe_serialize( $newvalue );
 540  
 541      $alloptions = wp_load_alloptions();
 542      if ( isset( $alloptions[$option_name] ) ) {
 543          $alloptions[$option_name] = $newvalue;
 544          wp_cache_set( 'alloptions', $alloptions, 'options' );
 545      } else {
 546          wp_cache_set( $option_name, $newvalue, 'options' );
 547      }
 548  
 549      $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->options SET option_value = %s WHERE option_name = %s", $newvalue, $option_name ) );
 550      if ( $wpdb->rows_affected == 1 ) {
 551          do_action( "update_option_{$option_name}", $oldvalue, $_newvalue );
 552          return true;
 553      }
 554      return false;
 555  }
 556  
 557  /**
 558   * Add a new option.
 559   *
 560   * You do not need to serialize values, if the value needs to be serialize, then
 561   * it will be serialized before it is inserted into the database. Remember,
 562   * resources can not be serialized or added as an option.
 563   *
 564   * You can create options without values and then add values later. Does not
 565   * check whether the option has already been added, but does check that you
 566   * aren't adding a protected WordPress option. Care should be taken to not name
 567   * options, the same as the ones which are protected and to not add options
 568   * that were already added.
 569   *
 570   * The filter named 'add_option_$optionname', with the $optionname being
 571   * replaced with the option's name, will be called. The hook should accept two
 572   * parameters, the first is the option name, and the second is the value.
 573   *
 574   * @package WordPress
 575   * @subpackage Option
 576   * @since 1.0.0
 577   * @link http://alex.vort-x.net/blog/ Thanks Alex Stapleton
 578   *
 579   * @param string $name Option name to add. Expects to NOT be SQL escaped.
 580   * @param mixed $value Optional. Option value, can be anything.
 581   * @param mixed $deprecated Optional. Description. Not used anymore.
 582   * @param bool $autoload Optional. Default is enabled. Whether to load the option when WordPress starts up.
 583   * @return null returns when finished.
 584   */
 585  function add_option( $name, $value = '', $deprecated = '', $autoload = 'yes' ) {
 586      global $wpdb;
 587  
 588      wp_protect_special_option( $name );
 589      $safe_name = $wpdb->escape( $name );
 590      $value = sanitize_option( $name, $value );
 591  
 592      // Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
 593      $notoptions = wp_cache_get( 'notoptions', 'options' );
 594      if ( !is_array( $notoptions ) || !isset( $notoptions[$name] ) )
 595          if ( false !== get_option( $safe_name ) )
 596              return;
 597  
 598      $value = maybe_serialize( $value );
 599      $autoload = ( 'no' === $autoload ) ? 'no' : 'yes';
 600  
 601      if ( 'yes' == $autoload ) {
 602          $alloptions = wp_load_alloptions();
 603          $alloptions[$name] = $value;
 604          wp_cache_set( 'alloptions', $alloptions, 'options' );
 605      } else {
 606          wp_cache_set( $name, $value, 'options' );
 607      }
 608  
 609      // This option exists now
 610      $notoptions = wp_cache_get( 'notoptions', 'options' ); // yes, again... we need it to be fresh
 611      if ( is_array( $notoptions ) && isset( $notoptions[$name] ) ) {
 612          unset( $notoptions[$name] );
 613          wp_cache_set( 'notoptions', $notoptions, 'options' );
 614      }
 615  
 616      $wpdb->query( $wpdb->prepare( "INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES (%s, %s, %s)", $name, $value, $autoload ) );
 617  
 618      do_action( "add_option_{$name}", $name, $value );
 619      return;
 620  }
 621  
 622  /**
 623   * Removes option by name and prevents removal of protected WordPress options.
 624   *
 625   * @package WordPress
 626   * @subpackage Option
 627   * @since 1.2.0
 628   *
 629   * @param string $name Option name to remove.
 630   * @return bool True, if succeed. False, if failure.
 631   */
 632  function delete_option( $name ) {
 633      global $wpdb;
 634  
 635      wp_protect_special_option( $name );
 636  
 637      // Get the ID, if no ID then return
 638      // expected_slashed ($name)
 639      $option = $wpdb->get_row( "SELECT option_id, autoload FROM $wpdb->options WHERE option_name = '$name'" );
 640      if ( is_null($option) || !$option->option_id )
 641          return false;
 642      // expected_slashed ($name)
 643      $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name = '$name'" );
 644      if ( 'yes' == $option->autoload ) {
 645          $alloptions = wp_load_alloptions();
 646          if ( isset( $alloptions[$name] ) ) {
 647              unset( $alloptions[$name] );
 648              wp_cache_set( 'alloptions', $alloptions, 'options' );
 649          }
 650      } else {
 651          wp_cache_delete( $name, 'options' );
 652      }
 653      return true;
 654  }
 655  
 656  /**
 657   * Saves and restores user interface settings stored in a cookie.
 658   *
 659   * Checks if the current user-settings cookie is updated and stores it. When no
 660   * cookie exists (different browser used), adds the last saved cookie restoring
 661   * the settings.
 662   *
 663   * @package WordPress
 664   * @subpackage Option
 665   * @since 2.7.0
 666   */
 667  function wp_user_settings() {
 668  
 669      if ( ! is_admin() )
 670          return;
 671  
 672      if ( defined('DOING_AJAX') )
 673          return;
 674  
 675      if ( ! $user = wp_get_current_user() )
 676          return;
 677  
 678      $settings = get_user_option( 'user-settings', $user->ID, false );
 679  
 680      if ( isset( $_COOKIE['wp-settings-' . $user->ID] ) ) {
 681          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-' . $user->ID] );
 682  
 683          if ( ! empty( $cookie ) && strpos( $cookie, '=' ) ) {
 684              if ( $cookie == $settings )
 685                  return;
 686  
 687              $last_time = (int) get_user_option( 'user-settings-time', $user->ID, false );
 688              $saved = isset( $_COOKIE['wp-settings-time-' . $user->ID]) ? preg_replace( '/[^0-9]/', '', $_COOKIE['wp-settings-time-' . $user->ID] ) : 0;
 689  
 690              if ( $saved > $last_time ) {
 691                  update_user_option( $user->ID, 'user-settings', $cookie, false );
 692                  update_user_option( $user->ID, 'user-settings-time', time() - 5, false );
 693                  return;
 694              }
 695          }
 696      }
 697  
 698      setcookie( 'wp-settings-' . $user->ID, $settings, time() + 31536000, SITECOOKIEPATH );
 699      setcookie( 'wp-settings-time-' . $user->ID, time(), time() + 31536000, SITECOOKIEPATH );
 700  }
 701  
 702  /**
 703   * Retrieve user interface setting value based on setting name.
 704   *
 705   * @package WordPress
 706   * @subpackage Option
 707   * @since 2.7.0
 708   *
 709   * @param string $name The name of the setting.
 710   * @param string $default Optional default value to return when $name is not set.
 711   * @return mixed the last saved user setting or the default value/false if it doesn't exist.
 712   */
 713  function get_user_setting( $name, $default = false ) {
 714  
 715      $arr = get_all_user_settings();
 716  
 717      return isset($arr[$name]) ? $arr[$name] : $default;
 718  }
 719  
 720  /**
 721   * Delete user interface settings.
 722   *
 723   * Deleting settings would reset them to the defaults.
 724   *
 725   * @package WordPress
 726   * @subpackage Option
 727   * @since 2.7.0
 728   *
 729   * @param mixed $names The name or array of names of the setting to be deleted.
 730   */
 731  function delete_user_setting( $names ) {
 732      global $current_user;
 733  
 734      $arr = get_all_user_settings();
 735      $names = (array) $names;
 736  
 737      foreach ( $names as $name ) {
 738          if ( isset($arr[$name]) ) {
 739              unset($arr[$name]);
 740              $settings = '';
 741          }
 742      }
 743  
 744      if ( isset($settings) ) {
 745          foreach ( $arr as $k => $v )
 746              $settings .= $k . '=' . $v . '&';
 747  
 748          $settings = rtrim($settings, '&');
 749  
 750          update_user_option( $current_user->ID, 'user-settings', $settings );
 751          setcookie('wp-settings-'.$current_user->ID, $settings, time() + 31536000, SITECOOKIEPATH);
 752      }
 753  }
 754  
 755  /**
 756   * Retrieve all user interface settings.
 757   *
 758   * @package WordPress
 759   * @subpackage Option
 760   * @since 2.7.0
 761   *
 762   * @return array the last saved user settings or empty array.
 763   */
 764  function get_all_user_settings() {
 765      if ( ! $user = wp_get_current_user() )
 766          return array();
 767  
 768      if ( isset($_COOKIE['wp-settings-'.$user->ID]) ) {
 769          $cookie = preg_replace( '/[^A-Za-z0-9=&_]/', '', $_COOKIE['wp-settings-'.$user->ID] );
 770  
 771          if ( $cookie && strpos($cookie, '=') ) { // the '=' cannot be 1st char
 772              parse_str($cookie, $arr);
 773              return $arr;
 774          }
 775      }
 776  
 777      return array();
 778  }
 779  
 780  /**
 781   * Delete the user settings of the current user.
 782   *
 783   * @package WordPress
 784   * @subpackage Option
 785   * @since 2.7.0
 786   */
 787  function delete_all_user_settings() {
 788      if ( ! $user = wp_get_current_user() )
 789          return;
 790  
 791      delete_usermeta( $user->ID, 'user-settings' );
 792      setcookie('wp-settings-'.$user->ID, ' ', time() - 31536000, SITECOOKIEPATH);
 793  }
 794  
 795  /**
 796   * Serialize data, if needed.
 797   *
 798   * @since 2.0.5
 799   *
 800   * @param mixed $data Data that might be serialized.
 801   * @return mixed A scalar data
 802   */
 803  function maybe_serialize( $data ) {
 804      if ( is_array( $data ) || is_object( $data ) )
 805          return serialize( $data );
 806  
 807      if ( is_serialized( $data ) )
 808          return serialize( $data );
 809  
 810      return $data;
 811  }
 812  
 813  /**
 814   * Strip HTML and put links at the bottom of stripped content.
 815   *
 816   * Searches for all of the links, strips them out of the content, and places
 817   * them at the bottom of the content with numbers.
 818   *
 819   * @since 0.71
 820   *
 821   * @param string $content Content to get links
 822   * @return string HTML stripped out of content with links at the bottom.
 823   */
 824  function make_url_footnote( $content ) {
 825      preg_match_all( '/<a(.+?)href=\"(.+?)\"(.*?)>(.+?)<\/a>/', $content, $matches );
 826      $links_summary = "\n";
 827      for ( $i=0; $i<count($matches[0]); $i++ ) {
 828          $link_match = $matches[0][$i];
 829          $link_number = '['.($i+1).']';
 830          $link_url = $matches[2][$i];
 831          $link_text = $matches[4][$i];
 832          $content = str_replace( $link_match, $link_text . ' ' . $link_number, $content );
 833          $link_url = ( ( strtolower( substr( $link_url, 0, 7 ) ) != 'http://' ) && ( strtolower( substr( $link_url, 0, 8 ) ) != 'https://' ) ) ? get_option( 'home' ) . $link_url : $link_url;
 834          $links_summary .= "\n" . $link_number . ' ' . $link_url;
 835      }
 836      $content  = strip_tags( $content );
 837      $content .= $links_summary;
 838      return $content;
 839  }
 840  
 841  /**
 842   * Retrieve post title from XMLRPC XML.
 843   *
 844   * If the title element is not part of the XML, then the default post title from
 845   * the $post_default_title will be used instead.
 846   *
 847   * @package WordPress
 848   * @subpackage XMLRPC
 849   * @since 0.71
 850   *
 851   * @global string $post_default_title Default XMLRPC post title.
 852   *
 853   * @param string $content XMLRPC XML Request content
 854   * @return string Post title
 855   */
 856  function xmlrpc_getposttitle( $content ) {
 857      global $post_default_title;
 858      if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
 859          $post_title = $matchtitle[0];
 860          $post_title = preg_replace( '/<title>/si', '', $post_title );
 861          $post_title = preg_replace( '/<\/title>/si', '', $post_title );
 862      } else {
 863          $post_title = $post_default_title;
 864      }
 865      return $post_title;
 866  }
 867  
 868  /**
 869   * Retrieve the post category or categories from XMLRPC XML.
 870   *
 871   * If the category element is not found, then the default post category will be
 872   * used. The return type then would be what $post_default_category. If the
 873   * category is found, then it will always be an array.
 874   *
 875   * @package WordPress
 876   * @subpackage XMLRPC
 877   * @since 0.71
 878   *
 879   * @global string $post_default_category Default XMLRPC post category.
 880   *
 881   * @param string $content XMLRPC XML Request content
 882   * @return string|array List of categories or category name.
 883   */
 884  function xmlrpc_getpostcategory( $content ) {
 885      global $post_default_category;
 886      if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
 887          $post_category = trim( $matchcat[1], ',' );
 888          $post_category = explode( ',', $post_category );
 889      } else {
 890          $post_category = $post_default_category;
 891      }
 892      return $post_category;
 893  }
 894  
 895  /**
 896   * XMLRPC XML content without title and category elements.
 897   *
 898   * @package WordPress
 899   * @subpackage XMLRPC
 900   * @since 0.71
 901   *
 902   * @param string $content XMLRPC XML Request content
 903   * @return string XMLRPC XML Request content without title and category elements.
 904   */
 905  function xmlrpc_removepostdata( $content ) {
 906      $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
 907      $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
 908      $content = trim( $content );
 909      return $content;
 910  }
 911  
 912  /**
 913   * Open the file handle for debugging.
 914   *
 915   * This function is used for XMLRPC feature, but it is general purpose enough
 916   * to be used in anywhere.
 917   *
 918   * @see fopen() for mode options.
 919   * @package WordPress
 920   * @subpackage Debug
 921   * @since 0.71
 922   * @uses $debug Used for whether debugging is enabled.
 923   *
 924   * @param string $filename File path to debug file.
 925   * @param string $mode Same as fopen() mode parameter.
 926   * @return bool|resource File handle. False on failure.
 927   */
 928  function debug_fopen( $filename, $mode ) {
 929      global $debug;
 930      if ( 1 == $debug ) {
 931          $fp = fopen( $filename, $mode );
 932          return $fp;
 933      } else {
 934          return false;
 935      }
 936  }
 937  
 938  /**
 939   * Write contents to the file used for debugging.
 940   *
 941   * Technically, this can be used to write to any file handle when the global
 942   * $debug is set to 1 or true.
 943   *
 944   * @package WordPress
 945   * @subpackage Debug
 946   * @since 0.71
 947   * @uses $debug Used for whether debugging is enabled.
 948   *
 949   * @param resource $fp File handle for debugging file.
 950   * @param string $string Content to write to debug file.
 951   */
 952  function debug_fwrite( $fp, $string ) {
 953      global $debug;
 954      if ( 1 == $debug )
 955          fwrite( $fp, $string );
 956  }
 957  
 958  /**
 959   * Close the debugging file handle.
 960   *
 961   * Technically, this can be used to close any file handle when the global $debug
 962   * is set to 1 or true.
 963   *
 964   * @package WordPress
 965   * @subpackage Debug
 966   * @since 0.71
 967   * @uses $debug Used for whether debugging is enabled.
 968   *
 969   * @param resource $fp Debug File handle.
 970   */
 971  function debug_fclose( $fp ) {
 972      global $debug;
 973      if ( 1 == $debug )
 974          fclose( $fp );
 975  }
 976  
 977  /**
 978   * Check content for video and audio links to add as enclosures.
 979   *
 980   * Will not add enclosures that have already been added. This is called as
 981   * pingbacks and trackbacks.
 982   *
 983   * @package WordPress
 984   * @since 1.5.0
 985   *
 986   * @uses $wpdb
 987   *
 988   * @param string $content Post Content
 989   * @param int $post_ID Post ID
 990   */
 991  function do_enclose( $content, $post_ID ) {
 992      global $wpdb;
 993      include_once ( ABSPATH . WPINC . '/class-IXR.php' );
 994  
 995      $log = debug_fopen( ABSPATH . 'enclosures.log', 'a' );
 996      $post_links = array();
 997      debug_fwrite( $log, 'BEGIN ' . date( 'YmdHis', time() ) . "\n" );
 998  
 999      $pung = get_enclosed( $post_ID );
1000  
1001      $ltrs = '\w';
1002      $gunk = '/#~:.?+=&%@!\-';
1003      $punc = '.:?\-';
1004      $any = $ltrs . $gunk . $punc;
1005  
1006      preg_match_all( "{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp );
1007  
1008      debug_fwrite( $log, 'Post contents:' );
1009      debug_fwrite( $log, $content . "\n" );
1010  
1011      foreach ( (array) $post_links_temp[0] as $link_test ) {
1012          if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
1013              $test = parse_url( $link_test );
1014              if ( isset( $test['query'] ) )
1015                  $post_links[] = $link_test;
1016              elseif ( $test['path'] != '/' && $test['path'] != '' )
1017                  $post_links[] = $link_test;
1018          }
1019      }
1020  
1021      foreach ( (array) $post_links as $url ) {
1022          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 . '%' ) ) ) {
1023              if ( $headers = wp_get_http_headers( $url) ) {
1024                  $len = (int) $headers['content-length'];
1025                  $type = $wpdb->escape( $headers['content-type'] );
1026                  $allowed_types = array( 'video', 'audio' );
1027                  if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
1028                      $meta_value = "$url\n$len\n$type\n";
1029                      $wpdb->query( $wpdb->prepare( "INSERT INTO `$wpdb->postmeta` ( `post_id` , `meta_key` , `meta_value` )
1030                      VALUES ( %d, 'enclosure' , %s)", $post_ID, $meta_value ) );
1031                  }
1032              }
1033          }
1034      }
1035  }
1036  
1037  /**
1038   * Perform a HTTP HEAD or GET request.
1039   *
1040   * If $file_path is a writable filename, this will do a GET request and write
1041   * the file to that path.
1042   *
1043   * @since 2.5.0
1044   *
1045   * @param string $url URL to fetch.
1046   * @param string|bool $file_path Optional. File path to write request to.
1047   * @param bool $deprecated Deprecated. Not used.
1048   * @return bool|string False on failure and string of headers if HEAD request.
1049   */
1050  function wp_get_http( $url, $file_path = false, $deprecated = false ) {
1051      @set_time_limit( 60 );
1052  
1053      $options = array();
1054      $options['redirection'] = 5;
1055  
1056      if ( false == $file_path )
1057          $options['method'] = 'HEAD';
1058      else
1059          $options['method'] = 'GET';
1060  
1061      $response = wp_remote_request($url, $options);
1062  
1063      if ( is_wp_error( $response ) )
1064          return false;
1065  
1066      $headers = wp_remote_retrieve_headers( $response );
1067      $headers['response'] = $response['response']['code'];
1068  
1069      if ( false == $file_path )
1070          return $headers;
1071  
1072      // GET request - write it to the supplied filename
1073      $out_fp = fopen($file_path, 'w');
1074      if ( !$out_fp )
1075          return $headers;
1076  
1077      fwrite( $out_fp,  $response['body']);
1078      fclose($out_fp);
1079  
1080      return $headers;
1081  }
1082  
1083  /**
1084   * Retrieve HTTP Headers from URL.
1085   *
1086   * @since 1.5.1
1087   *
1088   * @param string $url
1089   * @param bool $deprecated Not Used.
1090   * @return bool|string False on failure, headers on success.
1091   */
1092  function wp_get_http_headers( $url, $deprecated = false ) {
1093      $response = wp_remote_head( $url );
1094  
1095      if ( is_wp_error( $response ) )
1096          return false;
1097  
1098      return wp_remote_retrieve_headers( $response );
1099  }
1100  
1101  /**
1102   * Whether today is a new day.
1103   *
1104   * @since 0.71
1105   * @uses $day Today
1106   * @uses $previousday Previous day
1107   *
1108   * @return int 1 when new day, 0 if not a new day.
1109   */
1110  function is_new_day() {
1111      global $day, $previousday;
1112      if ( $day != $previousday )
1113          return 1;
1114      else
1115          return 0;
1116  }
1117  
1118  /**
1119   * Build URL query based on an associative and, or indexed array.
1120   *
1121   * This is a convenient function for easily building url queries. It sets the
1122   * separator to '&' and uses _http_build_query() function.
1123   *
1124   * @see _http_build_query() Used to build the query
1125   * @link http://us2.php.net/manual/en/function.http-build-query.php more on what
1126   *        http_build_query() does.
1127   *
1128   * @since 2.3.0
1129   *
1130   * @param array $data URL-encode key/value pairs.
1131   * @return string URL encoded string
1132   */
1133  function build_query( $data ) {
1134      return _http_build_query( $data, null, '&', '', false );
1135  }
1136  
1137  /**
1138   * Retrieve a modified URL query string.
1139   *
1140   * You can rebuild the URL and append a new query variable to the URL query by
1141   * using this function. You can also retrieve the full URL with query data.
1142   *
1143   * Adding a single key & value or an associative array. Setting a key value to
1144   * emptystring removes the key. Omitting oldquery_or_uri uses the $_SERVER
1145   * value.
1146   *
1147   * @since 1.5.0
1148   *
1149   * @param mixed $param1 Either newkey or an associative_array
1150   * @param mixed $param2 Either newvalue or oldquery or uri
1151   * @param mixed $param3 Optional. Old query or uri
1152   * @return string New URL query string.
1153   */
1154  function add_query_arg() {
1155      $ret = '';
1156      if ( is_array( func_get_arg(0) ) ) {
1157          if ( @func_num_args() < 2 || false === @func_get_arg( 1 ) )
1158              $uri = $_SERVER['REQUEST_URI'];
1159          else
1160              $uri = @func_get_arg( 1 );
1161      } else {
1162          if ( @func_num_args() < 3 || false === @func_get_arg( 2 ) )
1163              $uri = $_SERVER['REQUEST_URI'];
1164          else
1165              $uri = @func_get_arg( 2 );
1166      }
1167  
1168      if ( $frag = strstr( $uri, '#' ) )
1169          $uri = substr( $uri, 0, -strlen( $frag ) );
1170      else
1171          $frag = '';
1172  
1173      if ( preg_match( '|^https?://|i', $uri, $matches ) ) {
1174          $protocol = $matches[0];
1175          $uri = substr( $uri, strlen( $protocol ) );
1176      } else {
1177          $protocol = '';
1178      }
1179  
1180      if ( strpos( $uri, '?' ) !== false ) {
1181          $parts = explode( '?', $uri, 2 );
1182          if ( 1 == count( $parts ) ) {
1183              $base = '?';
1184              $query = $parts[0];
1185          } else {
1186              $base = $parts[0] . '?';
1187              $query = $parts[1];
1188          }
1189      } elseif ( !empty( $protocol ) || strpos( $uri, '=' ) === false ) {
1190          $base = $uri . '?';
1191          $query = '';
1192      } else {
1193          $base = '';
1194          $query = $uri;
1195      }
1196  
1197      wp_parse_str( $query, $qs );
1198      $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
1199      if ( is_array( func_get_arg( 0 ) ) ) {
1200          $kayvees = func_get_arg( 0 );
1201          $qs = array_merge( $qs, $kayvees );
1202      } else {
1203          $qs[func_get_arg( 0 )] = func_get_arg( 1 );
1204      }
1205  
1206      foreach ( (array) $qs as $k => $v ) {
1207          if ( $v === false )
1208              unset( $qs[$k] );
1209      }
1210  
1211      $ret = build_query( $qs );
1212      $ret = trim( $ret, '?' );
1213      $ret = preg_replace( '#=(&|$)#', '$1', $ret );
1214      $ret = $protocol . $base . $ret . $frag;
1215      $ret = rtrim( $ret, '?' );
1216      return $ret;
1217  }
1218  
1219  /**
1220   * Removes an item or list from the query string.
1221   *
1222   * @since 1.5.0
1223   *
1224   * @param string|array $key Query key or keys to remove.
1225   * @param bool $query When false uses the $_SERVER value.
1226   * @return string New URL query string.
1227   */
1228  function remove_query_arg( $key, $query=false ) {
1229      if ( is_array( $key ) ) { // removing multiple keys
1230          foreach ( $key as $k )
1231              $query = add_query_arg( $k, false, $query );
1232          return $query;
1233      }
1234      return add_query_arg( $key, false, $query );
1235  }
1236  
1237  /**
1238   * Walks the array while sanitizing the contents.
1239   *
1240   * @uses $wpdb Used to sanitize values
1241   * @since 0.71
1242   *
1243   * @param array $array Array to used to walk while sanitizing contents.
1244   * @return array Sanitized $array.
1245   */
1246  function add_magic_quotes( $array ) {
1247      global $wpdb;
1248  
1249      foreach ( (array) $array as $k => $v ) {
1250          if ( is_array( $v ) ) {
1251              $array[$k] = add_magic_quotes( $v );
1252          } else {
1253              $array[$k] = $wpdb->escape( $v );
1254          }
1255      }
1256      return $array;
1257  }
1258  
1259  /**
1260   * HTTP request for URI to retrieve content.
1261   *
1262   * @since 1.5.1
1263   * @uses wp_remote_get()
1264   *
1265   * @param string $uri URI/URL of web page to retrieve.
1266   * @return bool|string HTTP content. False on failure.
1267   */
1268  function wp_remote_fopen( $uri ) {
1269      $parsed_url = @parse_url( $uri );
1270  
1271      if ( !$parsed_url || !is_array( $parsed_url ) )
1272          return false;
1273  
1274      $options = array();
1275      $options['timeout'] = 10;
1276  
1277      $response = wp_remote_get( $uri, $options );
1278  
1279      if ( is_wp_error( $response ) )
1280          return false;
1281  
1282      return $response['body'];
1283  }
1284  
1285  /**
1286   * Setup the WordPress query.
1287   *
1288   * @since 2.0.0
1289   *
1290   * @param string $query_vars Default WP_Query arguments.
1291   */
1292  function wp( $query_vars = '' ) {
1293      global $wp, $wp_query, $wp_the_query;
1294      $wp->main( $query_vars );
1295  
1296      if( !isset($wp_the_query) )
1297          $wp_the_query = $wp_query;
1298  }
1299  
1300  /**
1301   * Retrieve the description for the HTTP status.
1302   *
1303   * @since 2.3.0
1304   *
1305   * @param int $code HTTP status code.
1306   * @return string Empty string if not found, or description if found.
1307   */
1308  function get_status_header_desc( $code ) {
1309      global $wp_header_to_desc;
1310  
1311      $code = absint( $code );
1312  
1313      if ( !isset( $wp_header_to_desc ) ) {
1314          $wp_header_to_desc = array(
1315              100 => 'Continue',
1316              101 => 'Switching Protocols',
1317  
1318              200 => 'OK',
1319              201 => 'Created',
1320              202 => 'Accepted',
1321              203 => 'Non-Authoritative Information',
1322              204 => 'No Content',
1323              205 => 'Reset Content',
1324              206 => 'Partial Content',
1325  
1326              300 => 'Multiple Choices',
1327              301 => 'Moved Permanently',
1328              302 => 'Found',
1329              303 => 'See Other',
1330              304 => 'Not Modified',
1331              305 => 'Use Proxy',
1332              307 => 'Temporary Redirect',
1333  
1334              400 => 'Bad Request',
1335              401 => 'Unauthorized',
1336              403 => 'Forbidden',
1337              404 => 'Not Found',
1338              405 => 'Method Not Allowed',
1339              406 => 'Not Acceptable',
1340              407 => 'Proxy Authentication Required',
1341              408 => 'Request Timeout',
1342              409 => 'Conflict',
1343              410 => 'Gone',
1344              411 => 'Length Required',
1345              412 => 'Precondition Failed',
1346              413 => 'Request Entity Too Large',
1347              414 => 'Request-URI Too Long',
1348              415 => 'Unsupported Media Type',
1349              416 => 'Requested Range Not Satisfiable',
1350              417 => 'Expectation Failed',
1351  
1352              500 => 'Internal Server Error',
1353              501 => 'Not Implemented',
1354              502 => 'Bad Gateway',
1355              503 => 'Service Unavailable',
1356              504 => 'Gateway Timeout',
1357              505 => 'HTTP Version Not Supported'
1358          );
1359      }
1360  
1361      if ( isset( $wp_header_to_desc[$code] ) )
1362          return $wp_header_to_desc[$code];
1363      else
1364          return '';
1365  }
1366  
1367  /**
1368   * Set HTTP status header.
1369   *
1370   * @since 2.0.0
1371   * @uses apply_filters() Calls 'status_header' on status header string, HTTP
1372   *        HTTP code, HTTP code description, and protocol string as separate
1373   *        parameters.
1374   *
1375   * @param int $header HTTP status code
1376   * @return null Does not return anything.
1377   */
1378  function status_header( $header ) {
1379      $text = get_status_header_desc( $header );
1380  
1381      if ( empty( $text ) )
1382          return false;
1383  
1384      $protocol = $_SERVER["SERVER_PROTOCOL"];
1385      if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
1386          $protocol = 'HTTP/1.0';
1387      $status_header = "$protocol $header $text";
1388      if ( function_exists( 'apply_filters' ) )
1389          $status_header = apply_filters( 'status_header', $status_header, $header, $text, $protocol );
1390  
1391      if ( version_compare( phpversion(), '4.3.0', '>=' ) )
1392          return @header( $status_header, true, $header );
1393      else
1394          return @header( $status_header );
1395  }
1396  
1397  /**
1398   * Sets the headers to prevent caching for the different browsers.
1399   *
1400   * Different browsers support different nocache headers, so several headers must
1401   * be sent so that all of them get the point that no caching should occur.
1402   *
1403   * @since 2.0.0
1404   */
1405  function nocache_headers() {
1406      // why are these @-silenced when other header calls aren't?
1407      @header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
1408      @header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
1409      @header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
1410      @header( 'Pragma: no-cache' );
1411  }
1412  
1413  /**
1414   * Set the headers for caching for 10 days with JavaScript content type.
1415   *
1416   * @since 2.1.0
1417   */
1418  function cache_javascript_headers() {
1419      $expiresOffset = 864000; // 10 days
1420      header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
1421      header( "Vary: Accept-Encoding" ); // Handle proxies
1422      header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
1423  }
1424  
1425  /**
1426   * Retrieve the number of database queries during the WordPress execution.
1427   *
1428   * @since 2.0.0
1429   *
1430   * @return int Number of database queries
1431   */
1432  function get_num_queries() {
1433      global $wpdb;
1434      return $wpdb->num_queries;
1435  }
1436  
1437  /**
1438   * Whether input is yes or no. Must be 'y' to be true.
1439   *
1440   * @since 1.0.0
1441   *
1442   * @param string $yn Character string containing either 'y' or 'n'
1443   * @return bool True if yes, false on anything else
1444   */
1445  function bool_from_yn( $yn ) {
1446      return ( strtolower( $yn ) == 'y' );
1447  }
1448  
1449  /**
1450   * Loads the feed template from the use of an action hook.
1451   *
1452   * If the feed action does not have a hook, then the function will die with a
1453   * message telling the visitor that the feed is not valid.
1454   *
1455   * It is better to only have one hook for each feed.
1456   *
1457   * @since 2.1.0
1458   * @uses $wp_query Used to tell if the use a comment feed.
1459   * @uses do_action() Calls 'do_feed_$feed' hook, if a hook exists for the feed.
1460   */
1461  function do_feed() {
1462      global $wp_query;
1463  
1464      $feed = get_query_var( 'feed' );
1465  
1466      // Remove the pad, if present.
1467      $feed = preg_replace( '/^_+/', '', $feed );
1468  
1469      if ( $feed == '' || $feed == 'feed' )
1470          $feed = get_default_feed();
1471  
1472      $hook = 'do_feed_' . $feed;
1473      if ( !has_action($hook) ) {
1474          $message = sprintf( __( 'ERROR: %s is not a valid feed template' ), wp_specialchars($feed));
1475          wp_die($message);
1476      }
1477  
1478      do_action( $hook, $wp_query->is_comment_feed );
1479  }
1480  
1481  /**
1482   * Load the RDF RSS 0.91 Feed template.
1483   *
1484   * @since 2.1.0
1485   */
1486  function do_feed_rdf() {
1487      load_template( ABSPATH . WPINC . '/feed-rdf.php' );
1488  }
1489  
1490  /**
1491   * Load the RSS 1.0 Feed Template
1492   *
1493   * @since 2.1.0
1494   */
1495  function do_feed_rss() {
1496      load_template( ABSPATH . WPINC . '/feed-rss.php' );
1497  }
1498  
1499  /**
1500   * Load either the RSS2 comment feed or the RSS2 posts feed.
1501   *
1502   * @since 2.1.0
1503   *
1504   * @param bool $for_comments True for the comment feed, false for normal feed.
1505   */
1506  function do_feed_rss2( $for_comments ) {
1507      if ( $for_comments )
1508          load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
1509      else
1510          load_template( ABSPATH . WPINC . '/feed-rss2.php' );
1511  }
1512  
1513  /**
1514   * Load either Atom comment feed or Atom posts feed.
1515   *
1516   * @since 2.1.0
1517   *
1518   * @param bool $for_comments True for the comment feed, false for normal feed.
1519   */
1520  function do_feed_atom( $for_comments ) {
1521      if ($for_comments)
1522          load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
1523      else
1524          load_template( ABSPATH . WPINC . '/feed-atom.php' );
1525  }
1526  
1527  /**
1528   * Display the robot.txt file content.
1529   *
1530   * The echo content should be with usage of the permalinks or for creating the
1531   * robot.txt file.
1532   *
1533   * @since 2.1.0
1534   * @uses do_action() Calls 'do_robotstxt' hook for displaying robot.txt rules.
1535   */
1536  function do_robots() {
1537      header( 'Content-Type: text/plain; charset=utf-8' );
1538  
1539      do_action( 'do_robotstxt' );
1540  
1541      if ( '0' == get_option( 'blog_public' ) ) {
1542          echo "User-agent: *\n";
1543          echo "Disallow: /\n";
1544      } else {
1545          echo "User-agent: *\n";
1546          echo "Disallow:\n";
1547      }
1548  }
1549  
1550  /**
1551   * Test whether blog is already installed.
1552   *
1553   * The cache will be checked first. If you have a cache plugin, which saves the
1554   * cache values, then this will work. If you use the default WordPress cache,
1555   * and the database goes away, then you might have problems.
1556   *
1557   * Checks for the option siteurl for whether WordPress is installed.
1558   *
1559   * @since 2.1.0
1560   * @uses $wpdb
1561   *
1562   * @return bool Whether blog is already installed.
1563   */
1564  function is_blog_installed() {
1565      global $wpdb;
1566  
1567      // Check cache first. If options table goes away and we have true cached, oh well.
1568      if ( wp_cache_get('is_blog_installed') )
1569          return true;
1570  
1571      $suppress = $wpdb->suppress_errors();
1572      $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
1573      $wpdb->suppress_errors($suppress);
1574  
1575      $installed = !empty( $installed ) ? true : false;
1576      wp_cache_set('is_blog_installed', $installed);
1577  
1578      return $installed;
1579  }
1580  
1581  /**
1582   * Retrieve URL with nonce added to URL query.
1583   *
1584   * @package WordPress
1585   * @subpackage Security
1586   * @since 2.0.4
1587   *
1588   * @param string $actionurl URL to add nonce action
1589   * @param string $action Optional. Nonce action name
1590   * @return string URL with nonce action added.
1591   */
1592  function wp_nonce_url( $actionurl, $action = -1 ) {
1593      $actionurl = str_replace( '&amp;', '&', $actionurl );
1594      return wp_specialchars( add_query_arg( '_wpnonce', wp_create_nonce( $action ), $actionurl ) );
1595  }
1596  
1597  /**
1598   * Retrieve or display nonce hidden field for forms.
1599   *
1600   * The nonce field is used to validate that the contents of the form came from
1601   * the location on the current site and not somewhere else. The nonce does not
1602   * offer absolute protection, but should protect against most cases. It is very
1603   * important to use nonce field in forms.
1604   *
1605   * If you set $echo to true and set $referer to true, then you will need to
1606   * retrieve the {@link wp_referer_field() wp referer field}. If you have the
1607   * $referer set to true and are echoing the nonce field, it will also echo the
1608   * referer field.
1609   *
1610   * The $action and $name are optional, but if you want to have better security,
1611   * it is strongly suggested to set those two parameters. It is easier to just
1612   * call the function without any parameters, because validation of the nonce
1613   * doesn't require any parameters, but since crackers know what the default is
1614   * it won't be difficult for them to find a way around your nonce and cause
1615   * damage.
1616   *
1617   * The input name will be whatever $name value you gave. The input value will be
1618   * the nonce creation value.
1619   *
1620   * @package WordPress
1621   * @subpackage Security
1622   * @since 2.0.4
1623   *
1624   * @param string $action Optional. Action name.
1625   * @param string $name Optional. Nonce name.
1626   * @param bool $referer Optional, default true. Whether to set the referer field for validation.
1627   * @param bool $echo Optional, default true. Whether to display or return hidden form field.
1628   * @return string Nonce field.
1629   */
1630  function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1631      $name = attribute_escape( $name );
1632      $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
1633      if ( $echo )
1634          echo $nonce_field;
1635  
1636      if ( $referer )
1637          wp_referer_field( $echo, 'previous' );
1638  
1639      return $nonce_field;
1640  }
1641  
1642  /**
1643   * Retrieve or display referer hidden field for forms.
1644   *
1645   * The referer link is the current Request URI from the server super global. The
1646   * input name is '_wp_http_referer', in case you wanted to check manually.
1647   *
1648   * @package WordPress
1649   * @subpackage Security
1650   * @since 2.0.4
1651   *
1652   * @param bool $echo Whether to echo or return the referer field.
1653   * @return string Referer field.
1654   */
1655  function wp_referer_field( $echo = true) {
1656      $ref = attribute_escape( $_SERVER['REQUEST_URI'] );
1657      $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. $ref . '" />';
1658  
1659      if ( $echo )
1660          echo $referer_field;
1661      return $referer_field;
1662  }
1663  
1664  /**
1665   * Retrieve or display original referer hidden field for forms.
1666   *
1667   * The input name is '_wp_original_http_referer' and will be either the same
1668   * value of {@link wp_referer_field()}, if that was posted already or it will
1669   * be the current page, if it doesn't exist.
1670   *
1671   * @package WordPress
1672   * @subpackage Security
1673   * @since 2.0.4
1674   *
1675   * @param bool $echo Whether to echo the original http referer
1676   * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to.
1677   * @return string Original referer field.
1678   */
1679  function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
1680      $jump_back_to = ( 'previous' == $jump_back_to ) ? wp_get_referer() : $_SERVER['REQUEST_URI'];
1681      $ref = ( wp_get_original_referer() ) ? wp_get_original_referer() : $jump_back_to;
1682      $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . attribute_escape( stripslashes( $ref ) ) . '" />';
1683      if ( $echo )
1684          echo $orig_referer_field;
1685      return $orig_referer_field;
1686  }
1687  
1688  /**
1689   * Retrieve referer from '_wp_http_referer', HTTP referer, or current page respectively.
1690   *
1691   * @package WordPress
1692   * @subpackage Security
1693   * @since 2.0.4
1694   *
1695   * @return string|bool False on failure. Referer URL on success.
1696   */
1697  function wp_get_referer() {
1698      $ref = '';
1699      if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
1700          $ref = $_REQUEST['_wp_http_referer'];
1701      else if ( ! empty( $_SERVER['HTTP_REFERER'] ) )
1702          $ref = $_SERVER['HTTP_REFERER'];
1703  
1704      if ( $ref !== $_SERVER['REQUEST_URI'] )
1705          return $ref;
1706      return false;
1707  }
1708  
1709  /**
1710   * Retrieve original referer that was posted, if it exists.
1711   *
1712   * @package WordPress
1713   * @subpackage Security
1714   * @since 2.0.4
1715   *
1716   * @return string|bool False if no original referer or original referer if set.
1717   */
1718  function wp_get_original_referer() {
1719      if ( !empty( $_REQUEST['_wp_original_http_referer'] ) )
1720          return $_REQUEST['_wp_original_http_referer'];
1721      return false;
1722  }
1723  
1724  /**
1725   * Recursive directory creation based on full path.
1726   *
1727   * Will attempt to set permissions on folders.
1728   *
1729   * @since 2.0.1
1730   *
1731   * @param string $target Full path to attempt to create.
1732   * @return bool Whether the path was created or not. True if path already exists.
1733   */
1734  function wp_mkdir_p( $target ) {
1735      // from php.net/mkdir user contributed notes
1736      $target = str_replace( '//', '/', $target );
1737      if ( file_exists( $target ) )
1738          return @is_dir( $target );
1739  
1740      // Attempting to create the directory may clutter up our display.
1741      if ( @mkdir( $target ) ) {
1742          $stat = @stat( dirname( $target ) );
1743          $dir_perms = $stat['mode'] & 0007777;  // Get the permission bits.
1744          @chmod( $target, $dir_perms );
1745          return true;
1746      } elseif ( is_dir( dirname( $target ) ) ) {
1747              return false;
1748      }
1749  
1750      // If the above failed, attempt to create the parent node, then try again.
1751      if ( ( $target != '/' ) && ( wp_mkdir_p( dirname( $target ) ) ) )
1752          return wp_mkdir_p( $target );
1753  
1754      return false;
1755  }
1756  
1757  /**
1758   * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
1759   *
1760   * @since 2.5.0
1761   *
1762   * @param string $path File path
1763   * @return bool True if path is absolute, false is not absolute.
1764   */
1765  function path_is_absolute( $path ) {
1766      // this is definitive if true but fails if $path does not exist or contains a symbolic link
1767      if ( realpath($path) == $path )
1768          return true;
1769  
1770      if ( strlen($path) == 0 || $path{0} == '.' )
1771          return false;
1772  
1773      // windows allows absolute paths like this
1774      if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
1775          return true;
1776  
1777      // a path starting with / or \ is absolute; anything else is relative
1778      return (bool) preg_match('#^[/\\\\]#', $path);
1779  }
1780  
1781  /**
1782   * Join two filesystem paths together (e.g. 'give me $path relative to $base').
1783   *
1784   * If the $path is absolute, then it the full path is returned.
1785   *
1786   * @since 2.5.0
1787   *
1788   * @param string $base
1789   * @param string $path
1790   * @return string The path with the base or absolute path.
1791   */
1792  function path_join( $base, $path ) {
1793      if ( path_is_absolute($path) )
1794          return $path;
1795  
1796      return rtrim($base, '/') . '/' . ltrim($path, '/');
1797  }
1798  
1799  /**
1800   * Get an array containing the current upload directory's path and url.
1801   *
1802   * Checks the 'upload_path' option, which should be from the web root folder,
1803   * and if it isn't empty it will be used. If it is empty, then the path will be
1804   * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
1805   * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
1806   *
1807   * The upload URL path is set either by the 'upload_url_path' option or by using
1808   * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
1809   *
1810   * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
1811   * the administration settings panel), then the time will be used. The format
1812   * will be year first and then month.
1813   *
1814   * If the path couldn't be created, then an error will be returned with the key
1815   * 'error' containing the error message. The error suggests that the parent
1816   * directory is not writable by the server.
1817   *
1818   * On success, the returned array will have many indices:
1819   * 'path' - base directory and sub directory or full path to upload directory.
1820   * 'url' - base url and sub directory or absolute URL to upload directory.
1821   * 'subdir' - sub directory if uploads use year/month folders option is on.
1822   * 'basedir' - path without subdir.
1823   * 'baseurl' - URL path without subdir.
1824   * 'error' - set to false.
1825   *
1826   * @since 2.0.0
1827   * @uses apply_filters() Calls 'upload_dir' on returned array.
1828   *
1829   * @param string $time Optional. Time formatted in 'yyyy/mm'.
1830   * @return array See above for description.
1831   */
1832  function wp_upload_dir( $time = null ) {
1833      $siteurl = get_option( 'siteurl' );
1834      $upload_path = get_option( 'upload_path' );
1835      $upload_path = trim($upload_path);
1836      if ( empty($upload_path) )
1837          $dir = WP_CONTENT_DIR . '/uploads';
1838      else
1839          $dir = $upload_path;
1840  
1841      // $dir is absolute, $path is (maybe) relative to ABSPATH
1842      $dir = path_join( ABSPATH, $dir );
1843  
1844      if ( !$url = get_option( 'upload_url_path' ) ) {
1845          if ( empty($upload_path) or ( $upload_path == $dir ) )
1846              $url = WP_CONTENT_URL . '/uploads';
1847          else
1848              $url = trailingslashit( $siteurl ) . $upload_path;
1849      }
1850  
1851      if ( defined('UPLOADS') ) {
1852          $dir = ABSPATH . UPLOADS;
1853          $url = trailingslashit( $siteurl ) . UPLOADS;
1854      }
1855  
1856      $bdir = $dir;
1857      $burl = $url;
1858  
1859      $subdir = '';
1860      if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
1861          // Generate the yearly and monthly dirs
1862          if ( !$time )
1863              $time = current_time( 'mysql' );
1864          $y = substr( $time, 0, 4 );
1865          $m = substr( $time, 5, 2 );
1866          $subdir = "/$y/$m";
1867      }
1868  
1869      $dir .= $subdir;
1870      $url .= $subdir;
1871  
1872      // Make sure we have an uploads dir
1873      if ( ! wp_mkdir_p( $dir ) ) {
1874          $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $dir );
1875          return array( 'error' => $message );
1876      }
1877  
1878      $uploads = array( 'path' => $dir, 'url' => $url, 'subdir' => $subdir, 'basedir' => $bdir, 'baseurl' => $burl, 'error' => false );
1879  
1880      return apply_filters( 'upload_dir', $uploads );
1881  }
1882  
1883  /**
1884   * Get a filename that is sanitized and unique for the given directory.
1885   *
1886   * If the filename is not unique, then a number will be added to the filename
1887   * before the extension, and will continue adding numbers until the filename is
1888   * unique.
1889   *
1890   * The callback must accept two parameters, the first one is the directory and
1891   * the second is the filename. The callback must be a function.
1892   *
1893   * @since 2.5
1894   *
1895   * @param string $dir
1896   * @param string $filename
1897   * @param string $unique_filename_callback Function name, must be a function.
1898   * @return string New filename, if given wasn't unique.
1899   */
1900  function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
1901      $filename = strtolower( $filename );
1902      // separate the filename into a name and extension
1903      $info = pathinfo($filename);
1904      $ext = !empty($info['extension']) ? $info['extension'] : '';
1905      $name = basename($filename, ".{$ext}");
1906  
1907      // edge case: if file is named '.ext', treat as an empty name
1908      if( $name === ".$ext" )
1909          $name = '';
1910  
1911      // Increment the file number until we have a unique file to save in $dir. Use $override['unique_filename_callback'] if supplied.
1912      if ( $unique_filename_callback && function_exists( $unique_filename_callback ) ) {
1913          $filename = $unique_filename_callback( $dir, $name );
1914      } else {
1915          $number = '';
1916  
1917          if ( !empty( $ext ) )
1918              $ext = strtolower( ".$ext" );
1919  
1920          $filename = str_replace( $ext, '', $filename );
1921          // Strip % so the server doesn't try to decode entities.
1922          $filename = str_replace('%', '', sanitize_title_with_dashes( $filename ) ) . $ext;
1923  
1924          while ( file_exists( $dir . "/$filename" ) ) {
1925              if ( '' == "$number$ext" )
1926                  $filename = $filename . ++$number . $ext;
1927              else
1928                  $filename = str_replace( "$number$ext", ++$number . $ext, $filename );
1929          }
1930      }
1931  
1932      return $filename;
1933  }
1934  
1935  /**
1936   * Create a file in the upload folder with given content.
1937   *
1938   * If there is an error, then the key 'error' will exist with the error message.
1939   * If success, then the key 'file' will have the unique file path, the 'url' key
1940   * will have the link to the new file. and the 'error' key will be set to false.
1941   *
1942   * This function will not move an uploaded file to the upload folder. It will
1943   * create a new file with the content in $bits parameter. If you move the upload
1944   * file, read the content of the uploaded file, and then you can give the
1945   * filename and content to this function, which will add it to the upload
1946   * folder.
1947   *
1948   * The permissions will be set on the new file automatically by this function.
1949   *
1950   * @since 2.0.0
1951   *
1952   * @param string $name
1953   * @param null $deprecated Not used. Set to null.
1954   * @param mixed $bits File content
1955   * @param string $time Optional. Time formatted in 'yyyy/mm'.
1956   * @return array
1957   */
1958  function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
1959      if ( empty( $name ) )
1960          return array( 'error' => __( 'Empty filename' ) );
1961  
1962      $wp_filetype = wp_check_filetype( $name );
1963      if ( !$wp_filetype['ext'] )
1964          return array( 'error' => __( 'Invalid file type' ) );
1965  
1966      $upload = wp_upload_dir( $time );
1967  
1968      if ( $upload['error'] !== false )
1969          return $upload;
1970  
1971      $filename = wp_unique_filename( $upload['path'], $name );
1972  
1973      $new_file = $upload['path'] . "/$filename";
1974      if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
1975          $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), dirname( $new_file ) );
1976          return array( 'error' => $message );
1977      }
1978  
1979      $ifp = @ fopen( $new_file, 'wb' );
1980      if ( ! $ifp )
1981          return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
1982  
1983      @fwrite( $ifp, $bits );
1984      fclose( $ifp );
1985      // Set correct file permissions
1986      $stat = @ stat( dirname( $new_file ) );
1987      $perms = $stat['mode'] & 0007777;
1988      $perms = $perms & 0000666;
1989      @ chmod( $new_file, $perms );
1990  
1991      // Compute the URL
1992      $url = $upload['url'] . "/$filename";
1993  
1994      return array( 'file' => $new_file, 'url' => $url, 'error' => false );
1995  }
1996  
1997  /**
1998   * Retrieve the file type based on the extension name.
1999   *
2000   * @package WordPress
2001   * @since 2.5.0
2002   * @uses apply_filters() Calls 'ext2type' hook on default supported types.
2003   *
2004   * @param string $ext The extension to search.
2005   * @return string|null The file type, example: audio, video, document, spreadsheet, etc. Null if not found.
2006   */
2007  function wp_ext2type( $ext ) {
2008      $ext2type = apply_filters('ext2type', array(
2009          'audio' => array('aac','ac3','aif','aiff','mp1','mp2','mp3','m3a','m4a','m4b','ogg','ram','wav','wma'),
2010          'video' => array('asf','avi','divx','dv','mov','mpg','mpeg','mp4','mpv','ogm','qt','rm','vob','wmv'),
2011          'document' => array('doc','docx','pages','odt','rtf','pdf'),
2012          'spreadsheet' => array('xls','xlsx','numbers','ods'),
2013          'interactive' => array('ppt','pptx','key','odp','swf'),
2014          'text' => array('txt'),
2015          'archive' => array('tar','bz2','gz','cab','dmg','rar','sea','sit','sqx','zip'),
2016          'code' => array('css','html','php','js'),
2017      ));
2018      foreach ( $ext2type as $type => $exts )
2019          if ( in_array($ext, $exts) )
2020              return $type;
2021  }
2022  
2023  /**
2024   * Retrieve the file type from the file name.
2025   *
2026   * You can optionally define the mime array, if needed.
2027   *
2028   * @since 2.0.4
2029   *
2030   * @param string $filename File name or path.
2031   * @param array $mimes Optional. Key is the file extension with value as the mime type.
2032   * @return array Values with extension first and mime type.
2033   */
2034  function wp_check_filetype( $filename, $mimes = null ) {
2035      // Accepted MIME types are set here as PCRE unless provided.
2036      $mimes = ( is_array( $mimes ) ) ? $mimes : apply_filters( 'upload_mimes', array(
2037          'jpg|jpeg|jpe' => 'image/jpeg',
2038          'gif' => 'image/gif',
2039          'png' => 'image/png',
2040          'bmp' => 'image/bmp',
2041          'tif|tiff' => 'image/tiff',
2042          'ico' => 'image/x-icon',
2043          'asf|asx|wax|wmv|wmx' => 'video/asf',
2044          'avi' => 'video/avi',
2045          'divx' => 'video/divx',
2046          'mov|qt' => 'video/quicktime',
2047          'mpeg|mpg|mpe|mp4' => 'video/mpeg',
2048          'txt|c|cc|h' => 'text/plain',
2049          'rtx' => 'text/richtext',
2050          'css' => 'text/css',
2051          'htm|html' => 'text/html',
2052          'mp3|m4a' => 'audio/mpeg',
2053          'ra|ram' => 'audio/x-realaudio',
2054          'wav' => 'audio/wav',
2055          'ogg' => 'audio/ogg',
2056          'mid|midi' => 'audio/midi',
2057          'wma' => 'audio/wma',
2058          'rtf' => 'application/rtf',
2059          'js' => 'application/javascript',
2060          'pdf' => 'application/pdf',
2061          'doc|docx' => 'application/msword',
2062          'pot|pps|ppt|pptx' => 'application/vnd.ms-powerpoint',
2063          'wri' => 'application/vnd.ms-write',
2064          'xla|xls|xlsx|xlt|xlw' => 'application/vnd.ms-excel',
2065          'mdb' => 'application/vnd.ms-access',
2066          'mpp' => 'application/vnd.ms-project',
2067          'swf' => 'application/x-shockwave-flash',
2068          'class' => 'application/java',
2069          'tar' => 'application/x-tar',
2070          'zip' => 'application/zip',
2071          'gz|gzip' => 'application/x-gzip',
2072          'exe' => 'application/x-msdownload',
2073          // openoffice formats
2074          'odt' => 'application/vnd.oasis.opendocument.text',
2075          'odp' => 'application/vnd.oasis.opendocument.presentation',
2076          'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
2077          'odg' => 'application/vnd.oasis.opendocument.graphics',
2078          'odc' => 'application/vnd.oasis.opendocument.chart',
2079          'odb' => 'application/vnd.oasis.opendocument.database',
2080          'odf' => 'application/vnd.oasis.opendocument.formula',
2081          )
2082      );
2083  
2084      $type = false;
2085      $ext = false;
2086  
2087      foreach ( $mimes as $ext_preg => $mime_match ) {
2088          $ext_preg = '!\.(' . $ext_preg . ')$!i';
2089          if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
2090              $type = $mime_match;
2091              $ext = $ext_matches[1];
2092              break;
2093          }
2094      }
2095  
2096      return compact( 'ext', 'type' );
2097  }
2098  
2099  /**
2100   * Retrieve nonce action "Are you sure" message.
2101   *
2102   * The action is split by verb and noun. The action format is as follows:
2103   * verb-action_extra. The verb is before the first dash and has the format of
2104   * letters and no spaces and numbers. The noun is after the dash and before the
2105   * underscore, if an underscore exists. The noun is also only letters.
2106   *
2107   * The filter will be called for any action, which is not defined by WordPress.
2108   * You may use the filter for your plugin to explain nonce actions to the user,
2109   * when they get the "Are you sure?" message. The filter is in the format of
2110   * 'explain_nonce_$verb-$noun' with the $verb replaced by the found verb and the
2111   * $noun replaced by the found noun. The two parameters that are given to the
2112   * hook are the localized "Are you sure you want to do this?" message with the
2113   * extra text (the text after the underscore).
2114   *
2115   * @package WordPress
2116   * @subpackage Security
2117   * @since 2.0.4
2118   *
2119   * @param string $action Nonce action.
2120   * @return string Are you sure message.
2121   */
2122  function wp_explain_nonce( $action ) {
2123      if ( $action !== -1 && preg_match( '/([a-z]+)-([a-z]+)(_(.+))?/', $action, $matches ) ) {
2124          $verb = $matches[1];
2125          $noun = $matches[2];
2126  
2127          $trans = array();
2128          $trans['update']['attachment'] = array( __( 'Your attempt to edit this attachment: &quot;%s&quot; has failed.' ), 'get_the_title' );
2129  
2130          $trans['add']['category']      = array( __( 'Your attempt to add this category has failed.' ), false );
2131          $trans['delete']['category']   = array( __( 'Your attempt to delete this category: &quot;%s&quot; has failed.' ), 'get_catname' );
2132          $trans['update']['category']   = array( __( 'Your attempt to edit this category: &quot;%s&quot; has failed.' ), 'get_catname' );
2133  
2134          $trans['delete']['comment']    = array( __( 'Your attempt to delete this comment: &quot;%s&quot; has failed.' ), 'use_id' );
2135          $trans['unapprove']['comment'] = array( __( 'Your attempt to unapprove this comment: &quot;%s&quot; has failed.' ), 'use_id' );
2136          $trans['approve']['comment']   = array( __( 'Your attempt to approve this comment: &quot;%s&quot; has failed.' ), 'use_id' );
2137          $trans['update']['comment']    = array( __( 'Your attempt to edit this comment: &quot;%s&quot; has failed.' ), 'use_id' );
2138          $trans['bulk']['comments']     = array( __( 'Your attempt to bulk modify comments has failed.' ), false );
2139          $trans['moderate']['comments'] = array( __( 'Your attempt to moderate comments has failed.' ), false );
2140  
2141          $trans['add']['bookmark']      = array( __( 'Your attempt to add this link has failed.' ), false );
2142          $trans['delete']['bookmark']   = array( __( 'Your attempt to delete this link: &quot;%s&quot; has failed.' ), 'use_id' );
2143          $trans['update']['bookmark']   = array( __( 'Your attempt to edit this link: &quot;%s&quot; has failed.' ), 'use_id' );
2144          $trans['bulk']['bookmarks']    = array( __( 'Your attempt to bulk modify links has failed.' ), false );
2145  
2146          $trans['add']['page']          = array( __( 'Your attempt to add this page has failed.' ), false );
2147          $trans['delete']['page']       = array( __( 'Your attempt to delete this page: &quot;%s&quot; has failed.' ), 'get_the_title' );
2148          $trans['update']['page']       = array( __( 'Your attempt to edit this page: &quot;%s&quot; has failed.' ), 'get_the_title' );
2149  
2150          $trans['edit']['plugin']       = array( __( 'Your attempt to edit this plugin file: &quot;%s&quot; has failed.' ), 'use_id' );
2151          $trans['activate']['plugin']   = array( __( 'Your attempt to activate this plugin: &quot;%s&quot; has failed.' ), 'use_id' );
2152          $trans['deactivate']['plugin'] = array( __( 'Your attempt to deactivate this plugin: &quot;%s&quot; has failed.' ), 'use_id' );
2153          $trans['upgrade']['plugin']    = array( __( 'Your attempt to upgrade this plugin: &quot;%s&quot; has failed.' ), 'use_id' );
2154  
2155          $trans['add']['post']          = array( __( 'Your attempt to add this post has failed.' ), false );
2156          $trans['delete']['post']       = array( __( 'Your attempt to delete this post: &quot;%s&quot; has failed.' ), 'get_the_title' );
2157          $trans['update']['post']       = array( __( 'Your attempt to edit this post: &quot;%s&quot; has failed.' ), 'get_the_title' );
2158  
2159          $trans['add']['user']          = array( __( 'Your attempt to add this user has failed.' ), false );
2160          $trans['delete']['users']      = array( __( 'Your attempt to delete users has failed.' ), false );
2161          $trans['bulk']['users']        = array( __( 'Your attempt to bulk modify users has failed.' ), false );
2162          $trans['update']['user']       = array( __( 'Your attempt to edit this user: &quot;%s&quot; has failed.' ), 'get_author_name' );
2163          $trans['update']['profile']    = array( __( 'Your attempt to modify the profile for: &quot;%s&quot; has failed.' ), 'get_author_name' );
2164  
2165          $trans['update']['options']    = array( __( 'Your attempt to edit your settings has failed.' ), false );
2166          $trans['update']['permalink']  = array( __( 'Your attempt to change your permalink structure to: %s has failed.' ), 'use_id' );
2167          $trans['edit']['file']         = array( __( 'Your attempt to edit this file: &quot;%s&quot; has failed.' ), 'use_id' );
2168          $trans['edit']['theme']        = array( __( 'Your attempt to edit this theme file: &quot;%s&quot; has failed.' ), 'use_id' );
2169          $trans['switch']['theme']      = array( __( 'Your attempt to switch to this theme: &quot;%s&quot; has failed.' ), 'use_id' );
2170  
2171          $trans['log']['out']           = array( sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'sitename' ) ), false );
2172  
2173          if ( isset( $trans[$verb][$noun] ) ) {
2174              if ( !empty( $trans[$verb][$noun][1] ) ) {
2175                  $lookup = $trans[$verb][$noun][1];
2176                  $object = $matches[4];
2177                  if ( 'use_id' != $lookup )
2178                      $object = call_user_func( $lookup, $object );
2179                  return sprintf( $trans[$verb][$noun][0], wp_specialchars($object) );
2180              } else {
2181                  return $trans[$verb][$noun][0];
2182              }
2183          }
2184      }
2185  
2186      return apply_filters( 'explain_nonce_' . $verb . '-' . $noun, __( 'Are you sure you want to do this?' ), $matches[4] );
2187  }
2188  
2189  /**
2190   * Display "Are You Sure" message to confirm the action being taken.
2191   *
2192   * If the action has the nonce explain message, then it will be displayed along
2193   * with the "Are you sure?" message.
2194   *
2195   * @package WordPress
2196   * @subpackage Security
2197   * @since 2.0.4
2198   *
2199   * @param string $action The nonce action.
2200   */
2201  function wp_nonce_ays( $action ) {
2202      $title = __( 'WordPress Failure Notice' );
2203      $html = wp_specialchars( wp_explain_nonce( $action ) );
2204      if ( wp_get_referer() )
2205          $html .= "</p><p><a href='" . remove_query_arg( 'updated', clean_url( wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
2206      elseif ( 'log-out' == $action )
2207          $html .= "</p><p>" . sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_nonce_url( site_url('wp-login.php?action=logout', 'login'), 'log-out' ) );
2208  
2209      wp_die( $html, $title);
2210  }
2211  
2212  /**
2213   * Kill WordPress execution and display HTML message with error message.
2214   *
2215   * Call this function complements the die() PHP function. The difference is that
2216   * HTML will be displayed to the user. It is recommended to use this function
2217   * only, when the execution should not continue any further. It is not
2218   * recommended to call this function very often and try to handle as many errors
2219   * as possible siliently.
2220   *
2221   * @since 2.0.4
2222   *
2223   * @param string $message Error message.
2224   * @param string $title Error title.
2225   * @param string|array $args Optional arguements to control behaviour.
2226   */
2227  function wp_die( $message, $title = '', $args = array() ) {
2228      global $wp_locale;
2229  
2230      $defaults = array( 'response' => 500 );
2231      $r = wp_parse_args($args, $defaults);
2232  
2233      if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
2234          if ( empty( $title ) ) {
2235              $error_data = $message->get_error_data();
2236              if ( is_array( $error_data ) && isset( $error_data['title'] ) )
2237                  $title = $error_data['title'];
2238          }
2239          $errors = $message->get_error_messages();
2240          switch ( count( $errors ) ) :
2241          case 0 :
2242              $message = '';
2243              break;
2244          case 1 :
2245              $message = "<p>{$errors[0]}</p>";
2246              break;
2247          default :
2248              $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
2249              break;
2250          endswitch;
2251      } elseif ( is_string( $message ) ) {
2252          $message = "<p>$message</p>";
2253      }
2254  
2255      if ( defined( 'WP_SITEURL' ) && '' != WP_SITEURL )
2256          $admin_dir = WP_SITEURL . '/wp-admin/';
2257      elseif ( function_exists( 'get_bloginfo' ) && '' != get_bloginfo( 'wpurl' ) )
2258          $admin_dir = get_bloginfo( 'wpurl' ) . '/wp-admin/';
2259      elseif ( strpos( $_SERVER['PHP_SELF'], 'wp-admin' ) !== false )
2260          $admin_dir = '';
2261      else
2262          $admin_dir = 'wp-admin/';
2263  
2264      if ( !function_exists( 'did_action' ) || !did_action( 'admin_head' ) ) :
2265      if( !headers_sent() ){
2266          status_header( $r['response'] );
2267          nocache_headers();
2268          header( 'Content-Type: text/html; charset=utf-8' );
2269      }
2270  
2271      if ( empty($title) ) {
2272          if ( function_exists( '__' ) )
2273              $title = __( 'WordPress &rsaquo; Error' );
2274          else
2275              $title = 'WordPress &rsaquo; Error';
2276      }
2277  
2278  ?>
2279  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2280  <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) ) language_attributes(); ?>>
2281  <head>
2282      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2283      <title><?php echo $title ?></title>
2284      <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install.css" type="text/css" />
2285  <?php
2286  if ( ( $wp_locale ) && ( 'rtl' == $wp_locale->text_direction ) ) : ?>
2287      <link rel="stylesheet" href="<?php echo $admin_dir; ?>css/install-rtl.css" type="text/css" />
2288  <?php endif; ?>
2289  </head>
2290  <body id="error-page">
2291  <?php endif; ?>
2292      <?php echo $message; ?>
2293      <?php if ( strlen($message) < 512) echo str_repeat(' ', 512-strlen($message)); ?>
2294  </body>
2295  </html>
2296  <?php
2297      die();
2298  }
2299  
2300  /**
2301   * Retrieve the WordPress home page URL.
2302   *
2303   * If the constant named 'WP_HOME' exists, then it willl be used and returned by
2304   * the function. This can be used to counter the redirection on your local
2305   * development environment.
2306   *
2307   * @access private
2308   * @package WordPress
2309   * @since 2.2.0
2310   *
2311   * @param string $url URL for the home location
2312   * @return string Homepage location.
2313   */
2314  function _config_wp_home( $url = '' ) {
2315      if ( defined( 'WP_HOME' ) )
2316          return WP_HOME;
2317      return $url;
2318  }
2319  
2320  /**
2321   * Retrieve the WordPress site URL.
2322   *
2323   * If the constant named 'WP_SITEURL' is defined, then the value in that
2324   * constant will always be returned. This can be used for debugging a site on
2325   * your localhost while not having to change the database to your URL.
2326   *
2327   * @access private
2328   * @package WordPress
2329   * @since 2.2.0
2330   *
2331   * @param string $url URL to set the WordPress site location.
2332   * @return string The WordPress Site URL
2333   */
2334  function _config_wp_siteurl( $url = '' ) {
2335      if ( defined( 'WP_SITEURL' ) )
2336          return WP_SITEURL;
2337      return $url;
2338  }
2339  
2340  /**
2341   * Set the localized direction for MCE plugin.
2342   *
2343   * Will only set the direction to 'rtl', if the WordPress locale has the text
2344   * direction set to 'rtl'.
2345   *
2346   * Fills in the 'directionality', 'plugins', and 'theme_advanced_button1' array
2347   * keys. These keys are then returned in the $input array.
2348   *
2349   * @access private
2350   * @package WordPress
2351   * @subpackage MCE
2352   * @since 2.1.0
2353   *
2354   * @param array $input MCE plugin array.
2355   * @return array Direction set for 'rtl', if needed by locale.
2356   */
2357  function _mce_set_direction( $input ) {
2358      global $wp_locale;
2359  
2360      if ( 'rtl' == $wp_locale->text_direction ) {
2361          $input['directionality'] = 'rtl';
2362          $input['plugins'] .= ',directionality';
2363          $input['theme_advanced_buttons1'] .= ',ltr';
2364      }
2365  
2366      return $input;
2367  }
2368  
2369  /**
2370   * Convert smiley code to the icon graphic file equivalent.
2371   *
2372   * You can turn off smilies, by going to the write setting screen and unchecking
2373   * the box, or by setting 'use_smilies' option to false or removing the option.
2374   *
2375   * Plugins may override the default smiley list by setting the $wpsmiliestrans
2376   * to an array, with the key the code the blogger types in and the value the
2377   * image file.
2378   *
2379   * The $wp_smiliessearch global is for the regular expression array and is
2380   * set each time the function is called. The $wp_smiliesreplace is the full
2381   * replacement. Supposely, the $wp_smiliessearch array is looped over using
2382   * preg_replace() or just setting the array of $wp_smiliessearch along with the
2383   * array of $wp_smiliesreplace in the search and replace parameters of
2384   * preg_replace(), which would be faster and less overhead. Either way, both are
2385   * used with preg_replace() and can be defined after the function is called.
2386   *
2387   * The full list of smilies can be found in the function and won't be listed in
2388   * the description. Probably should create a Codex page for it, so that it is
2389   * available.
2390   *
2391   * @global array $wpsmiliestrans
2392   * @global array $wp_smiliesreplace
2393   * @global array $wp_smiliessearch
2394   * @since 2.2.0
2395   */
2396  function smilies_init() {
2397      global $wpsmiliestrans, $wp_smiliessearch, $wp_smiliesreplace;
2398  
2399      // don't bother setting up smilies if they are disabled
2400      if ( !get_option( 'use_smilies' ) )
2401          return;
2402  
2403      if ( !isset( $wpsmiliestrans ) ) {
2404          $wpsmiliestrans = array(
2405          ':mrgreen:' => 'icon_mrgreen.gif',
2406          ':neutral:' => 'icon_neutral.gif',
2407          ':twisted:' => 'icon_twisted.gif',
2408            ':arrow:' => 'icon_arrow.gif',
2409            ':shock:' => 'icon_eek.gif',
2410            ':smile:' => 'icon_smile.gif',
2411              ':???:' => 'icon_confused.gif',
2412             ':cool:' => 'icon_cool.gif',
2413             ':evil:' => 'icon_evil.gif',
2414             ':grin:' => 'icon_biggrin.gif',
2415             ':idea:' => 'icon_idea.gif',
2416             ':oops:' => 'icon_redface.gif',
2417             ':razz:' => 'icon_razz.gif',
2418             ':roll:' => 'icon_rolleyes.gif',
2419             ':wink:' => 'icon_wink.gif',
2420              ':cry:' => 'icon_cry.gif',
2421              ':eek:' => 'icon_surprised.gif',
2422              ':lol:' => 'icon_lol.gif',
2423              ':mad:' => 'icon_mad.gif',
2424              ':sad:' => 'icon_sad.gif',
2425                '8-)' => 'icon_cool.gif',
2426                '8-O' => 'icon_eek.gif',
2427                ':-(' => 'icon_sad.gif',
2428                ':-)' => 'icon_smile.gif',
2429                ':-?' => 'icon_confused.gif',
2430                ':-D' => 'icon_biggrin.gif',
2431                ':-P' => 'icon_razz.gif',
2432                ':-o' => 'icon_surprised.gif',
2433                ':-x' => 'icon_mad.gif',
2434                ':-|' => 'icon_neutral.gif',
2435                ';-)' => 'icon_wink.gif',
2436                 '8)' => 'icon_cool.gif',
2437                 '8O' => 'icon_eek.gif',
2438                 ':(' => 'icon_sad.gif',
2439                 ':)' => 'icon_smile.gif',
2440                 ':?' => 'icon_confused.gif',
2441                 ':D' => 'icon_biggrin.gif',
2442                 ':P' => 'icon_razz.gif',
2443                 ':o' => 'icon_surprised.gif',
2444                 ':x' => 'icon_mad.gif',
2445                 ':|' => 'icon_neutral.gif',
2446                 ';)' => 'icon_wink.gif',
2447                ':!:' => 'icon_exclaim.gif',
2448                ':?:' => 'icon_question.gif',
2449          );
2450      }
2451  
2452      $siteurl = get_option( 'siteurl' );
2453      foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
2454          $wp_smiliessearch[] = '/(\s|^)' . preg_quote( $smiley, '/' ) . '(\s|$)/';
2455          $smiley_masked = attribute_escape( trim( $smiley ) );
2456          $wp_smiliesreplace[] = " <img src='$siteurl/wp-includes/images/smilies/$img' alt='$smiley_masked' class='wp-smiley' /> ";
2457      }
2458  }
2459  
2460  /**
2461   * Merge user defined arguments into defaults array.
2462   *
2463   * This function is used throughout WordPress to allow for both string or array
2464   * to be merged into another array.
2465   *
2466   * @since 2.2.0
2467   *
2468   * @param string|array $args Value to merge with $defaults
2469   * @param array $defaults Array that serves as the defaults.
2470   * @return array Merged user defined values with defaults.
2471   */
2472  function wp_parse_args( $args, $defaults = '' ) {
2473      if ( is_object( $args ) )
2474          $r = get_object_vars( $args );
2475      elseif ( is_array( $args ) )
2476          $r =& $args;
2477      else
2478          wp_parse_str( $args, $r );
2479  
2480      if ( is_array( $defaults ) )
2481          return array_merge( $defaults, $r );
2482      return $r;
2483  }
2484  
2485  /**
2486   * Determines if Widgets library should be loaded.
2487   *
2488   * Checks to make sure that the widgets library hasn't already been loaded. If
2489   * it hasn't, then it will load the widgets library and run an action hook.
2490   *
2491   * @since 2.2.0
2492   * @uses add_action() Calls '_admin_menu' hook with 'wp_widgets_add_menu' value.
2493   */
2494  function wp_maybe_load_widgets() {
2495      if ( !function_exists( 'dynamic_sidebar' ) ) {
2496          require_once ( ABSPATH . WPINC . '/widgets.php' );
2497          add_action( '_admin_menu', 'wp_widgets_add_menu' );
2498      }
2499  }
2500  
2501  /**
2502   * Append the Widgets menu to the themes main menu.
2503   *
2504   * @since 2.2.0
2505   * @uses $submenu The administration submenu list.
2506   */
2507  function wp_widgets_add_menu() {
2508      global $submenu;
2509      $submenu['themes.php'][7] = array( __( 'Widgets' ), 'switch_themes', 'widgets.php' );
2510      ksort( $submenu['themes.php'], SORT_NUMERIC );
2511  }
2512  
2513  /**
2514   * Flush all output buffers for PHP 5.2.
2515   *
2516   * Make sure all output buffers are flushed before our singletons our destroyed.
2517   *
2518   * @since 2.2.0
2519   */
2520  function wp_ob_end_flush_all() {
2521      while ( @ob_end_flush() );
2522  }
2523  
2524  /**
2525   * Load the correct database class file.
2526   *
2527   * This function is used to load the database class file either at runtime or by
2528   * wp-admin/setup-config.php We must globalise $wpdb to ensure that it is
2529   * defined globally by the inline code in wp-db.php.
2530   *
2531   * @since 2.5.0
2532   * @global $wpdb WordPress Database Object
2533   */
2534  function require_wp_db() {
2535      global $wpdb;
2536      if ( file_exists( WP_CONTENT_DIR . '/db.php' ) )
2537          require_once( WP_CONTENT_DIR . '/db.php' );
2538      else
2539          require_once ( ABSPATH . WPINC . '/wp-db.php' );
2540  }
2541  
2542  /**
2543   * Load custom DB error or display WordPress DB error.
2544   *
2545   * If a file exists in the wp-content directory named db-error.php, then it will
2546   * be loaded instead of displaying the WordPress DB error. If it is not found,
2547   * then the WordPress DB error will be displayed instead.
2548   *
2549   * The WordPress DB error sets the HTTP status header to 500 to try to prevent
2550   * search engines from caching the message. Custom DB messages should do the
2551   * same.
2552   *
2553   * This function was backported to the the WordPress 2.3.2, but originally was
2554   * added in WordPress 2.5.0.
2555   *
2556   * @since 2.3.2
2557   * @uses $wpdb
2558   */
2559  function dead_db() {
2560      global $wpdb;
2561  
2562      // Load custom DB error template, if present.
2563      if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
2564          require_once( WP_CONTENT_DIR . '/db-error.php' );
2565          die();
2566      }
2567  
2568      // If installing or in the admin, provide the verbose message.
2569      if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
2570          wp_die($wpdb->error);
2571  
2572      // Otherwise, be terse.
2573      status_header( 500 );
2574      nocache_headers();
2575      header( 'Content-Type: text/html; charset=utf-8' );
2576  ?>
2577  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2578  <html xmlns="http://www.w3.org/1999/xhtml" <?php if ( function_exists( 'language_attributes' ) ) language_attributes(); ?>>
2579  <head>
2580  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2581      <title>Database Error</title>
2582  
2583  </head>
2584  <body>
2585      <h1>Error establishing a database connection</h1>
2586  </body>
2587  </html>
2588  <?php
2589      die();
2590  }
2591  
2592  /**
2593   * Converts value to positive integer.
2594   *
2595   * @since 2.5.0
2596   *
2597   * @param mixed $maybeint Data you wish to have convered to an absolute integer
2598   * @return int An absolute integer
2599   */
2600  function absint( $maybeint ) {
2601      return abs( intval( $maybeint ) );
2602  }
2603  
2604  /**
2605   * Determines if the blog can be accessed over SSL.
2606   *
2607   * Determines if blog can be accessed over SSL by using cURL to access the site
2608   * using the https in the siteurl. Requires cURL extension to work correctly.
2609   *
2610   * @since 2.5.0
2611   *
2612   * @return bool Whether or not SSL access is available
2613   */
2614  function url_is_accessable_via_ssl($url)
2615  {
2616      if (in_array('curl', get_loaded_extensions())) {
2617          $ssl = preg_replace( '/^http:\/\//', 'https://',  $url );
2618  
2619          $ch = curl_init();
2620          curl_setopt($ch, CURLOPT_URL, $ssl);
2621          curl_setopt($ch, CURLOPT_FAILONERROR, true);
2622          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
2623          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
2624  
2625          curl_exec($ch);
2626  
2627          $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
2628          curl_close ($ch);
2629  
2630          if ($status == 200 || $status == 401) {
2631              return true;
2632          }
2633      }
2634      return false;
2635  }
2636  
2637  /**
2638   * Secure URL, if available or the given URL.
2639   *
2640   * @since 2.5.0
2641   *
2642   * @param string $url Complete URL path with transport.
2643   * @return string Secure or regular URL path.
2644   */
2645  function atom_service_url_filter($url)
2646  {
2647      if ( url_is_accessable_via_ssl($url) )
2648          return preg_replace( '/^http:\/\//', 'https://',  $url );
2649      else
2650          return $url;
2651  }
2652  
2653  /**
2654   * Marks a function as deprecated and informs when it has been used.
2655   *
2656   * There is a hook deprecated_function_run that will be called that can be used
2657   * to get the backtrace up to what file and function called the deprecated
2658   * function.
2659   *
2660   * The current behavior is to trigger an user error if WP_DEBUG is defined and
2661   * is true.
2662   *
2663   * This function is to be used in every function in depreceated.php
2664   *
2665   * @package WordPress
2666   * @package Debug
2667   * @since 2.5.0
2668   * @access private
2669   *
2670   * @uses do_action() Calls 'deprecated_function_run' and passes the function name and what to use instead.
2671   * @uses apply_filters() Calls 'deprecated_function_trigger_error' and expects boolean value of true to do trigger or false to not trigger error.
2672   *
2673   * @param string $function The function that was called
2674   * @param string $version The version of WordPress that deprecated the function
2675   * @param string $replacement Optional. The function that should have been called
2676   */
2677  function _deprecated_function($function, $version, $replacement=null) {
2678  
2679      do_action('deprecated_function_run', $function, $replacement);
2680  
2681      // Allow plugin to filter the output error trigger
2682      if( defined('WP_DEBUG') && ( true === WP_DEBUG ) && apply_filters( 'deprecated_function_trigger_error', true )) {
2683          if( !is_null($replacement) )
2684              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
2685          else
2686              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
2687      }
2688  }
2689  
2690  /**
2691   * Marks a file as deprecated and informs when it has been used.
2692   *
2693   * There is a hook deprecated_file_included that will be called that can be used
2694   * to get the backtrace up to what file and function included the deprecated
2695   * file.
2696   *
2697   * The current behavior is to trigger an user error if WP_DEBUG is defined and
2698   * is true.
2699   *
2700   * This function is to be used in every file that is depreceated
2701   *
2702   * @package WordPress
2703   * @package Debug
2704   * @since 2.5.0
2705   * @access private
2706   *
2707   * @uses do_action() Calls 'deprecated_file_included' and passes the file name and what to use instead.
2708   * @uses apply_filters() Calls 'deprecated_file_trigger_error' and expects boolean value of true to do trigger or false to not trigger error.
2709   *
2710   * @param string $file The file that was included
2711   * @param string $version The version of WordPress that deprecated the function
2712   * @param string $replacement Optional. The function that should have been called
2713   */
2714  function _deprecated_file($file, $version, $replacement=null) {
2715  
2716      do_action('deprecated_file_included', $file, $replacement);
2717  
2718      // Allow plugin to filter the output error trigger
2719      if( defined('WP_DEBUG') && ( true === WP_DEBUG ) && apply_filters( 'deprecated_file_trigger_error', true )) {
2720          if( !is_null($replacement) )
2721              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) );
2722          else
2723              trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) );
2724      }
2725  }
2726  
2727  /**
2728   * Is the server running earlier than 1.5.0 version of lighttpd
2729   *
2730   * @since 2.5.0
2731   *
2732   * @return bool Whether the server is running lighttpd < 1.5.0
2733   */
2734  function is_lighttpd_before_150() {
2735      $server_parts = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] )? $_SERVER['SERVER_SOFTWARE'] : '' );
2736      $server_parts[1] = isset( $server_parts[1] )? $server_parts[1] : '';
2737      return  'lighttpd' == $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' );
2738  }
2739  
2740  /**
2741   * Does the specified module exist in the apache config?
2742   *
2743   * @since 2.5.0
2744   *
2745   * @param string $mod e.g. mod_rewrite
2746   * @param bool $default The default return value if the module is not found
2747   * @return bool
2748   */
2749  function apache_mod_loaded($mod, $default = false) {
2750      global $is_apache;
2751  
2752      if ( !$is_apache )
2753          return false;
2754  
2755      if ( function_exists('apache_get_modules') ) {
2756          $mods = apache_get_modules();
2757          if ( in_array($mod, $mods) )
2758              return true;
2759      } elseif ( function_exists('phpinfo') ) {
2760              ob_start();
2761              phpinfo(8);
2762              $phpinfo = ob_get_clean();
2763              if ( false !== strpos($phpinfo, $mod) )
2764                  return true;
2765      }
2766      return $default;
2767  }
2768  
2769  /**
2770   * File validates against allowed set of defined rules.
2771   *
2772   * A return value of '1' means that the $file contains either '..' or './'. A
2773   * return value of '2' means that the $file contains ':' after the first
2774   * character. A return value of '3' means that the file is not in the allowed
2775   * files list.
2776   *
2777   * @since 1.2.0
2778   *
2779   * @param string $file File path.
2780   * @param array $allowed_files List of allowed files.
2781   * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
2782   */
2783  function validate_file( $file, $allowed_files = '' ) {
2784      if ( false !== strpos( $file, '..' ))
2785          return 1;
2786  
2787      if ( false !== strpos( $file, './' ))
2788          return 1;
2789  
2790      if (':' == substr( $file, 1, 1 ))
2791          return 2;
2792  
2793      if (!empty ( $allowed_files ) && (!in_array( $file, $allowed_files ) ) )
2794          return 3;
2795  
2796      return 0;
2797  }
2798  
2799  /**
2800   * Determine if SSL is used.
2801   *
2802   * @since 2.6.0
2803   *
2804   * @return bool True if SSL, false if not used.
2805   */
2806  function is_ssl() {
2807      if ( isset($_SERVER['HTTPS']) ) {
2808          if ( 'on' == strtolower($_SERVER['HTTPS']) )
2809              return true;
2810          if ( '1' == $_SERVER['HTTPS'] )
2811              return true;
2812      } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
2813          return true;
2814      }
2815      return false;
2816  }
2817  
2818  /**
2819   * Whether SSL login should be forced.
2820   *
2821   * @since 2.6.0
2822   *
2823   * @param string|bool $force Optional.
2824   * @return bool True if forced, false if not forced.
2825   */
2826  function force_ssl_login($force = '') {
2827      static $forced;
2828  
2829      if ( '' != $force ) {
2830          $old_forced = $forced;
2831          $forced = $force;
2832          return $old_forced;
2833      }
2834  
2835      return $forced;
2836  }
2837  
2838  /**
2839   * Whether to force SSL used for the Administration Panels.
2840   *
2841   * @since 2.6.0
2842   *
2843   * @param string|bool $force
2844   * @return bool True if forced, false if not forced.
2845   */
2846  function force_ssl_admin($force = '') {
2847      static $forced;
2848  
2849      if ( '' != $force ) {
2850          $old_forced = $forced;
2851          $forced = $force;
2852          return $old_forced;
2853      }
2854  
2855      return $forced;
2856  }
2857  
2858  /**
2859   * Guess the URL for the site.
2860   *
2861   * Will remove wp-admin links to retrieve only return URLs not in the wp-admin
2862   * directory.
2863   *
2864   * @since 2.6.0
2865   *
2866   * @return string
2867   */
2868  function wp_guess_url() {
2869      if ( defined('WP_SITEURL') && '' != WP_SITEURL ) {
2870          $url = WP_SITEURL;
2871      } else {
2872          $schema = ( isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ) ? 'https://' : 'http://';
2873          $url = preg_replace('|/wp-admin/.*|i', '', $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
2874      }
2875      return $url;
2876  }
2877  
2878  /**
2879   * Suspend cache invalidation.
2880   *
2881   * Turns cache invalidation on and off.  Useful during imports where you don't wont to do invalidations
2882   * every time a post is inserted.  Callers must be sure that what they are doing won't lead to an inconsistent
2883   * cache when invalidation is suspended.
2884   *
2885   * @since 2.7.0
2886   *
2887   * @param bool $suspend Whether to suspend or enable cache invalidation
2888   * @return bool The current suspend setting
2889   */
2890  function wp_suspend_cache_invalidation($suspend = true) {
2891      global $_wp_suspend_cache_invalidation;
2892  
2893      $current_suspend = $_wp_suspend_cache_invalidation;
2894      $_wp_suspend_cache_invalidation = $suspend;
2895      return $current_suspend;
2896  }
2897  
2898  /**
2899   * Copy an object.
2900   *
2901   * Returns a cloned copy of an object.
2902   *
2903   * @since 2.7.0
2904   *
2905   * @param object $object The object to clone
2906   * @return object The cloned object
2907   */
2908  function wp_clone( $object ) {
2909      static $can_clone;
2910      if ( !isset( $can_clone ) ) {
2911          $can_clone = version_compare( phpversion(), '5.0', '>=' );
2912      }
2913      return $can_clone ? clone( $object ) : $object;
2914  }
2915  
2916  
2917  ?>


Generated: Mon Mar 23 16:23:02 2009 Cross-referenced by PHPXref 0.7