Make WordPress Core

Ticket #26879: 26879-15.diff

File 26879-15.diff, 176.3 KB (added by extendwings, 8 years ago)
  • wp-admin/css/install.css

    diff --git a/wp-admin/css/install.css b/wp-admin/css/install.css
    index c033ea5..86ec9f1 100644
    a b submit { 
    211211        font-size: 18px;
    212212}
    213213
    214 #error-page {
     214body.error-page {
    215215        margin-top: 50px;
    216216}
    217217
    218 #error-page p {
     218body.error-page p {
    219219        font-size: 14px;
    220220        line-height: 18px;
    221221        margin: 25px 0 20px;
    222222}
    223223
    224 #error-page code, .code {
    225         font-family: Consolas, Monaco, monospace;
    226 }
    227 
    228224.wp-hide-pw > .dashicons {
    229225        line-height: inherit;
    230226}
  • wp-admin/setup-config.php

    diff --git a/wp-admin/setup-config.php b/wp-admin/setup-config.php
    index fd8d32b..04f060e 100644
    a b function setup_config_display_header( $body_classes = array() ) { 
    141141                        $step_1 .= '&language=' . $loaded_language;
    142142                }
    143143?>
    144 <h1 class="screen-reader-text"><?php _e( 'Before getting started' ) ?></h1>
    145 <p><?php _e( 'Welcome to WordPress. Before getting started, we need some information on the database. You will need to know the following items before proceeding.' ) ?></p>
     144<h1 class="screen-reader-text"><?php _e( 'Before getting started' ); ?></h1>
     145<p><?php _e( "OK! We need some information about your database." ); ?></p>
     146<p><?php _e( "This information is available through your web host. If you don't have it, you'll need to get in touch with them. Here's what you need:" ); ?></p>
    146147<ol>
    147148        <li><?php _e( 'Database name' ); ?></li>
    148149        <li><?php _e( 'Database username' ); ?></li>
    149150        <li><?php _e( 'Database password' ); ?></li>
    150151        <li><?php _e( 'Database host' ); ?></li>
    151         <li><?php _e( 'Table prefix (if you want to run more than one WordPress in a single database)' ); ?></li>
    152152</ol>
    153153<p><?php
     154        /* translators: 1: wp-config.php, 2: Codex URL */
     155        printf( __( "Once you fill in this information, WordPress will create a configuration file called %1$s. This connects WordPress with your database, where your content and settings will be stored. Need more help? Check out our <a href='%2$s'>documentation</a>." ),
     156                '<code>wp-config.php</code>',
     157                __( 'https://codex.wordpress.org/Editing_wp-config.php' )
     158        );
     159?></p>
     160<p><?php _e( "If you&#8217;re all ready&hellip;" ); ?></p>
     161<p><?php
    154162        /* translators: %s: wp-config.php */
    155163        printf( __( 'We&#8217;re going to use this information to create a %s file.' ),
    156164                '<code>wp-config.php</code>'
    function setup_config_display_header( $body_classes = array() ) { 
    171179?></p>
    172180<p><?php _e( 'In all likelihood, these items were supplied to you by your Web Host. If you don&#8217;t have this information, then you will need to contact them before you can continue. If you&#8217;re all ready&hellip;' ); ?></p>
    173181
    174 <p class="step"><a href="<?php echo $step_1; ?>" class="button button-large"><?php _e( 'Let&#8217;s go!' ); ?></a></p>
     182<p class="step"><a href="setup-config.php?step=1<?php if ( isset( $_GET['noapi'] ) ) echo '&amp;noapi'; ?>" class="button button-large"><?php _e( 'Let&#8217;s Go!' ); ?></a></p>
    175183<?php
    176184        break;
    177185
    function setup_config_display_header( $body_classes = array() ) { 
    244252                $install .= '?language=en_US';
    245253        }
    246254
    247         $tryagain_link = '</p><p class="step"><a href="' . $step_1 . '" onclick="javascript:history.go(-1);return false;" class="button button-large">' . __( 'Try again' ) . '</a>';
    248 
    249         if ( empty( $prefix ) )
    250                 wp_die( __( '<strong>ERROR</strong>: "Table Prefix" must not be empty.' . $tryagain_link ) );
     255        $tryagain_link = '</p><p class="step"><a href="setup-config.php?step=1" onclick="javascript:history.go(-1);return false;" class="button button-large">' . __( 'Try Again' ) . '</a>';
     256
     257        // Validate $prefix: it must not be empty
     258        if ( empty( $prefix ) ) {
     259                $die .= '<p style="text-align: center;">' . __( "Oops, the Table Prefix field can't be empty. Please go back and try again." ) . '</p>';
     260                $die .= '<p style="text-align: center;">' . sprintf(
     261                        /* translators: %s: Codex URL */
     262                        __( "Need more help? Check out our <a href='%s'>documentation</a>." ),
     263                        __( 'https://codex.wordpress.org/Editing_wp-config.php#table_prefix' )
     264                ) . '</p>';
     265                $die .= ( __( $tryagain_link ) );
     266                wp_die( $die );
     267        }
    251268
    252269        // Validate $prefix: it can only contain letters, numbers and underscores.
    253         if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
    254                 wp_die( __( '<strong>ERROR</strong>: "Table Prefix" can only contain numbers, letters, and underscores.' . $tryagain_link ) );
     270        if ( preg_match( '|[^a-z0-9_]|i', $prefix ) ) {
     271                $die .= '<p style="text-align: center;">' . __( "Oops, the Table Prefix field can only contain numbers, letters, and underscores. Please go back and try again. ") . '</p>';
     272                $die .= '<p style="text-align: center;">' . sprintf(
     273                        /* translators: %s: Codex URL */
     274                        __( "Need more help? Check out our <a href='%s'>documentation</a>." ),
     275                        __( 'https://codex.wordpress.org/Editing_wp-config.php#table_prefix' )
     276                ) . '</p>';
     277                $die .= ( __( $tryagain_link ) );
     278                wp_die( $die );
     279        }
    255280
    256281        // Test the db connection.
    257282        /**#@+
    function setup_config_display_header( $body_classes = array() ) { 
    343368?></p>
    344369<p><?php
    345370        /* translators: %s: wp-config.php */
    346         printf( __( 'You can create the %s manually and paste the following text into it.' ), '<code>wp-config.php</code>' );
     371        printf( __( 'To continue, manually create a file named %s in the root directory where the rest of your WordPress files are located and copy and paste the following text into the file:'), '<code>wp-config.php</code>' );
    347372?></p>
    348373<textarea id="wp-config" cols="98" rows="15" class="code" readonly="readonly"><?php
    349374                foreach ( $config_file as $line ) {
  • wp-includes/functions.php

    diff --git a/wp-includes/functions.php b/wp-includes/functions.php
    index bcd56f7..7be8371 100644
    a b function _default_wp_die_handler( $message, $title = '', $args = array() ) { 
    26132613                        $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>";
    26142614                        break;
    26152615                }
    2616         } elseif ( is_string( $message ) ) {
     2616        } elseif ( is_string( $message ) && empty( $r['raw'] ) ) {
    26172617                $message = "<p>$message</p>";
    26182618        }
    26192619
    function _default_wp_die_handler( $message, $title = '', $args = array() ) { 
    26372637                        $text_direction = 'rtl';
    26382638                elseif ( function_exists( 'is_rtl' ) && is_rtl() )
    26392639                        $text_direction = 'rtl';
     2640
     2641                $site_url = wp_guess_url();
     2642
     2643                $classes = 'wp-core-ui';
     2644                if ( ! empty( $r['error'] ) ) {
     2645                        $classes .= ' error-page';
     2646                }
     2647                if ( 'rtl' === $text_direction ) {
     2648                        $classes .= ' rtl';
     2649                }
    26402650?>
    26412651<!DOCTYPE html>
    26422652<!-- 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
    function _default_wp_die_handler( $message, $title = '', $args = array() ) { 
    26462656        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    26472657        <meta name="viewport" content="width=device-width">
    26482658        <title><?php echo $title ?></title>
    2649         <style type="text/css">
    2650                 html {
    2651                         background: #f1f1f1;
    2652                 }
    2653                 body {
    2654                         background: #fff;
    2655                         color: #444;
    2656                         font-family: "Open Sans", sans-serif;
    2657                         margin: 2em auto;
    2658                         padding: 1em 2em;
    2659                         max-width: 700px;
    2660                         -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);
    2661                         box-shadow: 0 1px 3px rgba(0,0,0,0.13);
    2662                 }
    2663                 h1 {
    2664                         border-bottom: 1px solid #dadada;
    2665                         clear: both;
    2666                         color: #666;
    2667                         font: 24px "Open Sans", sans-serif;
    2668                         margin: 30px 0 0 0;
    2669                         padding: 0;
    2670                         padding-bottom: 7px;
    2671                 }
    2672                 #error-page {
    2673                         margin-top: 50px;
    2674                 }
    2675                 #error-page p {
    2676                         font-size: 14px;
    2677                         line-height: 1.5;
    2678                         margin: 25px 0 20px;
    2679                 }
    2680                 #error-page code {
    2681                         font-family: Consolas, Monaco, monospace;
    2682                 }
    2683                 ul li {
    2684                         margin-bottom: 10px;
    2685                         font-size: 14px ;
    2686                 }
    2687                 a {
    2688                         color: #0073aa;
    2689                 }
    2690                 a:hover,
    2691                 a:active {
    2692                         color: #00a0d2;
    2693                 }
    2694                 a:focus {
    2695                         color: #124964;
    2696                     -webkit-box-shadow:
    2697                         0 0 0 1px #5b9dd9,
    2698                                 0 0 2px 1px rgba(30, 140, 190, .8);
    2699                     box-shadow:
    2700                         0 0 0 1px #5b9dd9,
    2701                                 0 0 2px 1px rgba(30, 140, 190, .8);
    2702                         outline: none;
    2703                 }
    2704                 .button {
    2705                         background: #f7f7f7;
    2706                         border: 1px solid #ccc;
    2707                         color: #555;
    2708                         display: inline-block;
    2709                         text-decoration: none;
    2710                         font-size: 13px;
    2711                         line-height: 26px;
    2712                         height: 28px;
    2713                         margin: 0;
    2714                         padding: 0 10px 1px;
    2715                         cursor: pointer;
    2716                         -webkit-border-radius: 3px;
    2717                         -webkit-appearance: none;
    2718                         border-radius: 3px;
    2719                         white-space: nowrap;
    2720                         -webkit-box-sizing: border-box;
    2721                         -moz-box-sizing:    border-box;
    2722                         box-sizing:         border-box;
    2723 
    2724                         -webkit-box-shadow: 0 1px 0 #ccc;
    2725                         box-shadow: 0 1px 0 #ccc;
    2726                         vertical-align: top;
    2727                 }
    2728 
    2729                 .button.button-large {
    2730                         height: 30px;
    2731                         line-height: 28px;
    2732                         padding: 0 12px 2px;
    2733                 }
    2734 
    2735                 .button:hover,
    2736                 .button:focus {
    2737                         background: #fafafa;
    2738                         border-color: #999;
    2739                         color: #23282d;
    2740                 }
    2741 
    2742                 .button:focus  {
    2743                         border-color: #5b9dd9;
    2744                         -webkit-box-shadow: 0 0 3px rgba( 0, 115, 170, .8 );
    2745                         box-shadow: 0 0 3px rgba( 0, 115, 170, .8 );
    2746                         outline: none;
    2747                 }
    2748 
    2749                 .button:active {
    2750                         background: #eee;
    2751                         border-color: #999;
    2752                         -webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
    2753                         box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
    2754                         -webkit-transform: translateY(1px);
    2755                         -ms-transform: translateY(1px);
    2756                         transform: translateY(1px);
    2757                 }
    2758 
    2759                 <?php
    2760                 if ( 'rtl' == $text_direction ) {
    2761                         echo 'body { font-family: Tahoma, Arial; }';
    2762                 }
    2763                 ?>
    2764         </style>
     2659        <link rel="stylesheet" type="text/css" href="<?php echo $site_url; ?>/wp-admin/css/install.css" />
     2660        <link rel="stylesheet" type="text/css" href="<?php echo $site_url; ?>/wp-includes/css/buttons.css" />
    27652661</head>
    2766 <body id="error-page">
     2662<body class="<?php echo $classes; ?>">
    27672663<?php endif; // ! did_action( 'admin_head' ) ?>
    27682664        <?php echo $message; ?>
    27692665</body>
  • new file wp-includes/functions.php.orig

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

    diff --git a/wp-load.php b/wp-load.php
    index 94a8b54..4465898 100644
    a b  
    7272        wp_load_translations_early();
    7373
    7474        // Die with an error message
    75         $die  = sprintf(
     75        $die = sprintf(
     76                __( '<h1 id="logo"><a href="%s">WordPress</a></h1>' ),
     77                /* translators: %s: WordPress url */
     78                __( 'https://wordpress.org/' )
     79        );
     80        $die .= '<h1>' . __( 'Welcome to WordPress' ) . '</h1>';
     81        $die .= '<p>' . __( "In just a few minutes, you'll be all set up with WordPress and ready to create your own corner of the web." ) . '</p>';
     82        $die .= '<p>' . sprintf(
     83                /* translators: %s: Codex plugins url, Codex themes url */
     84                __( 'This free and Open Source software is built and maintained by a community of hundreds of volunteers. Transform your website with countless of <a href="%1$s">plugins</a> and <a href="%2$s">themes</a> available from right within WordPress.' ),
     85                'https://wordpress.org/plugins/',
     86                'https://wordpress.org/themes/'
     87        ) . '</p>';
     88        $die .= '<p>' . __( 'Write your blog, build your first website, launch your business, share your photos with your friends. You can do just about anything you can imagine.' ) . '</p>';
     89        $die .= '<p>' . sprintf(
     90                __( '<a href="%1$s" class="button button-large">%2$s</a>' ),
     91                $path,
     92                __( "Let's Get Started!" )
     93        ) . '</p>';
     94        $die .= sprintf(
    7695                /* translators: %s: wp-config.php */
    7796                __( "There doesn't seem to be a %s file. I need this before we can get started." ),
    7897                '<code>wp-config.php</code>'
    7998        ) . '</p>';
    8099        $die .= '<p>' . sprintf(
    81100                /* translators: %s: Codex URL */
    82                 __( "Need more help? <a href='%s'>We got it</a>." ),
    83                 __( 'https://codex.wordpress.org/Editing_wp-config.php' )
     101                __( 'Need more help? <a href="%1$s">%2$s</a>.' ),
     102                __( 'https://codex.wordpress.org/Editing_wp-config.php' ),
     103                __( 'We got it' )
    84104        ) . '</p>';
    85105        $die .= '<p>' . sprintf(
    86106                /* translators: %s: wp-config.php */
    87107                __( "You can create a %s file through a web interface, but this doesn't work for all server setups. The safest way is to manually create the file." ),
    88108                '<code>wp-config.php</code>'
    89109        ) . '</p>';
    90         $die .= '<p><a href="' . $path . '" class="button button-large">' . __( "Create a Configuration File" ) . '</a>';
     110        $die .= '<p>' . sprintf(
     111                        '<a href="%s" class="button button-large">%s</a>',
     112                        $path,
     113                        __( 'Create a Configuration File' )
     114        ) . '</p>';
    91115
    92         wp_die( $die, __( 'WordPress &rsaquo; Error' ) );
     116        wp_die( $die, __( 'Welcome to WordPress!' ), array( 'error' => false, 'raw' => true ) );
    93117}