[ Index ]

WordPress Cross Reference

title

Body

[close]

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

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


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu