Browse Source

Fix route mis-matches with multibyte fixed segments

Fix URLs not matching routes when path prefixes contain multi-byte
characters that are received as URL encoded data.

The URL is also decoded inside Route::parse() when pattern matched, but
this initial sieve was missing URL encoding.

Refs #7556
Mark Story 10 years ago
parent
commit
4ed1381da2
2 changed files with 26 additions and 1 deletions
  1. 2 1
      src/Routing/RouteCollection.php
  2. 24 0
      tests/TestCase/Routing/RouteCollectionTest.php

+ 2 - 1
src/Routing/RouteCollection.php

@@ -110,8 +110,9 @@ class RouteCollection
      */
     public function parse($url)
     {
+        $decoded = urldecode($url);
         foreach (array_keys($this->_paths) as $path) {
-            if (strpos($url, $path) !== 0) {
+            if (strpos($decoded, $path) !== 0) {
                 continue;
             }
 

+ 24 - 0
tests/TestCase/Routing/RouteCollectionTest.php

@@ -106,6 +106,30 @@ class RouteCollectionTest extends TestCase
     }
 
     /**
+     * Test that parse decodes URL data before matching.
+     * This is important for multibyte URLs that pass through URL rewriting.
+     *
+     * @return void
+     */
+    public function testParseEncodedBytesInFixedSegment()
+    {
+        $routes = new RouteBuilder($this->collection, '/');
+        $routes->connect('/ден/:day-:month', ['controller' => 'Events', 'action' => 'index']);
+        $url = '/%D0%B4%D0%B5%D0%BD/15-%D0%BE%D0%BA%D1%82%D0%BE%D0%BC%D0%B2%D1%80%D0%B8?test=foo';
+        $result = $this->collection->parse($url);
+        $expected = [
+            'pass' => [],
+            'plugin' => null,
+            'controller' => 'Events',
+            'action' => 'index',
+            'day' => 15,
+            'month' => 'октомври',
+            '?' => ['test' => 'foo'],
+        ];
+        $this->assertEquals($expected, $result);
+    }
+
+    /**
      * Test that parsing checks all the related path scopes.
      *
      * @return void