From c155cac1cb13c271b55f1ca2f575098fb2cb41e9 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 20 Dec 2015 16:33:21 -0600 Subject: [PATCH 01/11] Allow the `comment_author_IP` value to be set --- lib/endpoints/class-wp-rest-comments-controller.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index 1ac353435c..93d77d3a0c 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -173,7 +173,11 @@ public function create_item( $request ) { if ( ! isset( $prepared_comment['comment_author_url'] ) ) { $prepared_comment['comment_author_url'] = ''; } - $prepared_comment['comment_author_IP'] = '127.0.0.1'; + if ( isset( $prepared_comment['comment_author_IP'] ) ) { + $prepared_comment['comment_author_IP'] = ( filter_var( $prepared_comment['comment_author_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) ? $prepared_comment['comment_author_IP'] : '127.0.0.1'; + } else { + $prepared_comment['comment_author_IP'] = '127.0.0.1'; + } $prepared_comment['comment_agent'] = ''; $prepared_comment['comment_approved'] = wp_allow_comment( $prepared_comment ); From 04b3fcd4c9be00653e7c888c1df9f1a6d4797138 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 20 Dec 2015 17:02:07 -0600 Subject: [PATCH 02/11] Move the comment_author_IP validation to the `prepare_item_for_database` method and return error if invalid --- lib/endpoints/class-wp-rest-comments-controller.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index 93d77d3a0c..eaf7486c27 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -173,9 +173,7 @@ public function create_item( $request ) { if ( ! isset( $prepared_comment['comment_author_url'] ) ) { $prepared_comment['comment_author_url'] = ''; } - if ( isset( $prepared_comment['comment_author_IP'] ) ) { - $prepared_comment['comment_author_IP'] = ( filter_var( $prepared_comment['comment_author_IP'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) ? $prepared_comment['comment_author_IP'] : '127.0.0.1'; - } else { + if ( ! isset( $prepared_comment['comment_author_IP'] ) ) { $prepared_comment['comment_author_IP'] = '127.0.0.1'; } $prepared_comment['comment_agent'] = ''; @@ -703,6 +701,14 @@ protected function prepare_item_for_database( $request ) { $prepared_comment['comment_author_url'] = $request['author_url']; } + if ( isset( $request['author_ip'] ) ) { + if ( filter_var( $request['author_ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) { + $prepared_comment['comment_author_IP'] = $request['author_ip']; + } else { + return new WP_Error( 'rest_invalid_author_ip', __( 'The IP address you provided is invalid.' ), array( 'status' => 400 ) ); + } + } + if ( isset( $request['type'] ) ) { $prepared_comment['comment_type'] = $request['type']; } From fac39453bdb47ada09c7de83d7d0eda2b650cee7 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 20 Dec 2015 19:56:36 -0600 Subject: [PATCH 03/11] Prevent fatal error when `prepare_item_for_database` returns a WP_Error --- lib/endpoints/class-wp-rest-comments-controller.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index eaf7486c27..c2ca9bef44 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -146,6 +146,9 @@ public function create_item( $request ) { } $prepared_comment = $this->prepare_item_for_database( $request ); + if ( is_wp_error( $prepared_comment ) ) { + return $prepared_comment; + } // Setting remaining values before wp_insert_comment so we can // use wp_allow_comment(). @@ -244,6 +247,9 @@ public function update_item( $request ) { } $prepared_args = $this->prepare_item_for_database( $request ); + if ( is_wp_error( $prepared_args ) ) { + return $prepared_args; + } if ( empty( $prepared_args ) && isset( $request['status'] ) ) { // Only the comment status is being changed. @@ -705,7 +711,7 @@ protected function prepare_item_for_database( $request ) { if ( filter_var( $request['author_ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) { $prepared_comment['comment_author_IP'] = $request['author_ip']; } else { - return new WP_Error( 'rest_invalid_author_ip', __( 'The IP address you provided is invalid.' ), array( 'status' => 400 ) ); + return new WP_Error( 'rest_comment_invalid_author_ip', __( 'The IP address you provided is invalid.' ), array( 'status' => 400 ) ); } } From 18bee8c339d086f22cb61af28447726086e9f28e Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 20 Dec 2015 19:56:59 -0600 Subject: [PATCH 04/11] Add unit tests for creating a comment with `author_ip` --- tests/test-rest-comments-controller.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/test-rest-comments-controller.php b/tests/test-rest-comments-controller.php index 8734b2518c..4cdf6a9788 100644 --- a/tests/test-rest-comments-controller.php +++ b/tests/test-rest-comments-controller.php @@ -539,7 +539,7 @@ public function test_create_comment_status_without_permission() { $this->assertErrorResponse( 'rest_comment_invalid_status', $response, 403 ); } - public function test_create_comment_with_status() { + public function test_create_comment_with_status_and_IP() { $post_id = $this->factory->post->create(); wp_set_current_user( $this->admin_id ); @@ -547,6 +547,7 @@ public function test_create_comment_with_status() { 'post' => $post_id, 'author_name' => 'Comic Book Guy', 'author_email' => 'cbg@androidsdungeon.com', + 'author_ip' => '139.130.4.5', 'author_url' => 'http://androidsdungeon.com', 'content' => 'Worst Comment Ever!', 'status' => 'approved', @@ -561,6 +562,26 @@ public function test_create_comment_with_status() { $data = $response->get_data(); $this->assertEquals( 'approved', $data['status'] ); + $this->assertEquals( '139.130.4.5', $data['author_ip'] ); + } + + public function test_create_comment_invalid_author_IP() { + wp_set_current_user( $this->admin_id ); + + $params = array( + 'author_name' => 'Comic Book Guy', + 'author_email' => 'cbg@androidsdungeon.com', + 'author_url' => 'http://androidsdungeon.com', + 'author_ip' => '867.5309', + 'content' => 'Worst Comment Ever!', + 'status' => 'approved', + ); + $request = new WP_REST_Request( 'POST', '/wp/v2/comments' ); + $request->add_header( 'content-type', 'application/json' ); + $request->set_body( wp_json_encode( $params ) ); + + $response = $this->server->dispatch( $request ); + $this->assertErrorResponse( 'rest_comment_invalid_author_ip', $response, 400 ); } public function test_create_comment_no_post_id() { From 377c48d915a1c42654394f1c99449ad2a9bac8e3 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sat, 7 May 2016 13:24:34 -0500 Subject: [PATCH 05/11] Remove read-only attribute from author_ip --- lib/endpoints/class-wp-rest-comments-controller.php | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index 697a8d4bac..88be5f8fe7 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -812,7 +812,6 @@ public function get_item_schema() { 'description' => __( 'IP address for the object author.' ), 'type' => 'string', 'context' => array( 'edit' ), - 'readonly' => true, ), 'author_name' => array( 'description' => __( 'Display name for the object author.' ), From 52542d316a8ae1bfd75e223135915d8a6978c176 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 8 May 2016 10:38:50 -0500 Subject: [PATCH 06/11] Use string format type of 'ipv4' to validate comment author IP address New function `rest_is_ip_address()` checks if a value is a valid v4 IP address. It uses regex because core cannot guarantee support for `filter_var`. --- .../class-wp-rest-comments-controller.php | 7 ++--- plugin.php | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index 88be5f8fe7..002f983fe9 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -748,11 +748,7 @@ protected function prepare_item_for_database( $request ) { } if ( isset( $request['author_ip'] ) ) { - if ( filter_var( $request['author_ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) { - $prepared_comment['comment_author_IP'] = $request['author_ip']; - } else { - return new WP_Error( 'rest_comment_invalid_author_ip', __( 'The IP address you provided is invalid.' ), array( 'status' => 400 ) ); - } + $prepared_comment['comment_author_IP'] = $request['author_ip']; } if ( isset( $request['type'] ) ) { @@ -811,6 +807,7 @@ public function get_item_schema() { 'author_ip' => array( 'description' => __( 'IP address for the object author.' ), 'type' => 'string', + 'format' => 'ipv4', 'context' => array( 'edit' ), ), 'author_name' => array( diff --git a/plugin.php b/plugin.php index 965e07ee48..b3d733ddc0 100755 --- a/plugin.php +++ b/plugin.php @@ -320,6 +320,11 @@ function rest_validate_request_arg( $value, $request, $param ) { return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.' ) ); } break; + case 'ipv4' : + if ( ! rest_is_ip_address( $value ) ) { + return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.'), $value ) ); + } + break; } } @@ -395,6 +400,9 @@ function rest_sanitize_request_arg( $value, $request, $param ) { case 'uri' : return esc_url_raw( $value ); + + case 'ipv4' : + return sanitize_text_field( $value ); } } @@ -402,3 +410,23 @@ function rest_sanitize_request_arg( $value, $request, $param ) { } } + +if ( ! function_exists( 'rest_is_ip_address' ) ) { + /** + * Determines if a IPv4 address is valid. + * + * Does not handle IPv6 addresses. + * + * @param string $ipv4 IP 32-bit address. + * @return string|false The valid IPv4 address, otherwise false. + */ + function rest_is_ip_address( $ipv4 ) { + $pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; + + if ( ! preg_match( $pattern, $ipv4 ) ) { + return false; + } + + return $ipv4; + } +} From ebdcd2510485c6e5542320c7f91c073eb7c9b602 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 8 May 2016 10:39:50 -0500 Subject: [PATCH 07/11] Use the schema to set `127.0.0.1` as the default comment author IP --- lib/endpoints/class-wp-rest-comments-controller.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index 002f983fe9..a97c248844 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -349,9 +349,7 @@ public function create_item( $request ) { if ( ! isset( $prepared_comment['comment_author_url'] ) ) { $prepared_comment['comment_author_url'] = ''; } - if ( ! isset( $prepared_comment['comment_author_IP'] ) ) { - $prepared_comment['comment_author_IP'] = '127.0.0.1'; - } + $prepared_comment['comment_agent'] = ''; $prepared_comment['comment_approved'] = wp_allow_comment( $prepared_comment ); @@ -809,6 +807,9 @@ public function get_item_schema() { 'type' => 'string', 'format' => 'ipv4', 'context' => array( 'edit' ), + 'arg_options' => array( + 'default' => '127.0.0.1', + ), ), 'author_name' => array( 'description' => __( 'Display name for the object author.' ), From 7f5c77ee492617b4b0c1fc4a3ac9dc400668e209 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 8 May 2016 10:40:39 -0500 Subject: [PATCH 08/11] Update tests and improve coverage --- tests/test-rest-comments-controller.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test-rest-comments-controller.php b/tests/test-rest-comments-controller.php index fc2897812d..583da7e91c 100644 --- a/tests/test-rest-comments-controller.php +++ b/tests/test-rest-comments-controller.php @@ -643,6 +643,7 @@ public function test_create_item_assign_different_user() { $data = $response->get_data(); $this->assertEquals( $subscriber_id, $data['author'] ); + $this->assertEquals( '127.0.0.1', $data['author_ip'] ); } public function test_create_comment_without_type() { @@ -839,7 +840,8 @@ public function test_create_comment_invalid_author_IP() { $request->set_body( wp_json_encode( $params ) ); $response = $this->server->dispatch( $request ); - $this->assertErrorResponse( 'rest_comment_invalid_author_ip', $response, 400 ); + + $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); } public function test_create_comment_no_post_id() { @@ -964,6 +966,7 @@ public function test_update_item() { 'author_name' => 'Disco Stu', 'author_url' => 'http://stusdisco.com', 'author_email' => 'stu@stusdisco.com', + 'author_ip' => '4.4.4.4', 'date' => '2014-11-07T10:14:25', 'karma' => 100, 'post' => $post_id, @@ -982,6 +985,7 @@ public function test_update_item() { $this->assertEquals( $params['author_name'], $comment['author_name'] ); $this->assertEquals( $params['author_url'], $comment['author_url'] ); $this->assertEquals( $params['author_email'], $comment['author_email'] ); + $this->assertEquals( $params['author_ip'], $comment['author_ip'] ); $this->assertEquals( $params['post'], $comment['post'] ); $this->assertEquals( $params['karma'], $comment['karma'] ); From a7b033f80dc9a95149059b5a9731a36745e90a59 Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 8 May 2016 10:48:24 -0500 Subject: [PATCH 09/11] Add space to fix PHPCS error --- plugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin.php b/plugin.php index b3d733ddc0..4ae237458c 100755 --- a/plugin.php +++ b/plugin.php @@ -322,7 +322,7 @@ function rest_validate_request_arg( $value, $request, $param ) { break; case 'ipv4' : if ( ! rest_is_ip_address( $value ) ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.'), $value ) ); + return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $value ) ); } break; } From d051e65d98df3eff31ccd28c8481141a5590159d Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 8 May 2016 11:35:21 -0500 Subject: [PATCH 10/11] Remove unneeded check on prepare_item_for_database returning a WP_Error on update --- lib/endpoints/class-wp-rest-comments-controller.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index a97c248844..7a58d9a495 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -433,9 +433,6 @@ public function update_item( $request ) { } $prepared_args = $this->prepare_item_for_database( $request ); - if ( is_wp_error( $prepared_args ) ) { - return $prepared_args; - } if ( empty( $prepared_args ) && isset( $request['status'] ) ) { // Only the comment status is being changed. From 6dde6ce0a5d5efda25374b002c148921083db2bc Mon Sep 17 00:00:00 2001 From: Rachel Baker Date: Sun, 8 May 2016 11:41:27 -0500 Subject: [PATCH 11/11] Similar to d051e65 this removes the unneeded check on comment create --- lib/endpoints/class-wp-rest-comments-controller.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/endpoints/class-wp-rest-comments-controller.php b/lib/endpoints/class-wp-rest-comments-controller.php index 7a58d9a495..ea9825d82f 100755 --- a/lib/endpoints/class-wp-rest-comments-controller.php +++ b/lib/endpoints/class-wp-rest-comments-controller.php @@ -319,9 +319,6 @@ public function create_item( $request ) { } $prepared_comment = $this->prepare_item_for_database( $request ); - if ( is_wp_error( $prepared_comment ) ) { - return $prepared_comment; - } // Setting remaining values before wp_insert_comment so we can // use wp_allow_comment().