Skip to content

Commit 8745b20

Browse files
committed
fix: Filters does not decode URI path
Router does decode it, so Filters also should decode.
1 parent 01a5624 commit 8745b20

File tree

6 files changed

+99
-2
lines changed

6 files changed

+99
-2
lines changed

system/CodeIgniter.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ protected function handleRequest(?RouteCollectionInterface $routes, Cache $cache
449449

450450
$routeFilter = $this->tryToRouteIt($routes);
451451

452+
// $uri is URL-encoded.
452453
$uri = $this->determinePath();
453454

454455
if ($this->enableFilters) {
@@ -813,6 +814,7 @@ protected function tryToRouteIt(?RouteCollectionInterface $routes = null)
813814
// $routes is defined in Config/Routes.php
814815
$this->router = Services::router($routes, $this->request);
815816

817+
// $path is URL-encoded.
816818
$path = $this->determinePath();
817819

818820
$this->benchmark->stop('bootstrap');

system/Filters/Filters.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,9 @@ public function initialize(?string $uri = null)
245245
return $this;
246246
}
247247

248+
// Decode URL-encoded string
249+
$uri = urldecode($uri);
250+
248251
$this->processGlobals($uri);
249252
$this->processMethods();
250253
$this->processFilters($uri);
@@ -639,7 +642,7 @@ private function checkExcept(string $uri, $paths): bool
639642
/**
640643
* Check the URI path as pseudo-regex
641644
*
642-
* @param string $uri URI path relative to baseURL (all lowercase)
645+
* @param string $uri URI path relative to baseURL (all lowercase, URL-decoded)
643646
* @param array $paths The except path patterns
644647
*/
645648
private function checkPseudoRegex(string $uri, array $paths): bool
@@ -652,7 +655,7 @@ private function checkPseudoRegex(string $uri, array $paths): bool
652655
$path = strtolower(str_replace('*', '.*', $path));
653656

654657
// Does this rule apply here?
655-
if (preg_match('#^' . $path . '$#', $uri, $match) === 1) {
658+
if (preg_match('#\A' . $path . '\z#u', $uri, $match) === 1) {
656659
return true;
657660
}
658661
}

tests/system/Filters/FiltersTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,52 @@ public function testMatchesURICaseInsensitively(): void
10561056
$this->assertSame($expected, $filters->initialize($uri)->getFilters());
10571057
}
10581058

1059+
public function testMatchesURIWithUnicode(): void
1060+
{
1061+
$_SERVER['REQUEST_METHOD'] = 'GET';
1062+
1063+
$config = [
1064+
'aliases' => [
1065+
'foo' => '',
1066+
'bar' => '',
1067+
'frak' => '',
1068+
'baz' => '',
1069+
],
1070+
'globals' => [
1071+
'before' => [
1072+
'foo' => ['except' => '日本語/*'],
1073+
'bar',
1074+
],
1075+
'after' => [
1076+
'foo' => ['except' => '日本語/*'],
1077+
'baz',
1078+
],
1079+
],
1080+
'filters' => [
1081+
'frak' => [
1082+
'before' => ['日本語/*'],
1083+
'after' => ['日本語/*'],
1084+
],
1085+
],
1086+
];
1087+
$filtersConfig = $this->createConfigFromArray(FiltersConfig::class, $config);
1088+
$filters = $this->createFilters($filtersConfig);
1089+
1090+
// URIs passed to Filters are URL-encoded.
1091+
$uri = '%E6%97%A5%E6%9C%AC%E8%AA%9E/foo/bar';
1092+
$expected = [
1093+
'before' => [
1094+
'bar',
1095+
'frak',
1096+
],
1097+
'after' => [
1098+
'baz',
1099+
'frak',
1100+
],
1101+
];
1102+
$this->assertSame($expected, $filters->initialize($uri)->getFilters());
1103+
}
1104+
10591105
/**
10601106
* @see https://github.com/codeigniter4/CodeIgniter4/issues/1907
10611107
*/

user_guide_src/source/changelogs/v4.4.7.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ SECURITY
2121
strings has been added. This check is equivalent to the URI Security found in
2222
CodeIgniter 3. This is enabled by default, but upgraded users need to add
2323
a setting to enable it. See :ref:`urls-uri-security` for details.
24+
- **Filters:** A bug where URI paths processed by Filters were not URL-decoded
25+
has been fixed. See :ref:`upgrade-447-filter-paths` for details.
2426

2527
********
2628
BREAKING

user_guide_src/source/incoming/filters.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ an array with the ``except`` key and a URI path (relative to BaseURL) to match a
140140

141141
.. literalinclude:: filters/006.php
142142

143+
.. Warning:: Prior to v4.4.7, due to a bug, the URI paths processed by the filter
144+
were not URL-decoded. In other words, the URI paths specified in the routing
145+
and the URI paths specified in the filter could be different.
146+
See :ref:`upgrade-447-filter-paths` for details.
147+
143148
Any place you can use a URI path (relative to BaseURL) in the filter settings, you can use a regular expression or, like in this example, use
144149
an asterisk (``*``) for a wildcard that will match all characters after that. In this example, any URI path starting with ``api/``
145150
would be exempted from CSRF protection, but the site's forms would all be protected.
@@ -175,6 +180,11 @@ a list of URI path (relative to BaseURL) patterns that filter should apply to:
175180

176181
.. literalinclude:: filters/009.php
177182

183+
.. Warning:: Prior to v4.4.7, due to a bug, the URI paths processed by the filter
184+
were not URL-decoded. In other words, the URI paths specified in the routing
185+
and the URI paths specified in the filter could be different.
186+
See :ref:`upgrade-447-filter-paths` for details.
187+
178188
.. _filters-filters-filter-arguments:
179189

180190
Filter Arguments

user_guide_src/source/installation/upgrade_447.rst

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,40 @@ The error page has been updated. Please update the following files:
4040
Breaking Changes
4141
****************
4242

43+
.. _upgrade-447-filter-paths:
44+
45+
Paths in Controller Filters
46+
===========================
47+
48+
A bug where URI paths processed by :doc:`../incoming/filters` were not URL-decoded has been fixed.
49+
50+
.. note:: Note that :doc:`Router <../incoming/routing>` processes URL-decoded URI paths.
51+
52+
``Config\Filters`` has some places to specify the URI paths. If the paths have
53+
different values when URL-decoded, change them to the URL-decoded values.
54+
55+
E.g.,:
56+
57+
.. code-block:: php
58+
59+
public array $globals = [
60+
'before' => [
61+
'csrf' => ['except' => '%E6%97%A5%E6%9C%AC%E8%AA%9E/*'],
62+
],
63+
// ...
64+
];
65+
66+
67+
68+
.. code-block:: php
69+
70+
public array $globals = [
71+
'before' => [
72+
'csrf' => ['except' => '日本語/*'],
73+
],
74+
// ...
75+
];
76+
4377
Time::difference() and DST
4478
==========================
4579

0 commit comments

Comments
 (0)