From 9deec9e7232e30c3e91c65ece2a19ad20a6a546d Mon Sep 17 00:00:00 2001 From: Mark Jaquith Date: Wed, 6 Apr 2016 21:01:11 +0000 Subject: [PATCH] REST API: Deliver parameters unadulterated instead of slashed. We goofed, and parameters accessed through the REST API's methods were slashed (inconsistently, even). This unslashes the data, so you get the un-messed-with data that was sent. Props joehoyle. Fixes #36419. git-svn-id: https://develop.svn.wordpress.org/trunk@37163 602fd350-edb4-49c9-b593-d223f7449a82 --- .../rest-api/class-wp-rest-server.php | 6 +- tests/phpunit/includes/spy-rest-server.php | 12 ++ tests/phpunit/tests/rest-api/rest-server.php | 127 ++++++++++++++++++ 3 files changed, 142 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index 25556962b4..ebf58de2bb 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -303,10 +303,10 @@ class WP_REST_Server { $request = new WP_REST_Request( $_SERVER['REQUEST_METHOD'], $path ); - $request->set_query_params( $_GET ); - $request->set_body_params( $_POST ); + $request->set_query_params( wp_unslash( $_GET ) ); + $request->set_body_params( wp_unslash( $_POST ) ); $request->set_file_params( $_FILES ); - $request->set_headers( $this->get_headers( $_SERVER ) ); + $request->set_headers( $this->get_headers( wp_unslash( $_SERVER ) ) ); $request->set_body( $this->get_raw_data() ); /* diff --git a/tests/phpunit/includes/spy-rest-server.php b/tests/phpunit/includes/spy-rest-server.php index 9a1b78a25e..4ba9017c0f 100644 --- a/tests/phpunit/includes/spy-rest-server.php +++ b/tests/phpunit/includes/spy-rest-server.php @@ -4,6 +4,7 @@ class Spy_REST_Server extends WP_REST_Server { public $sent_headers = array(); public $sent_body = ''; + public $last_request = null; /** * Get the raw $endpoints data from the server @@ -29,6 +30,17 @@ class Spy_REST_Server extends WP_REST_Server { $this->sent_headers[ $header ] = $value; } + /** + * Override the dispatch method so we can get a handle on the request object. + * + * @param WP_REST_Request $request + * @return WP_REST_Response Response returned by the callback. + */ + public function dispatch( $request ) { + $this->last_request = $request; + return parent::dispatch( $request ); + } + public function serve_request( $path = null ) { ob_start(); diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index 534487553d..21fc61c7b9 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -743,6 +743,133 @@ class Tests_REST_Server extends WP_Test_REST_TestCase { } } + public function test_serve_request_url_params_are_unslashed() { + + $this->server->register_route( 'test', '/test/(?P.*)', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => '__return_false', + 'args' => array( + 'data' => array(), + ), + ), + ) ); + + $result = $this->server->serve_request( '/test/data\\with\\slashes' ); + $url_params = $this->server->last_request->get_url_params(); + $this->assertEquals( 'data\\with\\slashes', $url_params['data'] ); + } + + public function test_serve_request_query_params_are_unslashed() { + + $this->server->register_route( 'test', '/test', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => '__return_false', + 'args' => array( + 'data' => array(), + ), + ), + ) ); + + // WordPress internally will slash the superglobals on bootstrap + $_GET = wp_slash( array( + 'data' => 'data\\with\\slashes', + ) ); + + $result = $this->server->serve_request( '/test' ); + $query_params = $this->server->last_request->get_query_params(); + $this->assertEquals( 'data\\with\\slashes', $query_params['data'] ); + } + + public function test_serve_request_body_params_are_unslashed() { + + $this->server->register_route( 'test', '/test', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => '__return_false', + 'args' => array( + 'data' => array(), + ), + ), + ) ); + + // WordPress internally will slash the superglobals on bootstrap + $_POST = wp_slash( array( + 'data' => 'data\\with\\slashes', + ) ); + + $result = $this->server->serve_request( '/test/data' ); + + $body_params = $this->server->last_request->get_body_params(); + $this->assertEquals( 'data\\with\\slashes', $body_params['data'] ); + } + + public function test_serve_request_json_params_are_unslashed() { + + $this->server->register_route( 'test', '/test', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => '__return_false', + 'args' => array( + 'data' => array(), + ), + ), + ) ); + + $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; + $GLOBALS['HTTP_RAW_POST_DATA'] = json_encode( array( + 'data' => 'data\\with\\slashes', + ) ); + + $result = $this->server->serve_request( '/test' ); + $json_params = $this->server->last_request->get_json_params(); + $this->assertEquals( 'data\\with\\slashes', $json_params['data'] ); + } + + public function test_serve_request_file_params_are_unslashed() { + + $this->server->register_route( 'test', '/test', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => '__return_false', + 'args' => array( + 'data' => array(), + ), + ), + ) ); + + // WordPress internally will slash the superglobals on bootstrap + $_FILES = array( + 'data' => array( + 'name' => 'data\\with\\slashes', + ), + ); + + $result = $this->server->serve_request( '/test/data\\with\\slashes' ); + $file_params = $this->server->last_request->get_file_params(); + $this->assertEquals( 'data\\with\\slashes', $file_params['data']['name'] ); + } + + public function test_serve_request_headers_are_unslashed() { + + $this->server->register_route( 'test', '/test', array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => '__return_false', + 'args' => array( + 'data' => array(), + ), + ), + ) ); + + // WordPress internally will slash the superglobals on bootstrap + $_SERVER['HTTP_X_MY_HEADER'] = wp_slash( 'data\\with\\slashes' ); + + $result = $this->server->serve_request( '/test/data\\with\\slashes' ); + $this->assertEquals( 'data\\with\\slashes', $this->server->last_request->get_header( 'x_my_header') ); + } + public function filter_wp_rest_server_class() { return 'Spy_REST_Server'; }