WordPress.org

Make WordPress Core

Changeset 30055


Ignore:
Timestamp:
10/28/2014 06:34:16 PM (6 years ago)
Author:
pento
Message:

Add wp_json_encode(), a wrapper for json_encode() that ensures everything is converted to UTF-8.

Change all core calls from json_encode() to wp_json_encode().

Fixes #28786.

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/customize.php

    r30014 r30055  
    275275    ?>
    276276    <script type="text/javascript">
    277         var _wpCustomizeSettings = <?php echo json_encode( $settings ); ?>;
     277        var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
    278278    </script>
    279279</div>
  • trunk/src/wp-admin/includes/ajax-actions.php

    r29758 r30055  
    287287    }
    288288
    289     wp_die( json_encode( $return ) );
     289    wp_die( wp_json_encode( $return ) );
    290290}
    291291
     
    13661366        $markup = ob_get_clean();
    13671367
    1368         echo json_encode(array(
     1368        echo wp_json_encode(array(
    13691369            'replace-id' => $type . '-' . $item->name,
    13701370            'markup' => $markup,
     
    13951395        wp_die( 0 );
    13961396
    1397     echo json_encode( $results );
     1397    echo wp_json_encode( $results );
    13981398    echo "\n";
    13991399
     
    18411841        $wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'], false );
    18421842        if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
    1843             echo json_encode( array(
     1843            echo wp_json_encode( array(
    18441844                'success' => false,
    18451845                'data'    => array(
     
    18561856
    18571857    if ( is_wp_error( $attachment_id ) ) {
    1858         echo json_encode( array(
     1858        echo wp_json_encode( array(
    18591859            'success' => false,
    18601860            'data'    => array(
     
    18781878        wp_die();
    18791879
    1880     echo json_encode( array(
     1880    echo wp_json_encode( array(
    18811881        'success' => true,
    18821882        'data'    => $attachment,
     
    19031903        case 'save' :
    19041904            $msg = wp_save_image($attachment_id);
    1905             $msg = json_encode($msg);
     1905            $msg = wp_json_encode($msg);
    19061906            wp_die( $msg );
    19071907            break;
  • trunk/src/wp-admin/includes/class-wp-list-table.php

    r29707 r30055  
    10591059        }
    10601060
    1061         die( json_encode( $response ) );
     1061        die( wp_json_encode( $response ) );
    10621062    }
    10631063
     
    10761076        );
    10771077
    1078         printf( "<script type='text/javascript'>list_args = %s;</script>\n", json_encode( $args ) );
     1078        printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
    10791079    }
    10801080}
  • trunk/src/wp-admin/includes/class-wp-themes-list-table.php

    r29767 r30055  
    274274            $args = array_merge( $args, $extra_args );
    275275
    276         printf( "<script type='text/javascript'>var theme_list_args = %s;</script>\n", json_encode( $args ) );
     276        printf( "<script type='text/javascript'>var theme_list_args = %s;</script>\n", wp_json_encode( $args ) );
    277277        parent::_js_vars();
    278278    }
  • trunk/src/wp-admin/includes/media.php

    r29776 r30055  
    18271827?>
    18281828var resize_height = <?php echo $large_size_h; ?>, resize_width = <?php echo $large_size_w; ?>,
    1829 wpUploaderInit = <?php echo json_encode($plupload_init); ?>;
     1829wpUploaderInit = <?php echo wp_json_encode( $plupload_init ); ?>;
    18301830</script>
    18311831
  • trunk/src/wp-admin/includes/misc.php

    r29707 r30055  
    622622                <input name="admin_color" id="admin_color_<?php echo esc_attr( $color ); ?>" type="radio" value="<?php echo esc_attr( $color ); ?>" class="tog" <?php checked( $color, $current_color ); ?> />
    623623                <input type="hidden" class="css_url" value="<?php echo esc_url( $color_info->url ); ?>" />
    624                 <input type="hidden" class="icon_colors" value="<?php echo esc_attr( json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" />
     624                <input type="hidden" class="icon_colors" value="<?php echo esc_attr( wp_json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" />
    625625                <label for="admin_color_<?php echo esc_attr( $color ); ?>"><?php echo esc_html( $color_info->name ); ?></label>
    626626                <table class="color-palette">
     
    666666    }
    667667
    668     echo '<script type="text/javascript">var _wpColorScheme = ' . json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n";
     668    echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ) ) . ";</script>\n";
    669669}
    670670add_action( 'admin_head', 'wp_color_scheme_settings' );
  • trunk/src/wp-admin/includes/nav-menu.php

    r29206 r30055  
    357357                    echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_post( $object_id ) ) ), 0, (object) $args );
    358358                } elseif ( 'json' == $response_format ) {
    359                     echo json_encode(
     359                    echo wp_json_encode(
    360360                        array(
    361361                            'ID' => $object_id,
     
    374374                } elseif ( 'json' == $response_format ) {
    375375                    $post_obj = get_term( $object_id, $object_type );
    376                     echo json_encode(
     376                    echo wp_json_encode(
    377377                        array(
    378378                            'ID' => $object_id,
     
    402402                    echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_post( $var_by_ref ) ) ), 0, (object) $args );
    403403                } elseif ( 'json' == $response_format ) {
    404                     echo json_encode(
     404                    echo wp_json_encode(
    405405                        array(
    406406                            'ID' => get_the_ID(),
     
    423423                    echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( $term ) ), 0, (object) $args );
    424424                } elseif ( 'json' == $response_format ) {
    425                     echo json_encode(
     425                    echo wp_json_encode(
    426426                        array(
    427427                            'ID' => $term->term_id,
  • trunk/src/wp-admin/includes/template.php

    r30040 r30055  
    19531953        //<![CDATA[
    19541954        (function($){
    1955             var options = <?php echo json_encode( $args ); ?>, setup;
     1955            var options = <?php echo wp_json_encode( $args ); ?>, setup;
    19561956
    19571957            if ( ! options )
  • trunk/src/wp-includes/class-wp-customize-manager.php

    r30014 r30055  
    518518        ?>
    519519        <script type="text/javascript">
    520             var _wpCustomizeSettings = <?php echo json_encode( $settings ); ?>;
     520            var _wpCustomizeSettings = <?php echo wp_json_encode( $settings ); ?>;
    521521        </script>
    522522        <?php
  • trunk/src/wp-includes/class-wp-customize-widgets.php

    r29903 r30055  
    741741            'customize-widgets',
    742742            'data',
    743             sprintf( 'var _wpCustomizeWidgetsSettings = %s;', json_encode( $settings ) )
     743            sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) )
    744744        );
    745745    }
     
    10561056        ?>
    10571057        <script type="text/javascript">
    1058             var _wpWidgetCustomizerPreviewSettings = <?php echo json_encode( $settings ); ?>;
     1058            var _wpWidgetCustomizerPreviewSettings = <?php echo wp_json_encode( $settings ); ?>;
    10591059        </script>
    10601060        <?php
  • trunk/src/wp-includes/class-wp-editor.php

    r30002 r30055  
    501501
    502502                if ( ! empty( $mce_external_plugins ) ) {
    503                     self::$first_init['external_plugins'] = json_encode( $mce_external_plugins );
     503                    self::$first_init['external_plugins'] = wp_json_encode( $mce_external_plugins );
    504504                }
    505505
     
    987987        }
    988988
    989         return "tinymce.addI18n( '$mce_locale', " . json_encode( $mce_translation ) . ");\n" .
     989        return "tinymce.addI18n( '$mce_locale', " . wp_json_encode( $mce_translation ) . ");\n" .
    990990            "tinymce.ScriptLoader.markDone( '$baseurl/langs/$mce_locale.js' );\n";
    991991    }
  • trunk/src/wp-includes/class.wp-scripts.php

    r28907 r30055  
    168168        }
    169169
    170         $script = "var $object_name = " . json_encode($l10n) . ';';
     170        $script = "var $object_name = " . wp_json_encode( $l10n ) . ';';
    171171
    172172        if ( !empty($after) )
  • trunk/src/wp-includes/functions.php

    r29915 r30055  
    26142614
    26152615/**
     2616 * Encode a variable into JSON, with some sanity checks
     2617 *
     2618 * @since 4.1.0
     2619 *
     2620 * @param mixed $data    Variable (usually an array or object) to encode as JSON
     2621 * @param int   $options Options to be passed to json_encode(). Default 0.
     2622 * @param int   $depth   Maximum depth to walk through $data. Must be greater than 0, default 512.t
     2623 *
     2624 * @return bool|string The JSON encoded string, or false if it cannot be encoded
     2625 */
     2626function wp_json_encode( $data, $options = 0, $depth = 512 ) {
     2627    // json_encode has had extra params added over the years.
     2628    // $options was added in 5.3, and $depth in 5.5.
     2629    // We need to make sure we call it with the correct arguments.
     2630    if ( version_compare( PHP_VERSION, '5.5', '>=' ) ) {
     2631        $args = array( $data, $options, $depth );
     2632    } else if ( version_compare( PHP_VERSION, '5.3', '>=' ) ) {
     2633        $args = array( $data, $options );
     2634    } else {
     2635        $args = array( $data );
     2636    }
     2637
     2638    $json = call_user_func_array( 'json_encode', $args );
     2639
     2640    if ( false !== $json ) {
     2641        // If json_encode was successful, no need to do more sanity checking
     2642        return $json;
     2643    }
     2644
     2645    try {
     2646        $args[0] = _wp_json_sanity_check( $data, $depth );
     2647    } catch ( Exception $e ) {
     2648        return false;
     2649    }
     2650
     2651    return call_user_func_array( 'json_encode', $args );
     2652}
     2653
     2654/**
     2655 * @ignore
     2656 */
     2657function _wp_json_sanity_check( $data, $depth ) {
     2658    if ( $depth < 0 ) {
     2659        throw new Exception( 'Reached depth limit' );
     2660    }
     2661
     2662    if ( is_array( $data ) ) {
     2663        $output = array();
     2664        foreach ( $data as $id => $el ) {
     2665            // Don't forget to sanitize the ID!
     2666            if ( is_string( $id ) ) {
     2667                $clean_id = _wp_json_convert_string( $id );
     2668            } else {
     2669                $clean_id = $id;
     2670            }
     2671
     2672            // Check the element type, so that we're only recursing if we really have to
     2673            if ( is_array( $el ) || is_object( $el ) ) {
     2674                $output[ $clean_id ] = _wp_json_sanity_check( $el, $depth - 1 );
     2675            } else if ( is_string( $el ) ) {
     2676                $output[ $clean_id ] = _wp_json_convert_string( $el );
     2677            } else {
     2678                $output[ $clean_id ] = $el;
     2679            }
     2680        }
     2681    } else if ( is_object( $data ) ) {
     2682        $output = new stdClass;
     2683        foreach ( $data as $id => $el ) {
     2684            if ( is_string( $id ) ) {
     2685                $clean_id = _wp_json_convert_string( $id );
     2686            } else {
     2687                $clean_id = $id;
     2688            }
     2689
     2690            if ( is_array( $el ) || is_object( $el ) ) {
     2691                $output->$clean_id = _wp_json_sanity_check( $el, $depth - 1 );
     2692            } else if ( is_string( $el ) ) {
     2693                $output->$clean_id = _wp_json_convert_string( $el );
     2694            } else {
     2695                $output->$clean_id = $el;
     2696            }
     2697        }
     2698    } else if ( is_string( $data ) ) {
     2699        return _wp_json_convert_string( $data );
     2700    } else {
     2701        return $data;
     2702    }
     2703
     2704    return $output;
     2705}
     2706
     2707/**
     2708 * @ignore
     2709 */
     2710function _wp_json_convert_string( $string ) {
     2711    static $use_mb = null;
     2712    if ( is_null( $use_mb ) ) {
     2713        $use_mb = function_exists( 'mb_convert_encoding' );
     2714    }
     2715
     2716    if ( $use_mb ) {
     2717        $encoding = mb_detect_encoding( $string, mb_detect_order(), true );
     2718        if ( $encoding ) {
     2719            return mb_convert_encoding( $string, 'UTF-8', $encoding );
     2720        } else {
     2721            return mb_convert_encoding( $string, 'UTF-8', 'UTF-8' );
     2722        }
     2723    } else {
     2724        return wp_check_invalid_utf8( $data, true );
     2725    }
     2726}
     2727
     2728/**
    26162729 * Send a JSON response back to an Ajax request.
    26172730 *
     
    26232736function wp_send_json( $response ) {
    26242737    @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
    2625     echo json_encode( $response );
     2738    echo wp_json_encode( $response );
    26262739    if ( defined( 'DOING_AJAX' ) && DOING_AJAX )
    26272740        wp_die();
  • trunk/src/wp-includes/media.php

    r29914 r30055  
    13991399    ?></ol>
    14001400    </noscript>
    1401     <script type="application/json" class="wp-playlist-script"><?php echo json_encode( $data ) ?></script>
     1401    <script type="application/json" class="wp-playlist-script"><?php echo wp_json_encode( $data ) ?></script>
    14021402</div>
    14031403    <?php
     
    25832583    );
    25842584
    2585     $script = 'var _wpPluploadSettings = ' . json_encode( $settings ) . ';';
     2585    $script = 'var _wpPluploadSettings = ' . wp_json_encode( $settings ) . ';';
    25862586
    25872587    if ( $data )
  • trunk/src/wp-includes/theme.php

    r30038 r30055  
    19401940    );
    19411941
    1942     $script = 'var _wpCustomizeLoaderSettings = ' . json_encode( $settings ) . ';';
     1942    $script = 'var _wpCustomizeLoaderSettings = ' . wp_json_encode( $settings ) . ';';
    19431943
    19441944    $data = $wp_scripts->get_data( 'customize-loader', 'data' );
  • trunk/src/wp-includes/update.php

    r29226 r30055  
    9595
    9696    $post_body = array(
    97         'translations' => json_encode( $translations ),
     97        'translations' => wp_json_encode( $translations ),
    9898    );
    9999
     
    275275        'timeout' => $timeout,
    276276        'body' => array(
    277             'plugins'      => json_encode( $to_send ),
    278             'translations' => json_encode( $translations ),
    279             'locale'       => json_encode( $locales ),
    280             'all'          => json_encode( true ),
     277            'plugins'      => wp_json_encode( $to_send ),
     278            'translations' => wp_json_encode( $translations ),
     279            'locale'       => wp_json_encode( $locales ),
     280            'all'          => wp_json_encode( true ),
    281281        ),
    282282        'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
     
    284284
    285285    if ( $extra_stats ) {
    286         $options['body']['update_stats'] = json_encode( $extra_stats );
     286        $options['body']['update_stats'] = wp_json_encode( $extra_stats );
    287287    }
    288288
     
    438438        'timeout' => $timeout,
    439439        'body' => array(
    440             'themes'       => json_encode( $request ),
    441             'translations' => json_encode( $translations ),
    442             'locale'       => json_encode( $locales ),
     440            'themes'       => wp_json_encode( $request ),
     441            'translations' => wp_json_encode( $translations ),
     442            'locale'       => wp_json_encode( $locales ),
    443443        ),
    444444        'user-agent'    => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
     
    446446
    447447    if ( $extra_stats ) {
    448         $options['body']['update_stats'] = json_encode( $extra_stats );
     448        $options['body']['update_stats'] = wp_json_encode( $extra_stats );
    449449    }
    450450
  • trunk/tests/phpunit/tests/functions.php

    r29756 r30055  
    530530        $this->assertEquals( array_slice( $original_urls, 0, 8 ), $urls );
    531531    }
     532
     533    /**
     534     * @ticket 28786
     535     */
     536    function test_wp_json_encode() {
     537        $this->assertEquals( wp_json_encode( 'a' ), '"a"' );
     538        $this->assertEquals( wp_json_encode( '这' ), '"\u8fd9"' );
     539
     540        $old_charsets = $charsets = mb_detect_order();
     541        if ( ! in_array( 'EUC-JP', $charsets ) ) {
     542            $charsets[] = 'EUC-JP';
     543            mb_detect_order( $charsets );
     544        }
     545
     546        $eucjp = mb_convert_encoding( 'aあb', 'EUC-JP', 'UTF-8' );
     547        $utf8 = mb_convert_encoding( $eucjp, 'UTF-8', 'EUC-JP' );
     548
     549        $this->assertEquals( 'aあb', $utf8 );
     550
     551        $this->assertEquals( wp_json_encode( $eucjp ), '"a\u3042b"' );
     552
     553        $this->assertEquals( wp_json_encode( array( 'a' ) ), '["a"]' );
     554
     555        $object = new stdClass;
     556        $object->a = 'b';
     557        $this->assertEquals( wp_json_encode( $object ), '{"a":"b"}' );
     558
     559        mb_detect_order( $old_charsets );
     560    }
     561
     562    /**
     563     * @ticket 28786
     564     */
     565    function test_wp_json_encode_depth() {
     566        $data = array( array( array( 1, 2, 3 ) ) );
     567        $json = wp_json_encode( $data, 0, 1 );
     568        $this->assertFalse( $json );
     569
     570        $data = array( 'あ', array( array( 1, 2, 3 ) ) );
     571        $json = wp_json_encode( $data, 0, 1 );
     572        $this->assertFalse( $json );
     573    }
    532574}
Note: See TracChangeset for help on using the changeset viewer.