From 007ec52958742ed768c74f37e21e6db2b75aa32e Mon Sep 17 00:00:00 2001 From: Gary Pendergast Date: Tue, 28 Oct 2014 18:35:19 +0000 Subject: [PATCH] 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. Built from https://develop.svn.wordpress.org/trunk@30055 git-svn-id: http://core.svn.wordpress.org/trunk@30055 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-admin/customize.php | 2 +- wp-admin/includes/ajax-actions.php | 14 +-- wp-admin/includes/class-wp-list-table.php | 4 +- .../includes/class-wp-themes-list-table.php | 2 +- wp-admin/includes/media.php | 2 +- wp-admin/includes/misc.php | 4 +- wp-admin/includes/nav-menu.php | 8 +- wp-admin/includes/template.php | 2 +- wp-includes/class-wp-customize-manager.php | 2 +- wp-includes/class-wp-customize-widgets.php | 4 +- wp-includes/class-wp-editor.php | 4 +- wp-includes/class.wp-scripts.php | 2 +- wp-includes/functions.php | 115 +++++++++++++++++- wp-includes/media.php | 4 +- wp-includes/theme.php | 2 +- wp-includes/update.php | 20 +-- wp-includes/version.php | 2 +- 17 files changed, 153 insertions(+), 40 deletions(-) diff --git a/wp-admin/customize.php b/wp-admin/customize.php index ed5255818e..1d795980f7 100644 --- a/wp-admin/customize.php +++ b/wp-admin/customize.php @@ -274,7 +274,7 @@ do_action( 'customize_controls_print_scripts' ); ?> diff --git a/wp-admin/includes/ajax-actions.php b/wp-admin/includes/ajax-actions.php index 799ef1ef8d..30dffbc31b 100644 --- a/wp-admin/includes/ajax-actions.php +++ b/wp-admin/includes/ajax-actions.php @@ -286,7 +286,7 @@ function wp_ajax_autocomplete_user() { ); } - wp_die( json_encode( $return ) ); + wp_die( wp_json_encode( $return ) ); } /** @@ -1365,7 +1365,7 @@ function wp_ajax_menu_get_metabox() { $markup = ob_get_clean(); - echo json_encode(array( + echo wp_json_encode(array( 'replace-id' => $type . '-' . $item->name, 'markup' => $markup, )); @@ -1394,7 +1394,7 @@ function wp_ajax_wp_link_ajax() { if ( ! isset( $results ) ) wp_die( 0 ); - echo json_encode( $results ); + echo wp_json_encode( $results ); echo "\n"; wp_die(); @@ -1840,7 +1840,7 @@ function wp_ajax_upload_attachment() { if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) { $wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'], false ); if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) { - echo json_encode( array( + echo wp_json_encode( array( 'success' => false, 'data' => array( 'message' => __( 'The uploaded file is not a valid image. Please try again.' ), @@ -1855,7 +1855,7 @@ function wp_ajax_upload_attachment() { $attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data ); if ( is_wp_error( $attachment_id ) ) { - echo json_encode( array( + echo wp_json_encode( array( 'success' => false, 'data' => array( 'message' => $attachment_id->get_error_message(), @@ -1877,7 +1877,7 @@ function wp_ajax_upload_attachment() { if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) ) wp_die(); - echo json_encode( array( + echo wp_json_encode( array( 'success' => true, 'data' => $attachment, ) ); @@ -1902,7 +1902,7 @@ function wp_ajax_image_editor() { switch ( $_POST['do'] ) { case 'save' : $msg = wp_save_image($attachment_id); - $msg = json_encode($msg); + $msg = wp_json_encode($msg); wp_die( $msg ); break; case 'scale' : diff --git a/wp-admin/includes/class-wp-list-table.php b/wp-admin/includes/class-wp-list-table.php index 8d2bc51e00..a617dc0d3f 100644 --- a/wp-admin/includes/class-wp-list-table.php +++ b/wp-admin/includes/class-wp-list-table.php @@ -1058,7 +1058,7 @@ class WP_List_Table { $response['total_pages_i18n'] = number_format_i18n( $this->_pagination_args['total_pages'] ); } - die( json_encode( $response ) ); + die( wp_json_encode( $response ) ); } /** @@ -1075,6 +1075,6 @@ class WP_List_Table { ) ); - printf( "\n", json_encode( $args ) ); + printf( "\n", wp_json_encode( $args ) ); } } diff --git a/wp-admin/includes/class-wp-themes-list-table.php b/wp-admin/includes/class-wp-themes-list-table.php index 866ecce741..859aca0fc7 100644 --- a/wp-admin/includes/class-wp-themes-list-table.php +++ b/wp-admin/includes/class-wp-themes-list-table.php @@ -273,7 +273,7 @@ class WP_Themes_List_Table extends WP_List_Table { if ( is_array( $extra_args ) ) $args = array_merge( $args, $extra_args ); - printf( "\n", json_encode( $args ) ); + printf( "\n", wp_json_encode( $args ) ); parent::_js_vars(); } } diff --git a/wp-admin/includes/media.php b/wp-admin/includes/media.php index 0eeeaea6f8..7f0f0c7ff5 100644 --- a/wp-admin/includes/media.php +++ b/wp-admin/includes/media.php @@ -1826,7 +1826,7 @@ if( !$large_size_w ) $large_size_w = 1024; ?> var resize_height = , resize_width = , -wpUploaderInit = ; +wpUploaderInit = ;
diff --git a/wp-admin/includes/misc.php b/wp-admin/includes/misc.php index f93e138819..6e47d9d427 100644 --- a/wp-admin/includes/misc.php +++ b/wp-admin/includes/misc.php @@ -621,7 +621,7 @@ function admin_color_scheme_picker( $user_id ) {
/> - + @@ -665,7 +665,7 @@ function wp_color_scheme_settings() { $icon_colors = array( 'base' => '#999', 'focus' => '#2ea2cc', 'current' => '#fff' ); } - echo '\n"; + echo '\n"; } add_action( 'admin_head', 'wp_color_scheme_settings' ); diff --git a/wp-admin/includes/nav-menu.php b/wp-admin/includes/nav-menu.php index 44f3ee0843..0ad8756b05 100644 --- a/wp-admin/includes/nav-menu.php +++ b/wp-admin/includes/nav-menu.php @@ -356,7 +356,7 @@ function _wp_ajax_menu_quick_search( $request = array() ) { if ( 'markup' == $response_format ) { echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_post( $object_id ) ) ), 0, (object) $args ); } elseif ( 'json' == $response_format ) { - echo json_encode( + echo wp_json_encode( array( 'ID' => $object_id, 'post_title' => get_the_title( $object_id ), @@ -373,7 +373,7 @@ function _wp_ajax_menu_quick_search( $request = array() ) { echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_term( $object_id, $object_type ) ) ), 0, (object) $args ); } elseif ( 'json' == $response_format ) { $post_obj = get_term( $object_id, $object_type ); - echo json_encode( + echo wp_json_encode( array( 'ID' => $object_id, 'post_title' => $post_obj->name, @@ -401,7 +401,7 @@ function _wp_ajax_menu_quick_search( $request = array() ) { $var_by_ref = get_the_ID(); echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( get_post( $var_by_ref ) ) ), 0, (object) $args ); } elseif ( 'json' == $response_format ) { - echo json_encode( + echo wp_json_encode( array( 'ID' => get_the_ID(), 'post_title' => get_the_title(), @@ -422,7 +422,7 @@ function _wp_ajax_menu_quick_search( $request = array() ) { if ( 'markup' == $response_format ) { echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', array( $term ) ), 0, (object) $args ); } elseif ( 'json' == $response_format ) { - echo json_encode( + echo wp_json_encode( array( 'ID' => $term->term_id, 'post_title' => $term->name, diff --git a/wp-admin/includes/template.php b/wp-admin/includes/template.php index 4fa9f0c38b..b0f2525664 100644 --- a/wp-admin/includes/template.php +++ b/wp-admin/includes/template.php @@ -1952,7 +1952,7 @@ final class WP_Internal_Pointers { add_data( 'customize-widgets', 'data', - sprintf( 'var _wpCustomizeWidgetsSettings = %s;', json_encode( $settings ) ) + sprintf( 'var _wpCustomizeWidgetsSettings = %s;', wp_json_encode( $settings ) ) ); } @@ -1055,7 +1055,7 @@ final class WP_Customize_Widgets { ?> =' ) ) { + $args = array( $data, $options, $depth ); + } else if ( version_compare( PHP_VERSION, '5.3', '>=' ) ) { + $args = array( $data, $options ); + } else { + $args = array( $data ); + } + + $json = call_user_func_array( 'json_encode', $args ); + + if ( false !== $json ) { + // If json_encode was successful, no need to do more sanity checking + return $json; + } + + try { + $args[0] = _wp_json_sanity_check( $data, $depth ); + } catch ( Exception $e ) { + return false; + } + + return call_user_func_array( 'json_encode', $args ); +} + +/** + * @ignore + */ +function _wp_json_sanity_check( $data, $depth ) { + if ( $depth < 0 ) { + throw new Exception( 'Reached depth limit' ); + } + + if ( is_array( $data ) ) { + $output = array(); + foreach ( $data as $id => $el ) { + // Don't forget to sanitize the ID! + if ( is_string( $id ) ) { + $clean_id = _wp_json_convert_string( $id ); + } else { + $clean_id = $id; + } + + // Check the element type, so that we're only recursing if we really have to + if ( is_array( $el ) || is_object( $el ) ) { + $output[ $clean_id ] = _wp_json_sanity_check( $el, $depth - 1 ); + } else if ( is_string( $el ) ) { + $output[ $clean_id ] = _wp_json_convert_string( $el ); + } else { + $output[ $clean_id ] = $el; + } + } + } else if ( is_object( $data ) ) { + $output = new stdClass; + foreach ( $data as $id => $el ) { + if ( is_string( $id ) ) { + $clean_id = _wp_json_convert_string( $id ); + } else { + $clean_id = $id; + } + + if ( is_array( $el ) || is_object( $el ) ) { + $output->$clean_id = _wp_json_sanity_check( $el, $depth - 1 ); + } else if ( is_string( $el ) ) { + $output->$clean_id = _wp_json_convert_string( $el ); + } else { + $output->$clean_id = $el; + } + } + } else if ( is_string( $data ) ) { + return _wp_json_convert_string( $data ); + } else { + return $data; + } + + return $output; +} + +/** + * @ignore + */ +function _wp_json_convert_string( $string ) { + static $use_mb = null; + if ( is_null( $use_mb ) ) { + $use_mb = function_exists( 'mb_convert_encoding' ); + } + + if ( $use_mb ) { + $encoding = mb_detect_encoding( $string, mb_detect_order(), true ); + if ( $encoding ) { + return mb_convert_encoding( $string, 'UTF-8', $encoding ); + } else { + return mb_convert_encoding( $string, 'UTF-8', 'UTF-8' ); + } + } else { + return wp_check_invalid_utf8( $data, true ); + } +} + /** * Send a JSON response back to an Ajax request. * @@ -2622,7 +2735,7 @@ function _scalar_wp_die_handler( $message = '' ) { */ function wp_send_json( $response ) { @header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) ); - echo json_encode( $response ); + echo wp_json_encode( $response ); if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) wp_die(); else diff --git a/wp-includes/media.php b/wp-includes/media.php index bbfdf4673a..4cb517a09b 100644 --- a/wp-includes/media.php +++ b/wp-includes/media.php @@ -1398,7 +1398,7 @@ function wp_playlist_shortcode( $attr ) { } ?> - + is_multisite() && ! is_upload_space_available() ); - $script = 'var _wpPluploadSettings = ' . json_encode( $settings ) . ';'; + $script = 'var _wpPluploadSettings = ' . wp_json_encode( $settings ) . ';'; if ( $data ) $script = "$data\n$script"; diff --git a/wp-includes/theme.php b/wp-includes/theme.php index db684761ca..632bac4015 100644 --- a/wp-includes/theme.php +++ b/wp-includes/theme.php @@ -1939,7 +1939,7 @@ function _wp_customize_loader_settings() { ), ); - $script = 'var _wpCustomizeLoaderSettings = ' . json_encode( $settings ) . ';'; + $script = 'var _wpCustomizeLoaderSettings = ' . wp_json_encode( $settings ) . ';'; $data = $wp_scripts->get_data( 'customize-loader', 'data' ); if ( $data ) diff --git a/wp-includes/update.php b/wp-includes/update.php index a9e25a8718..05a152adb9 100644 --- a/wp-includes/update.php +++ b/wp-includes/update.php @@ -94,7 +94,7 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) { ); $post_body = array( - 'translations' => json_encode( $translations ), + 'translations' => wp_json_encode( $translations ), ); if ( is_array( $extra_stats ) ) @@ -274,16 +274,16 @@ function wp_update_plugins( $extra_stats = array() ) { $options = array( 'timeout' => $timeout, 'body' => array( - 'plugins' => json_encode( $to_send ), - 'translations' => json_encode( $translations ), - 'locale' => json_encode( $locales ), - 'all' => json_encode( true ), + 'plugins' => wp_json_encode( $to_send ), + 'translations' => wp_json_encode( $translations ), + 'locale' => wp_json_encode( $locales ), + 'all' => wp_json_encode( true ), ), 'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) ); if ( $extra_stats ) { - $options['body']['update_stats'] = json_encode( $extra_stats ); + $options['body']['update_stats'] = wp_json_encode( $extra_stats ); } $url = $http_url = 'http://api.wordpress.org/plugins/update-check/1.1/'; @@ -437,15 +437,15 @@ function wp_update_themes( $extra_stats = array() ) { $options = array( 'timeout' => $timeout, 'body' => array( - 'themes' => json_encode( $request ), - 'translations' => json_encode( $translations ), - 'locale' => json_encode( $locales ), + 'themes' => wp_json_encode( $request ), + 'translations' => wp_json_encode( $translations ), + 'locale' => wp_json_encode( $locales ), ), 'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) ); if ( $extra_stats ) { - $options['body']['update_stats'] = json_encode( $extra_stats ); + $options['body']['update_stats'] = wp_json_encode( $extra_stats ); } $url = $http_url = 'http://api.wordpress.org/themes/update-check/1.1/'; diff --git a/wp-includes/version.php b/wp-includes/version.php index e40815c066..b65e8c1ebd 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.1-alpha-30054'; +$wp_version = '4.1-alpha-30055'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.