From 17ba58a5c27f77bac01e47ede89d0544907b2c21 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Sat, 17 Feb 2018 13:00:40 +0200 Subject: [PATCH] Framework\Uri: Improve query parameter handling --- system/src/Grav/Framework/Uri/Uri.php | 5 +- system/src/Grav/Framework/Uri/UriFactory.php | 52 ++++++++++++++++---- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/system/src/Grav/Framework/Uri/Uri.php b/system/src/Grav/Framework/Uri/Uri.php index 3d7fddecca..f9853f5d62 100644 --- a/system/src/Grav/Framework/Uri/Uri.php +++ b/system/src/Grav/Framework/Uri/Uri.php @@ -109,8 +109,7 @@ public function withQueryParam($key, $value) public function getQueryParams() { if ($this->queryParams === null) { - parse_str($this->getQuery(), $this->queryParams); - array_map(function($str) { return rawurldecode($str); }, $this->queryParams); + $this->queryParams = UriFactory::parseQuery($this->getQuery(), true); } return $this->queryParams; @@ -122,7 +121,7 @@ public function getQueryParams() */ public function withQueryParams(array $params) { - $query = $params ? http_build_query($params) : ''; + $query = UriFactory::buildQuery($params); return $this->withQuery($query); } diff --git a/system/src/Grav/Framework/Uri/UriFactory.php b/system/src/Grav/Framework/Uri/UriFactory.php index 61b45b90ea..81fd6e9672 100644 --- a/system/src/Grav/Framework/Uri/UriFactory.php +++ b/system/src/Grav/Framework/Uri/UriFactory.php @@ -80,7 +80,7 @@ public static function parseUrlFromEnvironment(array $env) // Build path. $request_uri = isset($env['REQUEST_URI']) ? $env['REQUEST_URI'] : ''; - $path = rawurldecode(parse_url('http://example.com' . $request_uri, PHP_URL_PATH)); + $path = parse_url('http://example.com' . $request_uri, PHP_URL_PATH); // Build query string. $query = isset($env['QUERY_STRING']) ? $env['QUERY_STRING'] : ''; @@ -107,24 +107,58 @@ public static function parseUrlFromEnvironment(array $env) } /** - * Advanced `parse_url()` method. + * UTF-8 aware parse_url() implementation. * - * @param string $uri + * @param string $url * @return array * @throws \InvalidArgumentException */ - public static function parseUrl($uri) + public static function parseUrl($url) { - if (!is_string($uri)) { - throw new \InvalidArgumentException('Uri must be a string'); + if (!is_string($url)) { + throw new \InvalidArgumentException('URL must be a string'); } - // Set Uri parts. - $parts = parse_url($uri); + $encodedUrl = preg_replace_callback( + '%[^:/@?&=#]+%u', + function ($matches) { return rawurlencode($matches[0]); }, + $url + ); + + $parts = parse_url($encodedUrl); if ($parts === false) { - throw new \InvalidArgumentException('Malformed URI: ' . $uri); + throw new \InvalidArgumentException('Malformed URL: ' . $encodedUrl); } return $parts; } + + /** + * Parse query string and return it as an array. + * + * @param string $query + * @params bool $decode + * @return mixed + */ + public static function parseQuery($query, $decode = false) + { + parse_str($query, $params); + + if ($decode) { + array_map(function($str) { return rawurldecode($str); }, $params); + } + + return $params; + } + + /** + * Build query string from variables. + * + * @param array $params + * @return string + */ + public static function buildQuery(array $params) + { + return $params ? http_build_query($params, null, ini_get('arg_separator.output'), PHP_QUERY_RFC3986) : ''; + } }