diff --git a/lib/Cake/Test/Case/View/HelperTest.php b/lib/Cake/Test/Case/View/HelperTest.php index 65d9d8eb5..6cecf1ea1 100644 --- a/lib/Cake/Test/Case/View/HelperTest.php +++ b/lib/Cake/Test/Case/View/HelperTest.php @@ -622,6 +622,9 @@ class HelperTest extends CakeTestCase { $result = $this->Helper->assetUrl('style', array('ext' => '.css')); $this->assertEquals('style.css', $result); + $result = $this->Helper->assetUrl('dir/sub dir/my image', array('ext' => '.jpg')); + $this->assertEquals('dir/sub%20dir/my%20image.jpg', $result); + $result = $this->Helper->assetUrl('foo.jpg?one=two&three=four'); $this->assertEquals('foo.jpg?one=two&three=four', $result); } diff --git a/lib/Cake/View/Helper.php b/lib/Cake/View/Helper.php index 0eb4eea9d..9e826f215 100644 --- a/lib/Cake/View/Helper.php +++ b/lib/Cake/View/Helper.php @@ -313,7 +313,7 @@ class Helper extends Object { if (isset($plugin)) { $path = Inflector::underscore($plugin) . '/' . $path; } - $path = h($this->assetTimestamp($this->webroot($path))); + $path = $this->_encodeUrl($this->assetTimestamp($this->webroot($path))); if (!empty($options['fullBase'])) { $base = $this->url('/', true); @@ -326,6 +326,21 @@ class Helper extends Object { return $path; } +/** + * Encodes a URL for use in HTML attributes. + * + * @param string $url The url to encode. + * @return string The url encoded for both URL & HTML contexts. + */ + protected function _encodeUrl($url) { + $path = parse_url($url, PHP_URL_PATH); + $encoded = implode('/', array_map( + 'rawurlencode', + explode('/', $path) + )); + return h(str_replace($path, $encoded, $url)); + } + /** * Adds a timestamp to a file based resource based on the value of `Asset.timestamp` in * Configure. If Asset.timestamp is true and debug > 0, or Asset.timestamp == 'force'