Make WordPress Core

Ticket #36356: 36356-wp_parse_url-revisited.patch

File 36356-wp_parse_url-revisited.patch, 8.3 KB (added by jrf, 8 years ago)

Complete patch including all previous changes and passing for PHP 5.2

  • src/wp-includes/http.php

    From 12e06a10ac46b7216bfbac41bc0015ff7bf49380 Mon Sep 17 00:00:00 2001
    From: jrfnl <github_nospam@adviesenzo.nl>
    Date: Fri, 30 Sep 2016 22:59:58 +0200
    Subject: [PATCH] Add the $component parameter to the wp_parse_url() function.
    
    ---
     src/wp-includes/http.php          | 73 +++++++++++++++++++++++++++----------
     tests/phpunit/tests/http/http.php | 77 ++++++++++++++++++++++++++++++++++++++-
     2 files changed, 129 insertions(+), 21 deletions(-)
    
    diff --git a/src/wp-includes/http.php b/src/wp-includes/http.php
    index 130eae3..3738b79 100644
    a b function ms_allowed_http_request_hosts( $is_external, $host ) { 
    633633 * when URL parsing failed.
    634634 *
    635635 * @since 4.4.0
    636  *
    637  * @param string $url The URL to parse.
    638  * @return bool|array False on failure; Array of URL components on success;
    639  *                    See parse_url()'s return values.
     636 * @since 4.7.0 The $component parameter was added for parity with PHP's parse_url().
     637 *
     638 * @param string $url       The URL to parse.
     639 * @param int    $component The specific component to retrieve. Use one of the PHP
     640 *                          predefined constants to specify which one.
     641 *                          Defaults to -1 (= return all parts as an array).
     642 *                          @see http://php.net/manual/en/function.parse-url.php
     643 * @return mixed False on failure; Array of URL components on success;
     644 *               When a specific component has been requested: null if the component doesn't
     645 *               exist in the given URL; a sting or - in the case of PHP_URL_PORT - integer
     646 *               when it does; See parse_url()'s return values.
    640647 */
    641 function wp_parse_url( $url ) {
    642         $parts = @parse_url( $url );
    643         if ( ! $parts ) {
    644                 // < PHP 5.4.7 compat, trouble with relative paths including a scheme break in the path
     648function wp_parse_url( $url, $component = -1 ) {
     649        $parts = @parse_url( $url, $component );
     650
     651        if ( version_compare( PHP_VERSION, '5.4.7', '>=' ) ) {
     652                return $parts;
     653        }
     654
     655        if ( false === $parts ) {
     656                // < PHP 5.4.7 compat, trouble with relative paths including a scheme break in the path.
    645657                if ( '/' == $url[0] && false !== strpos( $url, '://' ) ) {
    646                         // Since we know it's a relative path, prefix with a scheme/host placeholder and try again
    647                         if ( ! $parts = @parse_url( 'placeholder://placeholder' . $url ) ) {
     658                        if ( in_array( $component, array( PHP_URL_SCHEME, PHP_URL_HOST ), true ) ) {
     659                                return null;
     660                        }
     661                        // Since we know it's a relative path, prefix with a scheme/host placeholder and try again.
     662                        if ( ! $parts = @parse_url( 'placeholder://placeholder' . $url, $component ) ) {
    648663                                return $parts;
    649664                        }
    650                         // Remove the placeholder values
    651                         unset( $parts['scheme'], $parts['host'] );
     665                        // Remove the placeholder values.
     666                        if ( -1 === $component ) {
     667                                unset( $parts['scheme'], $parts['host'] );
     668                        }
    652669                } else {
    653670                        return $parts;
    654671                }
    655672        }
    656673
    657         // < PHP 5.4.7 compat, doesn't detect schemeless URL's host field
    658         if ( '//' == substr( $url, 0, 2 ) && ! isset( $parts['host'] ) ) {
    659                 $path_parts = explode( '/', substr( $parts['path'], 2 ), 2 );
    660                 $parts['host'] = $path_parts[0];
    661                 if ( isset( $path_parts[1] ) ) {
    662                         $parts['path'] = '/' . $path_parts[1];
    663                 } else {
    664                         unset( $parts['path'] );
     674        // < PHP 5.4.7 compat, doesn't detect a schemeless URL's host field.
     675        if ( '//' == substr( $url, 0, 2 ) ) {
     676                if ( -1 === $component && ! isset( $parts['host'] ) ) {
     677                        $path_parts = explode( '/', substr( $parts['path'], 2 ), 2 );
     678                        $parts['host'] = $path_parts[0];
     679                        if ( isset( $path_parts[1] ) ) {
     680                                $parts['path'] = '/' . $path_parts[1];
     681                        } else {
     682                                unset( $parts['path'] );
     683                        }
     684                } elseif ( PHP_URL_HOST === $component || PHP_URL_PATH === $component ) {
     685                        $all_parts = @parse_url( $url );
     686                        if ( ! isset( $all_parts['host'] ) ) {
     687                                $path_parts = explode( '/', substr( $all_parts['path'], 2 ), 2 );
     688                                if ( PHP_URL_PATH === $component ) {
     689                                        if ( isset( $path_parts[1] ) ) {
     690                                                $parts = '/' . $path_parts[1];
     691                                        } else {
     692                                                $parts = null;
     693                                        }
     694                                } elseif ( PHP_URL_HOST === $component ) {
     695                                        $parts = $path_parts[0];
     696                                }
     697                        }
    665698                }
    666699        }
    667700
  • tests/phpunit/tests/http/http.php

    diff --git a/tests/phpunit/tests/http/http.php b/tests/phpunit/tests/http/http.php
    index ed0b9ee..607eb47 100644
    a b  
    66 */
    77class Tests_HTTP_HTTP extends WP_UnitTestCase {
    88
     9        const FULL_TEST_URL = 'http://username:password@host.name:9090/path?arg1=value1&arg2=value2#anchor';
     10
    911        /**
    1012         * @dataProvider make_absolute_url_testcases
    1113         */
    class Tests_HTTP_HTTP extends WP_UnitTestCase { 
    7880        function parse_url_testcases() {
    7981                // 0: The URL, 1: The expected resulting structure
    8082                return array(
     83                        array( self::FULL_TEST_URL, array(
     84                                'scheme'   => 'http',
     85                                'host'     => 'host.name',
     86                                'port'     => 9090,
     87                                'user'     => 'username',
     88                                'pass'     => 'password',
     89                                'path'     => '/path',
     90                                'query'    => 'arg1=value1&arg2=value2',
     91                                'fragment' => 'anchor',
     92                        ) ),
    8193                        array( 'http://example.com/', array( 'scheme' => 'http', 'host' => 'example.com', 'path' => '/' ) ),
    8294
    8395                        // < PHP 5.4.7: Schemeless URL
    class Tests_HTTP_HTTP extends WP_UnitTestCase { 
    8597                        array( '//example.com/', array( 'host' => 'example.com', 'path' => '/' ) ),
    8698                        array( 'http://example.com//path/', array( 'scheme' => 'http', 'host' => 'example.com', 'path' => '//path/' ) ),
    8799
    88                         // < PHP 5.4.7: Scheme seperator in the URL
     100                        // < PHP 5.4.7: Scheme separator in the URL.
    89101                        array( 'http://example.com/http://example.net/', array( 'scheme' => 'http', 'host' => 'example.com', 'path' => '/http://example.net/' ) ),
    90102                        array( '/path/http://example.net/', array( 'path' => '/path/http://example.net/' ) ),
    91103
    class Tests_HTTP_HTTP extends WP_UnitTestCase { 
    104116        }
    105117
    106118        /**
     119         * @ticket 36356
     120     */
     121        function test_wp_parse_url_with_default_component() {
     122                $actual = wp_parse_url( self::FULL_TEST_URL, -1 );
     123                $this->assertEquals( array(
     124                        'scheme'   => 'http',
     125                        'host'     => 'host.name',
     126                        'port'     => 9090,
     127                        'user'     => 'username',
     128                        'pass'     => 'password',
     129                        'path'     => '/path',
     130                        'query'    => 'arg1=value1&arg2=value2',
     131                        'fragment' => 'anchor',
     132                ), $actual );
     133        }
     134
     135        /**
     136         * @ticket 36356
     137         *
     138         * @dataProvider parse_url_component_testcases
     139         */
     140        function test_wp_parse_url_with_component( $url, $component, $expected ) {
     141                $actual = wp_parse_url( $url, $component );
     142                $this->assertSame( $expected, $actual );
     143        }
     144
     145        function parse_url_component_testcases() {
     146                // 0: The URL, 1: The requested component, 2: The expected resulting structure.
     147                return array(
     148                        array( self::FULL_TEST_URL, PHP_URL_SCHEME, 'http' ),
     149                        array( self::FULL_TEST_URL, PHP_URL_USER, 'username' ),
     150                        array( self::FULL_TEST_URL, PHP_URL_PASS, 'password' ),
     151                        array( self::FULL_TEST_URL, PHP_URL_HOST, 'host.name' ),
     152                        array( self::FULL_TEST_URL, PHP_URL_PORT, 9090 ),
     153                        array( self::FULL_TEST_URL, PHP_URL_PATH, '/path' ),
     154                        array( self::FULL_TEST_URL, PHP_URL_QUERY, 'arg1=value1&arg2=value2' ),
     155                        array( self::FULL_TEST_URL, PHP_URL_FRAGMENT, 'anchor' ),
     156
     157                        // < PHP 5.4.7: Schemeless URL.
     158                        array( '//example.com/path/', PHP_URL_HOST, 'example.com' ),
     159                        array( '//example.com/path/', PHP_URL_PATH, '/path/' ),
     160                        array( '//example.com/', PHP_URL_HOST, 'example.com' ),
     161                        array( '//example.com/', PHP_URL_PATH, '/' ),
     162                        array( 'http://example.com//path/', PHP_URL_HOST, 'example.com' ),
     163                        array( 'http://example.com//path/', PHP_URL_PATH, '//path/' ),
     164
     165                        // < PHP 5.4.7: Scheme separator in the URL.
     166                        array( 'http://example.com/http://example.net/', PHP_URL_HOST, 'example.com' ),
     167                        array( 'http://example.com/http://example.net/', PHP_URL_PATH, '/http://example.net/' ),
     168                        array( '/path/http://example.net/', PHP_URL_HOST, null ),
     169                        array( '/path/http://example.net/', PHP_URL_PATH, '/path/http://example.net/' ),
     170
     171                        // < PHP 5.4.7: IPv6 literals in schemeless URLs are handled incorrectly.
     172                        array( '//[::FFFF::127.0.0.1]/', PHP_URL_HOST, '[::FFFF::127.0.0.1]' ),
     173                        array( '//[::FFFF::127.0.0.1]/', PHP_URL_PATH, '/' ),
     174
     175                        // PHP's parse_url() calls this an invalid URL, we handle it as a path.
     176                        array( '/://example.com/', PHP_URL_PATH, '/://example.com/' ),
     177
     178                );
     179        }
     180
     181        /**
    107182         * @ticket 35426
    108183         */
    109184        public function test_http_response_code_constants() {