8 require( ABSPATH . WPINC . '/option.php' );
11 * Converts given date string into a different format.
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.
16 * If $translate is true then the given date and format string will
17 * be passed to date_i18n() for translation.
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.
26 function mysql2date( $format, $date, $translate = true ) {
31 return strtotime( $date . ' +0000' );
33 $i = strtotime( $date );
39 return date_i18n( $format, $i );
41 return date( $format, $i );
45 * Retrieve the current time based on specified type.
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 * Other strings will be interpreted as PHP date formats (e.g. 'Y-m-d').
51 * If $gmt is set to either '1' or 'true', then both types will use GMT time.
52 * if $gmt is false, the output is adjusted with the GMT offset in the WordPress option.
56 * @param string $type 'mysql', 'timestamp', or PHP date format string (e.g. 'Y-m-d').
57 * @param int|bool $gmt Optional. Whether to use GMT timezone. Default is false.
58 * @return int|string String if $type is 'gmt', int if $type is 'timestamp'.
60 function current_time( $type, $gmt = 0 ) {
63 return ( $gmt ) ? gmdate( 'Y-m-d H:i:s' ) : gmdate( 'Y-m-d H:i:s', ( time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ) );
66 return ( $gmt ) ? time() : time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
69 return ( $gmt ) ? date( $type ) : date( $type, time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
75 * Retrieve the date in localized format, based on timestamp.
77 * If the locale specifies the locale month and weekday, then the locale will
78 * take over the format for the date. If it isn't, then the date format string
79 * will be used instead.
83 * @param string $dateformatstring Format to display the date.
84 * @param int $unixtimestamp Optional. Unix timestamp.
85 * @param bool $gmt Optional, default is false. Whether to convert to GMT for time.
86 * @return string The date, translated if locale specifies it.
88 function date_i18n( $dateformatstring, $unixtimestamp = false, $gmt = false ) {
94 $i = current_time( 'timestamp' );
97 // we should not let date() interfere with our
98 // specially computed timestamp
102 // store original value for language with untypical grammars
103 // see http://core.trac.wordpress.org/ticket/9396
104 $req_format = $dateformatstring;
106 $datefunc = $gmt? 'gmdate' : 'date';
108 if ( ( !empty( $wp_locale->month ) ) && ( !empty( $wp_locale->weekday ) ) ) {
109 $datemonth = $wp_locale->get_month( $datefunc( 'm', $i ) );
110 $datemonth_abbrev = $wp_locale->get_month_abbrev( $datemonth );
111 $dateweekday = $wp_locale->get_weekday( $datefunc( 'w', $i ) );
112 $dateweekday_abbrev = $wp_locale->get_weekday_abbrev( $dateweekday );
113 $datemeridiem = $wp_locale->get_meridiem( $datefunc( 'a', $i ) );
114 $datemeridiem_capital = $wp_locale->get_meridiem( $datefunc( 'A', $i ) );
115 $dateformatstring = ' '.$dateformatstring;
116 $dateformatstring = preg_replace( "/([^\\\])D/", "\\1" . backslashit( $dateweekday_abbrev ), $dateformatstring );
117 $dateformatstring = preg_replace( "/([^\\\])F/", "\\1" . backslashit( $datemonth ), $dateformatstring );
118 $dateformatstring = preg_replace( "/([^\\\])l/", "\\1" . backslashit( $dateweekday ), $dateformatstring );
119 $dateformatstring = preg_replace( "/([^\\\])M/", "\\1" . backslashit( $datemonth_abbrev ), $dateformatstring );
120 $dateformatstring = preg_replace( "/([^\\\])a/", "\\1" . backslashit( $datemeridiem ), $dateformatstring );
121 $dateformatstring = preg_replace( "/([^\\\])A/", "\\1" . backslashit( $datemeridiem_capital ), $dateformatstring );
123 $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
125 $timezone_formats = array( 'P', 'I', 'O', 'T', 'Z', 'e' );
126 $timezone_formats_re = implode( '|', $timezone_formats );
127 if ( preg_match( "/$timezone_formats_re/", $dateformatstring ) ) {
128 $timezone_string = get_option( 'timezone_string' );
129 if ( $timezone_string ) {
130 $timezone_object = timezone_open( $timezone_string );
131 $date_object = date_create( null, $timezone_object );
132 foreach( $timezone_formats as $timezone_format ) {
133 if ( false !== strpos( $dateformatstring, $timezone_format ) ) {
134 $formatted = date_format( $date_object, $timezone_format );
135 $dateformatstring = ' '.$dateformatstring;
136 $dateformatstring = preg_replace( "/([^\\\])$timezone_format/", "\\1" . backslashit( $formatted ), $dateformatstring );
137 $dateformatstring = substr( $dateformatstring, 1, strlen( $dateformatstring ) -1 );
142 $j = @$datefunc( $dateformatstring, $i );
145 * Filter the date formatted based on the locale.
149 * @param string $j Formatted date string.
150 * @param string $req_format Format to display the date.
151 * @param int $i Unix timestamp.
152 * @param bool $gmt Whether to convert to GMT for time. Default false.
154 $j = apply_filters( 'date_i18n', $j, $req_format, $i, $gmt );
159 * Convert integer number to format based on the locale.
163 * @param int $number The number to convert based on locale.
164 * @param int $decimals Precision of the number of decimal places.
165 * @return string Converted number in string format.
167 function number_format_i18n( $number, $decimals = 0 ) {
169 $formatted = number_format( $number, absint( $decimals ), $wp_locale->number_format['decimal_point'], $wp_locale->number_format['thousands_sep'] );
172 * Filter the number formatted based on the locale.
176 * @param string $formatted Converted number in string format.
178 return apply_filters( 'number_format_i18n', $formatted );
182 * Convert number of bytes largest unit bytes will fit into.
184 * It is easier to read 1kB than 1024 bytes and 1MB than 1048576 bytes. Converts
185 * number of bytes to human readable number by taking the number of that unit
186 * that the bytes will go into it. Supports TB value.
188 * Please note that integers in PHP are limited to 32 bits, unless they are on
189 * 64 bit architecture, then they have 64 bit size. If you need to place the
190 * larger size then what PHP integer type will hold, then use a string. It will
191 * be converted to a double, which should always have 64 bit length.
193 * Technically the correct unit names for powers of 1024 are KiB, MiB etc.
194 * @link http://en.wikipedia.org/wiki/Byte
198 * @param int|string $bytes Number of bytes. Note max integer size for integers.
199 * @param int $decimals Precision of number of decimal places. Deprecated.
200 * @return bool|string False on failure. Number string on success.
202 function size_format( $bytes, $decimals = 0 ) {
204 // ========================= Origin ====
205 'TB' => 1099511627776, // pow( 1024, 4)
206 'GB' => 1073741824, // pow( 1024, 3)
207 'MB' => 1048576, // pow( 1024, 2)
208 'kB' => 1024, // pow( 1024, 1)
209 'B ' => 1, // pow( 1024, 0)
211 foreach ( $quant as $unit => $mag )
212 if ( doubleval($bytes) >= $mag )
213 return number_format_i18n( $bytes / $mag, $decimals ) . ' ' . $unit;
219 * Get the week start and end from the datetime or date string from mysql.
223 * @param string $mysqlstring Date or datetime field type from mysql.
224 * @param int $start_of_week Optional. Start of the week as an integer.
225 * @return array Keys are 'start' and 'end'.
227 function get_weekstartend( $mysqlstring, $start_of_week = '' ) {
228 $my = substr( $mysqlstring, 0, 4 ); // Mysql string Year
229 $mm = substr( $mysqlstring, 8, 2 ); // Mysql string Month
230 $md = substr( $mysqlstring, 5, 2 ); // Mysql string day
231 $day = mktime( 0, 0, 0, $md, $mm, $my ); // The timestamp for mysqlstring day.
232 $weekday = date( 'w', $day ); // The day of the week from the timestamp
233 if ( !is_numeric($start_of_week) )
234 $start_of_week = get_option( 'start_of_week' );
236 if ( $weekday < $start_of_week )
239 $start = $day - DAY_IN_SECONDS * ( $weekday - $start_of_week ); // The most recent week start day on or before $day
240 $end = $start + 7 * DAY_IN_SECONDS - 1; // $start + 7 days - 1 second
241 return compact( 'start', 'end' );
245 * Unserialize value only if it was serialized.
249 * @param string $original Maybe unserialized original, if is needed.
250 * @return mixed Unserialized data can be any type.
252 function maybe_unserialize( $original ) {
253 if ( is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
254 return @unserialize( $original );
259 * Check value to find if it was serialized.
261 * If $data is not an string, then returned value will always be false.
262 * Serialized data is always a string.
266 * @param mixed $data Value to check to see if was serialized.
267 * @param bool $strict Optional. Whether to be strict about the end of the string. Defaults true.
268 * @return bool False if not serialized and true if it was.
270 function is_serialized( $data, $strict = true ) {
271 // if it isn't a string, it isn't serialized
272 if ( ! is_string( $data ) ) {
275 $data = trim( $data );
276 if ( 'N;' == $data ) {
279 if ( strlen( $data ) < 4 ) {
282 if ( ':' !== $data[1] ) {
286 $lastc = substr( $data, -1 );
287 if ( ';' !== $lastc && '}' !== $lastc ) {
291 $semicolon = strpos( $data, ';' );
292 $brace = strpos( $data, '}' );
293 // Either ; or } must exist.
294 if ( false === $semicolon && false === $brace )
296 // But neither must be in the first X characters.
297 if ( false !== $semicolon && $semicolon < 3 )
299 if ( false !== $brace && $brace < 4 )
306 if ( '"' !== substr( $data, -2, 1 ) ) {
309 } elseif ( false === strpos( $data, '"' ) ) {
312 // or else fall through
315 return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
319 $end = $strict ? '$' : '';
320 return (bool) preg_match( "/^{$token}:[0-9.E-]+;$end/", $data );
326 * Check whether serialized data is of string type.
330 * @param mixed $data Serialized data
331 * @return bool False if not a serialized string, true if it is.
333 function is_serialized_string( $data ) {
334 // if it isn't a string, it isn't a serialized string
335 if ( ! is_string( $data ) ) {
338 $data = trim( $data );
339 if ( strlen( $data ) < 4 ) {
341 } elseif ( ':' !== $data[1] ) {
343 } elseif ( ';' !== substr( $data, -1 ) ) {
345 } elseif ( $data[0] !== 's' ) {
347 } elseif ( '"' !== substr( $data, -2, 1 ) ) {
355 * Serialize data, if needed.
359 * @param mixed $data Data that might be serialized.
360 * @return mixed A scalar data
362 function maybe_serialize( $data ) {
363 if ( is_array( $data ) || is_object( $data ) )
364 return serialize( $data );
366 // Double serialization is required for backward compatibility.
367 // See http://core.trac.wordpress.org/ticket/12930
368 if ( is_serialized( $data, false ) )
369 return serialize( $data );
375 * Retrieve post title from XMLRPC XML.
377 * If the title element is not part of the XML, then the default post title from
378 * the $post_default_title will be used instead.
382 * @global string $post_default_title Default XMLRPC post title.
384 * @param string $content XMLRPC XML Request content
385 * @return string Post title
387 function xmlrpc_getposttitle( $content ) {
388 global $post_default_title;
389 if ( preg_match( '/<title>(.+?)<\/title>/is', $content, $matchtitle ) ) {
390 $post_title = $matchtitle[1];
392 $post_title = $post_default_title;
398 * Retrieve the post category or categories from XMLRPC XML.
400 * If the category element is not found, then the default post category will be
401 * used. The return type then would be what $post_default_category. If the
402 * category is found, then it will always be an array.
406 * @global string $post_default_category Default XMLRPC post category.
408 * @param string $content XMLRPC XML Request content
409 * @return string|array List of categories or category name.
411 function xmlrpc_getpostcategory( $content ) {
412 global $post_default_category;
413 if ( preg_match( '/<category>(.+?)<\/category>/is', $content, $matchcat ) ) {
414 $post_category = trim( $matchcat[1], ',' );
415 $post_category = explode( ',', $post_category );
417 $post_category = $post_default_category;
419 return $post_category;
423 * XMLRPC XML content without title and category elements.
427 * @param string $content XMLRPC XML Request content
428 * @return string XMLRPC XML Request content without title and category elements.
430 function xmlrpc_removepostdata( $content ) {
431 $content = preg_replace( '/<title>(.+?)<\/title>/si', '', $content );
432 $content = preg_replace( '/<category>(.+?)<\/category>/si', '', $content );
433 $content = trim( $content );
438 * Use RegEx to extract URLs from arbitrary content
442 * @param string $content
443 * @return array URLs found in passed string
445 function wp_extract_urls( $content ) {
447 "#((?:[\w-]+://?|[\w\d]+[.])[^\s()<>]+[.](?:\([\w\d]+\)|(?:[^`!()\[\]{};:'\".,<>?«»“”‘’\s]|(?:[:]\d+)?/?)+))#",
452 $post_links = array_unique( array_map( 'html_entity_decode', $post_links[0] ) );
454 return array_values( $post_links );
458 * Check content for video and audio links to add as enclosures.
460 * Will not add enclosures that have already been added and will
461 * remove enclosures that are no longer in the post. This is called as
462 * pingbacks and trackbacks.
468 * @param string $content Post Content
469 * @param int $post_ID Post ID
471 function do_enclose( $content, $post_ID ) {
474 //TODO: Tidy this ghetto code up and make the debug code optional
475 include_once( ABSPATH . WPINC . '/class-IXR.php' );
477 $post_links = array();
479 $pung = get_enclosed( $post_ID );
481 $post_links_temp = wp_extract_urls( $content );
483 foreach ( $pung as $link_test ) {
484 if ( ! in_array( $link_test, $post_links_temp ) ) { // link no longer in post
485 $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 ) . '%') );
486 foreach ( $mids as $mid )
487 delete_metadata_by_mid( 'post', $mid );
491 foreach ( (array) $post_links_temp as $link_test ) {
492 if ( !in_array( $link_test, $pung ) ) { // If we haven't pung it already
493 $test = @parse_url( $link_test );
494 if ( false === $test )
496 if ( isset( $test['query'] ) )
497 $post_links[] = $link_test;
498 elseif ( isset($test['path']) && ( $test['path'] != '/' ) && ($test['path'] != '' ) )
499 $post_links[] = $link_test;
503 foreach ( (array) $post_links as $url ) {
504 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 ) . '%' ) ) ) {
506 if ( $headers = wp_get_http_headers( $url) ) {
507 $len = isset( $headers['content-length'] ) ? (int) $headers['content-length'] : 0;
508 $type = isset( $headers['content-type'] ) ? $headers['content-type'] : '';
509 $allowed_types = array( 'video', 'audio' );
511 // Check to see if we can figure out the mime type from
513 $url_parts = @parse_url( $url );
514 if ( false !== $url_parts ) {
515 $extension = pathinfo( $url_parts['path'], PATHINFO_EXTENSION );
516 if ( !empty( $extension ) ) {
517 foreach ( wp_get_mime_types() as $exts => $mime ) {
518 if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
526 if ( in_array( substr( $type, 0, strpos( $type, "/" ) ), $allowed_types ) ) {
527 add_post_meta( $post_ID, 'enclosure', "$url\n$len\n$mime\n" );
535 * Perform a HTTP HEAD or GET request.
537 * If $file_path is a writable filename, this will do a GET request and write
538 * the file to that path.
542 * @param string $url URL to fetch.
543 * @param string|bool $file_path Optional. File path to write request to.
544 * @param int $red (private) The number of Redirects followed, Upon 5 being hit, returns false.
545 * @return bool|string False on failure and string of headers if HEAD request.
547 function wp_get_http( $url, $file_path = false, $red = 1 ) {
548 @set_time_limit( 60 );
554 $options['redirection'] = 5;
556 if ( false == $file_path )
557 $options['method'] = 'HEAD';
559 $options['method'] = 'GET';
561 $response = wp_safe_remote_request( $url, $options );
563 if ( is_wp_error( $response ) )
566 $headers = wp_remote_retrieve_headers( $response );
567 $headers['response'] = wp_remote_retrieve_response_code( $response );
569 // WP_HTTP no longer follows redirects for HEAD requests.
570 if ( 'HEAD' == $options['method'] && in_array($headers['response'], array(301, 302)) && isset( $headers['location'] ) ) {
571 return wp_get_http( $headers['location'], $file_path, ++$red );
574 if ( false == $file_path )
577 // GET request - write it to the supplied filename
578 $out_fp = fopen($file_path, 'w');
582 fwrite( $out_fp, wp_remote_retrieve_body( $response ) );
590 * Retrieve HTTP Headers from URL.
595 * @param bool $deprecated Not Used.
596 * @return bool|string False on failure, headers on success.
598 function wp_get_http_headers( $url, $deprecated = false ) {
599 if ( !empty( $deprecated ) )
600 _deprecated_argument( __FUNCTION__, '2.7' );
602 $response = wp_safe_remote_head( $url );
604 if ( is_wp_error( $response ) )
607 return wp_remote_retrieve_headers( $response );
611 * Whether today is a new day.
615 * @uses $previousday Previous day
617 * @return int 1 when new day, 0 if not a new day.
619 function is_new_day() {
620 global $currentday, $previousday;
621 if ( $currentday != $previousday )
628 * Build URL query based on an associative and, or indexed array.
630 * This is a convenient function for easily building url queries. It sets the
631 * separator to '&' and uses _http_build_query() function.
633 * @see _http_build_query() Used to build the query
634 * @link http://us2.php.net/manual/en/function.http-build-query.php more on what
635 * http_build_query() does.
639 * @param array $data URL-encode key/value pairs.
640 * @return string URL encoded string
642 function build_query( $data ) {
643 return _http_build_query( $data, null, '&', '', false );
646 // from php.net (modified by Mark Jaquith to behave like the native PHP5 function)
647 function _http_build_query($data, $prefix=null, $sep=null, $key='', $urlencode=true) {
650 foreach ( (array) $data as $k => $v ) {
653 if ( is_int($k) && $prefix != null )
656 $k = $key . '%5B' . $k . '%5D';
659 elseif ( $v === FALSE )
662 if ( is_array($v) || is_object($v) )
663 array_push($ret,_http_build_query($v, '', $sep, $k, $urlencode));
664 elseif ( $urlencode )
665 array_push($ret, $k.'='.urlencode($v));
667 array_push($ret, $k.'='.$v);
671 $sep = ini_get('arg_separator.output');
673 return implode($sep, $ret);
677 * Retrieve a modified URL query string.
679 * You can rebuild the URL and append a new query variable to the URL query by
680 * using this function. You can also retrieve the full URL with query data.
682 * Adding a single key & value or an associative array. Setting a key value to
683 * an empty string removes the key. Omitting oldquery_or_uri uses the $_SERVER
684 * value. Additional values provided are expected to be encoded appropriately
685 * with urlencode() or rawurlencode().
689 * @param mixed $param1 Either newkey or an associative_array
690 * @param mixed $param2 Either newvalue or oldquery or uri
691 * @param mixed $param3 Optional. Old query or uri
692 * @return string New URL query string.
694 function add_query_arg() {
696 $args = func_get_args();
697 if ( is_array( $args[0] ) ) {
698 if ( count( $args ) < 2 || false === $args[1] )
699 $uri = $_SERVER['REQUEST_URI'];
703 if ( count( $args ) < 3 || false === $args[2] )
704 $uri = $_SERVER['REQUEST_URI'];
709 if ( $frag = strstr( $uri, '#' ) )
710 $uri = substr( $uri, 0, -strlen( $frag ) );
714 if ( 0 === stripos( $uri, 'http://' ) ) {
715 $protocol = 'http://';
716 $uri = substr( $uri, 7 );
717 } elseif ( 0 === stripos( $uri, 'https://' ) ) {
718 $protocol = 'https://';
719 $uri = substr( $uri, 8 );
724 if ( strpos( $uri, '?' ) !== false ) {
725 list( $base, $query ) = explode( '?', $uri, 2 );
727 } elseif ( $protocol || strpos( $uri, '=' ) === false ) {
735 wp_parse_str( $query, $qs );
736 $qs = urlencode_deep( $qs ); // this re-URL-encodes things that were already in the query string
737 if ( is_array( $args[0] ) ) {
739 $qs = array_merge( $qs, $kayvees );
741 $qs[ $args[0] ] = $args[1];
744 foreach ( $qs as $k => $v ) {
749 $ret = build_query( $qs );
750 $ret = trim( $ret, '?' );
751 $ret = preg_replace( '#=(&|$)#', '$1', $ret );
752 $ret = $protocol . $base . $ret . $frag;
753 $ret = rtrim( $ret, '?' );
758 * Removes an item or list from the query string.
762 * @param string|array $key Query key or keys to remove.
763 * @param bool $query When false uses the $_SERVER value.
764 * @return string New URL query string.
766 function remove_query_arg( $key, $query=false ) {
767 if ( is_array( $key ) ) { // removing multiple keys
768 foreach ( $key as $k )
769 $query = add_query_arg( $k, false, $query );
772 return add_query_arg( $key, false, $query );
776 * Walks the array while sanitizing the contents.
780 * @param array $array Array to walk while sanitizing contents.
781 * @return array Sanitized $array.
783 function add_magic_quotes( $array ) {
784 foreach ( (array) $array as $k => $v ) {
785 if ( is_array( $v ) ) {
786 $array[$k] = add_magic_quotes( $v );
788 $array[$k] = addslashes( $v );
795 * HTTP request for URI to retrieve content.
798 * @uses wp_remote_get()
800 * @param string $uri URI/URL of web page to retrieve.
801 * @return bool|string HTTP content. False on failure.
803 function wp_remote_fopen( $uri ) {
804 $parsed_url = @parse_url( $uri );
806 if ( !$parsed_url || !is_array( $parsed_url ) )
810 $options['timeout'] = 10;
812 $response = wp_safe_remote_get( $uri, $options );
814 if ( is_wp_error( $response ) )
817 return wp_remote_retrieve_body( $response );
821 * Set up the WordPress query.
825 * @param string $query_vars Default WP_Query arguments.
827 function wp( $query_vars = '' ) {
828 global $wp, $wp_query, $wp_the_query;
829 $wp->main( $query_vars );
831 if ( !isset($wp_the_query) )
832 $wp_the_query = $wp_query;
836 * Retrieve the description for the HTTP status.
840 * @param int $code HTTP status code.
841 * @return string Empty string if not found, or description if found.
843 function get_status_header_desc( $code ) {
844 global $wp_header_to_desc;
846 $code = absint( $code );
848 if ( !isset( $wp_header_to_desc ) ) {
849 $wp_header_to_desc = array(
851 101 => 'Switching Protocols',
857 203 => 'Non-Authoritative Information',
859 205 => 'Reset Content',
860 206 => 'Partial Content',
861 207 => 'Multi-Status',
864 300 => 'Multiple Choices',
865 301 => 'Moved Permanently',
868 304 => 'Not Modified',
871 307 => 'Temporary Redirect',
873 400 => 'Bad Request',
874 401 => 'Unauthorized',
875 402 => 'Payment Required',
878 405 => 'Method Not Allowed',
879 406 => 'Not Acceptable',
880 407 => 'Proxy Authentication Required',
881 408 => 'Request Timeout',
884 411 => 'Length Required',
885 412 => 'Precondition Failed',
886 413 => 'Request Entity Too Large',
887 414 => 'Request-URI Too Long',
888 415 => 'Unsupported Media Type',
889 416 => 'Requested Range Not Satisfiable',
890 417 => 'Expectation Failed',
891 418 => 'I\'m a teapot',
892 422 => 'Unprocessable Entity',
894 424 => 'Failed Dependency',
895 426 => 'Upgrade Required',
896 428 => 'Precondition Required',
897 429 => 'Too Many Requests',
898 431 => 'Request Header Fields Too Large',
900 500 => 'Internal Server Error',
901 501 => 'Not Implemented',
902 502 => 'Bad Gateway',
903 503 => 'Service Unavailable',
904 504 => 'Gateway Timeout',
905 505 => 'HTTP Version Not Supported',
906 506 => 'Variant Also Negotiates',
907 507 => 'Insufficient Storage',
908 510 => 'Not Extended',
909 511 => 'Network Authentication Required',
913 if ( isset( $wp_header_to_desc[$code] ) )
914 return $wp_header_to_desc[$code];
920 * Set HTTP status header.
923 * @see get_status_header_desc()
925 * @param int $code HTTP status code.
927 function status_header( $code ) {
928 $description = get_status_header_desc( $code );
930 if ( empty( $description ) )
933 $protocol = $_SERVER['SERVER_PROTOCOL'];
934 if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
935 $protocol = 'HTTP/1.0';
936 $status_header = "$protocol $code $description";
937 if ( function_exists( 'apply_filters' ) )
940 * Filter an HTTP status header.
944 * @param string $status_header HTTP status header.
945 * @param int $code HTTP status code.
946 * @param string $description Description for the status code.
947 * @param string $protocol Server protocol.
949 $status_header = apply_filters( 'status_header', $status_header, $code, $description, $protocol );
951 @header( $status_header, true, $code );
955 * Gets the header information to prevent caching.
957 * The several different headers cover the different ways cache prevention is handled
958 * by different browsers
962 * @return array The associative array of header names and field values.
964 function wp_get_nocache_headers() {
966 'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
967 'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
968 'Pragma' => 'no-cache',
971 if ( function_exists('apply_filters') ) {
973 * Filter the cache-controlling headers.
977 * @param array $headers {
978 * Header names and field values.
980 * @type string $Expires Expires header.
981 * @type string $Cache-Control Cache-Control header.
982 * @type string $Pragma Pragma header.
985 $headers = (array) apply_filters( 'nocache_headers', $headers );
987 $headers['Last-Modified'] = false;
992 * Sets the headers to prevent caching for the different browsers.
994 * Different browsers support different nocache headers, so several headers must
995 * be sent so that all of them get the point that no caching should occur.
998 * @see wp_get_nocache_headers()
1000 function nocache_headers() {
1001 $headers = wp_get_nocache_headers();
1003 unset( $headers['Last-Modified'] );
1005 // In PHP 5.3+, make sure we are not sending a Last-Modified header.
1006 if ( function_exists( 'header_remove' ) ) {
1007 @header_remove( 'Last-Modified' );
1009 // In PHP 5.2, send an empty Last-Modified header, but only as a
1010 // last resort to override a header already sent. #WP23021
1011 foreach ( headers_list() as $header ) {
1012 if ( 0 === stripos( $header, 'Last-Modified' ) ) {
1013 $headers['Last-Modified'] = '';
1019 foreach( $headers as $name => $field_value )
1020 @header("{$name}: {$field_value}");
1024 * Set the headers for caching for 10 days with JavaScript content type.
1028 function cache_javascript_headers() {
1029 $expiresOffset = 10 * DAY_IN_SECONDS;
1030 header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) );
1031 header( "Vary: Accept-Encoding" ); // Handle proxies
1032 header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $expiresOffset ) . " GMT" );
1036 * Retrieve the number of database queries during the WordPress execution.
1040 * @return int Number of database queries
1042 function get_num_queries() {
1044 return $wpdb->num_queries;
1048 * Whether input is yes or no. Must be 'y' to be true.
1052 * @param string $yn Character string containing either 'y' or 'n'
1053 * @return bool True if yes, false on anything else
1055 function bool_from_yn( $yn ) {
1056 return ( strtolower( $yn ) == 'y' );
1060 * Loads the feed template from the use of an action hook.
1062 * If the feed action does not have a hook, then the function will die with a
1063 * message telling the visitor that the feed is not valid.
1065 * It is better to only have one hook for each feed.
1069 * @uses $wp_query Used to tell if the use a comment feed.
1071 function do_feed() {
1074 $feed = get_query_var( 'feed' );
1076 // Remove the pad, if present.
1077 $feed = preg_replace( '/^_+/', '', $feed );
1079 if ( $feed == '' || $feed == 'feed' )
1080 $feed = get_default_feed();
1082 $hook = 'do_feed_' . $feed;
1083 if ( ! has_action( $hook ) )
1084 wp_die( __( 'ERROR: This is not a valid feed template.' ), '', array( 'response' => 404 ) );
1087 * Fires once the given feed is loaded.
1089 * The dynamic hook name, $hook, refers to the feed name.
1093 * @param bool $is_comment_feed Whether the feed is a comment feed.
1095 do_action( $hook, $wp_query->is_comment_feed );
1099 * Load the RDF RSS 0.91 Feed template.
1103 function do_feed_rdf() {
1104 load_template( ABSPATH . WPINC . '/feed-rdf.php' );
1108 * Load the RSS 1.0 Feed Template.
1112 function do_feed_rss() {
1113 load_template( ABSPATH . WPINC . '/feed-rss.php' );
1117 * Load either the RSS2 comment feed or the RSS2 posts feed.
1121 * @param bool $for_comments True for the comment feed, false for normal feed.
1123 function do_feed_rss2( $for_comments ) {
1124 if ( $for_comments )
1125 load_template( ABSPATH . WPINC . '/feed-rss2-comments.php' );
1127 load_template( ABSPATH . WPINC . '/feed-rss2.php' );
1131 * Load either Atom comment feed or Atom posts feed.
1135 * @param bool $for_comments True for the comment feed, false for normal feed.
1137 function do_feed_atom( $for_comments ) {
1139 load_template( ABSPATH . WPINC . '/feed-atom-comments.php');
1141 load_template( ABSPATH . WPINC . '/feed-atom.php' );
1145 * Display the robots.txt file content.
1147 * The echo content should be with usage of the permalinks or for creating the
1152 function do_robots() {
1153 header( 'Content-Type: text/plain; charset=utf-8' );
1156 * Fires when displaying the robots.txt file.
1160 do_action( 'do_robotstxt' );
1162 $output = "User-agent: *\n";
1163 $public = get_option( 'blog_public' );
1164 if ( '0' == $public ) {
1165 $output .= "Disallow: /\n";
1167 $site_url = parse_url( site_url() );
1168 $path = ( !empty( $site_url['path'] ) ) ? $site_url['path'] : '';
1169 $output .= "Disallow: $path/wp-admin/\n";
1170 $output .= "Disallow: $path/wp-includes/\n";
1174 * Filter the robots.txt output.
1178 * @param string $output Robots.txt output.
1179 * @param bool $public Whether the site is considered "public".
1181 echo apply_filters( 'robots_txt', $output, $public );
1185 * Test whether blog is already installed.
1187 * The cache will be checked first. If you have a cache plugin, which saves the
1188 * cache values, then this will work. If you use the default WordPress cache,
1189 * and the database goes away, then you might have problems.
1191 * Checks for the option siteurl for whether WordPress is installed.
1196 * @return bool Whether blog is already installed.
1198 function is_blog_installed() {
1201 // Check cache first. If options table goes away and we have true cached, oh well.
1202 if ( wp_cache_get( 'is_blog_installed' ) )
1205 $suppress = $wpdb->suppress_errors();
1206 if ( ! defined( 'WP_INSTALLING' ) ) {
1207 $alloptions = wp_load_alloptions();
1209 // If siteurl is not set to autoload, check it specifically
1210 if ( !isset( $alloptions['siteurl'] ) )
1211 $installed = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'siteurl'" );
1213 $installed = $alloptions['siteurl'];
1214 $wpdb->suppress_errors( $suppress );
1216 $installed = !empty( $installed );
1217 wp_cache_set( 'is_blog_installed', $installed );
1222 // If visiting repair.php, return true and let it take over.
1223 if ( defined( 'WP_REPAIRING' ) )
1226 $suppress = $wpdb->suppress_errors();
1228 // Loop over the WP tables. If none exist, then scratch install is allowed.
1229 // If one or more exist, suggest table repair since we got here because the options
1230 // table could not be accessed.
1231 $wp_tables = $wpdb->tables();
1232 foreach ( $wp_tables as $table ) {
1233 // The existence of custom user tables shouldn't suggest an insane state or prevent a clean install.
1234 if ( defined( 'CUSTOM_USER_TABLE' ) && CUSTOM_USER_TABLE == $table )
1236 if ( defined( 'CUSTOM_USER_META_TABLE' ) && CUSTOM_USER_META_TABLE == $table )
1239 if ( ! $wpdb->get_results( "DESCRIBE $table;" ) )
1242 // One or more tables exist. We are insane.
1244 wp_load_translations_early();
1246 // Die with a DB error.
1247 $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' );
1251 $wpdb->suppress_errors( $suppress );
1253 wp_cache_set( 'is_blog_installed', false );
1259 * Retrieve URL with nonce added to URL query.
1263 * @param string $actionurl URL to add nonce action.
1264 * @param string $action Optional. Nonce action name.
1265 * @param string $name Optional. Nonce name.
1266 * @return string Escaped URL with nonce action added.
1268 function wp_nonce_url( $actionurl, $action = -1, $name = '_wpnonce' ) {
1269 $actionurl = str_replace( '&', '&', $actionurl );
1270 return esc_html( add_query_arg( $name, wp_create_nonce( $action ), $actionurl ) );
1274 * Retrieve or display nonce hidden field for forms.
1276 * The nonce field is used to validate that the contents of the form came from
1277 * the location on the current site and not somewhere else. The nonce does not
1278 * offer absolute protection, but should protect against most cases. It is very
1279 * important to use nonce field in forms.
1281 * The $action and $name are optional, but if you want to have better security,
1282 * it is strongly suggested to set those two parameters. It is easier to just
1283 * call the function without any parameters, because validation of the nonce
1284 * doesn't require any parameters, but since crackers know what the default is
1285 * it won't be difficult for them to find a way around your nonce and cause
1288 * The input name will be whatever $name value you gave. The input value will be
1289 * the nonce creation value.
1293 * @param string $action Optional. Action name.
1294 * @param string $name Optional. Nonce name.
1295 * @param bool $referer Optional, default true. Whether to set the referer field for validation.
1296 * @param bool $echo Optional, default true. Whether to display or return hidden form field.
1297 * @return string Nonce field.
1299 function wp_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) {
1300 $name = esc_attr( $name );
1301 $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . wp_create_nonce( $action ) . '" />';
1304 $nonce_field .= wp_referer_field( false );
1309 return $nonce_field;
1313 * Retrieve or display referer hidden field for forms.
1315 * The referer link is the current Request URI from the server super global. The
1316 * input name is '_wp_http_referer', in case you wanted to check manually.
1320 * @param bool $echo Whether to echo or return the referer field.
1321 * @return string Referer field.
1323 function wp_referer_field( $echo = true ) {
1324 $referer_field = '<input type="hidden" name="_wp_http_referer" value="'. esc_attr( wp_unslash( $_SERVER['REQUEST_URI'] ) ) . '" />';
1327 echo $referer_field;
1328 return $referer_field;
1332 * Retrieve or display original referer hidden field for forms.
1334 * The input name is '_wp_original_http_referer' and will be either the same
1335 * value of {@link wp_referer_field()}, if that was posted already or it will
1336 * be the current page, if it doesn't exist.
1340 * @param bool $echo Whether to echo the original http referer
1341 * @param string $jump_back_to Optional, default is 'current'. Can be 'previous' or page you want to jump back to.
1342 * @return string Original referer field.
1344 function wp_original_referer_field( $echo = true, $jump_back_to = 'current' ) {
1345 if ( ! $ref = wp_get_original_referer() ) {
1346 $ref = 'previous' == $jump_back_to ? wp_get_referer() : wp_unslash( $_SERVER['REQUEST_URI'] );
1348 $orig_referer_field = '<input type="hidden" name="_wp_original_http_referer" value="' . esc_attr( $ref ) . '" />';
1350 echo $orig_referer_field;
1351 return $orig_referer_field;
1355 * Retrieve referer from '_wp_http_referer' or HTTP referer. If it's the same
1356 * as the current request URL, will return false.
1360 * @return string|bool False on failure. Referer URL on success.
1362 function wp_get_referer() {
1363 if ( ! function_exists( 'wp_validate_redirect' ) )
1366 if ( ! empty( $_REQUEST['_wp_http_referer'] ) )
1367 $ref = wp_unslash( $_REQUEST['_wp_http_referer'] );
1368 else if ( ! empty( $_SERVER['HTTP_REFERER'] ) )
1369 $ref = wp_unslash( $_SERVER['HTTP_REFERER'] );
1371 if ( $ref && $ref !== wp_unslash( $_SERVER['REQUEST_URI'] ) )
1372 return wp_validate_redirect( $ref, false );
1377 * Retrieve original referer that was posted, if it exists.
1381 * @return string|bool False if no original referer or original referer if set.
1383 function wp_get_original_referer() {
1384 if ( ! empty( $_REQUEST['_wp_original_http_referer'] ) && function_exists( 'wp_validate_redirect' ) )
1385 return wp_validate_redirect( wp_unslash( $_REQUEST['_wp_original_http_referer'] ), false );
1390 * Recursive directory creation based on full path.
1392 * Will attempt to set permissions on folders.
1396 * @param string $target Full path to attempt to create.
1397 * @return bool Whether the path was created. True if path already exists.
1399 function wp_mkdir_p( $target ) {
1402 // strip the protocol
1403 if( wp_is_stream( $target ) ) {
1404 list( $wrapper, $target ) = explode( '://', $target, 2 );
1407 // from php.net/mkdir user contributed notes
1408 $target = str_replace( '//', '/', $target );
1410 // put the wrapper back on the target
1411 if( $wrapper !== null ) {
1412 $target = $wrapper . '://' . $target;
1415 // safe mode fails with a trailing slash under certain PHP versions.
1416 $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
1417 if ( empty($target) )
1420 if ( file_exists( $target ) )
1421 return @is_dir( $target );
1423 // We need to find the permissions of the parent folder that exists and inherit that.
1424 $target_parent = dirname( $target );
1425 while ( '.' != $target_parent && ! is_dir( $target_parent ) ) {
1426 $target_parent = dirname( $target_parent );
1429 // Get the permission bits.
1431 if ( $stat = @stat( $target_parent ) ) {
1432 $dir_perms = $stat['mode'] & 0007777;
1437 if ( @mkdir( $target, $dir_perms, true ) ) {
1439 // If a umask is set that modifies $dir_perms, we'll have to re-set the $dir_perms correctly with chmod()
1440 if ( $dir_perms != ( $dir_perms & ~umask() ) ) {
1441 $folder_parts = explode( '/', substr( $target, strlen( $target_parent ) + 1 ) );
1442 for ( $i = 1; $i <= count( $folder_parts ); $i++ ) {
1443 @chmod( $target_parent . '/' . implode( '/', array_slice( $folder_parts, 0, $i ) ), $dir_perms );
1454 * Test if a give filesystem path is absolute ('/foo/bar', 'c:\windows').
1458 * @param string $path File path
1459 * @return bool True if path is absolute, false is not absolute.
1461 function path_is_absolute( $path ) {
1462 // this is definitive if true but fails if $path does not exist or contains a symbolic link
1463 if ( realpath($path) == $path )
1466 if ( strlen($path) == 0 || $path[0] == '.' )
1469 // windows allows absolute paths like this
1470 if ( preg_match('#^[a-zA-Z]:\\\\#', $path) )
1473 // a path starting with / or \ is absolute; anything else is relative
1474 return ( $path[0] == '/' || $path[0] == '\\' );
1478 * Join two filesystem paths together (e.g. 'give me $path relative to $base').
1480 * If the $path is absolute, then it the full path is returned.
1484 * @param string $base
1485 * @param string $path
1486 * @return string The path with the base or absolute path.
1488 function path_join( $base, $path ) {
1489 if ( path_is_absolute($path) )
1492 return rtrim($base, '/') . '/' . ltrim($path, '/');
1496 * Normalize a filesystem path.
1498 * Replaces backslashes with forward slashes for Windows systems,
1499 * and ensures no duplicate slashes exist.
1503 * @param string $path Path to normalize.
1504 * @return string Normalized path.
1506 function wp_normalize_path( $path ) {
1507 $path = str_replace( '\\', '/', $path );
1508 $path = preg_replace( '|/+|','/', $path );
1513 * Determines a writable directory for temporary files.
1514 * Function's preference is the return value of <code>sys_get_temp_dir()</code>,
1515 * followed by your PHP temporary upload directory, followed by WP_CONTENT_DIR,
1516 * before finally defaulting to /tmp/
1518 * In the event that this function does not find a writable location,
1519 * It may be overridden by the <code>WP_TEMP_DIR</code> constant in
1520 * your <code>wp-config.php</code> file.
1524 * @return string Writable temporary directory
1526 function get_temp_dir() {
1528 if ( defined('WP_TEMP_DIR') )
1529 return trailingslashit(WP_TEMP_DIR);
1532 return trailingslashit( $temp );
1534 if ( function_exists('sys_get_temp_dir') ) {
1535 $temp = sys_get_temp_dir();
1536 if ( @is_dir( $temp ) && wp_is_writable( $temp ) )
1537 return trailingslashit( $temp );
1540 $temp = ini_get('upload_tmp_dir');
1541 if ( @is_dir( $temp ) && wp_is_writable( $temp ) )
1542 return trailingslashit( $temp );
1544 $temp = WP_CONTENT_DIR . '/';
1545 if ( is_dir( $temp ) && wp_is_writable( $temp ) )
1553 * Determine if a directory is writable.
1555 * This function is used to work around certain ACL issues
1556 * in PHP primarily affecting Windows Servers.
1558 * @see win_is_writable()
1562 * @param string $path
1565 function wp_is_writable( $path ) {
1566 if ( 'WIN' === strtoupper( substr( PHP_OS, 0, 3 ) ) )
1567 return win_is_writable( $path );
1569 return @is_writable( $path );
1573 * Workaround for Windows bug in is_writable() function
1575 * PHP has issues with Windows ACL's for determine if a
1576 * directory is writable or not, this works around them by
1577 * checking the ability to open files rather than relying
1578 * upon PHP to interprate the OS ACL.
1580 * @link http://bugs.php.net/bug.php?id=27609
1581 * @link http://bugs.php.net/bug.php?id=30931
1585 * @param string $path
1588 function win_is_writable( $path ) {
1590 if ( $path[strlen( $path ) - 1] == '/' ) // if it looks like a directory, check a random file within the directory
1591 return win_is_writable( $path . uniqid( mt_rand() ) . '.tmp');
1592 else if ( is_dir( $path ) ) // If it's a directory (and not a file) check a random file within the directory
1593 return win_is_writable( $path . '/' . uniqid( mt_rand() ) . '.tmp' );
1595 // check tmp file for read/write capabilities
1596 $should_delete_tmp_file = !file_exists( $path );
1597 $f = @fopen( $path, 'a' );
1601 if ( $should_delete_tmp_file )
1607 * Get an array containing the current upload directory's path and url.
1609 * Checks the 'upload_path' option, which should be from the web root folder,
1610 * and if it isn't empty it will be used. If it is empty, then the path will be
1611 * 'WP_CONTENT_DIR/uploads'. If the 'UPLOADS' constant is defined, then it will
1612 * override the 'upload_path' option and 'WP_CONTENT_DIR/uploads' path.
1614 * The upload URL path is set either by the 'upload_url_path' option or by using
1615 * the 'WP_CONTENT_URL' constant and appending '/uploads' to the path.
1617 * If the 'uploads_use_yearmonth_folders' is set to true (checkbox if checked in
1618 * the administration settings panel), then the time will be used. The format
1619 * will be year first and then month.
1621 * If the path couldn't be created, then an error will be returned with the key
1622 * 'error' containing the error message. The error suggests that the parent
1623 * directory is not writable by the server.
1625 * On success, the returned array will have many indices:
1626 * 'path' - base directory and sub directory or full path to upload directory.
1627 * 'url' - base url and sub directory or absolute URL to upload directory.
1628 * 'subdir' - sub directory if uploads use year/month folders option is on.
1629 * 'basedir' - path without subdir.
1630 * 'baseurl' - URL path without subdir.
1631 * 'error' - set to false.
1635 * @param string $time Optional. Time formatted in 'yyyy/mm'.
1636 * @return array See above for description.
1638 function wp_upload_dir( $time = null ) {
1639 $siteurl = get_option( 'siteurl' );
1640 $upload_path = trim( get_option( 'upload_path' ) );
1642 if ( empty( $upload_path ) || 'wp-content/uploads' == $upload_path ) {
1643 $dir = WP_CONTENT_DIR . '/uploads';
1644 } elseif ( 0 !== strpos( $upload_path, ABSPATH ) ) {
1645 // $dir is absolute, $upload_path is (maybe) relative to ABSPATH
1646 $dir = path_join( ABSPATH, $upload_path );
1648 $dir = $upload_path;
1651 if ( !$url = get_option( 'upload_url_path' ) ) {
1652 if ( empty($upload_path) || ( 'wp-content/uploads' == $upload_path ) || ( $upload_path == $dir ) )
1653 $url = WP_CONTENT_URL . '/uploads';
1655 $url = trailingslashit( $siteurl ) . $upload_path;
1658 // Obey the value of UPLOADS. This happens as long as ms-files rewriting is disabled.
1659 // We also sometimes obey UPLOADS when rewriting is enabled -- see the next block.
1660 if ( defined( 'UPLOADS' ) && ! ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) ) {
1661 $dir = ABSPATH . UPLOADS;
1662 $url = trailingslashit( $siteurl ) . UPLOADS;
1665 // If multisite (and if not the main site in a post-MU network)
1666 if ( is_multisite() && ! ( is_main_network() && is_main_site() && defined( 'MULTISITE' ) ) ) {
1668 if ( ! get_site_option( 'ms_files_rewriting' ) ) {
1669 // If ms-files rewriting is disabled (networks created post-3.5), it is fairly straightforward:
1670 // Append sites/%d if we're not on the main site (for post-MU networks). (The extra directory
1671 // prevents a four-digit ID from conflicting with a year-based directory for the main site.
1672 // But if a MU-era network has disabled ms-files rewriting manually, they don't need the extra
1673 // directory, as they never had wp-content/uploads for the main site.)
1675 if ( defined( 'MULTISITE' ) )
1676 $ms_dir = '/sites/' . get_current_blog_id();
1678 $ms_dir = '/' . get_current_blog_id();
1683 } elseif ( defined( 'UPLOADS' ) && ! ms_is_switched() ) {
1684 // Handle the old-form ms-files.php rewriting if the network still has that enabled.
1685 // When ms-files rewriting is enabled, then we only listen to UPLOADS when:
1686 // 1) we are not on the main site in a post-MU network,
1687 // as wp-content/uploads is used there, and
1688 // 2) we are not switched, as ms_upload_constants() hardcodes
1689 // these constants to reflect the original blog ID.
1691 // Rather than UPLOADS, we actually use BLOGUPLOADDIR if it is set, as it is absolute.
1692 // (And it will be set, see ms_upload_constants().) Otherwise, UPLOADS can be used, as
1693 // as it is relative to ABSPATH. For the final piece: when UPLOADS is used with ms-files
1694 // rewriting in multisite, the resulting URL is /files. (#WP22702 for background.)
1696 if ( defined( 'BLOGUPLOADDIR' ) )
1697 $dir = untrailingslashit( BLOGUPLOADDIR );
1699 $dir = ABSPATH . UPLOADS;
1700 $url = trailingslashit( $siteurl ) . 'files';
1708 if ( get_option( 'uploads_use_yearmonth_folders' ) ) {
1709 // Generate the yearly and monthly dirs
1711 $time = current_time( 'mysql' );
1712 $y = substr( $time, 0, 4 );
1713 $m = substr( $time, 5, 2 );
1721 * Filter the uploads directory data.
1725 * @param array $uploads Array of upload directory data with keys of 'path',
1726 * 'url', 'subdir, 'basedir', and 'error'.
1728 $uploads = apply_filters( 'upload_dir',
1732 'subdir' => $subdir,
1733 'basedir' => $basedir,
1734 'baseurl' => $baseurl,
1738 // Make sure we have an uploads dir
1739 if ( ! wp_mkdir_p( $uploads['path'] ) ) {
1740 if ( 0 === strpos( $uploads['basedir'], ABSPATH ) )
1741 $error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir'];
1743 $error_path = basename( $uploads['basedir'] ) . $uploads['subdir'];
1745 $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
1746 $uploads['error'] = $message;
1753 * Get a filename that is sanitized and unique for the given directory.
1755 * If the filename is not unique, then a number will be added to the filename
1756 * before the extension, and will continue adding numbers until the filename is
1759 * The callback is passed three parameters, the first one is the directory, the
1760 * second is the filename, and the third is the extension.
1764 * @param string $dir
1765 * @param string $filename
1766 * @param mixed $unique_filename_callback Callback.
1767 * @return string New filename, if given wasn't unique.
1769 function wp_unique_filename( $dir, $filename, $unique_filename_callback = null ) {
1770 // sanitize the file name before we begin processing
1771 $filename = sanitize_file_name($filename);
1773 // separate the filename into a name and extension
1774 $info = pathinfo($filename);
1775 $ext = !empty($info['extension']) ? '.' . $info['extension'] : '';
1776 $name = basename($filename, $ext);
1778 // edge case: if file is named '.ext', treat as an empty name
1779 if ( $name === $ext )
1782 // Increment the file number until we have a unique file to save in $dir. Use callback if supplied.
1783 if ( $unique_filename_callback && is_callable( $unique_filename_callback ) ) {
1784 $filename = call_user_func( $unique_filename_callback, $dir, $name, $ext );
1788 // change '.ext' to lower case
1789 if ( $ext && strtolower($ext) != $ext ) {
1790 $ext2 = strtolower($ext);
1791 $filename2 = preg_replace( '|' . preg_quote($ext) . '$|', $ext2, $filename );
1793 // check for both lower and upper case extension or image sub-sizes may be overwritten
1794 while ( file_exists($dir . "/$filename") || file_exists($dir . "/$filename2") ) {
1795 $new_number = $number + 1;
1796 $filename = str_replace( "$number$ext", "$new_number$ext", $filename );
1797 $filename2 = str_replace( "$number$ext2", "$new_number$ext2", $filename2 );
1798 $number = $new_number;
1803 while ( file_exists( $dir . "/$filename" ) ) {
1804 if ( '' == "$number$ext" )
1805 $filename = $filename . ++$number . $ext;
1807 $filename = str_replace( "$number$ext", ++$number . $ext, $filename );
1815 * Create a file in the upload folder with given content.
1817 * If there is an error, then the key 'error' will exist with the error message.
1818 * If success, then the key 'file' will have the unique file path, the 'url' key
1819 * will have the link to the new file. and the 'error' key will be set to false.
1821 * This function will not move an uploaded file to the upload folder. It will
1822 * create a new file with the content in $bits parameter. If you move the upload
1823 * file, read the content of the uploaded file, and then you can give the
1824 * filename and content to this function, which will add it to the upload
1827 * The permissions will be set on the new file automatically by this function.
1831 * @param string $name
1832 * @param null $deprecated Never used. Set to null.
1833 * @param mixed $bits File content
1834 * @param string $time Optional. Time formatted in 'yyyy/mm'.
1837 function wp_upload_bits( $name, $deprecated, $bits, $time = null ) {
1838 if ( !empty( $deprecated ) )
1839 _deprecated_argument( __FUNCTION__, '2.0' );
1841 if ( empty( $name ) )
1842 return array( 'error' => __( 'Empty filename' ) );
1844 $wp_filetype = wp_check_filetype( $name );
1845 if ( ! $wp_filetype['ext'] && ! current_user_can( 'unfiltered_upload' ) )
1846 return array( 'error' => __( 'Invalid file type' ) );
1848 $upload = wp_upload_dir( $time );
1850 if ( $upload['error'] !== false )
1854 * Filter whether to treat the upload bits as an error.
1856 * Passing a non-array to the filter will effectively short-circuit preparing
1857 * the upload bits, returning that value instead.
1861 * @param mixed $upload_bits_error An array of upload bits data, or a non-array error to return.
1863 $upload_bits_error = apply_filters( 'wp_upload_bits', array( 'name' => $name, 'bits' => $bits, 'time' => $time ) );
1864 if ( !is_array( $upload_bits_error ) ) {
1865 $upload[ 'error' ] = $upload_bits_error;
1869 $filename = wp_unique_filename( $upload['path'], $name );
1871 $new_file = $upload['path'] . "/$filename";
1872 if ( ! wp_mkdir_p( dirname( $new_file ) ) ) {
1873 if ( 0 === strpos( $upload['basedir'], ABSPATH ) )
1874 $error_path = str_replace( ABSPATH, '', $upload['basedir'] ) . $upload['subdir'];
1876 $error_path = basename( $upload['basedir'] ) . $upload['subdir'];
1878 $message = sprintf( __( 'Unable to create directory %s. Is its parent directory writable by the server?' ), $error_path );
1879 return array( 'error' => $message );
1882 $ifp = @ fopen( $new_file, 'wb' );
1884 return array( 'error' => sprintf( __( 'Could not write file %s' ), $new_file ) );
1886 @fwrite( $ifp, $bits );
1890 // Set correct file permissions
1891 $stat = @ stat( dirname( $new_file ) );
1892 $perms = $stat['mode'] & 0007777;
1893 $perms = $perms & 0000666;
1894 @ chmod( $new_file, $perms );
1898 $url = $upload['url'] . "/$filename";
1900 return array( 'file' => $new_file, 'url' => $url, 'error' => false );
1904 * Retrieve the file type based on the extension name.
1908 * @param string $ext The extension to search.
1909 * @return string|null The file type, example: audio, video, document, spreadsheet, etc.
1910 * Null if not found.
1912 function wp_ext2type( $ext ) {
1913 $ext = strtolower( $ext );
1916 * Filter file type based on the extension name.
1920 * @see wp_ext2type()
1922 * @param array $ext2type Multi-dimensional array with extensions for a default set
1925 $ext2type = apply_filters( 'ext2type', array(
1926 'image' => array( 'jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'tif', 'tiff', 'ico' ),
1927 'audio' => array( 'aac', 'ac3', 'aif', 'aiff', 'm3a', 'm4a', 'm4b', 'mka', 'mp1', 'mp2', 'mp3', 'ogg', 'oga', 'ram', 'wav', 'wma' ),
1928 'video' => array( 'asf', 'avi', 'divx', 'dv', 'flv', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'mpv', 'ogm', 'ogv', 'qt', 'rm', 'vob', 'wmv' ),
1929 'document' => array( 'doc', 'docx', 'docm', 'dotm', 'odt', 'pages', 'pdf', 'rtf', 'wp', 'wpd' ),
1930 'spreadsheet' => array( 'numbers', 'ods', 'xls', 'xlsx', 'xlsm', 'xlsb' ),
1931 'interactive' => array( 'swf', 'key', 'ppt', 'pptx', 'pptm', 'pps', 'ppsx', 'ppsm', 'sldx', 'sldm', 'odp' ),
1932 'text' => array( 'asc', 'csv', 'tsv', 'txt' ),
1933 'archive' => array( 'bz2', 'cab', 'dmg', 'gz', 'rar', 'sea', 'sit', 'sqx', 'tar', 'tgz', 'zip', '7z' ),
1934 'code' => array( 'css', 'htm', 'html', 'php', 'js' ),
1937 foreach ( $ext2type as $type => $exts )
1938 if ( in_array( $ext, $exts ) )
1945 * Retrieve the file type from the file name.
1947 * You can optionally define the mime array, if needed.
1951 * @param string $filename File name or path.
1952 * @param array $mimes Optional. Key is the file extension with value as the mime type.
1953 * @return array Values with extension first and mime type.
1955 function wp_check_filetype( $filename, $mimes = null ) {
1956 if ( empty($mimes) )
1957 $mimes = get_allowed_mime_types();
1961 foreach ( $mimes as $ext_preg => $mime_match ) {
1962 $ext_preg = '!\.(' . $ext_preg . ')$!i';
1963 if ( preg_match( $ext_preg, $filename, $ext_matches ) ) {
1964 $type = $mime_match;
1965 $ext = $ext_matches[1];
1970 return compact( 'ext', 'type' );
1974 * Attempt to determine the real file type of a file.
1975 * If unable to, the file name extension will be used to determine type.
1977 * If it's determined that the extension does not match the file's real type,
1978 * then the "proper_filename" value will be set with a proper filename and extension.
1980 * Currently this function only supports validating images known to getimagesize().
1984 * @param string $file Full path to the file.
1985 * @param string $filename The name of the file (may differ from $file due to $file being in a tmp directory)
1986 * @param array $mimes Optional. Key is the file extension with value as the mime type.
1987 * @return array Values for the extension, MIME, and either a corrected filename or false if original $filename is valid
1989 function wp_check_filetype_and_ext( $file, $filename, $mimes = null ) {
1991 $proper_filename = false;
1993 // Do basic extension validation and MIME mapping
1994 $wp_filetype = wp_check_filetype( $filename, $mimes );
1995 extract( $wp_filetype );
1997 // We can't do any further validation without a file to work with
1998 if ( ! file_exists( $file ) )
1999 return compact( 'ext', 'type', 'proper_filename' );
2001 // We're able to validate images using GD
2002 if ( $type && 0 === strpos( $type, 'image/' ) && function_exists('getimagesize') ) {
2004 // Attempt to figure out what type of image it actually is
2005 $imgstats = @getimagesize( $file );
2007 // If getimagesize() knows what kind of image it really is and if the real MIME doesn't match the claimed MIME
2008 if ( !empty($imgstats['mime']) && $imgstats['mime'] != $type ) {
2010 * Filter the list mapping image mime types to their respective extensions.
2014 * @param array $mime_to_ext Array of image mime types and their matching extensions.
2016 $mime_to_ext = apply_filters( 'getimagesize_mimes_to_exts', array(
2017 'image/jpeg' => 'jpg',
2018 'image/png' => 'png',
2019 'image/gif' => 'gif',
2020 'image/bmp' => 'bmp',
2021 'image/tiff' => 'tif',
2024 // Replace whatever is after the last period in the filename with the correct extension
2025 if ( ! empty( $mime_to_ext[ $imgstats['mime'] ] ) ) {
2026 $filename_parts = explode( '.', $filename );
2027 array_pop( $filename_parts );
2028 $filename_parts[] = $mime_to_ext[ $imgstats['mime'] ];
2029 $new_filename = implode( '.', $filename_parts );
2031 if ( $new_filename != $filename )
2032 $proper_filename = $new_filename; // Mark that it changed
2034 // Redefine the extension / MIME
2035 $wp_filetype = wp_check_filetype( $new_filename, $mimes );
2036 extract( $wp_filetype );
2042 * Filter the "real" file type of the given file.
2046 * @param array $wp_check_filetype_and_ext File data array containing 'ext', 'type', and
2047 * 'proper_filename' keys.
2048 * @param string $file Full path to the file.
2049 * @param string $filename The name of the file (may differ from $file due to
2050 * $file being in a tmp directory).
2051 * @param array $mimes Key is the file extension with value as the mime type.
2053 return apply_filters( 'wp_check_filetype_and_ext', compact( 'ext', 'type', 'proper_filename' ), $file, $filename, $mimes );
2057 * Retrieve list of mime types and file extensions.
2061 * @return array Array of mime types keyed by the file extension regex corresponding to those types.
2063 function wp_get_mime_types() {
2065 * Filter the list of mime types and file extensions.
2067 * This filter should be used to add, not remove, mime types. To remove
2068 * mime types, use the 'upload_mimes' filter.
2072 * @param array $wp_get_mime_types Mime types keyed by the file extension regex
2073 * corresponding to those types.
2075 return apply_filters( 'mime_types', array(
2077 'jpg|jpeg|jpe' => 'image/jpeg',
2078 'gif' => 'image/gif',
2079 'png' => 'image/png',
2080 'bmp' => 'image/bmp',
2081 'tif|tiff' => 'image/tiff',
2082 'ico' => 'image/x-icon',
2084 'asf|asx' => 'video/x-ms-asf',
2085 'wmv' => 'video/x-ms-wmv',
2086 'wmx' => 'video/x-ms-wmx',
2087 'wm' => 'video/x-ms-wm',
2088 'avi' => 'video/avi',
2089 'divx' => 'video/divx',
2090 'flv' => 'video/x-flv',
2091 'mov|qt' => 'video/quicktime',
2092 'mpeg|mpg|mpe' => 'video/mpeg',
2093 'mp4|m4v' => 'video/mp4',
2094 'ogv' => 'video/ogg',
2095 'webm' => 'video/webm',
2096 'mkv' => 'video/x-matroska',
2098 'txt|asc|c|cc|h' => 'text/plain',
2099 'csv' => 'text/csv',
2100 'tsv' => 'text/tab-separated-values',
2101 'ics' => 'text/calendar',
2102 'rtx' => 'text/richtext',
2103 'css' => 'text/css',
2104 'htm|html' => 'text/html',
2105 'vtt' => 'text/vtt',
2107 'mp3|m4a|m4b' => 'audio/mpeg',
2108 'ra|ram' => 'audio/x-realaudio',
2109 'wav' => 'audio/wav',
2110 'ogg|oga' => 'audio/ogg',
2111 'mid|midi' => 'audio/midi',
2112 'wma' => 'audio/x-ms-wma',
2113 'wax' => 'audio/x-ms-wax',
2114 'mka' => 'audio/x-matroska',
2115 // Misc application formats
2116 'rtf' => 'application/rtf',
2117 'js' => 'application/javascript',
2118 'pdf' => 'application/pdf',
2119 'swf' => 'application/x-shockwave-flash',
2120 'class' => 'application/java',
2121 'tar' => 'application/x-tar',
2122 'zip' => 'application/zip',
2123 'gz|gzip' => 'application/x-gzip',
2124 'rar' => 'application/rar',
2125 '7z' => 'application/x-7z-compressed',
2126 'exe' => 'application/x-msdownload',
2127 // MS Office formats
2128 'doc' => 'application/msword',
2129 'pot|pps|ppt' => 'application/vnd.ms-powerpoint',
2130 'wri' => 'application/vnd.ms-write',
2131 'xla|xls|xlt|xlw' => 'application/vnd.ms-excel',
2132 'mdb' => 'application/vnd.ms-access',
2133 'mpp' => 'application/vnd.ms-project',
2134 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2135 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
2136 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
2137 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12',
2138 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2139 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
2140 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
2141 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
2142 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
2143 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
2144 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2145 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
2146 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2147 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
2148 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
2149 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
2150 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
2151 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
2152 'sldm' => 'application/vnd.ms-powerpoint.slide.macroEnabled.12',
2153 'onetoc|onetoc2|onetmp|onepkg' => 'application/onenote',
2154 // OpenOffice formats
2155 'odt' => 'application/vnd.oasis.opendocument.text',
2156 'odp' => 'application/vnd.oasis.opendocument.presentation',
2157 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
2158 'odg' => 'application/vnd.oasis.opendocument.graphics',
2159 'odc' => 'application/vnd.oasis.opendocument.chart',
2160 'odb' => 'application/vnd.oasis.opendocument.database',
2161 'odf' => 'application/vnd.oasis.opendocument.formula',
2162 // WordPerfect formats
2163 'wp|wpd' => 'application/wordperfect',
2165 'key' => 'application/vnd.apple.keynote',
2166 'numbers' => 'application/vnd.apple.numbers',
2167 'pages' => 'application/vnd.apple.pages',
2171 * Retrieve list of allowed mime types and file extensions.
2175 * @uses wp_get_upload_mime_types() to fetch the list of mime types
2177 * @param int|WP_User $user Optional. User to check. Defaults to current user.
2178 * @return array Array of mime types keyed by the file extension regex corresponding to those types.
2180 function get_allowed_mime_types( $user = null ) {
2181 $t = wp_get_mime_types();
2183 unset( $t['swf'], $t['exe'] );
2184 if ( function_exists( 'current_user_can' ) )
2185 $unfiltered = $user ? user_can( $user, 'unfiltered_html' ) : current_user_can( 'unfiltered_html' );
2187 if ( empty( $unfiltered ) )
2188 unset( $t['htm|html'] );
2191 * Filter list of allowed mime types and file extensions.
2195 * @param array $t Mime types keyed by the file extension regex corresponding to
2196 * those types. 'swf' and 'exe' removed from full list. 'htm|html' also
2197 * removed depending on '$user' capabilities.
2198 * @param int|WP_User|null $user User ID, User object or null if not provided (indicates current user).
2200 return apply_filters( 'upload_mimes', $t, $user );
2204 * Display "Are You Sure" message to confirm the action being taken.
2206 * If the action has the nonce explain message, then it will be displayed along
2207 * with the "Are you sure?" message.
2211 * @param string $action The nonce action.
2213 function wp_nonce_ays( $action ) {
2214 $title = __( 'WordPress Failure Notice' );
2215 if ( 'log-out' == $action ) {
2216 $html = sprintf( __( 'You are attempting to log out of %s' ), get_bloginfo( 'name' ) ) . '</p><p>';
2217 $redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
2218 $html .= sprintf( __( "Do you really want to <a href='%s'>log out</a>?"), wp_logout_url( $redirect_to ) );
2220 $html = __( 'Are you sure you want to do this?' );
2221 if ( wp_get_referer() )
2222 $html .= "</p><p><a href='" . esc_url( remove_query_arg( 'updated', wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>";
2225 wp_die( $html, $title, array('response' => 403) );
2229 * Kill WordPress execution and display HTML message with error message.
2231 * This function complements the die() PHP function. The difference is that
2232 * HTML will be displayed to the user. It is recommended to use this function
2233 * only, when the execution should not continue any further. It is not
2234 * recommended to call this function very often and try to handle as many errors
2235 * as possible silently.
2239 * @param string $message Error message.
2240 * @param string $title Error title.
2241 * @param string|array $args Optional arguments to control behavior.
2243 function wp_die( $message = '', $title = '', $args = array() ) {
2244 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2246 * Filter callback for killing WordPress execution for AJAX requests.
2250 * @param callback $function Callback function name.
2252 $function = apply_filters( 'wp_die_ajax_handler', '_ajax_wp_die_handler' );
2253 } elseif ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
2255 * Filter callback for killing WordPress execution for XML-RPC requests.
2259 * @param callback $function Callback function name.
2261 $function = apply_filters( 'wp_die_xmlrpc_handler', '_xmlrpc_wp_die_handler' );
2264 * Filter callback for killing WordPress execution for all non-AJAX, non-XML-RPC requests.
2268 * @param callback $function Callback function name.
2270 $function = apply_filters( 'wp_die_handler', '_default_wp_die_handler' );
2273 call_user_func( $function, $message, $title, $args );
2277 * Kill WordPress execution and display HTML message with error message.
2279 * This is the default handler for wp_die if you want a custom one for your
2280 * site then you can overload using the wp_die_handler filter in wp_die
2285 * @param string $message Error message.
2286 * @param string $title Error title.
2287 * @param string|array $args Optional arguments to control behavior.
2289 function _default_wp_die_handler( $message, $title = '', $args = array() ) {
2290 $defaults = array( 'response' => 500 );
2291 $r = wp_parse_args($args, $defaults);
2293 $have_gettext = function_exists('__');
2295 if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) {
2296 if ( empty( $title ) ) {
2297 $error_data = $message->get_error_data();
2298 if ( is_array( $error_data ) && isset( $error_data['title'] ) )
2299 $title = $error_data['title'];
2301 $errors = $message->get_error_messages();
2302 switch ( count( $errors ) ) :
2307 $message = "<p>{$errors[0]}</p>";
2310 $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
2313 } elseif ( is_string( $message ) ) {
2314 $message = "<p>$message</p>";
2317 if ( isset( $r['back_link'] ) && $r['back_link'] ) {
2318 $back_text = $have_gettext? __('« Back') : '« Back';
2319 $message .= "\n<p><a href='javascript:history.back()'>$back_text</a></p>";
2322 if ( ! did_action( 'admin_head' ) ) :
2323 if ( !headers_sent() ) {
2324 status_header( $r['response'] );
2326 header( 'Content-Type: text/html; charset=utf-8' );
2329 if ( empty($title) )
2330 $title = $have_gettext ? __('WordPress › Error') : 'WordPress › Error';
2332 $text_direction = 'ltr';
2333 if ( isset($r['text_direction']) && 'rtl' == $r['text_direction'] )
2334 $text_direction = 'rtl';
2335 elseif ( function_exists( 'is_rtl' ) && is_rtl() )
2336 $text_direction = 'rtl';
2339 <!-- 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
2341 <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'"; ?>>
2343 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2344 <title><?php echo $title ?></title>
2345 <style type="text/css">
2347 background: #f1f1f1;
2352 font-family: "Open Sans", sans-serif;
2356 -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);
2357 box-shadow: 0 1px 3px rgba(0,0,0,0.13);
2360 border-bottom: 1px solid #dadada;
2363 font: 24px "Open Sans", sans-serif;
2366 padding-bottom: 7px;
2374 margin: 25px 0 20px;
2377 font-family: Consolas, Monaco, monospace;
2380 margin-bottom: 10px;
2385 text-decoration: none;
2391 background: #f7f7f7;
2392 border: 1px solid #cccccc;
2394 display: inline-block;
2395 text-decoration: none;
2400 padding: 0 10px 1px;
2402 -webkit-border-radius: 3px;
2403 -webkit-appearance: none;
2405 white-space: nowrap;
2406 -webkit-box-sizing: border-box;
2407 -moz-box-sizing: border-box;
2408 box-sizing: border-box;
2410 -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08);
2411 box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba(0,0,0,.08);
2412 vertical-align: top;
2415 .button.button-large {
2423 background: #fafafa;
2429 -webkit-box-shadow: 1px 1px 1px rgba(0,0,0,.2);
2430 box-shadow: 1px 1px 1px rgba(0,0,0,.2);
2437 -webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
2438 box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
2441 <?php if ( 'rtl' == $text_direction ) : ?>
2442 body { font-family: Tahoma, Arial; }
2446 <body id="error-page">
2447 <?php endif; // ! did_action( 'admin_head' ) ?>
2448 <?php echo $message; ?>
2456 * Kill WordPress execution and display XML message with error message.
2458 * This is the handler for wp_die when processing XMLRPC requests.
2463 * @param string $message Error message.
2464 * @param string $title Error title.
2465 * @param string|array $args Optional arguments to control behavior.
2467 function _xmlrpc_wp_die_handler( $message, $title = '', $args = array() ) {
2468 global $wp_xmlrpc_server;
2469 $defaults = array( 'response' => 500 );
2471 $r = wp_parse_args($args, $defaults);
2473 if ( $wp_xmlrpc_server ) {
2474 $error = new IXR_Error( $r['response'] , $message);
2475 $wp_xmlrpc_server->output( $error->getXml() );
2481 * Kill WordPress ajax execution.
2483 * This is the handler for wp_die when processing Ajax requests.
2488 * @param string $message Optional. Response to print.
2490 function _ajax_wp_die_handler( $message = '' ) {
2491 if ( is_scalar( $message ) )
2492 die( (string) $message );
2497 * Kill WordPress execution.
2499 * This is the handler for wp_die when processing APP requests.
2504 * @param string $message Optional. Response to print.
2506 function _scalar_wp_die_handler( $message = '' ) {
2507 if ( is_scalar( $message ) )
2508 die( (string) $message );
2513 * Send a JSON response back to an Ajax request.
2517 * @param mixed $response Variable (usually an array or object) to encode as JSON, then print and die.
2519 function wp_send_json( $response ) {
2520 @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
2521 echo json_encode( $response );
2522 if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
2529 * Send a JSON response back to an Ajax request, indicating success.
2533 * @param mixed $data Data to encode as JSON, then print and die.
2535 function wp_send_json_success( $data = null ) {
2536 $response = array( 'success' => true );
2538 if ( isset( $data ) )
2539 $response['data'] = $data;
2541 wp_send_json( $response );
2545 * Send a JSON response back to an Ajax request, indicating failure.
2549 * @param mixed $data Data to encode as JSON, then print and die.
2551 function wp_send_json_error( $data = null ) {
2552 $response = array( 'success' => false );
2554 if ( isset( $data ) )
2555 $response['data'] = $data;
2557 wp_send_json( $response );
2561 * Retrieve the WordPress home page URL.
2563 * If the constant named 'WP_HOME' exists, then it will be used and returned by
2564 * the function. This can be used to counter the redirection on your local
2565 * development environment.
2570 * @param string $url URL for the home location
2571 * @return string Homepage location.
2573 function _config_wp_home( $url = '' ) {
2574 if ( defined( 'WP_HOME' ) )
2575 return untrailingslashit( WP_HOME );
2580 * Retrieve the WordPress site URL.
2582 * If the constant named 'WP_SITEURL' is defined, then the value in that
2583 * constant will always be returned. This can be used for debugging a site on
2584 * your localhost while not having to change the database to your URL.
2589 * @param string $url URL to set the WordPress site location.
2590 * @return string The WordPress Site URL
2592 function _config_wp_siteurl( $url = '' ) {
2593 if ( defined( 'WP_SITEURL' ) )
2594 return untrailingslashit( WP_SITEURL );
2599 * Set the localized direction for MCE plugin.
2601 * Will only set the direction to 'rtl', if the WordPress locale has the text
2602 * direction set to 'rtl'.
2604 * Fills in the 'directionality' setting, enables the 'directionality' plugin,
2605 * and adds the 'ltr' button to 'toolbar1', formerly 'theme_advanced_buttons1' array
2606 * keys. These keys are then returned in the $input (TinyMCE settings) array.
2611 * @param array $input MCE settings array.
2612 * @return array Direction set for 'rtl', if needed by locale.
2614 function _mce_set_direction( $input ) {
2616 $input['directionality'] = 'rtl';
2617 $input['plugins'] .= ',directionality';
2618 $input['toolbar1'] .= ',ltr';
2626 * Convert smiley code to the icon graphic file equivalent.
2628 * You can turn off smilies, by going to the write setting screen and unchecking
2629 * the box, or by setting 'use_smilies' option to false or removing the option.
2631 * Plugins may override the default smiley list by setting the $wpsmiliestrans
2632 * to an array, with the key the code the blogger types in and the value the
2635 * The $wp_smiliessearch global is for the regular expression and is set each
2636 * time the function is called.
2638 * The full list of smilies can be found in the function and won't be listed in
2639 * the description. Probably should create a Codex page for it, so that it is
2642 * @global array $wpsmiliestrans
2643 * @global array $wp_smiliessearch
2646 function smilies_init() {
2647 global $wpsmiliestrans, $wp_smiliessearch;
2649 // don't bother setting up smilies if they are disabled
2650 if ( !get_option( 'use_smilies' ) )
2653 if ( !isset( $wpsmiliestrans ) ) {
2654 $wpsmiliestrans = array(
2655 ':mrgreen:' => 'icon_mrgreen.gif',
2656 ':neutral:' => 'icon_neutral.gif',
2657 ':twisted:' => 'icon_twisted.gif',
2658 ':arrow:' => 'icon_arrow.gif',
2659 ':shock:' => 'icon_eek.gif',
2660 ':smile:' => 'icon_smile.gif',
2661 ':???:' => 'icon_confused.gif',
2662 ':cool:' => 'icon_cool.gif',
2663 ':evil:' => 'icon_evil.gif',
2664 ':grin:' => 'icon_biggrin.gif',
2665 ':idea:' => 'icon_idea.gif',
2666 ':oops:' => 'icon_redface.gif',
2667 ':razz:' => 'icon_razz.gif',
2668 ':roll:' => 'icon_rolleyes.gif',
2669 ':wink:' => 'icon_wink.gif',
2670 ':cry:' => 'icon_cry.gif',
2671 ':eek:' => 'icon_surprised.gif',
2672 ':lol:' => 'icon_lol.gif',
2673 ':mad:' => 'icon_mad.gif',
2674 ':sad:' => 'icon_sad.gif',
2675 '8-)' => 'icon_cool.gif',
2676 '8-O' => 'icon_eek.gif',
2677 ':-(' => 'icon_sad.gif',
2678 ':-)' => 'icon_smile.gif',
2679 ':-?' => 'icon_confused.gif',
2680 ':-D' => 'icon_biggrin.gif',
2681 ':-P' => 'icon_razz.gif',
2682 ':-o' => 'icon_surprised.gif',
2683 ':-x' => 'icon_mad.gif',
2684 ':-|' => 'icon_neutral.gif',
2685 ';-)' => 'icon_wink.gif',
2686 // This one transformation breaks regular text with frequency.
2687 // '8)' => 'icon_cool.gif',
2688 '8O' => 'icon_eek.gif',
2689 ':(' => 'icon_sad.gif',
2690 ':)' => 'icon_smile.gif',
2691 ':?' => 'icon_confused.gif',
2692 ':D' => 'icon_biggrin.gif',
2693 ':P' => 'icon_razz.gif',
2694 ':o' => 'icon_surprised.gif',
2695 ':x' => 'icon_mad.gif',
2696 ':|' => 'icon_neutral.gif',
2697 ';)' => 'icon_wink.gif',
2698 ':!:' => 'icon_exclaim.gif',
2699 ':?:' => 'icon_question.gif',
2703 if (count($wpsmiliestrans) == 0) {
2708 * NOTE: we sort the smilies in reverse key order. This is to make sure
2709 * we match the longest possible smilie (:???: vs :?) as the regular
2710 * expression used below is first-match
2712 krsort($wpsmiliestrans);
2714 $wp_smiliessearch = '/((?:\s|^)';
2717 foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
2718 $firstchar = substr($smiley, 0, 1);
2719 $rest = substr($smiley, 1);
2722 if ($firstchar != $subchar) {
2723 if ($subchar != '') {
2724 $wp_smiliessearch .= ')(?=\s|$))|((?:\s|^)'; ;
2726 $subchar = $firstchar;
2727 $wp_smiliessearch .= preg_quote($firstchar, '/') . '(?:';
2729 $wp_smiliessearch .= '|';
2731 $wp_smiliessearch .= preg_quote($rest, '/');
2734 $wp_smiliessearch .= ')(?=\s|$))/m';
2739 * Merge user defined arguments into defaults array.
2741 * This function is used throughout WordPress to allow for both string or array
2742 * to be merged into another array.
2746 * @param string|array $args Value to merge with $defaults
2747 * @param array $defaults Array that serves as the defaults.
2748 * @return array Merged user defined values with defaults.
2750 function wp_parse_args( $args, $defaults = '' ) {
2751 if ( is_object( $args ) )
2752 $r = get_object_vars( $args );
2753 elseif ( is_array( $args ) )
2756 wp_parse_str( $args, $r );
2758 if ( is_array( $defaults ) )
2759 return array_merge( $defaults, $r );
2764 * Clean up an array, comma- or space-separated list of IDs.
2768 * @param array|string $list
2769 * @return array Sanitized array of IDs
2771 function wp_parse_id_list( $list ) {
2772 if ( !is_array($list) )
2773 $list = preg_split('/[\s,]+/', $list);
2775 return array_unique(array_map('absint', $list));
2779 * Extract a slice of an array, given a list of keys.
2783 * @param array $array The original array
2784 * @param array $keys The list of keys
2785 * @return array The array slice
2787 function wp_array_slice_assoc( $array, $keys ) {
2789 foreach ( $keys as $key )
2790 if ( isset( $array[ $key ] ) )
2791 $slice[ $key ] = $array[ $key ];
2797 * Filters a list of objects, based on a set of key => value arguments.
2801 * @param array $list An array of objects to filter
2802 * @param array $args An array of key => value arguments to match against each object
2803 * @param string $operator The logical operation to perform. 'or' means only one element
2804 * from the array needs to match; 'and' means all elements must match. The default is 'and'.
2805 * @param bool|string $field A field from the object to place instead of the entire object
2806 * @return array A list of objects or object fields
2808 function wp_filter_object_list( $list, $args = array(), $operator = 'and', $field = false ) {
2809 if ( ! is_array( $list ) )
2812 $list = wp_list_filter( $list, $args, $operator );
2815 $list = wp_list_pluck( $list, $field );
2821 * Filters a list of objects, based on a set of key => value arguments.
2825 * @param array $list An array of objects to filter
2826 * @param array $args An array of key => value arguments to match against each object
2827 * @param string $operator The logical operation to perform:
2828 * 'AND' means all elements from the array must match;
2829 * 'OR' means only one element needs to match;
2830 * 'NOT' means no elements may match.
2831 * The default is 'AND'.
2834 function wp_list_filter( $list, $args = array(), $operator = 'AND' ) {
2835 if ( ! is_array( $list ) )
2838 if ( empty( $args ) )
2841 $operator = strtoupper( $operator );
2842 $count = count( $args );
2843 $filtered = array();
2845 foreach ( $list as $key => $obj ) {
2846 $to_match = (array) $obj;
2849 foreach ( $args as $m_key => $m_value ) {
2850 if ( array_key_exists( $m_key, $to_match ) && $m_value == $to_match[ $m_key ] )
2854 if ( ( 'AND' == $operator && $matched == $count )
2855 || ( 'OR' == $operator && $matched > 0 )
2856 || ( 'NOT' == $operator && 0 == $matched ) ) {
2857 $filtered[$key] = $obj;
2865 * Pluck a certain field out of each object in a list.
2869 * @param array $list A list of objects or arrays
2870 * @param int|string $field A field from the object to place instead of the entire object
2873 function wp_list_pluck( $list, $field ) {
2874 foreach ( $list as $key => $value ) {
2875 if ( is_object( $value ) )
2876 $list[ $key ] = $value->$field;
2878 $list[ $key ] = $value[ $field ];
2885 * Determines if Widgets library should be loaded.
2887 * Checks to make sure that the widgets library hasn't already been loaded. If
2888 * it hasn't, then it will load the widgets library and run an action hook.
2891 * @uses add_action() Calls '_admin_menu' hook with 'wp_widgets_add_menu' value.
2893 function wp_maybe_load_widgets() {
2895 * Filter whether to load the Widgets library.
2899 * @param bool $wp_maybe_load_widgets Whether to load the Widgets library.
2902 if ( ! apply_filters( 'load_default_widgets', true ) ) {
2905 require_once( ABSPATH . WPINC . '/default-widgets.php' );
2906 add_action( '_admin_menu', 'wp_widgets_add_menu' );
2910 * Append the Widgets menu to the themes main menu.
2913 * @uses $submenu The administration submenu list.
2915 function wp_widgets_add_menu() {
2918 if ( ! current_theme_supports( 'widgets' ) )
2921 $submenu['themes.php'][7] = array( __( 'Widgets' ), 'edit_theme_options', 'widgets.php' );
2922 ksort( $submenu['themes.php'], SORT_NUMERIC );
2926 * Flush all output buffers for PHP 5.2.
2928 * Make sure all output buffers are flushed before our singletons our destroyed.
2932 function wp_ob_end_flush_all() {
2933 $levels = ob_get_level();
2934 for ($i=0; $i<$levels; $i++)
2939 * Load custom DB error or display WordPress DB error.
2941 * If a file exists in the wp-content directory named db-error.php, then it will
2942 * be loaded instead of displaying the WordPress DB error. If it is not found,
2943 * then the WordPress DB error will be displayed instead.
2945 * The WordPress DB error sets the HTTP status header to 500 to try to prevent
2946 * search engines from caching the message. Custom DB messages should do the
2949 * This function was backported to WordPress 2.3.2, but originally was added
2950 * in WordPress 2.5.0.
2955 function dead_db() {
2958 wp_load_translations_early();
2960 // Load custom DB error template, if present.
2961 if ( file_exists( WP_CONTENT_DIR . '/db-error.php' ) ) {
2962 require_once( WP_CONTENT_DIR . '/db-error.php' );
2966 // If installing or in the admin, provide the verbose message.
2967 if ( defined('WP_INSTALLING') || defined('WP_ADMIN') )
2968 wp_die($wpdb->error);
2970 // Otherwise, be terse.
2971 status_header( 500 );
2973 header( 'Content-Type: text/html; charset=utf-8' );
2976 <html xmlns="http://www.w3.org/1999/xhtml"<?php if ( is_rtl() ) echo ' dir="rtl"'; ?>>
2978 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
2979 <title><?php _e( 'Database Error' ); ?></title>
2983 <h1><?php _e( 'Error establishing a database connection' ); ?></h1>
2991 * Converts value to nonnegative integer.
2995 * @param mixed $maybeint Data you wish to have converted to a nonnegative integer
2996 * @return int An nonnegative integer
2998 function absint( $maybeint ) {
2999 return abs( intval( $maybeint ) );
3003 * Determines if the blog can be accessed over SSL.
3005 * Determines if blog can be accessed over SSL by using cURL to access the site
3006 * using the https in the siteurl. Requires cURL extension to work correctly.
3010 * @param string $url
3011 * @return bool Whether SSL access is available
3013 function url_is_accessable_via_ssl($url)
3015 if ( in_array( 'curl', get_loaded_extensions() ) ) {
3016 $ssl = set_url_scheme( $url, 'https' );
3019 curl_setopt($ch, CURLOPT_URL, $ssl);
3020 curl_setopt($ch, CURLOPT_FAILONERROR, true);
3021 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
3022 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
3023 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
3027 $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
3030 if ($status == 200 || $status == 401) {
3038 * Marks a function as deprecated and informs when it has been used.
3040 * There is a hook deprecated_function_run that will be called that can be used
3041 * to get the backtrace up to what file and function called the deprecated
3044 * The current behavior is to trigger a user error if WP_DEBUG is true.
3046 * This function is to be used in every function that is deprecated.
3051 * @param string $function The function that was called
3052 * @param string $version The version of WordPress that deprecated the function
3053 * @param string $replacement Optional. The function that should have been called
3055 function _deprecated_function( $function, $version, $replacement = null ) {
3058 * Fires when a deprecated function is called.
3062 * @param string $function The function that was called.
3063 * @param string $replacement The function that should have been called.
3064 * @param string $version The version of WordPress that deprecated the function.
3066 do_action( 'deprecated_function_run', $function, $replacement, $version );
3069 * Filter whether to trigger an error for deprecated functions.
3073 * @param bool $trigger Whether to trigger the error for deprecated functions. Default true.
3075 if ( WP_DEBUG && apply_filters( 'deprecated_function_trigger_error', true ) ) {
3076 if ( function_exists( '__' ) ) {
3077 if ( ! is_null( $replacement ) )
3078 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $function, $version, $replacement ) );
3080 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $function, $version ) );
3082 if ( ! is_null( $replacement ) )
3083 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $function, $version, $replacement ) );
3085 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $function, $version ) );
3091 * Marks a file as deprecated and informs when it has been used.
3093 * There is a hook deprecated_file_included that will be called that can be used
3094 * to get the backtrace up to what file and function included the deprecated
3097 * The current behavior is to trigger a user error if WP_DEBUG is true.
3099 * This function is to be used in every file that is deprecated.
3104 * @param string $file The file that was included
3105 * @param string $version The version of WordPress that deprecated the file
3106 * @param string $replacement Optional. The file that should have been included based on ABSPATH
3107 * @param string $message Optional. A message regarding the change
3109 function _deprecated_file( $file, $version, $replacement = null, $message = '' ) {
3112 * Fires when a deprecated file is called.
3116 * @param string $file The file that was called.
3117 * @param string $replacement The file that should have been included based on ABSPATH.
3118 * @param string $version The version of WordPress that deprecated the file.
3119 * @param string $message A message regarding the change.
3121 do_action( 'deprecated_file_included', $file, $replacement, $version, $message );
3124 * Filter whether to trigger an error for deprecated files.
3128 * @param bool $trigger Whether to trigger the error for deprecated files. Default true.
3130 if ( WP_DEBUG && apply_filters( 'deprecated_file_trigger_error', true ) ) {
3131 $message = empty( $message ) ? '' : ' ' . $message;
3132 if ( function_exists( '__' ) ) {
3133 if ( ! is_null( $replacement ) )
3134 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.'), $file, $version, $replacement ) . $message );
3136 trigger_error( sprintf( __('%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.'), $file, $version ) . $message );
3138 if ( ! is_null( $replacement ) )
3139 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.', $file, $version, $replacement ) . $message );
3141 trigger_error( sprintf( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.', $file, $version ) . $message );
3146 * Marks a function argument as deprecated and informs when it has been used.
3148 * This function is to be used whenever a deprecated function argument is used.
3149 * Before this function is called, the argument must be checked for whether it was
3150 * used by comparing it to its default value or evaluating whether it is empty.
3153 * if ( !empty($deprecated) )
3154 * _deprecated_argument( __FUNCTION__, '3.0' );
3157 * There is a hook deprecated_argument_run that will be called that can be used
3158 * to get the backtrace up to what file and function used the deprecated
3161 * The current behavior is to trigger a user error if WP_DEBUG is true.
3166 * @param string $function The function that was called
3167 * @param string $version The version of WordPress that deprecated the argument used
3168 * @param string $message Optional. A message regarding the change.
3170 function _deprecated_argument( $function, $version, $message = null ) {
3173 * Fires when a deprecated argument is called.
3177 * @param string $function The function that was called.
3178 * @param string $message A message regarding the change.
3179 * @param string $version The version of WordPress that deprecated the argument used.
3181 do_action( 'deprecated_argument_run', $function, $message, $version );
3184 * Filter whether to trigger an error for deprecated arguments.
3188 * @param bool $trigger Whether to trigger the error for deprecated arguments. Default true.
3190 if ( WP_DEBUG && apply_filters( 'deprecated_argument_trigger_error', true ) ) {
3191 if ( function_exists( '__' ) ) {
3192 if ( ! is_null( $message ) )
3193 trigger_error( sprintf( __('%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s'), $function, $version, $message ) );
3195 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 ) );
3197 if ( ! is_null( $message ) )
3198 trigger_error( sprintf( '%1$s was called with an argument that is <strong>deprecated</strong> since version %2$s! %3$s', $function, $version, $message ) );
3200 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 ) );
3206 * Marks something as being incorrectly called.
3208 * There is a hook doing_it_wrong_run that will be called that can be used
3209 * to get the backtrace up to what file and function called the deprecated
3212 * The current behavior is to trigger a user error if WP_DEBUG is true.
3217 * @param string $function The function that was called.
3218 * @param string $message A message explaining what has been done incorrectly.
3219 * @param string $version The version of WordPress where the message was added.
3221 function _doing_it_wrong( $function, $message, $version ) {
3224 * Fires when the given function is being used incorrectly.
3228 * @param string $function The function that was called.
3229 * @param string $message A message explaining what has been done incorrectly.
3230 * @param string $version The version of WordPress where the message was added.
3232 do_action( 'doing_it_wrong_run', $function, $message, $version );
3235 * Filter whether to trigger an error for _doing_it_wrong() calls.
3239 * @param bool $trigger Whether to trigger the error for _doing_it_wrong() calls. Default true.
3241 if ( WP_DEBUG && apply_filters( 'doing_it_wrong_trigger_error', true ) ) {
3242 if ( function_exists( '__' ) ) {
3243 $version = is_null( $version ) ? '' : sprintf( __( '(This message was added in version %s.)' ), $version );
3244 $message .= ' ' . __( 'Please see <a href="http://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.' );
3245 trigger_error( sprintf( __( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s' ), $function, $message, $version ) );
3247 $version = is_null( $version ) ? '' : sprintf( '(This message was added in version %s.)', $version );
3248 $message .= ' Please see <a href="http://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information.';
3249 trigger_error( sprintf( '%1$s was called <strong>incorrectly</strong>. %2$s %3$s', $function, $message, $version ) );
3255 * Is the server running earlier than 1.5.0 version of lighttpd?
3259 * @return bool Whether the server is running lighttpd < 1.5.0
3261 function is_lighttpd_before_150() {
3262 $server_parts = explode( '/', isset( $_SERVER['SERVER_SOFTWARE'] )? $_SERVER['SERVER_SOFTWARE'] : '' );
3263 $server_parts[1] = isset( $server_parts[1] )? $server_parts[1] : '';
3264 return 'lighttpd' == $server_parts[0] && -1 == version_compare( $server_parts[1], '1.5.0' );
3268 * Does the specified module exist in the Apache config?
3272 * @param string $mod e.g. mod_rewrite
3273 * @param bool $default The default return value if the module is not found
3276 function apache_mod_loaded($mod, $default = false) {
3282 if ( function_exists('apache_get_modules') ) {
3283 $mods = apache_get_modules();
3284 if ( in_array($mod, $mods) )
3286 } elseif ( function_exists('phpinfo') ) {
3289 $phpinfo = ob_get_clean();
3290 if ( false !== strpos($phpinfo, $mod) )
3297 * Check if IIS 7+ supports pretty permalinks.
3303 function iis7_supports_permalinks() {
3306 $supports_permalinks = false;
3308 /* First we check if the DOMDocument class exists. If it does not exist, then we cannot
3309 * easily update the xml configuration file, hence we just bail out and tell user that
3310 * pretty permalinks cannot be used.
3312 * Next we check if the URL Rewrite Module 1.1 is loaded and enabled for the web site. When
3313 * URL Rewrite 1.1 is loaded it always sets a server variable called 'IIS_UrlRewriteModule'.
3314 * Lastly we make sure that PHP is running via FastCGI. This is important because if it runs
3315 * via ISAPI then pretty permalinks will not work.
3317 $supports_permalinks = class_exists('DOMDocument') && isset($_SERVER['IIS_UrlRewriteModule']) && ( php_sapi_name() == 'cgi-fcgi' );
3321 * Filter whether IIS 7+ supports pretty permalinks.
3325 * @param bool $supports_permalinks Whether IIS7 supports permalinks. Default false.
3327 return apply_filters( 'iis7_supports_permalinks', $supports_permalinks );
3331 * File validates against allowed set of defined rules.
3333 * A return value of '1' means that the $file contains either '..' or './'. A
3334 * return value of '2' means that the $file contains ':' after the first
3335 * character. A return value of '3' means that the file is not in the allowed
3340 * @param string $file File path.
3341 * @param array $allowed_files List of allowed files.
3342 * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
3344 function validate_file( $file, $allowed_files = '' ) {
3345 if ( false !== strpos( $file, '..' ) )
3348 if ( false !== strpos( $file, './' ) )
3351 if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files ) )
3354 if (':' == substr( $file, 1, 1 ) )
3361 * Determine if SSL is used.
3365 * @return bool True if SSL, false if not used.
3368 if ( isset($_SERVER['HTTPS']) ) {
3369 if ( 'on' == strtolower($_SERVER['HTTPS']) )
3371 if ( '1' == $_SERVER['HTTPS'] )
3373 } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
3380 * Whether SSL login should be forced.
3384 * @param string|bool $force Optional.
3385 * @return bool True if forced, false if not forced.
3387 function force_ssl_login( $force = null ) {
3388 static $forced = false;
3390 if ( !is_null( $force ) ) {
3391 $old_forced = $forced;
3400 * Whether to force SSL used for the Administration Screens.
3404 * @param string|bool $force
3405 * @return bool True if forced, false if not forced.
3407 function force_ssl_admin( $force = null ) {
3408 static $forced = false;
3410 if ( !is_null( $force ) ) {
3411 $old_forced = $forced;
3420 * Guess the URL for the site.
3422 * Will remove wp-admin links to retrieve only return URLs not in the wp-admin
3429 function wp_guess_url() {
3430 if ( defined('WP_SITEURL') && '' != WP_SITEURL ) {
3433 $abspath_fix = str_replace( '\\', '/', ABSPATH );
3434 $script_filename_dir = dirname( $_SERVER['SCRIPT_FILENAME'] );
3436 // The request is for the admin
3437 if ( strpos( $_SERVER['REQUEST_URI'], 'wp-admin' ) !== false || strpos( $_SERVER['REQUEST_URI'], 'wp-login.php' ) !== false ) {
3438 $path = preg_replace( '#/(wp-admin/.*|wp-login.php)#i', '', $_SERVER['REQUEST_URI'] );
3440 // The request is for a file in ABSPATH
3441 } elseif ( $script_filename_dir . '/' == $abspath_fix ) {
3442 // Strip off any file/query params in the path
3443 $path = preg_replace( '#/[^/]*$#i', '', $_SERVER['PHP_SELF'] );
3446 if ( false !== strpos( $_SERVER['SCRIPT_FILENAME'], $abspath_fix ) ) {
3447 // Request is hitting a file inside ABSPATH
3448 $directory = str_replace( ABSPATH, '', $script_filename_dir );
3449 // Strip off the sub directory, and any file/query paramss
3450 $path = preg_replace( '#/' . preg_quote( $directory, '#' ) . '/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] );
3451 } elseif ( false !== strpos( $abspath_fix, $script_filename_dir ) ) {
3452 // Request is hitting a file above ABSPATH
3453 $subdirectory = substr( $abspath_fix, strpos( $abspath_fix, $script_filename_dir ) + strlen( $script_filename_dir ) );
3454 // Strip off any file/query params from the path, appending the sub directory to the install
3455 $path = preg_replace( '#/[^/]*$#i', '' , $_SERVER['REQUEST_URI'] ) . $subdirectory;
3457 $path = $_SERVER['REQUEST_URI'];
3461 $schema = is_ssl() ? 'https://' : 'http://'; // set_url_scheme() is not defined yet
3462 $url = $schema . $_SERVER['HTTP_HOST'] . $path;
3465 return rtrim($url, '/');
3469 * Temporarily suspend cache additions.
3471 * Stops more data being added to the cache, but still allows cache retrieval.
3472 * This is useful for actions, such as imports, when a lot of data would otherwise
3473 * be almost uselessly added to the cache.
3475 * Suspension lasts for a single page load at most. Remember to call this
3476 * function again if you wish to re-enable cache adds earlier.
3480 * @param bool $suspend Optional. Suspends additions if true, re-enables them if false.
3481 * @return bool The current suspend setting
3483 function wp_suspend_cache_addition( $suspend = null ) {
3484 static $_suspend = false;
3486 if ( is_bool( $suspend ) )
3487 $_suspend = $suspend;
3493 * Suspend cache invalidation.
3495 * Turns cache invalidation on and off. Useful during imports where you don't wont to do invalidations
3496 * every time a post is inserted. Callers must be sure that what they are doing won't lead to an inconsistent
3497 * cache when invalidation is suspended.
3501 * @param bool $suspend Whether to suspend or enable cache invalidation
3502 * @return bool The current suspend setting
3504 function wp_suspend_cache_invalidation($suspend = true) {
3505 global $_wp_suspend_cache_invalidation;
3507 $current_suspend = $_wp_suspend_cache_invalidation;
3508 $_wp_suspend_cache_invalidation = $suspend;
3509 return $current_suspend;
3513 * Whether a site is the main site of the current network.
3517 * @param int $site_id Optional. Site ID to test. Defaults to current site.
3518 * @return bool True if $site_id is the main site of the network, or if not running multisite.
3520 function is_main_site( $site_id = null ) {
3521 // This is the current network's information; 'site' is old terminology.
3522 global $current_site;
3524 if ( ! is_multisite() )
3528 $site_id = get_current_blog_id();
3530 return (int) $site_id === (int) $current_site->blog_id;
3534 * Whether a network is the main network of the multisite install.
3538 * @param int $network_id Optional. Network ID to test. Defaults to current network.
3539 * @return bool True if $network_id is the main network, or if not running multisite.
3541 function is_main_network( $network_id = null ) {
3544 if ( ! is_multisite() )
3547 $current_network_id = (int) get_current_site()->id;
3549 if ( ! $network_id )
3550 $network_id = $current_network_id;
3551 $network_id = (int) $network_id;
3553 if ( defined( 'PRIMARY_NETWORK_ID' ) )
3554 return $network_id === (int) PRIMARY_NETWORK_ID;
3556 if ( 1 === $current_network_id )
3557 return $network_id === $current_network_id;
3559 $primary_network_id = (int) wp_cache_get( 'primary_network_id', 'site-options' );
3561 if ( $primary_network_id )
3562 return $network_id === $primary_network_id;
3564 $primary_network_id = (int) $wpdb->get_var( "SELECT id FROM $wpdb->site ORDER BY id LIMIT 1" );
3565 wp_cache_add( 'primary_network_id', $primary_network_id, 'site-options' );
3567 return $network_id === $primary_network_id;
3571 * Whether global terms are enabled.
3576 * @return bool True if multisite and global terms enabled
3578 function global_terms_enabled() {
3579 if ( ! is_multisite() )
3582 static $global_terms = null;
3583 if ( is_null( $global_terms ) ) {
3586 * Filter whether global terms are enabled.
3588 * Passing a non-null value to the filter will effectively short-circuit the function,
3589 * returning the value of the 'global_terms_enabled' site option instead.
3593 * @param null $anbled Whether global terms are enabled.
3595 $filter = apply_filters( 'global_terms_enabled', null );
3596 if ( ! is_null( $filter ) )
3597 $global_terms = (bool) $filter;
3599 $global_terms = (bool) get_site_option( 'global_terms_enabled', false );
3601 return $global_terms;
3605 * gmt_offset modification for smart timezone handling.
3607 * Overrides the gmt_offset option if we have a timezone_string available.
3611 * @return float|bool
3613 function wp_timezone_override_offset() {
3614 if ( !$timezone_string = get_option( 'timezone_string' ) ) {
3618 $timezone_object = timezone_open( $timezone_string );
3619 $datetime_object = date_create();
3620 if ( false === $timezone_object || false === $datetime_object ) {
3623 return round( timezone_offset_get( $timezone_object, $datetime_object ) / HOUR_IN_SECONDS, 2 );
3627 * Sort-helper for timezones.
3635 function _wp_timezone_choice_usort_callback( $a, $b ) {
3636 // Don't use translated versions of Etc
3637 if ( 'Etc' === $a['continent'] && 'Etc' === $b['continent'] ) {
3638 // Make the order of these more like the old dropdown
3639 if ( 'GMT+' === substr( $a['city'], 0, 4 ) && 'GMT+' === substr( $b['city'], 0, 4 ) ) {
3640 return -1 * ( strnatcasecmp( $a['city'], $b['city'] ) );
3642 if ( 'UTC' === $a['city'] ) {
3643 if ( 'GMT+' === substr( $b['city'], 0, 4 ) ) {
3648 if ( 'UTC' === $b['city'] ) {
3649 if ( 'GMT+' === substr( $a['city'], 0, 4 ) ) {
3654 return strnatcasecmp( $a['city'], $b['city'] );
3656 if ( $a['t_continent'] == $b['t_continent'] ) {
3657 if ( $a['t_city'] == $b['t_city'] ) {
3658 return strnatcasecmp( $a['t_subcity'], $b['t_subcity'] );
3660 return strnatcasecmp( $a['t_city'], $b['t_city'] );
3662 // Force Etc to the bottom of the list
3663 if ( 'Etc' === $a['continent'] ) {
3666 if ( 'Etc' === $b['continent'] ) {
3669 return strnatcasecmp( $a['t_continent'], $b['t_continent'] );
3674 * Gives a nicely formatted list of timezone strings.
3678 * @param string $selected_zone Selected Zone
3681 function wp_timezone_choice( $selected_zone ) {
3682 static $mo_loaded = false;
3684 $continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
3686 // Load translations for continents and cities
3687 if ( !$mo_loaded ) {
3688 $locale = get_locale();
3689 $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
3690 load_textdomain( 'continents-cities', $mofile );
3695 foreach ( timezone_identifiers_list() as $zone ) {
3696 $zone = explode( '/', $zone );
3697 if ( !in_array( $zone[0], $continents ) ) {
3701 // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
3703 0 => ( isset( $zone[0] ) && $zone[0] ),
3704 1 => ( isset( $zone[1] ) && $zone[1] ),
3705 2 => ( isset( $zone[2] ) && $zone[2] ),
3707 $exists[3] = ( $exists[0] && 'Etc' !== $zone[0] );
3708 $exists[4] = ( $exists[1] && $exists[3] );
3709 $exists[5] = ( $exists[2] && $exists[3] );
3712 'continent' => ( $exists[0] ? $zone[0] : '' ),
3713 'city' => ( $exists[1] ? $zone[1] : '' ),
3714 'subcity' => ( $exists[2] ? $zone[2] : '' ),
3715 't_continent' => ( $exists[3] ? translate( str_replace( '_', ' ', $zone[0] ), 'continents-cities' ) : '' ),
3716 't_city' => ( $exists[4] ? translate( str_replace( '_', ' ', $zone[1] ), 'continents-cities' ) : '' ),
3717 't_subcity' => ( $exists[5] ? translate( str_replace( '_', ' ', $zone[2] ), 'continents-cities' ) : '' )
3720 usort( $zonen, '_wp_timezone_choice_usort_callback' );
3722 $structure = array();
3724 if ( empty( $selected_zone ) ) {
3725 $structure[] = '<option selected="selected" value="">' . __( 'Select a city' ) . '</option>';
3728 foreach ( $zonen as $key => $zone ) {
3729 // Build value in an array to join later
3730 $value = array( $zone['continent'] );
3732 if ( empty( $zone['city'] ) ) {
3733 // It's at the continent level (generally won't happen)
3734 $display = $zone['t_continent'];
3736 // It's inside a continent group
3738 // Continent optgroup
3739 if ( !isset( $zonen[$key - 1] ) || $zonen[$key - 1]['continent'] !== $zone['continent'] ) {
3740 $label = $zone['t_continent'];
3741 $structure[] = '<optgroup label="'. esc_attr( $label ) .'">';
3744 // Add the city to the value
3745 $value[] = $zone['city'];
3747 $display = $zone['t_city'];
3748 if ( !empty( $zone['subcity'] ) ) {
3749 // Add the subcity to the value
3750 $value[] = $zone['subcity'];
3751 $display .= ' - ' . $zone['t_subcity'];
3756 $value = join( '/', $value );
3758 if ( $value === $selected_zone ) {
3759 $selected = 'selected="selected" ';
3761 $structure[] = '<option ' . $selected . 'value="' . esc_attr( $value ) . '">' . esc_html( $display ) . "</option>";
3763 // Close continent optgroup
3764 if ( !empty( $zone['city'] ) && ( !isset($zonen[$key + 1]) || (isset( $zonen[$key + 1] ) && $zonen[$key + 1]['continent'] !== $zone['continent']) ) ) {
3765 $structure[] = '</optgroup>';
3770 $structure[] = '<optgroup label="'. esc_attr__( 'UTC' ) .'">';
3772 if ( 'UTC' === $selected_zone )
3773 $selected = 'selected="selected" ';
3774 $structure[] = '<option ' . $selected . 'value="' . esc_attr( 'UTC' ) . '">' . __('UTC') . '</option>';
3775 $structure[] = '</optgroup>';
3777 // Do manual UTC offsets
3778 $structure[] = '<optgroup label="'. esc_attr__( 'Manual Offsets' ) .'">';
3779 $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,
3780 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);
3781 foreach ( $offset_range as $offset ) {
3783 $offset_name = '+' . $offset;
3785 $offset_name = (string) $offset;
3787 $offset_value = $offset_name;
3788 $offset_name = str_replace(array('.25','.5','.75'), array(':15',':30',':45'), $offset_name);
3789 $offset_name = 'UTC' . $offset_name;
3790 $offset_value = 'UTC' . $offset_value;
3792 if ( $offset_value === $selected_zone )
3793 $selected = 'selected="selected" ';
3794 $structure[] = '<option ' . $selected . 'value="' . esc_attr( $offset_value ) . '">' . esc_html( $offset_name ) . "</option>";
3797 $structure[] = '</optgroup>';
3799 return join( "\n", $structure );
3803 * Strip close comment and close php tags from file headers used by WP.
3804 * See http://core.trac.wordpress.org/ticket/8497
3808 * @param string $str
3811 function _cleanup_header_comment($str) {
3812 return trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $str));
3816 * Permanently deletes posts, pages, attachments, and comments which have been in the trash for EMPTY_TRASH_DAYS.
3820 function wp_scheduled_delete() {
3823 $delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );
3825 $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);
3827 foreach ( (array) $posts_to_delete as $post ) {
3828 $post_id = (int) $post['post_id'];
3832 $del_post = get_post($post_id);
3834 if ( !$del_post || 'trash' != $del_post->post_status ) {
3835 delete_post_meta($post_id, '_wp_trash_meta_status');
3836 delete_post_meta($post_id, '_wp_trash_meta_time');
3838 wp_delete_post($post_id);
3842 $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);
3844 foreach ( (array) $comments_to_delete as $comment ) {
3845 $comment_id = (int) $comment['comment_id'];
3849 $del_comment = get_comment($comment_id);
3851 if ( !$del_comment || 'trash' != $del_comment->comment_approved ) {
3852 delete_comment_meta($comment_id, '_wp_trash_meta_time');
3853 delete_comment_meta($comment_id, '_wp_trash_meta_status');
3855 wp_delete_comment($comment_id);
3861 * Retrieve metadata from a file.
3863 * Searches for metadata in the first 8kiB of a file, such as a plugin or theme.
3864 * Each piece of metadata must be on its own line. Fields can not span multiple
3865 * lines, the value will get cut at the end of the first line.
3867 * If the file data is not within that first 8kiB, then the author should correct
3868 * their plugin file and move the data headers to the top.
3870 * @see http://codex.wordpress.org/File_Header
3873 * @param string $file Path to the file
3874 * @param array $default_headers List of headers, in the format array('HeaderKey' => 'Header Name')
3875 * @param string $context If specified adds filter hook "extra_{$context}_headers"
3877 function get_file_data( $file, $default_headers, $context = '' ) {
3878 // We don't need to write to the file, so just open for reading.
3879 $fp = fopen( $file, 'r' );
3881 // Pull only the first 8kiB of the file in.
3882 $file_data = fread( $fp, 8192 );
3884 // PHP will close file handle, but we are good citizens.
3887 // Make sure we catch CR-only line endings.
3888 $file_data = str_replace( "\r", "\n", $file_data );
3891 * Filter extra file headers by context.
3893 * The dynamic portion of the hook name, $context, refers to the context
3894 * where extra headers might be loaded.
3898 * @param array $extra_context_headers Empty array by default.
3900 if ( $context && $extra_headers = apply_filters( "extra_{$context}_headers", array() ) ) {
3901 $extra_headers = array_combine( $extra_headers, $extra_headers ); // keys equal values
3902 $all_headers = array_merge( $extra_headers, (array) $default_headers );
3904 $all_headers = $default_headers;
3907 foreach ( $all_headers as $field => $regex ) {
3908 if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] )
3909 $all_headers[ $field ] = _cleanup_header_comment( $match[1] );
3911 $all_headers[ $field ] = '';
3914 return $all_headers;
3920 * Useful for returning true to filters easily.
3923 * @see __return_false()
3926 function __return_true() {
3933 * Useful for returning false to filters easily.
3936 * @see __return_true()
3937 * @return bool false
3939 function __return_false() {
3946 * Useful for returning 0 to filters easily.
3951 function __return_zero() {
3956 * Returns an empty array.
3958 * Useful for returning an empty array to filters easily.
3961 * @return array Empty array
3963 function __return_empty_array() {
3970 * Useful for returning null to filters easily.
3975 function __return_null() {
3980 * Returns an empty string.
3982 * Useful for returning an empty string to filters easily.
3985 * @see __return_null()
3986 * @return string Empty string
3988 function __return_empty_string() {
3993 * Send a HTTP header to disable content type sniffing in browsers which support it.
3995 * @link http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx
3996 * @link http://src.chromium.org/viewvc/chrome?view=rev&revision=6985
4001 function send_nosniff_header() {
4002 @header( 'X-Content-Type-Options: nosniff' );
4006 * Returns a MySQL expression for selecting the week number based on the start_of_week option.
4010 * @param string $column
4013 function _wp_mysql_week( $column ) {
4014 switch ( $start_of_week = (int) get_option( 'start_of_week' ) ) {
4017 return "WEEK( $column, 0 )";
4019 return "WEEK( $column, 1 )";
4025 return "WEEK( DATE_SUB( $column, INTERVAL $start_of_week DAY ), 0 )";
4030 * Finds hierarchy loops using a callback function that maps object IDs to parent IDs.
4035 * @param callback $callback function that accepts ( ID, $callback_args ) and outputs parent_ID
4036 * @param int $start The ID to start the loop check at
4037 * @param int $start_parent the parent_ID of $start to use instead of calling $callback( $start ). Use null to always use $callback
4038 * @param array $callback_args optional additional arguments to send to $callback
4039 * @return array IDs of all members of loop
4041 function wp_find_hierarchy_loop( $callback, $start, $start_parent, $callback_args = array() ) {
4042 $override = is_null( $start_parent ) ? array() : array( $start => $start_parent );
4044 if ( !$arbitrary_loop_member = wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override, $callback_args ) )
4047 return wp_find_hierarchy_loop_tortoise_hare( $callback, $arbitrary_loop_member, $override, $callback_args, true );
4051 * Uses the "The Tortoise and the Hare" algorithm to detect loops.
4053 * For every step of the algorithm, the hare takes two steps and the tortoise one.
4054 * If the hare ever laps the tortoise, there must be a loop.
4059 * @param callback $callback function that accepts ( ID, callback_arg, ... ) and outputs parent_ID
4060 * @param int $start The ID to start the loop check at
4061 * @param array $override an array of ( ID => parent_ID, ... ) to use instead of $callback
4062 * @param array $callback_args optional additional arguments to send to $callback
4063 * @param bool $_return_loop Return loop members or just detect presence of loop?
4064 * Only set to true if you already know the given $start is part of a loop
4065 * (otherwise the returned array might include branches)
4066 * @return mixed scalar ID of some arbitrary member of the loop, or array of IDs of all members of loop if $_return_loop
4068 function wp_find_hierarchy_loop_tortoise_hare( $callback, $start, $override = array(), $callback_args = array(), $_return_loop = false ) {
4069 $tortoise = $hare = $evanescent_hare = $start;
4072 // Set evanescent_hare to one past hare
4073 // Increment hare two steps
4077 ( $evanescent_hare = isset( $override[$hare] ) ? $override[$hare] : call_user_func_array( $callback, array_merge( array( $hare ), $callback_args ) ) )
4079 ( $hare = isset( $override[$evanescent_hare] ) ? $override[$evanescent_hare] : call_user_func_array( $callback, array_merge( array( $evanescent_hare ), $callback_args ) ) )
4081 if ( $_return_loop )
4082 $return[$tortoise] = $return[$evanescent_hare] = $return[$hare] = true;
4084 // tortoise got lapped - must be a loop
4085 if ( $tortoise == $evanescent_hare || $tortoise == $hare )
4086 return $_return_loop ? $return : $tortoise;
4088 // Increment tortoise by one step
4089 $tortoise = isset( $override[$tortoise] ) ? $override[$tortoise] : call_user_func_array( $callback, array_merge( array( $tortoise ), $callback_args ) );
4096 * Send a HTTP header to limit rendering of pages to same origin iframes.
4098 * @link https://developer.mozilla.org/en/the_x-frame-options_response_header
4103 function send_frame_options_header() {
4104 @header( 'X-Frame-Options: SAMEORIGIN' );
4108 * Retrieve a list of protocols to allow in HTML attributes.
4114 * @return array Array of allowed protocols
4116 function wp_allowed_protocols() {
4119 if ( empty( $protocols ) ) {
4120 $protocols = array( 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet', 'mms', 'rtsp', 'svn', 'tel', 'fax', 'xmpp' );
4123 * Filter the list of protocols allowed in HTML attributes.
4127 * @param array $protocols Array of allowed protocols e.g. 'http', 'ftp', 'tel', and more.
4129 $protocols = apply_filters( 'kses_allowed_protocols', $protocols );
4136 * Return a comma separated string of functions that have been called to get to the current point in code.
4138 * @link http://core.trac.wordpress.org/ticket/19589
4141 * @param string $ignore_class A class to ignore all function calls within - useful when you want to just give info about the callee
4142 * @param int $skip_frames A number of stack frames to skip - useful for unwinding back to the source of the issue
4143 * @param bool $pretty Whether or not you want a comma separated string or raw array returned
4144 * @return string|array Either a string containing a reversed comma separated trace or an array of individual calls.
4146 function wp_debug_backtrace_summary( $ignore_class = null, $skip_frames = 0, $pretty = true ) {
4147 if ( version_compare( PHP_VERSION, '5.2.5', '>=' ) )
4148 $trace = debug_backtrace( false );
4150 $trace = debug_backtrace();
4153 $check_class = ! is_null( $ignore_class );
4154 $skip_frames++; // skip this function
4156 foreach ( $trace as $call ) {
4157 if ( $skip_frames > 0 ) {
4159 } elseif ( isset( $call['class'] ) ) {
4160 if ( $check_class && $ignore_class == $call['class'] )
4161 continue; // Filter out calls
4163 $caller[] = "{$call['class']}{$call['type']}{$call['function']}";
4165 if ( in_array( $call['function'], array( 'do_action', 'apply_filters' ) ) ) {
4166 $caller[] = "{$call['function']}('{$call['args'][0]}')";
4167 } elseif ( in_array( $call['function'], array( 'include', 'include_once', 'require', 'require_once' ) ) ) {
4168 $caller[] = $call['function'] . "('" . str_replace( array( WP_CONTENT_DIR, ABSPATH ) , '', $call['args'][0] ) . "')";
4170 $caller[] = $call['function'];
4175 return join( ', ', array_reverse( $caller ) );
4181 * Retrieve ids that are not already present in the cache
4185 * @param array $object_ids ID list
4186 * @param string $cache_key The cache bucket to check against
4190 function _get_non_cached_ids( $object_ids, $cache_key ) {
4192 foreach ( $object_ids as $id ) {
4194 if ( !wp_cache_get( $id, $cache_key ) ) {
4203 * Test if the current device has the capability to upload files.
4208 * @return bool true|false
4210 function _device_can_upload() {
4211 if ( ! wp_is_mobile() )
4214 $ua = $_SERVER['HTTP_USER_AGENT'];
4216 if ( strpos($ua, 'iPhone') !== false
4217 || strpos($ua, 'iPad') !== false
4218 || strpos($ua, 'iPod') !== false ) {
4219 return preg_match( '#OS ([\d_]+) like Mac OS X#', $ua, $version ) && version_compare( $version[1], '6', '>=' );
4226 * Test if a given path is a stream URL
4228 * @param string $path The resource path or URL
4229 * @return bool True if the path is a stream URL
4231 function wp_is_stream( $path ) {
4232 $wrappers = stream_get_wrappers();
4233 $wrappers_re = '(' . join('|', $wrappers) . ')';
4235 return preg_match( "!^$wrappers_re://!", $path ) === 1;
4239 * Test if the supplied date is valid for the Gregorian calendar
4243 * @return bool true|false
4245 function wp_checkdate( $month, $day, $year, $source_date ) {
4247 * Filter whether the given date is valid for the Gregorian calendar.
4251 * @param bool $checkdate Whether the given date is valid.
4252 * @param string $source_date Date to check.
4254 return apply_filters( 'wp_checkdate', checkdate( $month, $day, $year ), $source_date );
4258 * Load the auth check for monitoring whether the user is still logged in.
4260 * Can be disabled with remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
4262 * This is disabled for certain screens where a login screen could cause an
4263 * inconvenient interruption. A filter called wp_auth_check_load can be used
4264 * for fine-grained control.
4268 function wp_auth_check_load() {
4269 if ( ! is_admin() && ! is_user_logged_in() )
4272 if ( defined( 'IFRAME_REQUEST' ) )
4275 $screen = get_current_screen();
4276 $hidden = array( 'update', 'update-network', 'update-core', 'update-core-network', 'upgrade', 'upgrade-network', 'network' );
4277 $show = ! in_array( $screen->id, $hidden );
4280 * Filter whether to load the authentication check.
4284 * @param bool $show Whether to load the authentication check.
4285 * @param WP_Screen $screen The current screen object.
4287 if ( apply_filters( 'wp_auth_check_load', $show, $screen ) ) {
4288 wp_enqueue_style( 'wp-auth-check' );
4289 wp_enqueue_script( 'wp-auth-check' );
4291 add_action( 'admin_print_footer_scripts', 'wp_auth_check_html', 5 );
4292 add_action( 'wp_print_footer_scripts', 'wp_auth_check_html', 5 );
4297 * Output the HTML that shows the wp-login dialog when the user is no longer logged in.
4301 function wp_auth_check_html() {
4302 $login_url = wp_login_url();
4303 $current_domain = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'];
4304 $same_domain = ( strpos( $login_url, $current_domain ) === 0 );
4306 if ( $same_domain && force_ssl_login() && ! force_ssl_admin() )
4307 $same_domain = false;
4310 * Filter whether the authentication check originated at the same domain.
4314 * @param bool $same_domain Whether the authentication check originated at the same domain.
4316 $same_domain = apply_filters( 'wp_auth_check_same_domain', $same_domain );
4317 $wrap_class = $same_domain ? 'hidden' : 'hidden fallback';
4320 <div id="wp-auth-check-wrap" class="<?php echo $wrap_class; ?>">
4321 <div id="wp-auth-check-bg"></div>
4322 <div id="wp-auth-check">
4323 <div class="wp-auth-check-close" tabindex="0" title="<?php esc_attr_e('Close'); ?>"></div>
4326 if ( $same_domain ) {
4328 <div id="wp-auth-check-form" data-src="<?php echo esc_url( add_query_arg( array( 'interim-login' => 1 ), $login_url ) ); ?>"></div>
4333 <div class="wp-auth-fallback">
4334 <p><b class="wp-auth-fallback-expired" tabindex="0"><?php _e('Session expired'); ?></b></p>
4335 <p><a href="<?php echo esc_url( $login_url ); ?>" target="_blank"><?php _e('Please log in again.'); ?></a>
4336 <?php _e('The login page will open in a new window. After logging in you can close it and return to this page.'); ?></p>
4344 * Check whether a user is still logged in, for the heartbeat.
4346 * Send a result that shows a log-in box if the user is no longer logged in,
4347 * or if their cookie is within the grace period.
4351 function wp_auth_check( $response ) {
4352 $response['wp-auth-check'] = is_user_logged_in() && empty( $GLOBALS['login_grace_period'] );
4357 * Return RegEx body to liberally match an opening HTML tag that:
4358 * 1. Is self-closing or
4359 * 2. Has no body but has a closing tag of the same name or
4360 * 3. Contains a body and a closing tag of the same name
4362 * Note: this RegEx does not balance inner tags and does not attempt to produce valid HTML
4366 * @param string $tag An HTML tag name. Example: 'video'
4369 function get_tag_regex( $tag ) {
4370 if ( empty( $tag ) )
4372 return sprintf( '<%1$s[^<]*(?:>[\s\S]*<\/%1$s>|\s*\/>)', tag_escape( $tag ) );
4376 * Return a canonical form of the provided charset appropriate for passing to PHP
4377 * functions such as htmlspecialchars() and charset html attributes.
4379 * @link http://core.trac.wordpress.org/ticket/23688
4382 * @param string A charset name
4383 * @return string The canonical form of the charset
4385 function _canonical_charset( $charset ) {
4386 if ( 'UTF-8' === $charset || 'utf-8' === $charset || 'utf8' === $charset ||
4387 'UTF8' === $charset )
4390 if ( 'ISO-8859-1' === $charset || 'iso-8859-1' === $charset ||
4391 'iso8859-1' === $charset || 'ISO8859-1' === $charset )
4392 return 'ISO-8859-1';
4398 * Sets the mbstring internal encoding to a binary safe encoding whne func_overload is enabled.
4400 * When mbstring.func_overload is in use for multi-byte encodings, the results from strlen() and
4401 * similar functions respect the utf8 characters, causing binary data to return incorrect lengths.
4403 * This function overrides the mbstring encoding to a binary-safe encoding, and resets it to the
4404 * users expected encoding afterwards through the `reset_mbstring_encoding` function.
4406 * It is safe to recursively call this function, however each `mbstring_binary_safe_encoding()`
4407 * call must be followed up with an equal number of `reset_mbstring_encoding()` calls.
4409 * @see reset_mbstring_encoding()
4413 * @param bool $reset Whether to reset the encoding back to a previously-set encoding.
4415 function mbstring_binary_safe_encoding( $reset = false ) {
4416 static $encodings = array();
4417 static $overloaded = null;
4419 if ( is_null( $overloaded ) )
4420 $overloaded = function_exists( 'mb_internal_encoding' ) && ( ini_get( 'mbstring.func_overload' ) & 2 );
4422 if ( false === $overloaded )
4426 $encoding = mb_internal_encoding();
4427 array_push( $encodings, $encoding );
4428 mb_internal_encoding( 'ISO-8859-1' );
4431 if ( $reset && $encodings ) {
4432 $encoding = array_pop( $encodings );
4433 mb_internal_encoding( $encoding );
4438 * Resets the mbstring internal encoding to a users previously set encoding.
4440 * @see mbstring_binary_safe_encoding()
4444 function reset_mbstring_encoding() {
4445 mbstring_binary_safe_encoding( true );