[ Index ] |
WordPress Cross Reference |
[Summary view] [Print] [Text view]
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( '&', '&', $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? __('« Back') : '« 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 › Error') : 'WordPress › 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 25 01:41:18 2014 | WordPress honlapkészítés: online1.hu |