REST API: Change “ipv4” types to “ip” to support ipv6.

Stop presuming IP address are IPv4, instead make the type “ip” to be agnostic of IP version. This fixes requests with ipv6 addresses for comments in core.

Props dd32, schlessera, danielbachhuber.
Fixes #38818.

git-svn-id: https://develop.svn.wordpress.org/trunk@39296 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Joe Hoyle 2016-11-18 19:32:03 +00:00
parent db07183b6f
commit ba5a196d9e
4 changed files with 41 additions and 14 deletions

View File

@ -869,23 +869,23 @@ function rest_parse_request_arg( $value, $request, $param ) {
}
/**
* Determines if a IPv4 address is valid.
* Determines if an IP address is valid.
*
* Does not handle IPv6 addresses.
* Handles both IPv4 and IPv6 addresses.
*
* @since 4.7.0
*
* @param string $ipv4 IP 32-bit address.
* @return string|false The valid IPv4 address, otherwise false.
* @param string $ip IP address.
* @return string|false The valid IP 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]?)$/';
function rest_is_ip_address( $ip ) {
$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 ) ) {
if ( ! preg_match( $ipv4_pattern, $ip ) && ! Requests_IPv6::check_ipv6( $ip ) ) {
return false;
}
return $ipv4;
return $ip;
}
/**
@ -1053,9 +1053,9 @@ function rest_validate_value_from_schema( $value, $args, $param = '' ) {
return new WP_Error( 'rest_invalid_email', __( 'Invalid email address.' ) );
}
break;
case 'ipv4' :
case 'ip' :
if ( ! rest_is_ip_address( $value ) ) {
/* translators: %s: IP address */
/* translators: %s: IP address */
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $value ) );
}
break;
@ -1156,7 +1156,7 @@ function rest_sanitize_value_from_schema( $value, $args ) {
case 'uri' :
return esc_url_raw( $value );
case 'ipv4' :
case 'ip' :
return sanitize_text_field( $value );
}
}

View File

@ -1115,7 +1115,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
'author_ip' => array(
'description' => __( 'IP address for the object author.' ),
'type' => 'string',
'format' => 'ipv4',
'format' => 'ip',
'context' => array( 'edit' ),
'default' => '127.0.0.1',
),

View File

@ -65,6 +65,17 @@ class WP_Test_REST_Schema_Sanitization extends WP_UnitTestCase {
$this->assertEquals( 'invalid', rest_sanitize_value_from_schema( 'invalid', $schema ) );
}
public function test_format_ip() {
$schema = array(
'type' => 'string',
'format' => 'ip',
);
$this->assertEquals( '127.0.0.1', rest_sanitize_value_from_schema( '127.0.0.1', $schema ) );
$this->assertEquals( 'hello', rest_sanitize_value_from_schema( 'hello', $schema ) );
$this->assertEquals( '2001:DB8:0:0:8:800:200C:417A', rest_sanitize_value_from_schema( '2001:DB8:0:0:8:800:200C:417A', $schema ) );
}
public function test_type_array() {
$schema = array(
'type' => 'array',

View File

@ -83,14 +83,30 @@ class WP_Test_REST_Schema_Validation extends WP_UnitTestCase {
$this->assertWPError( rest_validate_value_from_schema( '2016-06-30', $schema ) );
}
public function test_format_ipv4() {
public function test_format_ip() {
$schema = array(
'type' => 'string',
'format' => 'ipv4',
'format' => 'ip',
);
// IPv4.
$this->assertTrue( rest_validate_value_from_schema( '127.0.0.1', $schema ) );
$this->assertWPError( rest_validate_value_from_schema( '3333.3333.3333.3333', $schema ) );
$this->assertWPError( rest_validate_value_from_schema( '1', $schema ) );
// IPv6.
$this->assertTrue( rest_validate_value_from_schema( '::1', $schema ) ); // Loopback, compressed, non-routable.
$this->assertTrue( rest_validate_value_from_schema( '::', $schema ) ); // Unspecified, compressed, non-routable.
$this->assertTrue( rest_validate_value_from_schema( '0:0:0:0:0:0:0:1', $schema ) ); // Loopback, full.
$this->assertTrue( rest_validate_value_from_schema( '0:0:0:0:0:0:0:0', $schema ) ); // Unspecified, full.
$this->assertTrue( rest_validate_value_from_schema( '2001:DB8:0:0:8:800:200C:417A', $schema ) ); // Unicast, full.
$this->assertTrue( rest_validate_value_from_schema( 'FF01:0:0:0:0:0:0:101', $schema ) ); // Multicast, full.
$this->assertTrue( rest_validate_value_from_schema( '2001:DB8::8:800:200C:417A', $schema ) ); // Unicast, compressed.
$this->assertTrue( rest_validate_value_from_schema( 'FF01::101', $schema ) ); // Multicast, compressed.
$this->assertTrue( rest_validate_value_from_schema( 'fe80::217:f2ff:fe07:ed62', $schema ) );
$this->assertWPError( rest_validate_value_from_schema( '', $schema ) ); // Empty string.
$this->assertWPError( rest_validate_value_from_schema( '2001:DB8:0:0:8:800:200C:417A:221', $schema ) ); // Unicast, full.
$this->assertWPError( rest_validate_value_from_schema( 'FF01::101::2', $schema ) ); // Multicast, compressed.
}
public function test_type_array() {