From 7f97c946e0c5893877bbaecee7a0b535c794d8aa Mon Sep 17 00:00:00 2001 From: MGatner Date: Tue, 4 May 2021 15:06:12 +0000 Subject: [PATCH 1/2] Make function static --- system/HTTP/URI.php | 226 +++++++++++++++++----------------- tests/system/HTTP/URITest.php | 27 +++- 2 files changed, 137 insertions(+), 116 deletions(-) diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index 1d1abc11070f..27e8534f6ff3 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -142,6 +142,116 @@ class URI //-------------------------------------------------------------------- + /** + * Builds a representation of the string from the component parts. + * + * @param string $scheme + * @param string $authority + * @param string $path + * @param string $query + * @param string $fragment + * + * @return string + */ + public static function createURIString(string $scheme = null, string $authority = null, string $path = null, string $query = null, string $fragment = null): string + { + $uri = ''; + if (! empty($scheme)) + { + $uri .= $scheme . '://'; + } + + if (! empty($authority)) + { + $uri .= $authority; + } + + if ($path !== '') + { + $uri .= substr($uri, -1, 1) !== '/' ? '/' . ltrim($path, '/') : ltrim($path, '/'); + } + + if ($query) + { + $uri .= '?' . $query; + } + + if ($fragment) + { + $uri .= '#' . $fragment; + } + + return $uri; + } + + /** + * Used when resolving and merging paths to correctly interpret and + * remove single and double dot segments from the path per + * RFC 3986 Section 5.2.4 + * + * @see http://tools.ietf.org/html/rfc3986#section-5.2.4 + * + * @param string $path + * + * @return string + * @internal + */ + public static function removeDotSegments(string $path): string + { + if ($path === '' || $path === '/') + { + return $path; + } + + $output = []; + + $input = explode('/', $path); + + if ($input[0] === '') + { + unset($input[0]); + $input = array_values($input); + } + + // This is not a perfect representation of the + // RFC, but matches most cases and is pretty + // much what Guzzle uses. Should be good enough + // for almost every real use case. + foreach ($input as $segment) + { + if ($segment === '..') + { + array_pop($output); + } + elseif ($segment !== '.' && $segment !== '') + { + $output[] = $segment; + } + } + + $output = implode('/', $output); + $output = ltrim($output, '/ '); + + if ($output !== '/') + { + // Add leading slash if necessary + if (strpos($path, '/') === 0) + { + $output = '/' . $output; + } + + // Add trailing slash if necessary + if (substr($path, -1, 1) === '/') + { + $output .= '/'; + } + } + + return $output; + } + + //-------------------------------------------------------------------- + /** * Constructor. * @@ -592,51 +702,7 @@ public function __toString(): string //-------------------------------------------------------------------- /** - * Builds a representation of the string from the component parts. - * - * @param string $scheme - * @param string $authority - * @param string $path - * @param string $query - * @param string $fragment - * - * @return string - */ - public static function createURIString(string $scheme = null, string $authority = null, string $path = null, string $query = null, string $fragment = null): string - { - $uri = ''; - if (! empty($scheme)) - { - $uri .= $scheme . '://'; - } - - if (! empty($authority)) - { - $uri .= $authority; - } - - if ($path !== '') - { - $uri .= substr($uri, -1, 1) !== '/' ? '/' . ltrim($path, '/') : ltrim($path, '/'); - } - - if ($query) - { - $uri .= '?' . $query; - } - - if ($fragment) - { - $uri .= '#' . $fragment; - } - - return $uri; - } - - //-------------------------------------------------------------------- - - /** - * Parses the given string an saves the appropriate authority pieces. + * Parses the given string and saves the appropriate authority pieces. * * @param string $str * @@ -947,7 +1013,7 @@ protected function filterPath(string $path = null): string $path = urldecode($path); // Remove dot segments - $path = $this->removeDotSegments($path); + $path = self::removeDotSegments($path); // Fix up some leading slash edge cases... if (strpos($orig, './') === 0) @@ -1140,74 +1206,6 @@ protected function mergePaths(URI $base, URI $reference): string //-------------------------------------------------------------------- - /** - * Used when resolving and merging paths to correctly interpret and - * remove single and double dot segments from the path per - * RFC 3986 Section 5.2.4 - * - * @see http://tools.ietf.org/html/rfc3986#section-5.2.4 - * - * @param string $path - * - * @return string - * @internal param \CodeIgniter\HTTP\URI $uri - */ - public function removeDotSegments(string $path): string - { - if ($path === '' || $path === '/') - { - return $path; - } - - $output = []; - - $input = explode('/', $path); - - if ($input[0] === '') - { - unset($input[0]); - $input = array_values($input); - } - - // This is not a perfect representation of the - // RFC, but matches most cases and is pretty - // much what Guzzle uses. Should be good enough - // for almost every real use case. - foreach ($input as $segment) - { - if ($segment === '..') - { - array_pop($output); - } - elseif ($segment !== '.' && $segment !== '') - { - $output[] = $segment; - } - } - - $output = implode('/', $output); - $output = ltrim($output, '/ '); - - if ($output !== '/') - { - // Add leading slash if necessary - if (strpos($path, '/') === 0) - { - $output = '/' . $output; - } - - // Add trailing slash if necessary - if (substr($path, -1, 1) === '/') - { - $output .= '/'; - } - } - - return $output; - } - - //-------------------------------------------------------------------- - /** * This is equivalent to the native PHP parse_str() function. * This version allows the dot to be used as a key of the query string. diff --git a/tests/system/HTTP/URITest.php b/tests/system/HTTP/URITest.php index ce50eba6a172..8c5ee3297658 100644 --- a/tests/system/HTTP/URITest.php +++ b/tests/system/HTTP/URITest.php @@ -567,6 +567,30 @@ public function testSetAuthorityReconstitutes() public function defaultDots() { return [ + [ + '', + '', + ], + [ + '/', + '/', + ], + [ + '.', + '', + ], + [ + '..', + '', + ], + [ + '/.', + '/', + ], + [ + '/..', + '/', + ], [ '/foo/..', '/', @@ -641,8 +665,7 @@ public function defaultDots() */ public function testRemoveDotSegments($path, $expected) { - $uri = new URI(); - $this->assertEquals($expected, $uri->removeDotSegments($path)); + $this->assertEquals($expected, URI::removeDotSegments($path)); } //-------------------------------------------------------------------- From 0275e69bee8985d658919a7c5f4ae2fc499699ef Mon Sep 17 00:00:00 2001 From: MGatner Date: Tue, 4 May 2021 15:10:41 +0000 Subject: [PATCH 2/2] Fix logic bug --- system/HTTP/URI.php | 23 ++++++++++------------- tests/system/HTTP/URITest.php | 4 ++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index 27e8534f6ff3..0ec29286319e 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -193,7 +193,7 @@ public static function createURIString(string $scheme = null, string $authority * * @param string $path * - * @return string + * @return string * @internal */ public static function removeDotSegments(string $path): string @@ -230,21 +230,18 @@ public static function removeDotSegments(string $path): string } $output = implode('/', $output); - $output = ltrim($output, '/ '); + $output = trim($output, '/ '); - if ($output !== '/') + // Add leading slash if necessary + if (strpos($path, '/') === 0) { - // Add leading slash if necessary - if (strpos($path, '/') === 0) - { - $output = '/' . $output; - } + $output = '/' . $output; + } - // Add trailing slash if necessary - if (substr($path, -1, 1) === '/') - { - $output .= '/'; - } + // Add trailing slash if necessary + if ($output !== '/' && substr($path, -1, 1) === '/') + { + $output .= '/'; } return $output; diff --git a/tests/system/HTTP/URITest.php b/tests/system/HTTP/URITest.php index 8c5ee3297658..2486195f463d 100644 --- a/tests/system/HTTP/URITest.php +++ b/tests/system/HTTP/URITest.php @@ -591,6 +591,10 @@ public function defaultDots() '/..', '/', ], + [ + '//', + '/', + ], [ '/foo/..', '/',