Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 761724a

Browse files
committed
[Routing] Adjust urlescaping rules, fixes #752
Only + and % are now encoded in generated routes, since they are the only characters that, if not encoded, could cause problems/conflicts when decoded. Namely + turns into a space, and % followed by numbers could do funky things. The matcher decodes everything which works since nothing will have %NN without being escaped, and + are escaped as well.
1 parent fb19e84 commit 761724a

File tree

6 files changed

+31
-16
lines changed

6 files changed

+31
-16
lines changed

src/Symfony/Component/Routing/Generator/UrlGenerator.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
125125
}
126126

127127
if (!$isEmpty || !$optional) {
128-
// %2F is not valid in a URL, so we don't encode it (which is fine as the requirements explicitly allowed it)
129-
$url = $token[1].str_replace('%2F', '/', rawurlencode($tparams[$token[3]])).$url;
128+
$url = $token[1].strtr($tparams[$token[3]], array('%'=>'%25', '+'=>'%2B')).$url;
130129
}
131130

132131
$optional = false;

src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ private function addMatcher($supportsRedirections)
6161
public function match(\$pathinfo)
6262
{
6363
\$allow = array();
64+
\$pathinfo = urldecode(\$pathinfo);
6465
6566
$code
6667
throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException();

src/Symfony/Component/Routing/Matcher/UrlMatcher.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ public function match($pathinfo)
9393

9494
protected function matchCollection($pathinfo, RouteCollection $routes)
9595
{
96+
$pathinfo = urldecode($pathinfo);
97+
9698
foreach ($routes as $name => $route) {
9799
if ($route instanceof RouteCollection) {
98100
if (false === strpos($route->getPrefix(), '{') && $route->getPrefix() !== substr($pathinfo, 0, strlen($route->getPrefix()))) {

tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function __construct(RequestContext $context)
2323
public function match($pathinfo)
2424
{
2525
$allow = array();
26+
$pathinfo = urldecode($pathinfo);
2627

2728
// foo
2829
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#x', $pathinfo, $matches)) {
@@ -106,38 +107,38 @@ public function match($pathinfo)
106107
$matches['_route'] = 'foo';
107108
return $matches;
108109
}
109-
110+
110111
// bar
111112
if (preg_match('#^/a/b/(?P<bar>[^/]+?)$#x', $pathinfo, $matches)) {
112113
$matches['_route'] = 'bar';
113114
return $matches;
114115
}
115-
116+
116117
// foo1
117118
if (preg_match('#^/a/b/(?P<foo1>[^/]+?)$#x', $pathinfo, $matches)) {
118119
$matches['_route'] = 'foo1';
119120
return $matches;
120121
}
121-
122+
122123
// bar1
123124
if (preg_match('#^/a/b/(?P<bar1>[^/]+?)$#x', $pathinfo, $matches)) {
124125
$matches['_route'] = 'bar1';
125126
return $matches;
126127
}
127-
128+
128129
}
129-
130+
130131
// ababa
131132
if ($pathinfo === '/ababa') {
132133
return array('_route' => 'ababa');
133134
}
134-
135+
135136
// foo
136137
if (preg_match('#^/aba/(?P<foo>[^/]+?)$#x', $pathinfo, $matches)) {
137138
$matches['_route'] = 'foo';
138139
return $matches;
139140
}
140-
141+
141142
}
142143

143144
// foo

tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher2.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public function __construct(RequestContext $context)
2323
public function match($pathinfo)
2424
{
2525
$allow = array();
26+
$pathinfo = urldecode($pathinfo);
2627

2728
// foo
2829
if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#x', $pathinfo, $matches)) {
@@ -118,38 +119,38 @@ public function match($pathinfo)
118119
$matches['_route'] = 'foo';
119120
return $matches;
120121
}
121-
122+
122123
// bar
123124
if (preg_match('#^/a/b/(?P<bar>[^/]+?)$#x', $pathinfo, $matches)) {
124125
$matches['_route'] = 'bar';
125126
return $matches;
126127
}
127-
128+
128129
// foo1
129130
if (preg_match('#^/a/b/(?P<foo1>[^/]+?)$#x', $pathinfo, $matches)) {
130131
$matches['_route'] = 'foo1';
131132
return $matches;
132133
}
133-
134+
134135
// bar1
135136
if (preg_match('#^/a/b/(?P<bar1>[^/]+?)$#x', $pathinfo, $matches)) {
136137
$matches['_route'] = 'bar1';
137138
return $matches;
138139
}
139-
140+
140141
}
141-
142+
142143
// ababa
143144
if ($pathinfo === '/ababa') {
144145
return array('_route' => 'ababa');
145146
}
146-
147+
147148
// foo
148149
if (preg_match('#^/aba/(?P<foo>[^/]+?)$#x', $pathinfo, $matches)) {
149150
$matches['_route'] = 'foo';
150151
return $matches;
151152
}
152-
153+
153154
}
154155

155156
// foo

tests/Symfony/Tests/Component/Routing/Matcher/UrlMatcherTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@ public function testMatchWithDynamicPrefix()
150150
$this->assertEquals(array('_locale' => 'fr', '_route' => 'foo', 'foo' => 'foo'), $matcher->match('/fr/b/foo'));
151151
}
152152

153+
public function testMatchNonAlpha()
154+
{
155+
$collection = new RouteCollection();
156+
$chars = '!"$%éà &\'()*+,./:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\[]^_`abcdefghijklmnopqrstuvwxyz{|}~-';
157+
$collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '['.preg_quote($chars).']+')));
158+
159+
$matcher = new UrlMatcher($collection, new RequestContext(), array());
160+
$this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.urlencode($chars).'/bar'));
161+
$this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.strtr($chars, array('%' => '%25', '+' => '%2B')).'/bar'));
162+
}
163+
153164
public function testMatchRegression()
154165
{
155166
$coll = new RouteCollection();

0 commit comments

Comments
 (0)