From c05b5d8b61b203617b89f242be164fba9e8b4dec Mon Sep 17 00:00:00 2001 From: Jonathan Desrosiers Date: Thu, 13 Dec 2018 16:29:57 +0000 Subject: [PATCH] REST API: Slash existing meta values when comparing with incoming meta upates. When comparing the old and new values for a meta key being set, ensure both values are sanitized using the same logic so that equal values match. props boonebgorges, dcavins, MattGeri, pilou69, TimothyBlynJacobs, kadamwhite. Merges [43740] to trunk. Fixes #42069. git-svn-id: https://develop.svn.wordpress.org/trunk@44113 602fd350-edb4-49c9-b593-d223f7449a82 --- .../fields/class-wp-rest-meta-fields.php | 8 +- .../tests/rest-api/rest-post-meta-fields.php | 92 +++++++++++++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php b/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php index 059f78c6e8..a24a5f649c 100644 --- a/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php +++ b/src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php @@ -317,19 +317,17 @@ abstract class WP_REST_Meta_Fields { ); } - $meta_key = wp_slash( $meta_key ); - $meta_value = wp_slash( $value ); - // Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false. $old_value = get_metadata( $meta_type, $object_id, $meta_key ); + $subtype = get_object_subtype( $meta_type, $object_id ); if ( 1 === count( $old_value ) ) { - if ( $old_value[0] === $meta_value ) { + if ( (string) sanitize_meta( $meta_key, $value, $meta_type, $subtype ) === $old_value[0] ) { return true; } } - if ( ! update_metadata( $meta_type, $object_id, $meta_key, $meta_value ) ) { + if ( ! update_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) { return new WP_Error( 'rest_meta_database_error', __( 'Could not update meta value in database.' ), diff --git a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php index 2b09d994d1..dc2401b1c3 100644 --- a/tests/phpunit/tests/rest-api/rest-post-meta-fields.php +++ b/tests/phpunit/tests/rest-api/rest-post-meta-fields.php @@ -192,6 +192,48 @@ class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { ) ); + register_meta( + 'post', + 'test_boolean_update', + array( + 'single' => true, + 'type' => 'boolean', + 'sanitize_callback' => 'absint', + 'show_in_rest' => true, + ) + ); + + register_meta( + 'post', + 'test_textured_text_update', + array( + 'single' => true, + 'type' => 'string', + 'sanitize_callback' => 'sanitize_text_field', + 'show_in_rest' => true, + ) + ); + + register_meta( + 'post', + 'test_json_encoded', + array( + 'single' => true, + 'type' => 'string', + 'show_in_rest' => true, + ) + ); + + register_meta( + 'post', + 'test\'slashed\'key', + array( + 'single' => true, + 'type' => 'string', + 'show_in_rest' => true, + ) + ); + /** @var WP_REST_Server $wp_rest_server */ global $wp_rest_server; $wp_rest_server = new Spy_REST_Server; @@ -1255,6 +1297,56 @@ class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase { return $data; } + /** + * @ticket 42069 + * @dataProvider data_update_value_return_success_with_same_value + */ + public function test_update_value_return_success_with_same_value( $meta_key, $meta_value ) { + add_post_meta( self::$post_id, $meta_key, $meta_value ); + + $this->grant_write_permission(); + + $data = array( + 'meta' => array( + $meta_key => $meta_value, + ), + ); + + $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d', self::$post_id ) ); + $request->set_body_params( $data ); + + $response = rest_get_server()->dispatch( $request ); + + $this->assertEquals( 200, $response->get_status() ); + } + + public function data_update_value_return_success_with_same_value() { + return array( + array( 'test_boolean_update', false ), + array( 'test_boolean_update', true ), + array( 'test_textured_text_update', 'She said, "What about the > 10,000 penguins in the kitchen?"' ), + array( 'test_textured_text_update', "He's about to do something rash..." ), + array( 'test_json_encoded', json_encode( array( 'foo' => 'bar' ) ) ), + array( 'test\'slashed\'key', 'Hello' ), + ); + } + + /** + * @ticket 42069 + */ + public function test_slashed_meta_key() { + + add_post_meta( self::$post_id, 'test\'slashed\'key', 'Hello' ); + + $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) ); + + $response = rest_get_server()->dispatch( $request ); + $data = $response->get_data(); + + $this->assertArrayHasKey( 'test\'slashed\'key', $data['meta'] ); + $this->assertEquals( 'Hello', $data['meta']['test\'slashed\'key'] ); + } + /** * Internal function used to disable an insert query which * will trigger a wpdb error for testing purposes.