From 465b15caa8e7023c4d18f3869c63c8e9d5d30796 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 5 Jun 2018 21:18:46 +0200 Subject: [PATCH 1/9] [Routing] fix matching host patterns, utf8 prefixes and non-capturing groups --- .../Matcher/Dumper/PhpMatcherDumper.php | 7 +- .../Matcher/Dumper/StaticPrefixCollection.php | 16 +- .../Component/Routing/RouteCompiler.php | 2 +- .../Tests/Fixtures/dumper/url_matcher1.php | 96 +- .../Tests/Fixtures/dumper/url_matcher10.php | 2006 ++++++++--------- .../Tests/Fixtures/dumper/url_matcher12.php | 36 +- .../Tests/Fixtures/dumper/url_matcher13.php | 10 +- .../Tests/Fixtures/dumper/url_matcher2.php | 96 +- .../Tests/Fixtures/dumper/url_matcher8.php | 12 +- .../Routing/Tests/Matcher/UrlMatcherTest.php | 37 + .../Routing/Tests/RouteCompilerTest.php | 1 + 11 files changed, 1185 insertions(+), 1134 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 0a7937916025..adb2b0a1c014 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -376,10 +376,10 @@ private function compileDynamicRoutes(RouteCollection $collection, bool $matchHo if ($hostRegex) { preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); $state->vars = array(); - $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')'; + $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; $state->hostVars = $state->vars; } else { - $hostRegex = '[^/]*+'; + $hostRegex = '(?:(?:[^.]*+\.)++)'; $state->hostVars = array(); } $state->mark += strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?"); @@ -406,6 +406,7 @@ private function compileDynamicRoutes(RouteCollection $collection, bool $matchHo $rx = ")$}{$modifiers}"; $code .= "\n .'{$rx}',"; $state->regex .= $rx; + $state->markTail = 0; // if the regex is too large, throw a signaling exception to recompute with smaller chunk size set_error_handler(function ($type, $message) { throw 0 === strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); }); @@ -427,7 +428,7 @@ private function compileDynamicRoutes(RouteCollection $collection, bool $matchHo EOF; } - $matchedPathinfo = $matchHost ? '$host.$pathinfo' : '$pathinfo'; + $matchedPathinfo = $matchHost ? '$host.\'.\'.$pathinfo' : '$pathinfo'; unset($state->getVars); return <<getCommonPrefix($prefix, $prefix); - } + list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix); for ($i = \count($this->items) - 1; 0 <= $i; --$i) { $item = $this->items[$i]; @@ -102,7 +100,7 @@ public function addRoute(string $prefix, $route, string $staticPrefix = null) if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) { // the new route is a child of a previous one, let's nest it - $item->addRoute($prefix, $route, $staticPrefix); + $item->addRoute($prefix, $route); } else { // the new route and a previous one have a common prefix, let's merge them $child = new self($commonPrefix); @@ -176,7 +174,7 @@ private function getCommonPrefix(string $prefix, string $anotherPrefix): array break; } $subPattern = substr($prefix, $i, $j - $i); - if ($prefix !== $anotherPrefix && !preg_match('{(?> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) { + do { + // Prevent cutting in the middle of an UTF-8 characters + --$i; + } while (0b10 === (\ord($prefix[$i]) >> 6)); + } return array(substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)); } diff --git a/src/Symfony/Component/Routing/RouteCompiler.php b/src/Symfony/Component/Routing/RouteCompiler.php index 7a89edd4897d..91b4a297cc17 100644 --- a/src/Symfony/Component/Routing/RouteCompiler.php +++ b/src/Symfony/Component/Routing/RouteCompiler.php @@ -321,7 +321,7 @@ private static function transformCapturingGroupsToNonCapturings(string $regexp): continue; } $regexp = substr_replace($regexp, '?:', $i, 0); - $i += 2; + ++$i; } return $regexp; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php index 615a3cba3090..b39bc7f2bae0 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -79,50 +79,50 @@ public function match($rawPathinfo) return $ret; } - $matchedPathinfo = $host.$pathinfo; + $matchedPathinfo = $host.'.'.$pathinfo; $regexList = array( 0 => '{^(?' - .'|[^/]*+(?' - .'|/foo/(baz|symfony)(*:34)' + .'|(?:(?:[^.]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:46)' .'|/bar(?' - .'|/([^/]++)(*:57)' - .'|head/([^/]++)(*:77)' + .'|/([^/]++)(*:69)' + .'|head/([^/]++)(*:89)' .')' .'|/test/([^/]++)/(?' - .'|(*:103)' + .'|(*:115)' .')' - .'|/([\']+)(*:119)' + .'|/([\']+)(*:131)' .'|/a/(?' .'|b\'b/([^/]++)(?' - .'|(*:148)' - .'|(*:156)' + .'|(*:160)' + .'|(*:168)' .')' - .'|(.*)(*:169)' + .'|(.*)(*:181)' .'|b\'b/([^/]++)(?' - .'|(*:192)' - .'|(*:200)' + .'|(*:204)' + .'|(*:212)' .')' .')' - .'|/multi/hello(?:/([^/]++))?(*:236)' + .'|/multi/hello(?:/([^/]++))?(*:248)' .'|/([^/]++)/b/([^/]++)(?' - .'|(*:267)' - .'|(*:275)' + .'|(*:279)' + .'|(*:287)' .')' - .'|/aba/([^/]++)(*:297)' - .')|(?i:([^\\.]++)\\.example\\.com)(?' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' .'|/route1(?' - .'|3/([^/]++)(*:357)' - .'|4/([^/]++)(*:375)' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' .')' - .')|(?i:c\\.example\\.com)(?' - .'|/route15/([^/]++)(*:425)' - .')|[^/]*+(?' - .'|/route16/([^/]++)(*:460)' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^.]*+\\.)++)(?' + .'|/route16/([^/]++)(*:488)' .'|/a/(?' - .'|a\\.\\.\\.(*:481)' + .'|a\\.\\.\\.(*:509)' .'|b/(?' - .'|([^/]++)(*:502)' - .'|c/([^/]++)(*:520)' + .'|([^/]++)(*:530)' + .'|c/([^/]++)(*:548)' .')' .')' .')' @@ -132,7 +132,7 @@ public function match($rawPathinfo) foreach ($regexList as $offset => $regex) { while (preg_match($regex, $matchedPathinfo, $matches)) { switch ($m = (int) $matches['MARK']) { - case 103: + case 115: $matches = array('foo' => $matches[1] ?? null); // baz4 @@ -159,7 +159,7 @@ public function match($rawPathinfo) not_bazbaz6: break; - case 148: + case 160: $matches = array('foo' => $matches[1] ?? null); // foo1 @@ -173,14 +173,14 @@ public function match($rawPathinfo) not_foo1: break; - case 192: + case 204: $matches = array('foo1' => $matches[1] ?? null); // foo2 return $this->mergeDefaults(array('_route' => 'foo2') + $matches, array()); break; - case 267: + case 279: $matches = array('_locale' => $matches[1] ?? null, 'foo' => $matches[2] ?? null); // foo3 @@ -189,23 +189,23 @@ public function match($rawPathinfo) break; default: $routes = array( - 34 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null), - 57 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null), - 77 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null), - 119 => array(array('_route' => 'quoter'), array('quoter'), null, null), - 156 => array(array('_route' => 'bar1'), array('bar'), null, null), - 169 => array(array('_route' => 'overridden'), array('var'), null, null), - 200 => array(array('_route' => 'bar2'), array('bar1'), null, null), - 236 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null), - 275 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null), - 297 => array(array('_route' => 'foo4'), array('foo'), null, null), - 357 => array(array('_route' => 'route13'), array('var1', 'name'), null, null), - 375 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null), - 425 => array(array('_route' => 'route15'), array('name'), null, null), - 460 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null), - 481 => array(array('_route' => 'a'), array(), null, null), - 502 => array(array('_route' => 'b'), array('var'), null, null), - 520 => array(array('_route' => 'c'), array('var'), null, null), + 46 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null), + 69 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null), + 89 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null), + 131 => array(array('_route' => 'quoter'), array('quoter'), null, null), + 168 => array(array('_route' => 'bar1'), array('bar'), null, null), + 181 => array(array('_route' => 'overridden'), array('var'), null, null), + 212 => array(array('_route' => 'bar2'), array('bar1'), null, null), + 248 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null), + 287 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null), + 309 => array(array('_route' => 'foo4'), array('foo'), null, null), + 371 => array(array('_route' => 'route13'), array('var1', 'name'), null, null), + 389 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null), + 441 => array(array('_route' => 'route15'), array('name'), null, null), + 488 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null), + 509 => array(array('_route' => 'a'), array(), null, null), + 530 => array(array('_route' => 'b'), array('var'), null, null), + 548 => array(array('_route' => 'c'), array('var'), null, null), ); list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m]; @@ -231,7 +231,7 @@ public function match($rawPathinfo) return $ret; } - if (520 === $m) { + if (548 === $m) { break; } $regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m)); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php index e976cd73f027..81ded3417cdd 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher10.php @@ -909,877 +909,877 @@ public function match($rawPathinfo) .')$}sD', 24786 => '{^(?' .'|/5(?' - .'|b69b9/([^/]++)/([^/]++)/([^/]++)/5b69b9(*:24845)' + .'|b69b9/([^/]++)/([^/]++)/([^/]++)/5b69b9(*:24837)' .'|9(?' - .'|b90e/([^/]++)/([^/]++)/([^/]++)/59b90e(*:24897)' - .'|c330/([^/]++)/([^/]++)/([^/]++)/59c330(*:24945)' + .'|b90e/([^/]++)/([^/]++)/([^/]++)/59b90e(*:24889)' + .'|c330/([^/]++)/([^/]++)/([^/]++)/59c330(*:24937)' .')' .'|3(?' - .'|fde9/([^/]++)/([^/]++)/([^/]++)/53fde9(*:24998)' - .'|e3a7/([^/]++)/([^/]++)/([^/]++)/53e3a7(*:25046)' + .'|fde9/([^/]++)/([^/]++)/([^/]++)/53fde9(*:24990)' + .'|e3a7/([^/]++)/([^/]++)/([^/]++)/53e3a7(*:25038)' .')' .'|e(?' - .'|a164/([^/]++)/([^/]++)/([^/]++)/5ea164(*:25099)' - .'|3881/([^/]++)/([^/]++)/([^/]++)/5e3881(*:25147)' - .'|9f92/([^/]++)/([^/]++)/([^/]++)/5e9f92(*:25195)' - .'|c91a/([^/]++)/([^/]++)/([^/]++)/5ec91a(*:25243)' + .'|a164/([^/]++)/([^/]++)/([^/]++)/5ea164(*:25091)' + .'|3881/([^/]++)/([^/]++)/([^/]++)/5e3881(*:25139)' + .'|9f92/([^/]++)/([^/]++)/([^/]++)/5e9f92(*:25187)' + .'|c91a/([^/]++)/([^/]++)/([^/]++)/5ec91a(*:25235)' .')' .'|7(?' - .'|3703/([^/]++)/([^/]++)/([^/]++)/573703(*:25296)' - .'|51ec/([^/]++)/([^/]++)/([^/]++)/5751ec(*:25344)' - .'|05e1/([^/]++)/([^/]++)/([^/]++)/5705e1(*:25392)' + .'|3703/([^/]++)/([^/]++)/([^/]++)/573703(*:25288)' + .'|51ec/([^/]++)/([^/]++)/([^/]++)/5751ec(*:25336)' + .'|05e1/([^/]++)/([^/]++)/([^/]++)/5705e1(*:25384)' .')' .'|8(?' - .'|ae74/([^/]++)/([^/]++)/([^/]++)/58ae74(*:25445)' - .'|d4d1/([^/]++)/([^/]++)/([^/]++)/58d4d1(*:25493)' - .'|07a6/([^/]++)/([^/]++)/([^/]++)/5807a6(*:25541)' - .'|e4d4/([^/]++)/([^/]++)/([^/]++)/58e4d4(*:25589)' + .'|ae74/([^/]++)/([^/]++)/([^/]++)/58ae74(*:25437)' + .'|d4d1/([^/]++)/([^/]++)/([^/]++)/58d4d1(*:25485)' + .'|07a6/([^/]++)/([^/]++)/([^/]++)/5807a6(*:25533)' + .'|e4d4/([^/]++)/([^/]++)/([^/]++)/58e4d4(*:25581)' .')' .'|d(?' - .'|44ee/([^/]++)/([^/]++)/([^/]++)/5d44ee(*:25642)' - .'|d9db/([^/]++)/([^/]++)/([^/]++)/5dd9db(*:25690)' + .'|44ee/([^/]++)/([^/]++)/([^/]++)/5d44ee(*:25634)' + .'|d9db/([^/]++)/([^/]++)/([^/]++)/5dd9db(*:25682)' .')' .'|5(?' - .'|b37c/([^/]++)/([^/]++)/([^/]++)/55b37c(*:25743)' - .'|743c/([^/]++)/([^/]++)/([^/]++)/55743c(*:25791)' - .'|6f39/([^/]++)/([^/]++)/([^/]++)/556f39(*:25839)' + .'|b37c/([^/]++)/([^/]++)/([^/]++)/55b37c(*:25735)' + .'|743c/([^/]++)/([^/]++)/([^/]++)/55743c(*:25783)' + .'|6f39/([^/]++)/([^/]++)/([^/]++)/556f39(*:25831)' .')' .'|c(?' - .'|0492/([^/]++)/([^/]++)/([^/]++)/5c0492(*:25892)' - .'|572e/([^/]++)/([^/]++)/([^/]++)/5c572e(*:25940)' - .'|9362/([^/]++)/([^/]++)/([^/]++)/5c9362(*:25988)' + .'|0492/([^/]++)/([^/]++)/([^/]++)/5c0492(*:25884)' + .'|572e/([^/]++)/([^/]++)/([^/]++)/5c572e(*:25932)' + .'|9362/([^/]++)/([^/]++)/([^/]++)/5c9362(*:25980)' .')' .'|4(?' - .'|8731/([^/]++)/([^/]++)/([^/]++)/548731(*:26041)' - .'|a367/([^/]++)/([^/]++)/([^/]++)/54a367(*:26089)' + .'|8731/([^/]++)/([^/]++)/([^/]++)/548731(*:26033)' + .'|a367/([^/]++)/([^/]++)/([^/]++)/54a367(*:26081)' .')' .'|0(?' - .'|0e75/([^/]++)/([^/]++)/([^/]++)/500e75(*:26142)' - .'|c3d7/([^/]++)/([^/]++)/([^/]++)/50c3d7(*:26190)' + .'|0e75/([^/]++)/([^/]++)/([^/]++)/500e75(*:26134)' + .'|c3d7/([^/]++)/([^/]++)/([^/]++)/50c3d7(*:26182)' .')' .'|f(?' - .'|2c22/([^/]++)/([^/]++)/([^/]++)/5f2c22(*:26243)' - .'|0f5e/([^/]++)/([^/]++)/([^/]++)/5f0f5e(*:26291)' + .'|2c22/([^/]++)/([^/]++)/([^/]++)/5f2c22(*:26235)' + .'|0f5e/([^/]++)/([^/]++)/([^/]++)/5f0f5e(*:26283)' .')' - .'|1ef18/([^/]++)/([^/]++)/([^/]++)/51ef18(*:26341)' + .'|1ef18/([^/]++)/([^/]++)/([^/]++)/51ef18(*:26333)' .')' .'|/b(?' .'|5(?' - .'|b41f/([^/]++)/([^/]++)/([^/]++)/b5b41f(*:26399)' - .'|dc4e/([^/]++)/([^/]++)/([^/]++)/b5dc4e(*:26447)' - .'|6a18/([^/]++)/([^/]++)/([^/]++)/b56a18(*:26495)' - .'|5ec2/([^/]++)/([^/]++)/([^/]++)/b55ec2(*:26543)' + .'|b41f/([^/]++)/([^/]++)/([^/]++)/b5b41f(*:26391)' + .'|dc4e/([^/]++)/([^/]++)/([^/]++)/b5dc4e(*:26439)' + .'|6a18/([^/]++)/([^/]++)/([^/]++)/b56a18(*:26487)' + .'|5ec2/([^/]++)/([^/]++)/([^/]++)/b55ec2(*:26535)' .')' - .'|337e8/([^/]++)/([^/]++)/([^/]++)/b337e8(*:26593)' + .'|337e8/([^/]++)/([^/]++)/([^/]++)/b337e8(*:26585)' .'|a(?' - .'|2fd3/([^/]++)/([^/]++)/([^/]++)/ba2fd3(*:26645)' - .'|3866/([^/]++)/([^/]++)/([^/]++)/ba3866(*:26693)' + .'|2fd3/([^/]++)/([^/]++)/([^/]++)/ba2fd3(*:26637)' + .'|3866/([^/]++)/([^/]++)/([^/]++)/ba3866(*:26685)' .')' .'|2(?' - .'|eeb7/([^/]++)/([^/]++)/([^/]++)/b2eeb7(*:26746)' - .'|f627/([^/]++)/([^/]++)/([^/]++)/b2f627(*:26794)' + .'|eeb7/([^/]++)/([^/]++)/([^/]++)/b2eeb7(*:26738)' + .'|f627/([^/]++)/([^/]++)/([^/]++)/b2f627(*:26786)' .')' .'|7(?' - .'|3dfe/([^/]++)/([^/]++)/([^/]++)/b73dfe(*:26847)' - .'|bb35/([^/]++)/([^/]++)/([^/]++)/b7bb35(*:26895)' - .'|ee6f/([^/]++)/([^/]++)/([^/]++)/b7ee6f(*:26943)' - .'|892f/([^/]++)/([^/]++)/([^/]++)/b7892f(*:26991)' - .'|0683/([^/]++)/([^/]++)/([^/]++)/b70683(*:27039)' + .'|3dfe/([^/]++)/([^/]++)/([^/]++)/b73dfe(*:26839)' + .'|bb35/([^/]++)/([^/]++)/([^/]++)/b7bb35(*:26887)' + .'|ee6f/([^/]++)/([^/]++)/([^/]++)/b7ee6f(*:26935)' + .'|892f/([^/]++)/([^/]++)/([^/]++)/b7892f(*:26983)' + .'|0683/([^/]++)/([^/]++)/([^/]++)/b70683(*:27031)' .')' .'|4(?' - .'|288d/([^/]++)/([^/]++)/([^/]++)/b4288d(*:27092)' - .'|a528/([^/]++)/([^/]++)/([^/]++)/b4a528(*:27140)' + .'|288d/([^/]++)/([^/]++)/([^/]++)/b4288d(*:27084)' + .'|a528/([^/]++)/([^/]++)/([^/]++)/b4a528(*:27132)' .')' .'|e(?' - .'|3159/([^/]++)/([^/]++)/([^/]++)/be3159(*:27193)' - .'|b22f/([^/]++)/([^/]++)/([^/]++)/beb22f(*:27241)' - .'|a595/([^/]++)/([^/]++)/([^/]++)/bea595(*:27289)' + .'|3159/([^/]++)/([^/]++)/([^/]++)/be3159(*:27185)' + .'|b22f/([^/]++)/([^/]++)/([^/]++)/beb22f(*:27233)' + .'|a595/([^/]++)/([^/]++)/([^/]++)/bea595(*:27281)' .')' .'|1(?' - .'|eec3/([^/]++)/([^/]++)/([^/]++)/b1eec3(*:27342)' - .'|37fd/([^/]++)/([^/]++)/([^/]++)/b137fd(*:27390)' + .'|eec3/([^/]++)/([^/]++)/([^/]++)/b1eec3(*:27334)' + .'|37fd/([^/]++)/([^/]++)/([^/]++)/b137fd(*:27382)' .')' .'|0(?' - .'|56eb/([^/]++)/([^/]++)/([^/]++)/b056eb(*:27443)' - .'|b183/([^/]++)/([^/]++)/([^/]++)/b0b183(*:27491)' + .'|56eb/([^/]++)/([^/]++)/([^/]++)/b056eb(*:27435)' + .'|b183/([^/]++)/([^/]++)/([^/]++)/b0b183(*:27483)' .')' - .'|f6276/([^/]++)/([^/]++)/([^/]++)/bf6276(*:27541)' + .'|f6276/([^/]++)/([^/]++)/([^/]++)/bf6276(*:27533)' .'|6(?' - .'|edc1/([^/]++)/([^/]++)/([^/]++)/b6edc1(*:27593)' - .'|a108/([^/]++)/([^/]++)/([^/]++)/b6a108(*:27641)' + .'|edc1/([^/]++)/([^/]++)/([^/]++)/b6edc1(*:27585)' + .'|a108/([^/]++)/([^/]++)/([^/]++)/b6a108(*:27633)' .')' - .'|86e8d/([^/]++)/([^/]++)/([^/]++)/b86e8d(*:27691)' + .'|86e8d/([^/]++)/([^/]++)/([^/]++)/b86e8d(*:27683)' .')' .'|/2(?' .'|8(?' - .'|5e19/([^/]++)/([^/]++)/([^/]++)/285e19(*:27749)' + .'|5e19/([^/]++)/([^/]++)/([^/]++)/285e19(*:27741)' .'|2(?' - .'|3f4/([^/]++)/([^/]++)/([^/]++)/2823f4(*:27800)' - .'|67a/([^/]++)/([^/]++)/([^/]++)/28267a(*:27847)' + .'|3f4/([^/]++)/([^/]++)/([^/]++)/2823f4(*:27792)' + .'|67a/([^/]++)/([^/]++)/([^/]++)/28267a(*:27839)' .')' - .'|8cc0/([^/]++)/([^/]++)/([^/]++)/288cc0(*:27896)' - .'|7e03/([^/]++)/([^/]++)/([^/]++)/287e03(*:27944)' + .'|8cc0/([^/]++)/([^/]++)/([^/]++)/288cc0(*:27888)' + .'|7e03/([^/]++)/([^/]++)/([^/]++)/287e03(*:27936)' .')' .'|d(?' - .'|6cc4/([^/]++)/([^/]++)/([^/]++)/2d6cc4(*:27997)' - .'|ea61/([^/]++)/([^/]++)/([^/]++)/2dea61(*:28045)' - .'|ace7/([^/]++)/([^/]++)/([^/]++)/2dace7(*:28093)' + .'|6cc4/([^/]++)/([^/]++)/([^/]++)/2d6cc4(*:27989)' + .'|ea61/([^/]++)/([^/]++)/([^/]++)/2dea61(*:28037)' + .'|ace7/([^/]++)/([^/]++)/([^/]++)/2dace7(*:28085)' .')' .'|b(?' - .'|8a61/([^/]++)/([^/]++)/([^/]++)/2b8a61(*:28146)' - .'|b232/([^/]++)/([^/]++)/([^/]++)/2bb232(*:28194)' - .'|a596/([^/]++)/([^/]++)/([^/]++)/2ba596(*:28242)' - .'|cab9/([^/]++)/([^/]++)/([^/]++)/2bcab9(*:28290)' + .'|8a61/([^/]++)/([^/]++)/([^/]++)/2b8a61(*:28138)' + .'|b232/([^/]++)/([^/]++)/([^/]++)/2bb232(*:28186)' + .'|a596/([^/]++)/([^/]++)/([^/]++)/2ba596(*:28234)' + .'|cab9/([^/]++)/([^/]++)/([^/]++)/2bcab9(*:28282)' .')' .'|9(?' - .'|8f95/([^/]++)/([^/]++)/([^/]++)/298f95(*:28343)' - .'|1597/([^/]++)/([^/]++)/([^/]++)/291597(*:28391)' + .'|8f95/([^/]++)/([^/]++)/([^/]++)/298f95(*:28335)' + .'|1597/([^/]++)/([^/]++)/([^/]++)/291597(*:28383)' .')' - .'|58be1/([^/]++)/([^/]++)/([^/]++)/258be1(*:28441)' + .'|58be1/([^/]++)/([^/]++)/([^/]++)/258be1(*:28433)' .'|3(?' - .'|3509/([^/]++)/([^/]++)/([^/]++)/233509(*:28493)' - .'|ce18/([^/]++)/([^/]++)/([^/]++)/23ce18(*:28541)' + .'|3509/([^/]++)/([^/]++)/([^/]++)/233509(*:28485)' + .'|ce18/([^/]++)/([^/]++)/([^/]++)/23ce18(*:28533)' .')' .'|6(?' - .'|dd0d/([^/]++)/([^/]++)/([^/]++)/26dd0d(*:28594)' - .'|408f/([^/]++)/([^/]++)/([^/]++)/26408f(*:28642)' + .'|dd0d/([^/]++)/([^/]++)/([^/]++)/26dd0d(*:28586)' + .'|408f/([^/]++)/([^/]++)/([^/]++)/26408f(*:28634)' .')' .'|f(?' - .'|37d1/([^/]++)/([^/]++)/([^/]++)/2f37d1(*:28695)' - .'|885d/([^/]++)/([^/]++)/([^/]++)/2f885d(*:28743)' + .'|37d1/([^/]++)/([^/]++)/([^/]++)/2f37d1(*:28687)' + .'|885d/([^/]++)/([^/]++)/([^/]++)/2f885d(*:28735)' .')' .'|2(?' - .'|91d2/([^/]++)/([^/]++)/([^/]++)/2291d2(*:28796)' - .'|ac3c/([^/]++)/([^/]++)/([^/]++)/22ac3c(*:28844)' - .'|fb0c/([^/]++)/([^/]++)/([^/]++)/22fb0c(*:28892)' + .'|91d2/([^/]++)/([^/]++)/([^/]++)/2291d2(*:28788)' + .'|ac3c/([^/]++)/([^/]++)/([^/]++)/22ac3c(*:28836)' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/22fb0c(*:28884)' .')' .'|4(?' - .'|6819/([^/]++)/([^/]++)/([^/]++)/246819(*:28945)' - .'|896e/([^/]++)/([^/]++)/([^/]++)/24896e(*:28993)' + .'|6819/([^/]++)/([^/]++)/([^/]++)/246819(*:28937)' + .'|896e/([^/]++)/([^/]++)/([^/]++)/24896e(*:28985)' .')' .'|a(?' - .'|fe45/([^/]++)/([^/]++)/([^/]++)/2afe45(*:29046)' - .'|084e/([^/]++)/([^/]++)/([^/]++)/2a084e(*:29094)' - .'|9d12/([^/]++)/([^/]++)/([^/]++)/2a9d12(*:29142)' - .'|b564/([^/]++)/([^/]++)/([^/]++)/2ab564(*:29190)' + .'|fe45/([^/]++)/([^/]++)/([^/]++)/2afe45(*:29038)' + .'|084e/([^/]++)/([^/]++)/([^/]++)/2a084e(*:29086)' + .'|9d12/([^/]++)/([^/]++)/([^/]++)/2a9d12(*:29134)' + .'|b564/([^/]++)/([^/]++)/([^/]++)/2ab564(*:29182)' .')' .'|1(?' - .'|7eed/([^/]++)/([^/]++)/([^/]++)/217eed(*:29243)' - .'|0f76/([^/]++)/([^/]++)/([^/]++)/210f76(*:29291)' + .'|7eed/([^/]++)/([^/]++)/([^/]++)/217eed(*:29235)' + .'|0f76/([^/]++)/([^/]++)/([^/]++)/210f76(*:29283)' .')' - .'|e65f2/([^/]++)/([^/]++)/([^/]++)/2e65f2(*:29341)' - .'|ca65f/([^/]++)/([^/]++)/([^/]++)/2ca65f(*:29390)' - .'|0aee3/([^/]++)/([^/]++)/([^/]++)/20aee3(*:29439)' + .'|e65f2/([^/]++)/([^/]++)/([^/]++)/2e65f2(*:29333)' + .'|ca65f/([^/]++)/([^/]++)/([^/]++)/2ca65f(*:29382)' + .'|0aee3/([^/]++)/([^/]++)/([^/]++)/20aee3(*:29431)' .')' .'|/e(?' .'|8(?' - .'|c065/([^/]++)/([^/]++)/([^/]++)/e8c065(*:29497)' - .'|20a4/([^/]++)/([^/]++)/([^/]++)/e820a4(*:29545)' + .'|c065/([^/]++)/([^/]++)/([^/]++)/e8c065(*:29489)' + .'|20a4/([^/]++)/([^/]++)/([^/]++)/e820a4(*:29537)' .')' .'|2(?' - .'|230b/([^/]++)/([^/]++)/([^/]++)/e2230b(*:29598)' - .'|a2dc/([^/]++)/([^/]++)/([^/]++)/e2a2dc(*:29646)' - .'|05ee/([^/]++)/([^/]++)/([^/]++)/e205ee(*:29694)' + .'|230b/([^/]++)/([^/]++)/([^/]++)/e2230b(*:29590)' + .'|a2dc/([^/]++)/([^/]++)/([^/]++)/e2a2dc(*:29638)' + .'|05ee/([^/]++)/([^/]++)/([^/]++)/e205ee(*:29686)' .')' .'|b(?' - .'|d962/([^/]++)/([^/]++)/([^/]++)/ebd962(*:29747)' - .'|6fdc/([^/]++)/([^/]++)/([^/]++)/eb6fdc(*:29795)' + .'|d962/([^/]++)/([^/]++)/([^/]++)/ebd962(*:29739)' + .'|6fdc/([^/]++)/([^/]++)/([^/]++)/eb6fdc(*:29787)' .')' .'|d(?' - .'|265b/([^/]++)/([^/]++)/([^/]++)/ed265b(*:29848)' - .'|fbe1/([^/]++)/([^/]++)/([^/]++)/edfbe1(*:29896)' - .'|e7e2/([^/]++)/([^/]++)/([^/]++)/ede7e2(*:29944)' + .'|265b/([^/]++)/([^/]++)/([^/]++)/ed265b(*:29840)' + .'|fbe1/([^/]++)/([^/]++)/([^/]++)/edfbe1(*:29888)' + .'|e7e2/([^/]++)/([^/]++)/([^/]++)/ede7e2(*:29936)' .')' .'|6(?' - .'|b4b2/([^/]++)/([^/]++)/([^/]++)/e6b4b2(*:29997)' - .'|cb2a/([^/]++)/([^/]++)/([^/]++)/e6cb2a(*:30045)' + .'|b4b2/([^/]++)/([^/]++)/([^/]++)/e6b4b2(*:29989)' + .'|cb2a/([^/]++)/([^/]++)/([^/]++)/e6cb2a(*:30037)' .')' .'|5(?' - .'|f6ad/([^/]++)/([^/]++)/([^/]++)/e5f6ad(*:30098)' - .'|55eb/([^/]++)/([^/]++)/([^/]++)/e555eb(*:30146)' - .'|841d/([^/]++)/([^/]++)/([^/]++)/e5841d(*:30194)' - .'|7c6b/([^/]++)/([^/]++)/([^/]++)/e57c6b(*:30242)' + .'|f6ad/([^/]++)/([^/]++)/([^/]++)/e5f6ad(*:30090)' + .'|55eb/([^/]++)/([^/]++)/([^/]++)/e555eb(*:30138)' + .'|841d/([^/]++)/([^/]++)/([^/]++)/e5841d(*:30186)' + .'|7c6b/([^/]++)/([^/]++)/([^/]++)/e57c6b(*:30234)' .')' - .'|aae33/([^/]++)/([^/]++)/([^/]++)/eaae33(*:30292)' + .'|aae33/([^/]++)/([^/]++)/([^/]++)/eaae33(*:30284)' .'|4(?' - .'|bb4c/([^/]++)/([^/]++)/([^/]++)/e4bb4c(*:30344)' - .'|9b8b/([^/]++)/([^/]++)/([^/]++)/e49b8b(*:30392)' + .'|bb4c/([^/]++)/([^/]++)/([^/]++)/e4bb4c(*:30336)' + .'|9b8b/([^/]++)/([^/]++)/([^/]++)/e49b8b(*:30384)' .')' .'|7(?' - .'|0611/([^/]++)/([^/]++)/([^/]++)/e70611(*:30445)' - .'|f8a7/([^/]++)/([^/]++)/([^/]++)/e7f8a7(*:30493)' - .'|44f9/([^/]++)/([^/]++)/([^/]++)/e744f9(*:30541)' + .'|0611/([^/]++)/([^/]++)/([^/]++)/e70611(*:30437)' + .'|f8a7/([^/]++)/([^/]++)/([^/]++)/e7f8a7(*:30485)' + .'|44f9/([^/]++)/([^/]++)/([^/]++)/e744f9(*:30533)' .')' .'|9(?' - .'|95f9/([^/]++)/([^/]++)/([^/]++)/e995f9(*:30594)' - .'|4550/([^/]++)/([^/]++)/([^/]++)/e94550(*:30642)' - .'|7ee2/([^/]++)/([^/]++)/([^/]++)/e97ee2(*:30690)' + .'|95f9/([^/]++)/([^/]++)/([^/]++)/e995f9(*:30586)' + .'|4550/([^/]++)/([^/]++)/([^/]++)/e94550(*:30634)' + .'|7ee2/([^/]++)/([^/]++)/([^/]++)/e97ee2(*:30682)' .')' .'|e(?' - .'|fc9e/([^/]++)/([^/]++)/([^/]++)/eefc9e(*:30743)' - .'|b69a/([^/]++)/([^/]++)/([^/]++)/eeb69a(*:30791)' + .'|fc9e/([^/]++)/([^/]++)/([^/]++)/eefc9e(*:30735)' + .'|b69a/([^/]++)/([^/]++)/([^/]++)/eeb69a(*:30783)' .')' .'|0(?' - .'|7413/([^/]++)/([^/]++)/([^/]++)/e07413(*:30844)' - .'|cf1f/([^/]++)/([^/]++)/([^/]++)/e0cf1f(*:30892)' - .'|ec45/([^/]++)/([^/]++)/([^/]++)/e0ec45(*:30940)' + .'|7413/([^/]++)/([^/]++)/([^/]++)/e07413(*:30836)' + .'|cf1f/([^/]++)/([^/]++)/([^/]++)/e0cf1f(*:30884)' + .'|ec45/([^/]++)/([^/]++)/([^/]++)/e0ec45(*:30932)' .')' - .'|f4e3b/([^/]++)/([^/]++)/([^/]++)/ef4e3b(*:30990)' - .'|c5aa0/([^/]++)/([^/]++)/([^/]++)/ec5aa0(*:31039)' + .'|f4e3b/([^/]++)/([^/]++)/([^/]++)/ef4e3b(*:30982)' + .'|c5aa0/([^/]++)/([^/]++)/([^/]++)/ec5aa0(*:31031)' .')' .'|/f(?' .'|f(?' - .'|4d5f/([^/]++)/([^/]++)/([^/]++)/ff4d5f(*:31097)' - .'|eabd/([^/]++)/([^/]++)/([^/]++)/ffeabd(*:31145)' + .'|4d5f/([^/]++)/([^/]++)/([^/]++)/ff4d5f(*:31089)' + .'|eabd/([^/]++)/([^/]++)/([^/]++)/ffeabd(*:31137)' .')' .'|3(?' - .'|f27a/([^/]++)/([^/]++)/([^/]++)/f3f27a(*:31198)' - .'|8762/([^/]++)/([^/]++)/([^/]++)/f38762(*:31246)' + .'|f27a/([^/]++)/([^/]++)/([^/]++)/f3f27a(*:31190)' + .'|8762/([^/]++)/([^/]++)/([^/]++)/f38762(*:31238)' .')' .'|4(?' - .'|be00/([^/]++)/([^/]++)/([^/]++)/f4be00(*:31299)' - .'|5526/([^/]++)/([^/]++)/([^/]++)/f45526(*:31347)' - .'|7d0a/([^/]++)/([^/]++)/([^/]++)/f47d0a(*:31395)' + .'|be00/([^/]++)/([^/]++)/([^/]++)/f4be00(*:31291)' + .'|5526/([^/]++)/([^/]++)/([^/]++)/f45526(*:31339)' + .'|7d0a/([^/]++)/([^/]++)/([^/]++)/f47d0a(*:31387)' .')' .'|0(?' - .'|e52b/([^/]++)/([^/]++)/([^/]++)/f0e52b(*:31448)' - .'|adc8/([^/]++)/([^/]++)/([^/]++)/f0adc8(*:31496)' + .'|e52b/([^/]++)/([^/]++)/([^/]++)/f0e52b(*:31440)' + .'|adc8/([^/]++)/([^/]++)/([^/]++)/f0adc8(*:31488)' .')' - .'|de926/([^/]++)/([^/]++)/([^/]++)/fde926(*:31546)' + .'|de926/([^/]++)/([^/]++)/([^/]++)/fde926(*:31538)' .'|5(?' - .'|deae/([^/]++)/([^/]++)/([^/]++)/f5deae(*:31598)' - .'|7a2f/([^/]++)/([^/]++)/([^/]++)/f57a2f(*:31646)' + .'|deae/([^/]++)/([^/]++)/([^/]++)/f5deae(*:31590)' + .'|7a2f/([^/]++)/([^/]++)/([^/]++)/f57a2f(*:31638)' .')' .'|7(?' - .'|6a89/([^/]++)/([^/]++)/([^/]++)/f76a89(*:31699)' - .'|9921/([^/]++)/([^/]++)/([^/]++)/f79921(*:31747)' - .'|e905/([^/]++)/([^/]++)/([^/]++)/f7e905(*:31795)' + .'|6a89/([^/]++)/([^/]++)/([^/]++)/f76a89(*:31691)' + .'|9921/([^/]++)/([^/]++)/([^/]++)/f79921(*:31739)' + .'|e905/([^/]++)/([^/]++)/([^/]++)/f7e905(*:31787)' .')' .'|2(?' - .'|9c21/([^/]++)/([^/]++)/([^/]++)/f29c21(*:31848)' - .'|201f/([^/]++)/([^/]++)/([^/]++)/f2201f(*:31896)' + .'|9c21/([^/]++)/([^/]++)/([^/]++)/f29c21(*:31840)' + .'|201f/([^/]++)/([^/]++)/([^/]++)/f2201f(*:31888)' .')' .'|a(?' - .'|e0b2/([^/]++)/([^/]++)/([^/]++)/fae0b2(*:31949)' - .'|14d4/([^/]++)/([^/]++)/([^/]++)/fa14d4(*:31997)' - .'|3a3c/([^/]++)/([^/]++)/([^/]++)/fa3a3c(*:32045)' - .'|83a1/([^/]++)/([^/]++)/([^/]++)/fa83a1(*:32093)' + .'|e0b2/([^/]++)/([^/]++)/([^/]++)/fae0b2(*:31941)' + .'|14d4/([^/]++)/([^/]++)/([^/]++)/fa14d4(*:31989)' + .'|3a3c/([^/]++)/([^/]++)/([^/]++)/fa3a3c(*:32037)' + .'|83a1/([^/]++)/([^/]++)/([^/]++)/fa83a1(*:32085)' .')' .'|c(?' - .'|cb3c/([^/]++)/([^/]++)/([^/]++)/fccb3c(*:32146)' - .'|8001/([^/]++)/([^/]++)/([^/]++)/fc8001(*:32194)' - .'|3cf4/([^/]++)/([^/]++)/([^/]++)/fc3cf4(*:32242)' - .'|4930/([^/]++)/([^/]++)/([^/]++)/fc4930(*:32290)' - .')' - .'|64eac/([^/]++)/([^/]++)/([^/]++)/f64eac(*:32340)' - .'|b8970/([^/]++)/([^/]++)/([^/]++)/fb8970(*:32389)' - .'|1c159/([^/]++)/([^/]++)/([^/]++)/f1c159(*:32438)' + .'|cb3c/([^/]++)/([^/]++)/([^/]++)/fccb3c(*:32138)' + .'|8001/([^/]++)/([^/]++)/([^/]++)/fc8001(*:32186)' + .'|3cf4/([^/]++)/([^/]++)/([^/]++)/fc3cf4(*:32234)' + .'|4930/([^/]++)/([^/]++)/([^/]++)/fc4930(*:32282)' + .')' + .'|64eac/([^/]++)/([^/]++)/([^/]++)/f64eac(*:32332)' + .'|b8970/([^/]++)/([^/]++)/([^/]++)/fb8970(*:32381)' + .'|1c159/([^/]++)/([^/]++)/([^/]++)/f1c159(*:32430)' .'|9(?' - .'|028f/([^/]++)/([^/]++)/([^/]++)/f9028f(*:32490)' - .'|a40a/([^/]++)/([^/]++)/([^/]++)/f9a40a(*:32538)' + .'|028f/([^/]++)/([^/]++)/([^/]++)/f9028f(*:32482)' + .'|a40a/([^/]++)/([^/]++)/([^/]++)/f9a40a(*:32530)' .')' .'|e(?' - .'|8c15/([^/]++)/([^/]++)/([^/]++)/fe8c15(*:32591)' - .'|c8d4/([^/]++)/([^/]++)/([^/]++)/fec8d4(*:32639)' - .'|7ee8/([^/]++)/([^/]++)/([^/]++)/fe7ee8(*:32687)' + .'|8c15/([^/]++)/([^/]++)/([^/]++)/fe8c15(*:32583)' + .'|c8d4/([^/]++)/([^/]++)/([^/]++)/fec8d4(*:32631)' + .'|7ee8/([^/]++)/([^/]++)/([^/]++)/fe7ee8(*:32679)' .')' .')' .'|/3(?' .'|8(?' .'|9(?' - .'|bc7/([^/]++)/([^/]++)/([^/]++)/389bc7(*:32749)' - .'|13e/([^/]++)/([^/]++)/([^/]++)/38913e(*:32796)' + .'|bc7/([^/]++)/([^/]++)/([^/]++)/389bc7(*:32741)' + .'|13e/([^/]++)/([^/]++)/([^/]++)/38913e(*:32788)' .')' - .'|71bd/([^/]++)/([^/]++)/([^/]++)/3871bd(*:32845)' + .'|71bd/([^/]++)/([^/]++)/([^/]++)/3871bd(*:32837)' .')' .'|d(?' - .'|c487/([^/]++)/([^/]++)/([^/]++)/3dc487(*:32898)' - .'|2d8c/([^/]++)/([^/]++)/([^/]++)/3d2d8c(*:32946)' - .'|8e28/([^/]++)/([^/]++)/([^/]++)/3d8e28(*:32994)' - .'|f1d4/([^/]++)/([^/]++)/([^/]++)/3df1d4(*:33042)' + .'|c487/([^/]++)/([^/]++)/([^/]++)/3dc487(*:32890)' + .'|2d8c/([^/]++)/([^/]++)/([^/]++)/3d2d8c(*:32938)' + .'|8e28/([^/]++)/([^/]++)/([^/]++)/3d8e28(*:32986)' + .'|f1d4/([^/]++)/([^/]++)/([^/]++)/3df1d4(*:33034)' .')' - .'|7f0e8/([^/]++)/([^/]++)/([^/]++)/37f0e8(*:33092)' + .'|7f0e8/([^/]++)/([^/]++)/([^/]++)/37f0e8(*:33084)' .'|3(?' - .'|e807/([^/]++)/([^/]++)/([^/]++)/33e807(*:33144)' - .'|28bd/([^/]++)/([^/]++)/([^/]++)/3328bd(*:33192)' + .'|e807/([^/]++)/([^/]++)/([^/]++)/33e807(*:33136)' + .'|28bd/([^/]++)/([^/]++)/([^/]++)/3328bd(*:33184)' .')' .'|a(?' .'|0(?' - .'|772/([^/]++)/([^/]++)/([^/]++)/3a0772(*:33248)' - .'|66b/([^/]++)/([^/]++)/([^/]++)/3a066b(*:33295)' + .'|772/([^/]++)/([^/]++)/([^/]++)/3a0772(*:33240)' + .'|66b/([^/]++)/([^/]++)/([^/]++)/3a066b(*:33287)' .')' - .'|835d/([^/]++)/([^/]++)/([^/]++)/3a835d(*:33344)' + .'|835d/([^/]++)/([^/]++)/([^/]++)/3a835d(*:33336)' .')' .'|0(?' - .'|bb38/([^/]++)/([^/]++)/([^/]++)/30bb38(*:33397)' - .'|3ed4/([^/]++)/([^/]++)/([^/]++)/303ed4(*:33445)' - .'|ef30/([^/]++)/([^/]++)/([^/]++)/30ef30(*:33493)' - .'|1ad0/([^/]++)/([^/]++)/([^/]++)/301ad0(*:33541)' + .'|bb38/([^/]++)/([^/]++)/([^/]++)/30bb38(*:33389)' + .'|3ed4/([^/]++)/([^/]++)/([^/]++)/303ed4(*:33437)' + .'|ef30/([^/]++)/([^/]++)/([^/]++)/30ef30(*:33485)' + .'|1ad0/([^/]++)/([^/]++)/([^/]++)/301ad0(*:33533)' .')' .'|4(?' - .'|9389/([^/]++)/([^/]++)/([^/]++)/349389(*:33594)' - .'|35c3/([^/]++)/([^/]++)/([^/]++)/3435c3(*:33642)' + .'|9389/([^/]++)/([^/]++)/([^/]++)/349389(*:33586)' + .'|35c3/([^/]++)/([^/]++)/([^/]++)/3435c3(*:33634)' .')' .'|62(?' - .'|1f1/([^/]++)/([^/]++)/([^/]++)/3621f1(*:33695)' - .'|e80/([^/]++)/([^/]++)/([^/]++)/362e80(*:33742)' + .'|1f1/([^/]++)/([^/]++)/([^/]++)/3621f1(*:33687)' + .'|e80/([^/]++)/([^/]++)/([^/]++)/362e80(*:33734)' .')' .'|5(?' - .'|cf86/([^/]++)/([^/]++)/([^/]++)/35cf86(*:33795)' - .'|2407/([^/]++)/([^/]++)/([^/]++)/352407(*:33843)' + .'|cf86/([^/]++)/([^/]++)/([^/]++)/35cf86(*:33787)' + .'|2407/([^/]++)/([^/]++)/([^/]++)/352407(*:33835)' .')' - .'|2b30a/([^/]++)/([^/]++)/([^/]++)/32b30a(*:33893)' - .'|1839b/([^/]++)/([^/]++)/([^/]++)/31839b(*:33942)' + .'|2b30a/([^/]++)/([^/]++)/([^/]++)/32b30a(*:33885)' + .'|1839b/([^/]++)/([^/]++)/([^/]++)/31839b(*:33934)' .'|b(?' - .'|5dca/([^/]++)/([^/]++)/([^/]++)/3b5dca(*:33994)' - .'|3dba/([^/]++)/([^/]++)/([^/]++)/3b3dba(*:34042)' + .'|5dca/([^/]++)/([^/]++)/([^/]++)/3b5dca(*:33986)' + .'|3dba/([^/]++)/([^/]++)/([^/]++)/3b3dba(*:34034)' .')' - .'|e89eb/([^/]++)/([^/]++)/([^/]++)/3e89eb(*:34092)' - .'|cef96/([^/]++)/([^/]++)/([^/]++)/3cef96(*:34141)' + .'|e89eb/([^/]++)/([^/]++)/([^/]++)/3e89eb(*:34084)' + .'|cef96/([^/]++)/([^/]++)/([^/]++)/3cef96(*:34133)' .')' .'|/0(?' .'|8(?' - .'|7408/([^/]++)/([^/]++)/([^/]++)/087408(*:34199)' - .'|b255/([^/]++)/([^/]++)/([^/]++)/08b255(*:34247)' - .'|c543/([^/]++)/([^/]++)/([^/]++)/08c543(*:34295)' - .'|d986/([^/]++)/([^/]++)/([^/]++)/08d986(*:34343)' - .'|419b/([^/]++)/([^/]++)/([^/]++)/08419b(*:34391)' + .'|7408/([^/]++)/([^/]++)/([^/]++)/087408(*:34191)' + .'|b255/([^/]++)/([^/]++)/([^/]++)/08b255(*:34239)' + .'|c543/([^/]++)/([^/]++)/([^/]++)/08c543(*:34287)' + .'|d986/([^/]++)/([^/]++)/([^/]++)/08d986(*:34335)' + .'|419b/([^/]++)/([^/]++)/([^/]++)/08419b(*:34383)' .')' .'|7(?' - .'|563a/([^/]++)/([^/]++)/([^/]++)/07563a(*:34444)' - .'|6a0c/([^/]++)/([^/]++)/([^/]++)/076a0c(*:34492)' - .'|a96b/([^/]++)/([^/]++)/([^/]++)/07a96b(*:34540)' - .'|c580/([^/]++)/([^/]++)/([^/]++)/07c580(*:34588)' - .'|8719/([^/]++)/([^/]++)/([^/]++)/078719(*:34636)' + .'|563a/([^/]++)/([^/]++)/([^/]++)/07563a(*:34436)' + .'|6a0c/([^/]++)/([^/]++)/([^/]++)/076a0c(*:34484)' + .'|a96b/([^/]++)/([^/]++)/([^/]++)/07a96b(*:34532)' + .'|c580/([^/]++)/([^/]++)/([^/]++)/07c580(*:34580)' + .'|8719/([^/]++)/([^/]++)/([^/]++)/078719(*:34628)' .')' .'|f(?' - .'|cbc6/([^/]++)/([^/]++)/([^/]++)/0fcbc6(*:34689)' - .'|9661/([^/]++)/([^/]++)/([^/]++)/0f9661(*:34737)' + .'|cbc6/([^/]++)/([^/]++)/([^/]++)/0fcbc6(*:34681)' + .'|9661/([^/]++)/([^/]++)/([^/]++)/0f9661(*:34729)' .'|f(?' - .'|39b/([^/]++)/([^/]++)/([^/]++)/0ff39b(*:34788)' - .'|803/([^/]++)/([^/]++)/([^/]++)/0ff803(*:34835)' + .'|39b/([^/]++)/([^/]++)/([^/]++)/0ff39b(*:34780)' + .'|803/([^/]++)/([^/]++)/([^/]++)/0ff803(*:34827)' .')' - .'|840b/([^/]++)/([^/]++)/([^/]++)/0f840b(*:34884)' + .'|840b/([^/]++)/([^/]++)/([^/]++)/0f840b(*:34876)' .')' .'|1(?' - .'|f78b/([^/]++)/([^/]++)/([^/]++)/01f78b(*:34937)' - .'|3a00/([^/]++)/([^/]++)/([^/]++)/013a00(*:34985)' - .'|8825/([^/]++)/([^/]++)/([^/]++)/018825(*:35033)' + .'|f78b/([^/]++)/([^/]++)/([^/]++)/01f78b(*:34929)' + .'|3a00/([^/]++)/([^/]++)/([^/]++)/013a00(*:34977)' + .'|8825/([^/]++)/([^/]++)/([^/]++)/018825(*:35025)' .')' .'|6(?' .'|9(?' - .'|d3b/([^/]++)/([^/]++)/([^/]++)/069d3b(*:35089)' - .'|97f/([^/]++)/([^/]++)/([^/]++)/06997f(*:35136)' + .'|d3b/([^/]++)/([^/]++)/([^/]++)/069d3b(*:35081)' + .'|97f/([^/]++)/([^/]++)/([^/]++)/06997f(*:35128)' .')' - .'|1412/([^/]++)/([^/]++)/([^/]++)/061412(*:35185)' + .'|1412/([^/]++)/([^/]++)/([^/]++)/061412(*:35177)' .')' .'|4(?' - .'|ecb1/([^/]++)/([^/]++)/([^/]++)/04ecb1(*:35238)' - .'|3c3d/([^/]++)/([^/]++)/([^/]++)/043c3d(*:35286)' + .'|ecb1/([^/]++)/([^/]++)/([^/]++)/04ecb1(*:35230)' + .'|3c3d/([^/]++)/([^/]++)/([^/]++)/043c3d(*:35278)' .')' - .'|0ac8e/([^/]++)/([^/]++)/([^/]++)/00ac8e(*:35336)' + .'|0ac8e/([^/]++)/([^/]++)/([^/]++)/00ac8e(*:35328)' .'|5(?' - .'|1e4e/([^/]++)/([^/]++)/([^/]++)/051e4e(*:35388)' - .'|37fb/([^/]++)/([^/]++)/([^/]++)/0537fb(*:35436)' + .'|1e4e/([^/]++)/([^/]++)/([^/]++)/051e4e(*:35380)' + .'|37fb/([^/]++)/([^/]++)/([^/]++)/0537fb(*:35428)' .')' .'|d(?' - .'|7de1/([^/]++)/([^/]++)/([^/]++)/0d7de1(*:35489)' - .'|3180/([^/]++)/([^/]++)/([^/]++)/0d3180(*:35537)' - .'|0871/([^/]++)/([^/]++)/([^/]++)/0d0871(*:35585)' + .'|7de1/([^/]++)/([^/]++)/([^/]++)/0d7de1(*:35481)' + .'|3180/([^/]++)/([^/]++)/([^/]++)/0d3180(*:35529)' + .'|0871/([^/]++)/([^/]++)/([^/]++)/0d0871(*:35577)' .')' - .'|cb929/([^/]++)/([^/]++)/([^/]++)/0cb929(*:35635)' + .'|cb929/([^/]++)/([^/]++)/([^/]++)/0cb929(*:35627)' .'|2(?' - .'|a32a/([^/]++)/([^/]++)/([^/]++)/02a32a(*:35687)' - .'|4d7f/([^/]++)/([^/]++)/([^/]++)/024d7f(*:35735)' + .'|a32a/([^/]++)/([^/]++)/([^/]++)/02a32a(*:35679)' + .'|4d7f/([^/]++)/([^/]++)/([^/]++)/024d7f(*:35727)' .')' - .'|efe32/([^/]++)/([^/]++)/([^/]++)/0efe32(*:35785)' - .'|a113e/([^/]++)/([^/]++)/([^/]++)/0a113e(*:35834)' - .'|b8aff/([^/]++)/([^/]++)/([^/]++)/0b8aff(*:35883)' + .'|efe32/([^/]++)/([^/]++)/([^/]++)/0efe32(*:35777)' + .'|a113e/([^/]++)/([^/]++)/([^/]++)/0a113e(*:35826)' + .'|b8aff/([^/]++)/([^/]++)/([^/]++)/0b8aff(*:35875)' .')' .'|/a(?' .'|7(?' - .'|6088/([^/]++)/([^/]++)/([^/]++)/a76088(*:35941)' - .'|aeed/([^/]++)/([^/]++)/([^/]++)/a7aeed(*:35989)' - .'|33fa/([^/]++)/([^/]++)/([^/]++)/a733fa(*:36037)' + .'|6088/([^/]++)/([^/]++)/([^/]++)/a76088(*:35933)' + .'|aeed/([^/]++)/([^/]++)/([^/]++)/a7aeed(*:35981)' + .'|33fa/([^/]++)/([^/]++)/([^/]++)/a733fa(*:36029)' .')' .'|9a(?' - .'|665/([^/]++)/([^/]++)/([^/]++)/a9a665(*:36090)' - .'|1d5/([^/]++)/([^/]++)/([^/]++)/a9a1d5(*:36137)' + .'|665/([^/]++)/([^/]++)/([^/]++)/a9a665(*:36082)' + .'|1d5/([^/]++)/([^/]++)/([^/]++)/a9a1d5(*:36129)' .')' .'|8(?' - .'|6c45/([^/]++)/([^/]++)/([^/]++)/a86c45(*:36190)' - .'|849b/([^/]++)/([^/]++)/([^/]++)/a8849b(*:36238)' + .'|6c45/([^/]++)/([^/]++)/([^/]++)/a86c45(*:36182)' + .'|849b/([^/]++)/([^/]++)/([^/]++)/a8849b(*:36230)' .'|e(?' - .'|864/([^/]++)/([^/]++)/([^/]++)/a8e864(*:36289)' - .'|cba/([^/]++)/([^/]++)/([^/]++)/a8ecba(*:36336)' + .'|864/([^/]++)/([^/]++)/([^/]++)/a8e864(*:36281)' + .'|cba/([^/]++)/([^/]++)/([^/]++)/a8ecba(*:36328)' .')' .')' .'|c(?' - .'|c3e0/([^/]++)/([^/]++)/([^/]++)/acc3e0(*:36390)' - .'|f4b8/([^/]++)/([^/]++)/([^/]++)/acf4b8(*:36438)' + .'|c3e0/([^/]++)/([^/]++)/([^/]++)/acc3e0(*:36382)' + .'|f4b8/([^/]++)/([^/]++)/([^/]++)/acf4b8(*:36430)' .')' .'|b(?' - .'|d815/([^/]++)/([^/]++)/([^/]++)/abd815(*:36491)' - .'|233b/([^/]++)/([^/]++)/([^/]++)/ab233b(*:36539)' - .'|a3b6/([^/]++)/([^/]++)/([^/]++)/aba3b6(*:36587)' - .'|88b1/([^/]++)/([^/]++)/([^/]++)/ab88b1(*:36635)' + .'|d815/([^/]++)/([^/]++)/([^/]++)/abd815(*:36483)' + .'|233b/([^/]++)/([^/]++)/([^/]++)/ab233b(*:36531)' + .'|a3b6/([^/]++)/([^/]++)/([^/]++)/aba3b6(*:36579)' + .'|88b1/([^/]++)/([^/]++)/([^/]++)/ab88b1(*:36627)' .')' .'|5(?' - .'|3240/([^/]++)/([^/]++)/([^/]++)/a53240(*:36688)' - .'|cdd4/([^/]++)/([^/]++)/([^/]++)/a5cdd4(*:36736)' + .'|3240/([^/]++)/([^/]++)/([^/]++)/a53240(*:36680)' + .'|cdd4/([^/]++)/([^/]++)/([^/]++)/a5cdd4(*:36728)' .')' .'|f(?' .'|d(?' - .'|483/([^/]++)/([^/]++)/([^/]++)/afd483(*:36792)' - .'|a33/([^/]++)/([^/]++)/([^/]++)/afda33(*:36839)' + .'|483/([^/]++)/([^/]++)/([^/]++)/afd483(*:36784)' + .'|a33/([^/]++)/([^/]++)/([^/]++)/afda33(*:36831)' .')' - .'|f162/([^/]++)/([^/]++)/([^/]++)/aff162(*:36888)' + .'|f162/([^/]++)/([^/]++)/([^/]++)/aff162(*:36880)' .')' .'|e(?' - .'|0eb3/([^/]++)/([^/]++)/([^/]++)/ae0eb3(*:36941)' - .'|b313/([^/]++)/([^/]++)/([^/]++)/aeb313(*:36989)' + .'|0eb3/([^/]++)/([^/]++)/([^/]++)/ae0eb3(*:36933)' + .'|b313/([^/]++)/([^/]++)/([^/]++)/aeb313(*:36981)' .')' .'|1(?' - .'|d33d/([^/]++)/([^/]++)/([^/]++)/a1d33d(*:37042)' - .'|140a/([^/]++)/([^/]++)/([^/]++)/a1140a(*:37090)' + .'|d33d/([^/]++)/([^/]++)/([^/]++)/a1d33d(*:37034)' + .'|140a/([^/]++)/([^/]++)/([^/]++)/a1140a(*:37082)' .')' - .'|ddfa9/([^/]++)/([^/]++)/([^/]++)/addfa9(*:37140)' + .'|ddfa9/([^/]++)/([^/]++)/([^/]++)/addfa9(*:37132)' .'|6(?' - .'|7f09/([^/]++)/([^/]++)/([^/]++)/a67f09(*:37192)' - .'|4c94/([^/]++)/([^/]++)/([^/]++)/a64c94(*:37240)' + .'|7f09/([^/]++)/([^/]++)/([^/]++)/a67f09(*:37184)' + .'|4c94/([^/]++)/([^/]++)/([^/]++)/a64c94(*:37232)' .')' - .'|a169b/([^/]++)/([^/]++)/([^/]++)/aa169b(*:37290)' - .'|4300b/([^/]++)/([^/]++)/([^/]++)/a4300b(*:37339)' - .'|3d68b/([^/]++)/([^/]++)/([^/]++)/a3d68b(*:37388)' + .'|a169b/([^/]++)/([^/]++)/([^/]++)/aa169b(*:37282)' + .'|4300b/([^/]++)/([^/]++)/([^/]++)/a4300b(*:37331)' + .'|3d68b/([^/]++)/([^/]++)/([^/]++)/a3d68b(*:37380)' .')' .'|/1(?' .'|0(?' .'|a(?' - .'|7cd/([^/]++)/([^/]++)/([^/]++)/10a7cd(*:37449)' - .'|5ab/([^/]++)/([^/]++)/([^/]++)/10a5ab(*:37496)' + .'|7cd/([^/]++)/([^/]++)/([^/]++)/10a7cd(*:37441)' + .'|5ab/([^/]++)/([^/]++)/([^/]++)/10a5ab(*:37488)' .')' - .'|9a0c/([^/]++)/([^/]++)/([^/]++)/109a0c(*:37545)' + .'|9a0c/([^/]++)/([^/]++)/([^/]++)/109a0c(*:37537)' .')' - .'|3f320/([^/]++)/([^/]++)/([^/]++)/13f320(*:37595)' + .'|3f320/([^/]++)/([^/]++)/([^/]++)/13f320(*:37587)' .'|6(?' - .'|c222/([^/]++)/([^/]++)/([^/]++)/16c222(*:37647)' - .'|8908/([^/]++)/([^/]++)/([^/]++)/168908(*:37695)' + .'|c222/([^/]++)/([^/]++)/([^/]++)/16c222(*:37639)' + .'|8908/([^/]++)/([^/]++)/([^/]++)/168908(*:37687)' .')' .'|5(?' - .'|de21/([^/]++)/([^/]++)/([^/]++)/15de21(*:37748)' - .'|95af/([^/]++)/([^/]++)/([^/]++)/1595af(*:37796)' + .'|de21/([^/]++)/([^/]++)/([^/]++)/15de21(*:37740)' + .'|95af/([^/]++)/([^/]++)/([^/]++)/1595af(*:37788)' .')' .'|1(?' - .'|b921/([^/]++)/([^/]++)/([^/]++)/11b921(*:37849)' - .'|4193/([^/]++)/([^/]++)/([^/]++)/114193(*:37897)' + .'|b921/([^/]++)/([^/]++)/([^/]++)/11b921(*:37841)' + .'|4193/([^/]++)/([^/]++)/([^/]++)/114193(*:37889)' .')' - .'|bb91f/([^/]++)/([^/]++)/([^/]++)/1bb91f(*:37947)' + .'|bb91f/([^/]++)/([^/]++)/([^/]++)/1bb91f(*:37939)' .'|7(?' - .'|28ef/([^/]++)/([^/]++)/([^/]++)/1728ef(*:37999)' - .'|c276/([^/]++)/([^/]++)/([^/]++)/17c276(*:38047)' - .'|0c94/([^/]++)/([^/]++)/([^/]++)/170c94(*:38095)' + .'|28ef/([^/]++)/([^/]++)/([^/]++)/1728ef(*:37991)' + .'|c276/([^/]++)/([^/]++)/([^/]++)/17c276(*:38039)' + .'|0c94/([^/]++)/([^/]++)/([^/]++)/170c94(*:38087)' .')' .'|85(?' - .'|c29/([^/]++)/([^/]++)/([^/]++)/185c29(*:38148)' - .'|e65/([^/]++)/([^/]++)/([^/]++)/185e65(*:38195)' + .'|c29/([^/]++)/([^/]++)/([^/]++)/185c29(*:38140)' + .'|e65/([^/]++)/([^/]++)/([^/]++)/185e65(*:38187)' .')' .'|9(?' - .'|2fc0/([^/]++)/([^/]++)/([^/]++)/192fc0(*:38248)' + .'|2fc0/([^/]++)/([^/]++)/([^/]++)/192fc0(*:38240)' .'|b(?' - .'|c91/([^/]++)/([^/]++)/([^/]++)/19bc91(*:38299)' - .'|650/([^/]++)/([^/]++)/([^/]++)/19b650(*:38346)' + .'|c91/([^/]++)/([^/]++)/([^/]++)/19bc91(*:38291)' + .'|650/([^/]++)/([^/]++)/([^/]++)/19b650(*:38338)' .')' - .'|05ae/([^/]++)/([^/]++)/([^/]++)/1905ae(*:38395)' + .'|05ae/([^/]++)/([^/]++)/([^/]++)/1905ae(*:38387)' .')' .'|e(?' - .'|cfb4/([^/]++)/([^/]++)/([^/]++)/1ecfb4(*:38448)' - .'|fa39/([^/]++)/([^/]++)/([^/]++)/1efa39(*:38496)' - .'|056d/([^/]++)/([^/]++)/([^/]++)/1e056d(*:38544)' + .'|cfb4/([^/]++)/([^/]++)/([^/]++)/1ecfb4(*:38440)' + .'|fa39/([^/]++)/([^/]++)/([^/]++)/1efa39(*:38488)' + .'|056d/([^/]++)/([^/]++)/([^/]++)/1e056d(*:38536)' .')' - .'|aa48f/([^/]++)/([^/]++)/([^/]++)/1aa48f(*:38594)' + .'|aa48f/([^/]++)/([^/]++)/([^/]++)/1aa48f(*:38586)' .'|f(?' - .'|c214/([^/]++)/([^/]++)/([^/]++)/1fc214(*:38646)' - .'|5089/([^/]++)/([^/]++)/([^/]++)/1f5089(*:38694)' - .'|4477/([^/]++)/([^/]++)/([^/]++)/1f4477(*:38742)' + .'|c214/([^/]++)/([^/]++)/([^/]++)/1fc214(*:38638)' + .'|5089/([^/]++)/([^/]++)/([^/]++)/1f5089(*:38686)' + .'|4477/([^/]++)/([^/]++)/([^/]++)/1f4477(*:38734)' .')' .'|c(?' - .'|c363/([^/]++)/([^/]++)/([^/]++)/1cc363(*:38795)' - .'|1d4d/([^/]++)/([^/]++)/([^/]++)/1c1d4d(*:38843)' - .'|e927/([^/]++)/([^/]++)/([^/]++)/1ce927(*:38891)' + .'|c363/([^/]++)/([^/]++)/([^/]++)/1cc363(*:38787)' + .'|1d4d/([^/]++)/([^/]++)/([^/]++)/1c1d4d(*:38835)' + .'|e927/([^/]++)/([^/]++)/([^/]++)/1ce927(*:38883)' .')' .')' .'|/6(?' .'|3(?' - .'|538f/([^/]++)/([^/]++)/([^/]++)/63538f(*:38950)' - .'|2cee/([^/]++)/([^/]++)/([^/]++)/632cee(*:38998)' - .'|95eb/([^/]++)/([^/]++)/([^/]++)/6395eb(*:39046)' + .'|538f/([^/]++)/([^/]++)/([^/]++)/63538f(*:38942)' + .'|2cee/([^/]++)/([^/]++)/([^/]++)/632cee(*:38990)' + .'|95eb/([^/]++)/([^/]++)/([^/]++)/6395eb(*:39038)' .')' .'|9(?' - .'|421f/([^/]++)/([^/]++)/([^/]++)/69421f(*:39099)' - .'|2f93/([^/]++)/([^/]++)/([^/]++)/692f93(*:39147)' + .'|421f/([^/]++)/([^/]++)/([^/]++)/69421f(*:39091)' + .'|2f93/([^/]++)/([^/]++)/([^/]++)/692f93(*:39139)' .')' - .'|5658f/([^/]++)/([^/]++)/([^/]++)/65658f(*:39197)' + .'|5658f/([^/]++)/([^/]++)/([^/]++)/65658f(*:39189)' .'|4(?' - .'|7bba/([^/]++)/([^/]++)/([^/]++)/647bba(*:39249)' - .'|223c/([^/]++)/([^/]++)/([^/]++)/64223c(*:39297)' + .'|7bba/([^/]++)/([^/]++)/([^/]++)/647bba(*:39241)' + .'|223c/([^/]++)/([^/]++)/([^/]++)/64223c(*:39289)' .')' .'|e(?' - .'|2713/([^/]++)/([^/]++)/([^/]++)/6e2713(*:39350)' - .'|0721/([^/]++)/([^/]++)/([^/]++)/6e0721(*:39398)' - .'|7b33/([^/]++)/([^/]++)/([^/]++)/6e7b33(*:39446)' + .'|2713/([^/]++)/([^/]++)/([^/]++)/6e2713(*:39342)' + .'|0721/([^/]++)/([^/]++)/([^/]++)/6e0721(*:39390)' + .'|7b33/([^/]++)/([^/]++)/([^/]++)/6e7b33(*:39438)' .')' .'|0(?' - .'|5ff7/([^/]++)/([^/]++)/([^/]++)/605ff7(*:39499)' - .'|8159/([^/]++)/([^/]++)/([^/]++)/608159(*:39547)' + .'|5ff7/([^/]++)/([^/]++)/([^/]++)/605ff7(*:39491)' + .'|8159/([^/]++)/([^/]++)/([^/]++)/608159(*:39539)' .')' .'|a(?' - .'|ca97/([^/]++)/([^/]++)/([^/]++)/6aca97(*:39600)' - .'|10bb/([^/]++)/([^/]++)/([^/]++)/6a10bb(*:39648)' - .'|ab12/([^/]++)/([^/]++)/([^/]++)/6aab12(*:39696)' + .'|ca97/([^/]++)/([^/]++)/([^/]++)/6aca97(*:39592)' + .'|10bb/([^/]++)/([^/]++)/([^/]++)/6a10bb(*:39640)' + .'|ab12/([^/]++)/([^/]++)/([^/]++)/6aab12(*:39688)' .')' .'|7(?' - .'|66aa/([^/]++)/([^/]++)/([^/]++)/6766aa(*:39749)' - .'|e103/([^/]++)/([^/]++)/([^/]++)/67e103(*:39797)' + .'|66aa/([^/]++)/([^/]++)/([^/]++)/6766aa(*:39741)' + .'|e103/([^/]++)/([^/]++)/([^/]++)/67e103(*:39789)' .'|d(?' - .'|96d/([^/]++)/([^/]++)/([^/]++)/67d96d(*:39848)' - .'|16d/([^/]++)/([^/]++)/([^/]++)/67d16d(*:39895)' + .'|96d/([^/]++)/([^/]++)/([^/]++)/67d96d(*:39840)' + .'|16d/([^/]++)/([^/]++)/([^/]++)/67d16d(*:39887)' .')' - .'|0e8a/([^/]++)/([^/]++)/([^/]++)/670e8a(*:39944)' - .'|7e09/([^/]++)/([^/]++)/([^/]++)/677e09(*:39992)' + .'|0e8a/([^/]++)/([^/]++)/([^/]++)/670e8a(*:39936)' + .'|7e09/([^/]++)/([^/]++)/([^/]++)/677e09(*:39984)' .')' .'|8(?' - .'|264b/([^/]++)/([^/]++)/([^/]++)/68264b(*:40045)' - .'|053a/([^/]++)/([^/]++)/([^/]++)/68053a(*:40093)' + .'|264b/([^/]++)/([^/]++)/([^/]++)/68264b(*:40037)' + .'|053a/([^/]++)/([^/]++)/([^/]++)/68053a(*:40085)' .')' .'|c(?' - .'|2979/([^/]++)/([^/]++)/([^/]++)/6c2979(*:40146)' - .'|d67d/([^/]++)/([^/]++)/([^/]++)/6cd67d(*:40194)' - .'|3cf7/([^/]++)/([^/]++)/([^/]++)/6c3cf7(*:40242)' - .'|fe0e/([^/]++)/([^/]++)/([^/]++)/6cfe0e(*:40290)' - .')' - .'|bc24f/([^/]++)/([^/]++)/([^/]++)/6bc24f(*:40340)' - .'|f2268/([^/]++)/([^/]++)/([^/]++)/6f2268(*:40389)' - .'|1b4a6/([^/]++)/([^/]++)/([^/]++)/61b4a6(*:40438)' - .'|21461/([^/]++)/([^/]++)/([^/]++)/621461(*:40487)' - .'|d0f84/([^/]++)/([^/]++)/([^/]++)/6d0f84(*:40536)' - .'|60229/([^/]++)/([^/]++)/([^/]++)/660229(*:40585)' + .'|2979/([^/]++)/([^/]++)/([^/]++)/6c2979(*:40138)' + .'|d67d/([^/]++)/([^/]++)/([^/]++)/6cd67d(*:40186)' + .'|3cf7/([^/]++)/([^/]++)/([^/]++)/6c3cf7(*:40234)' + .'|fe0e/([^/]++)/([^/]++)/([^/]++)/6cfe0e(*:40282)' + .')' + .'|bc24f/([^/]++)/([^/]++)/([^/]++)/6bc24f(*:40332)' + .'|f2268/([^/]++)/([^/]++)/([^/]++)/6f2268(*:40381)' + .'|1b4a6/([^/]++)/([^/]++)/([^/]++)/61b4a6(*:40430)' + .'|21461/([^/]++)/([^/]++)/([^/]++)/621461(*:40479)' + .'|d0f84/([^/]++)/([^/]++)/([^/]++)/6d0f84(*:40528)' + .'|60229/([^/]++)/([^/]++)/([^/]++)/660229(*:40577)' .')' .'|/c(?' .'|f(?' - .'|6735/([^/]++)/([^/]++)/([^/]++)/cf6735(*:40643)' - .'|bce4/([^/]++)/([^/]++)/([^/]++)/cfbce4(*:40691)' + .'|6735/([^/]++)/([^/]++)/([^/]++)/cf6735(*:40635)' + .'|bce4/([^/]++)/([^/]++)/([^/]++)/cfbce4(*:40683)' .')' .'|3(?' .'|99(?' - .'|86/([^/]++)/([^/]++)/([^/]++)/c39986(*:40747)' - .'|2e/([^/]++)/([^/]++)/([^/]++)/c3992e(*:40793)' + .'|86/([^/]++)/([^/]++)/([^/]++)/c39986(*:40739)' + .'|2e/([^/]++)/([^/]++)/([^/]++)/c3992e(*:40785)' .')' - .'|61bc/([^/]++)/([^/]++)/([^/]++)/c361bc(*:40842)' - .'|2d9b/([^/]++)/([^/]++)/([^/]++)/c32d9b(*:40890)' + .'|61bc/([^/]++)/([^/]++)/([^/]++)/c361bc(*:40834)' + .'|2d9b/([^/]++)/([^/]++)/([^/]++)/c32d9b(*:40882)' .')' - .'|75b6f/([^/]++)/([^/]++)/([^/]++)/c75b6f(*:40940)' + .'|75b6f/([^/]++)/([^/]++)/([^/]++)/c75b6f(*:40932)' .'|c(?' .'|b(?' - .'|1d4/([^/]++)/([^/]++)/([^/]++)/ccb1d4(*:40995)' - .'|098/([^/]++)/([^/]++)/([^/]++)/ccb098(*:41042)' + .'|1d4/([^/]++)/([^/]++)/([^/]++)/ccb1d4(*:40987)' + .'|098/([^/]++)/([^/]++)/([^/]++)/ccb098(*:41034)' .')' - .'|c0aa/([^/]++)/([^/]++)/([^/]++)/ccc0aa(*:41091)' - .'|1aa4/([^/]++)/([^/]++)/([^/]++)/cc1aa4(*:41139)' + .'|c0aa/([^/]++)/([^/]++)/([^/]++)/ccc0aa(*:41083)' + .'|1aa4/([^/]++)/([^/]++)/([^/]++)/cc1aa4(*:41131)' .')' .'|b(?' - .'|cb58/([^/]++)/([^/]++)/([^/]++)/cbcb58(*:41192)' - .'|b6a3/([^/]++)/([^/]++)/([^/]++)/cbb6a3(*:41240)' + .'|cb58/([^/]++)/([^/]++)/([^/]++)/cbcb58(*:41184)' + .'|b6a3/([^/]++)/([^/]++)/([^/]++)/cbb6a3(*:41232)' .')' - .'|9892a/([^/]++)/([^/]++)/([^/]++)/c9892a(*:41290)' - .'|6e19e/([^/]++)/([^/]++)/([^/]++)/c6e19e(*:41339)' - .'|dc0d6/([^/]++)/([^/]++)/([^/]++)/cdc0d6(*:41388)' - .'|5ab0b/([^/]++)/([^/]++)/([^/]++)/c5ab0b(*:41437)' + .'|9892a/([^/]++)/([^/]++)/([^/]++)/c9892a(*:41282)' + .'|6e19e/([^/]++)/([^/]++)/([^/]++)/c6e19e(*:41331)' + .'|dc0d6/([^/]++)/([^/]++)/([^/]++)/cdc0d6(*:41380)' + .'|5ab0b/([^/]++)/([^/]++)/([^/]++)/c5ab0b(*:41429)' .'|a(?' - .'|9c26/([^/]++)/([^/]++)/([^/]++)/ca9c26(*:41489)' - .'|8155/([^/]++)/([^/]++)/([^/]++)/ca8155(*:41537)' - .'|7591/([^/]++)/([^/]++)/([^/]++)/ca7591(*:41585)' + .'|9c26/([^/]++)/([^/]++)/([^/]++)/ca9c26(*:41481)' + .'|8155/([^/]++)/([^/]++)/([^/]++)/ca8155(*:41529)' + .'|7591/([^/]++)/([^/]++)/([^/]++)/ca7591(*:41577)' .')' .'|0(?' - .'|6d06/([^/]++)/([^/]++)/([^/]++)/c06d06(*:41638)' - .'|f168/([^/]++)/([^/]++)/([^/]++)/c0f168(*:41686)' + .'|6d06/([^/]++)/([^/]++)/([^/]++)/c06d06(*:41630)' + .'|f168/([^/]++)/([^/]++)/([^/]++)/c0f168(*:41678)' .')' .'|8(?' - .'|ed21/([^/]++)/([^/]++)/([^/]++)/c8ed21(*:41739)' - .'|fbbc/([^/]++)/([^/]++)/([^/]++)/c8fbbc(*:41787)' - .'|c41c/([^/]++)/([^/]++)/([^/]++)/c8c41c(*:41835)' + .'|ed21/([^/]++)/([^/]++)/([^/]++)/c8ed21(*:41731)' + .'|fbbc/([^/]++)/([^/]++)/([^/]++)/c8fbbc(*:41779)' + .'|c41c/([^/]++)/([^/]++)/([^/]++)/c8c41c(*:41827)' .')' - .'|15da1/([^/]++)/([^/]++)/([^/]++)/c15da1(*:41885)' + .'|15da1/([^/]++)/([^/]++)/([^/]++)/c15da1(*:41877)' .'|2(?' - .'|626d/([^/]++)/([^/]++)/([^/]++)/c2626d(*:41937)' - .'|aee8/([^/]++)/([^/]++)/([^/]++)/c2aee8(*:41985)' - .'|2abf/([^/]++)/([^/]++)/([^/]++)/c22abf(*:42033)' + .'|626d/([^/]++)/([^/]++)/([^/]++)/c2626d(*:41929)' + .'|aee8/([^/]++)/([^/]++)/([^/]++)/c2aee8(*:41977)' + .'|2abf/([^/]++)/([^/]++)/([^/]++)/c22abf(*:42025)' .')' - .'|e78d1/([^/]++)/([^/]++)/([^/]++)/ce78d1(*:42083)' + .'|e78d1/([^/]++)/([^/]++)/([^/]++)/ce78d1(*:42075)' .'|4(?' - .'|015b/([^/]++)/([^/]++)/([^/]++)/c4015b(*:42135)' - .'|b31c/([^/]++)/([^/]++)/([^/]++)/c4b31c(*:42183)' + .'|015b/([^/]++)/([^/]++)/([^/]++)/c4015b(*:42127)' + .'|b31c/([^/]++)/([^/]++)/([^/]++)/c4b31c(*:42175)' .')' .')' .'|/8(?' .'|5(?' - .'|422a/([^/]++)/([^/]++)/([^/]++)/85422a(*:42242)' - .'|1ddf/([^/]++)/([^/]++)/([^/]++)/851ddf(*:42290)' - .'|fc37/([^/]++)/([^/]++)/([^/]++)/85fc37(*:42338)' + .'|422a/([^/]++)/([^/]++)/([^/]++)/85422a(*:42234)' + .'|1ddf/([^/]++)/([^/]++)/([^/]++)/851ddf(*:42282)' + .'|fc37/([^/]++)/([^/]++)/([^/]++)/85fc37(*:42330)' .')' .'|1(?' - .'|4481/([^/]++)/([^/]++)/([^/]++)/814481(*:42391)' - .'|e74d/([^/]++)/([^/]++)/([^/]++)/81e74d(*:42439)' + .'|4481/([^/]++)/([^/]++)/([^/]++)/814481(*:42383)' + .'|e74d/([^/]++)/([^/]++)/([^/]++)/81e74d(*:42431)' .')' .'|d(?' .'|3(?' - .'|420/([^/]++)/([^/]++)/([^/]++)/8d3420(*:42495)' - .'|17b/([^/]++)/([^/]++)/([^/]++)/8d317b(*:42542)' + .'|420/([^/]++)/([^/]++)/([^/]++)/8d3420(*:42487)' + .'|17b/([^/]++)/([^/]++)/([^/]++)/8d317b(*:42534)' .')' - .'|f707/([^/]++)/([^/]++)/([^/]++)/8df707(*:42591)' - .'|6dc3/([^/]++)/([^/]++)/([^/]++)/8d6dc3(*:42639)' + .'|f707/([^/]++)/([^/]++)/([^/]++)/8df707(*:42583)' + .'|6dc3/([^/]++)/([^/]++)/([^/]++)/8d6dc3(*:42631)' .')' .'|e(?' - .'|efcf/([^/]++)/([^/]++)/([^/]++)/8eefcf(*:42692)' - .'|bda5/([^/]++)/([^/]++)/([^/]++)/8ebda5(*:42740)' - .'|82ab/([^/]++)/([^/]++)/([^/]++)/8e82ab(*:42788)' + .'|efcf/([^/]++)/([^/]++)/([^/]++)/8eefcf(*:42684)' + .'|bda5/([^/]++)/([^/]++)/([^/]++)/8ebda5(*:42732)' + .'|82ab/([^/]++)/([^/]++)/([^/]++)/8e82ab(*:42780)' .')' .'|b(?' - .'|16eb/([^/]++)/([^/]++)/([^/]++)/8b16eb(*:42841)' - .'|6dd7/([^/]++)/([^/]++)/([^/]++)/8b6dd7(*:42889)' - .'|5040/([^/]++)/([^/]++)/([^/]++)/8b5040(*:42937)' + .'|16eb/([^/]++)/([^/]++)/([^/]++)/8b16eb(*:42833)' + .'|6dd7/([^/]++)/([^/]++)/([^/]++)/8b6dd7(*:42881)' + .'|5040/([^/]++)/([^/]++)/([^/]++)/8b5040(*:42929)' .')' .'|c(?' - .'|7bbb/([^/]++)/([^/]++)/([^/]++)/8c7bbb(*:42990)' - .'|6744/([^/]++)/([^/]++)/([^/]++)/8c6744(*:43038)' - .'|235f/([^/]++)/([^/]++)/([^/]++)/8c235f(*:43086)' + .'|7bbb/([^/]++)/([^/]++)/([^/]++)/8c7bbb(*:42982)' + .'|6744/([^/]++)/([^/]++)/([^/]++)/8c6744(*:43030)' + .'|235f/([^/]++)/([^/]++)/([^/]++)/8c235f(*:43078)' .')' .'|8(?' - .'|4d24/([^/]++)/([^/]++)/([^/]++)/884d24(*:43139)' - .'|ae63/([^/]++)/([^/]++)/([^/]++)/88ae63(*:43187)' + .'|4d24/([^/]++)/([^/]++)/([^/]++)/884d24(*:43131)' + .'|ae63/([^/]++)/([^/]++)/([^/]++)/88ae63(*:43179)' .')' .'|7(?' - .'|5715/([^/]++)/([^/]++)/([^/]++)/875715(*:43240)' - .'|2488/([^/]++)/([^/]++)/([^/]++)/872488(*:43288)' + .'|5715/([^/]++)/([^/]++)/([^/]++)/875715(*:43232)' + .'|2488/([^/]++)/([^/]++)/([^/]++)/872488(*:43280)' .')' .'|4(?' - .'|1172/([^/]++)/([^/]++)/([^/]++)/841172(*:43341)' - .'|6c26/([^/]++)/([^/]++)/([^/]++)/846c26(*:43389)' - .'|f7e6/([^/]++)/([^/]++)/([^/]++)/84f7e6(*:43437)' - .'|7cc5/([^/]++)/([^/]++)/([^/]++)/847cc5(*:43485)' + .'|1172/([^/]++)/([^/]++)/([^/]++)/841172(*:43333)' + .'|6c26/([^/]++)/([^/]++)/([^/]++)/846c26(*:43381)' + .'|f7e6/([^/]++)/([^/]++)/([^/]++)/84f7e6(*:43429)' + .'|7cc5/([^/]++)/([^/]++)/([^/]++)/847cc5(*:43477)' .')' .'|f(?' - .'|ecb2/([^/]++)/([^/]++)/([^/]++)/8fecb2(*:43538)' - .'|7d80/([^/]++)/([^/]++)/([^/]++)/8f7d80(*:43586)' - .'|468c/([^/]++)/([^/]++)/([^/]++)/8f468c(*:43634)' + .'|ecb2/([^/]++)/([^/]++)/([^/]++)/8fecb2(*:43530)' + .'|7d80/([^/]++)/([^/]++)/([^/]++)/8f7d80(*:43578)' + .'|468c/([^/]++)/([^/]++)/([^/]++)/8f468c(*:43626)' .')' - .'|a0e11/([^/]++)/([^/]++)/([^/]++)/8a0e11(*:43684)' + .'|a0e11/([^/]++)/([^/]++)/([^/]++)/8a0e11(*:43676)' .'|2(?' - .'|f2b3/([^/]++)/([^/]++)/([^/]++)/82f2b3(*:43736)' - .'|489c/([^/]++)/([^/]++)/([^/]++)/82489c(*:43784)' + .'|f2b3/([^/]++)/([^/]++)/([^/]++)/82f2b3(*:43728)' + .'|489c/([^/]++)/([^/]++)/([^/]++)/82489c(*:43776)' .')' .'|6(?' - .'|b122/([^/]++)/([^/]++)/([^/]++)/86b122(*:43837)' - .'|0320/([^/]++)/([^/]++)/([^/]++)/860320(*:43885)' + .'|b122/([^/]++)/([^/]++)/([^/]++)/86b122(*:43829)' + .'|0320/([^/]++)/([^/]++)/([^/]++)/860320(*:43877)' .')' .'|9(?' - .'|2c91/([^/]++)/([^/]++)/([^/]++)/892c91(*:43938)' - .'|fcd0/([^/]++)/([^/]++)/([^/]++)/89fcd0(*:43986)' + .'|2c91/([^/]++)/([^/]++)/([^/]++)/892c91(*:43930)' + .'|fcd0/([^/]++)/([^/]++)/([^/]++)/89fcd0(*:43978)' .')' - .'|065d0/([^/]++)/([^/]++)/([^/]++)/8065d0(*:44036)' + .'|065d0/([^/]++)/([^/]++)/([^/]++)/8065d0(*:44028)' .')' .'|/d(?' .'|6(?' - .'|4a34/([^/]++)/([^/]++)/([^/]++)/d64a34(*:44094)' - .'|c651/([^/]++)/([^/]++)/([^/]++)/d6c651(*:44142)' + .'|4a34/([^/]++)/([^/]++)/([^/]++)/d64a34(*:44086)' + .'|c651/([^/]++)/([^/]++)/([^/]++)/d6c651(*:44134)' .')' .'|f(?' - .'|877f/([^/]++)/([^/]++)/([^/]++)/df877f(*:44195)' - .'|263d/([^/]++)/([^/]++)/([^/]++)/df263d(*:44243)' - .'|7f28/([^/]++)/([^/]++)/([^/]++)/df7f28(*:44291)' - .'|6d23/([^/]++)/([^/]++)/([^/]++)/df6d23(*:44339)' + .'|877f/([^/]++)/([^/]++)/([^/]++)/df877f(*:44187)' + .'|263d/([^/]++)/([^/]++)/([^/]++)/df263d(*:44235)' + .'|7f28/([^/]++)/([^/]++)/([^/]++)/df7f28(*:44283)' + .'|6d23/([^/]++)/([^/]++)/([^/]++)/df6d23(*:44331)' .')' .'|b(?' - .'|85e2/([^/]++)/([^/]++)/([^/]++)/db85e2(*:44392)' - .'|e272/([^/]++)/([^/]++)/([^/]++)/dbe272(*:44440)' + .'|85e2/([^/]++)/([^/]++)/([^/]++)/db85e2(*:44384)' + .'|e272/([^/]++)/([^/]++)/([^/]++)/dbe272(*:44432)' .')' .'|d(?' .'|45(?' - .'|85/([^/]++)/([^/]++)/([^/]++)/dd4585(*:44496)' - .'|04/([^/]++)/([^/]++)/([^/]++)/dd4504(*:44542)' + .'|85/([^/]++)/([^/]++)/([^/]++)/dd4585(*:44488)' + .'|04/([^/]++)/([^/]++)/([^/]++)/dd4504(*:44534)' .')' - .'|8eb9/([^/]++)/([^/]++)/([^/]++)/dd8eb9(*:44591)' + .'|8eb9/([^/]++)/([^/]++)/([^/]++)/dd8eb9(*:44583)' .')' .'|a(?' - .'|ca41/([^/]++)/([^/]++)/([^/]++)/daca41(*:44644)' - .'|8ce5/([^/]++)/([^/]++)/([^/]++)/da8ce5(*:44692)' - .'|0d11/([^/]++)/([^/]++)/([^/]++)/da0d11(*:44740)' + .'|ca41/([^/]++)/([^/]++)/([^/]++)/daca41(*:44636)' + .'|8ce5/([^/]++)/([^/]++)/([^/]++)/da8ce5(*:44684)' + .'|0d11/([^/]++)/([^/]++)/([^/]++)/da0d11(*:44732)' .')' .'|4(?' - .'|90d7/([^/]++)/([^/]++)/([^/]++)/d490d7(*:44793)' - .'|c2e4/([^/]++)/([^/]++)/([^/]++)/d4c2e4(*:44841)' + .'|90d7/([^/]++)/([^/]++)/([^/]++)/d490d7(*:44785)' + .'|c2e4/([^/]++)/([^/]++)/([^/]++)/d4c2e4(*:44833)' .')' .'|8(?' - .'|6ea6/([^/]++)/([^/]++)/([^/]++)/d86ea6(*:44894)' - .'|40cc/([^/]++)/([^/]++)/([^/]++)/d840cc(*:44942)' + .'|6ea6/([^/]++)/([^/]++)/([^/]++)/d86ea6(*:44886)' + .'|40cc/([^/]++)/([^/]++)/([^/]++)/d840cc(*:44934)' .')' .'|c(?' - .'|82d6/([^/]++)/([^/]++)/([^/]++)/dc82d6(*:44995)' - .'|6a70/([^/]++)/([^/]++)/([^/]++)/dc6a70(*:45043)' - .'|5689/([^/]++)/([^/]++)/([^/]++)/dc5689(*:45091)' + .'|82d6/([^/]++)/([^/]++)/([^/]++)/dc82d6(*:44987)' + .'|6a70/([^/]++)/([^/]++)/([^/]++)/dc6a70(*:45035)' + .'|5689/([^/]++)/([^/]++)/([^/]++)/dc5689(*:45083)' .')' .'|7(?' - .'|a728/([^/]++)/([^/]++)/([^/]++)/d7a728(*:45144)' - .'|0732/([^/]++)/([^/]++)/([^/]++)/d70732(*:45192)' - .'|9aac/([^/]++)/([^/]++)/([^/]++)/d79aac(*:45240)' + .'|a728/([^/]++)/([^/]++)/([^/]++)/d7a728(*:45136)' + .'|0732/([^/]++)/([^/]++)/([^/]++)/d70732(*:45184)' + .'|9aac/([^/]++)/([^/]++)/([^/]++)/d79aac(*:45232)' .')' - .'|14220/([^/]++)/([^/]++)/([^/]++)/d14220(*:45290)' + .'|14220/([^/]++)/([^/]++)/([^/]++)/d14220(*:45282)' .'|5(?' - .'|cfea/([^/]++)/([^/]++)/([^/]++)/d5cfea(*:45342)' - .'|8072/([^/]++)/([^/]++)/([^/]++)/d58072(*:45390)' - .'|54f7/([^/]++)/([^/]++)/([^/]++)/d554f7(*:45438)' - .'|16b1/([^/]++)/([^/]++)/([^/]++)/d516b1(*:45486)' - .'|6b9f/([^/]++)/([^/]++)/([^/]++)/d56b9f(*:45534)' + .'|cfea/([^/]++)/([^/]++)/([^/]++)/d5cfea(*:45334)' + .'|8072/([^/]++)/([^/]++)/([^/]++)/d58072(*:45382)' + .'|54f7/([^/]++)/([^/]++)/([^/]++)/d554f7(*:45430)' + .'|16b1/([^/]++)/([^/]++)/([^/]++)/d516b1(*:45478)' + .'|6b9f/([^/]++)/([^/]++)/([^/]++)/d56b9f(*:45526)' .')' - .'|045c5/([^/]++)/([^/]++)/([^/]++)/d045c5(*:45584)' + .'|045c5/([^/]++)/([^/]++)/([^/]++)/d045c5(*:45576)' .'|2(?' - .'|ed45/([^/]++)/([^/]++)/([^/]++)/d2ed45(*:45636)' - .'|40e3/([^/]++)/([^/]++)/([^/]++)/d240e3(*:45684)' + .'|ed45/([^/]++)/([^/]++)/([^/]++)/d2ed45(*:45628)' + .'|40e3/([^/]++)/([^/]++)/([^/]++)/d240e3(*:45676)' .')' - .'|93ed5/([^/]++)/([^/]++)/([^/]++)/d93ed5(*:45734)' + .'|93ed5/([^/]++)/([^/]++)/([^/]++)/d93ed5(*:45726)' .')' .'|/7(?' .'|b(?' - .'|cdf7/([^/]++)/([^/]++)/([^/]++)/7bcdf7(*:45792)' - .'|13b2/([^/]++)/([^/]++)/([^/]++)/7b13b2(*:45840)' + .'|cdf7/([^/]++)/([^/]++)/([^/]++)/7bcdf7(*:45784)' + .'|13b2/([^/]++)/([^/]++)/([^/]++)/7b13b2(*:45832)' .')' - .'|dcd34/([^/]++)/([^/]++)/([^/]++)/7dcd34(*:45890)' + .'|dcd34/([^/]++)/([^/]++)/([^/]++)/7dcd34(*:45882)' .'|f(?' - .'|24d2/([^/]++)/([^/]++)/([^/]++)/7f24d2(*:45942)' - .'|5d04/([^/]++)/([^/]++)/([^/]++)/7f5d04(*:45990)' - .'|1171/([^/]++)/([^/]++)/([^/]++)/7f1171(*:46038)' - .'|a732/([^/]++)/([^/]++)/([^/]++)/7fa732(*:46086)' + .'|24d2/([^/]++)/([^/]++)/([^/]++)/7f24d2(*:45934)' + .'|5d04/([^/]++)/([^/]++)/([^/]++)/7f5d04(*:45982)' + .'|1171/([^/]++)/([^/]++)/([^/]++)/7f1171(*:46030)' + .'|a732/([^/]++)/([^/]++)/([^/]++)/7fa732(*:46078)' .')' .'|6(?' - .'|6ebc/([^/]++)/([^/]++)/([^/]++)/766ebc(*:46139)' - .'|34ea/([^/]++)/([^/]++)/([^/]++)/7634ea(*:46187)' + .'|6ebc/([^/]++)/([^/]++)/([^/]++)/766ebc(*:46131)' + .'|34ea/([^/]++)/([^/]++)/([^/]++)/7634ea(*:46179)' .')' - .'|750ca/([^/]++)/([^/]++)/([^/]++)/7750ca(*:46237)' + .'|750ca/([^/]++)/([^/]++)/([^/]++)/7750ca(*:46229)' .'|1(?' .'|a(?' - .'|3cb/([^/]++)/([^/]++)/([^/]++)/71a3cb(*:46292)' - .'|d16/([^/]++)/([^/]++)/([^/]++)/71ad16(*:46339)' + .'|3cb/([^/]++)/([^/]++)/([^/]++)/71a3cb(*:46284)' + .'|d16/([^/]++)/([^/]++)/([^/]++)/71ad16(*:46331)' .')' - .'|43d7/([^/]++)/([^/]++)/([^/]++)/7143d7(*:46388)' + .'|43d7/([^/]++)/([^/]++)/([^/]++)/7143d7(*:46380)' .')' - .'|88d98/([^/]++)/([^/]++)/([^/]++)/788d98(*:46438)' + .'|88d98/([^/]++)/([^/]++)/([^/]++)/788d98(*:46430)' .'|2(?' - .'|da7f/([^/]++)/([^/]++)/([^/]++)/72da7f(*:46490)' - .'|50eb/([^/]++)/([^/]++)/([^/]++)/7250eb(*:46538)' + .'|da7f/([^/]++)/([^/]++)/([^/]++)/72da7f(*:46482)' + .'|50eb/([^/]++)/([^/]++)/([^/]++)/7250eb(*:46530)' .')' .'|c(?' - .'|590f/([^/]++)/([^/]++)/([^/]++)/7c590f(*:46591)' - .'|e328/([^/]++)/([^/]++)/([^/]++)/7ce328(*:46639)' - .')' - .'|a5392/([^/]++)/([^/]++)/([^/]++)/7a5392(*:46689)' - .'|95c7a/([^/]++)/([^/]++)/([^/]++)/795c7a(*:46738)' - .'|504ad/([^/]++)/([^/]++)/([^/]++)/7504ad(*:46787)' - .'|04afe/([^/]++)/([^/]++)/([^/]++)/704afe(*:46836)' - .'|4bba2/([^/]++)/([^/]++)/([^/]++)/74bba2(*:46885)' + .'|590f/([^/]++)/([^/]++)/([^/]++)/7c590f(*:46583)' + .'|e328/([^/]++)/([^/]++)/([^/]++)/7ce328(*:46631)' + .')' + .'|a5392/([^/]++)/([^/]++)/([^/]++)/7a5392(*:46681)' + .'|95c7a/([^/]++)/([^/]++)/([^/]++)/795c7a(*:46730)' + .'|504ad/([^/]++)/([^/]++)/([^/]++)/7504ad(*:46779)' + .'|04afe/([^/]++)/([^/]++)/([^/]++)/704afe(*:46828)' + .'|4bba2/([^/]++)/([^/]++)/([^/]++)/74bba2(*:46877)' .')' .'|/9(?' .'|b(?' - .'|72e3/([^/]++)/([^/]++)/([^/]++)/9b72e3(*:46943)' - .'|698e/([^/]++)/([^/]++)/([^/]++)/9b698e(*:46991)' + .'|72e3/([^/]++)/([^/]++)/([^/]++)/9b72e3(*:46935)' + .'|698e/([^/]++)/([^/]++)/([^/]++)/9b698e(*:46983)' .')' - .'|7e852/([^/]++)/([^/]++)/([^/]++)/97e852(*:47041)' - .'|4c7bb/([^/]++)/([^/]++)/([^/]++)/94c7bb(*:47090)' + .'|7e852/([^/]++)/([^/]++)/([^/]++)/97e852(*:47033)' + .'|4c7bb/([^/]++)/([^/]++)/([^/]++)/94c7bb(*:47082)' .'|9(?' - .'|c5e0/([^/]++)/([^/]++)/([^/]++)/99c5e0(*:47142)' - .'|6a7f/([^/]++)/([^/]++)/([^/]++)/996a7f(*:47190)' - .'|bcfc/([^/]++)/([^/]++)/([^/]++)/99bcfc(*:47238)' - .'|0827/([^/]++)/([^/]++)/([^/]++)/990827(*:47286)' + .'|c5e0/([^/]++)/([^/]++)/([^/]++)/99c5e0(*:47134)' + .'|6a7f/([^/]++)/([^/]++)/([^/]++)/996a7f(*:47182)' + .'|bcfc/([^/]++)/([^/]++)/([^/]++)/99bcfc(*:47230)' + .'|0827/([^/]++)/([^/]++)/([^/]++)/990827(*:47278)' .')' .'|a(?' - .'|d6aa/([^/]++)/([^/]++)/([^/]++)/9ad6aa(*:47339)' - .'|b0d8/([^/]++)/([^/]++)/([^/]++)/9ab0d8(*:47387)' + .'|d6aa/([^/]++)/([^/]++)/([^/]++)/9ad6aa(*:47331)' + .'|b0d8/([^/]++)/([^/]++)/([^/]++)/9ab0d8(*:47379)' .')' .'|c(?' - .'|f81d/([^/]++)/([^/]++)/([^/]++)/9cf81d(*:47440)' - .'|c138/([^/]++)/([^/]++)/([^/]++)/9cc138(*:47488)' - .'|82c7/([^/]++)/([^/]++)/([^/]++)/9c82c7(*:47536)' - .'|0180/([^/]++)/([^/]++)/([^/]++)/9c0180(*:47584)' + .'|f81d/([^/]++)/([^/]++)/([^/]++)/9cf81d(*:47432)' + .'|c138/([^/]++)/([^/]++)/([^/]++)/9cc138(*:47480)' + .'|82c7/([^/]++)/([^/]++)/([^/]++)/9c82c7(*:47528)' + .'|0180/([^/]++)/([^/]++)/([^/]++)/9c0180(*:47576)' .')' .'|f(?' - .'|396f/([^/]++)/([^/]++)/([^/]++)/9f396f(*:47637)' - .'|e859/([^/]++)/([^/]++)/([^/]++)/9fe859(*:47685)' - .'|53d8/([^/]++)/([^/]++)/([^/]++)/9f53d8(*:47733)' + .'|396f/([^/]++)/([^/]++)/([^/]++)/9f396f(*:47629)' + .'|e859/([^/]++)/([^/]++)/([^/]++)/9fe859(*:47677)' + .'|53d8/([^/]++)/([^/]++)/([^/]++)/9f53d8(*:47725)' .')' - .'|12d2b/([^/]++)/([^/]++)/([^/]++)/912d2b(*:47783)' - .'|59a55/([^/]++)/([^/]++)/([^/]++)/959a55(*:47832)' + .'|12d2b/([^/]++)/([^/]++)/([^/]++)/912d2b(*:47775)' + .'|59a55/([^/]++)/([^/]++)/([^/]++)/959a55(*:47824)' .'|6(?' - .'|ea64/([^/]++)/([^/]++)/([^/]++)/96ea64(*:47884)' - .'|b9bf/([^/]++)/([^/]++)/([^/]++)/96b9bf(*:47932)' + .'|ea64/([^/]++)/([^/]++)/([^/]++)/96ea64(*:47876)' + .'|b9bf/([^/]++)/([^/]++)/([^/]++)/96b9bf(*:47924)' .')' - .'|e3cfc/([^/]++)/([^/]++)/([^/]++)/9e3cfc(*:47982)' + .'|e3cfc/([^/]++)/([^/]++)/([^/]++)/9e3cfc(*:47974)' .'|2(?' - .'|fb0c/([^/]++)/([^/]++)/([^/]++)/92fb0c(*:48034)' - .'|262b/([^/]++)/([^/]++)/([^/]++)/92262b(*:48082)' - .'|32fe/([^/]++)/([^/]++)/([^/]++)/9232fe(*:48130)' - .'|977a/([^/]++)/([^/]++)/([^/]++)/92977a(*:48178)' - .')' - .'|8d6f5/([^/]++)/([^/]++)/([^/]++)/98d6f5(*:48228)' - .'|0794e/([^/]++)/([^/]++)/([^/]++)/90794e(*:48277)' - .'|34815/([^/]++)/([^/]++)/([^/]++)/934815(*:48326)' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/92fb0c(*:48026)' + .'|262b/([^/]++)/([^/]++)/([^/]++)/92262b(*:48074)' + .'|32fe/([^/]++)/([^/]++)/([^/]++)/9232fe(*:48122)' + .'|977a/([^/]++)/([^/]++)/([^/]++)/92977a(*:48170)' + .')' + .'|8d6f5/([^/]++)/([^/]++)/([^/]++)/98d6f5(*:48220)' + .'|0794e/([^/]++)/([^/]++)/([^/]++)/90794e(*:48269)' + .'|34815/([^/]++)/([^/]++)/([^/]++)/934815(*:48318)' .')' .'|/4(?' .'|e(?' - .'|4b5f/([^/]++)/([^/]++)/([^/]++)/4e4b5f(*:48384)' - .'|a06f/([^/]++)/([^/]++)/([^/]++)/4ea06f(*:48432)' + .'|4b5f/([^/]++)/([^/]++)/([^/]++)/4e4b5f(*:48376)' + .'|a06f/([^/]++)/([^/]++)/([^/]++)/4ea06f(*:48424)' .'|0(?' - .'|928/([^/]++)/([^/]++)/([^/]++)/4e0928(*:48483)' - .'|cb6/([^/]++)/([^/]++)/([^/]++)/4e0cb6(*:48530)' + .'|928/([^/]++)/([^/]++)/([^/]++)/4e0928(*:48475)' + .'|cb6/([^/]++)/([^/]++)/([^/]++)/4e0cb6(*:48522)' .')' .')' - .'|6922a/([^/]++)/([^/]++)/([^/]++)/46922a(*:48581)' + .'|6922a/([^/]++)/([^/]++)/([^/]++)/46922a(*:48573)' .'|4(?' - .'|c4c1/([^/]++)/([^/]++)/([^/]++)/44c4c1(*:48633)' - .'|3cb0/([^/]++)/([^/]++)/([^/]++)/443cb0(*:48681)' + .'|c4c1/([^/]++)/([^/]++)/([^/]++)/44c4c1(*:48625)' + .'|3cb0/([^/]++)/([^/]++)/([^/]++)/443cb0(*:48673)' .')' - .'|8ab2f/([^/]++)/([^/]++)/([^/]++)/48ab2f(*:48731)' + .'|8ab2f/([^/]++)/([^/]++)/([^/]++)/48ab2f(*:48723)' .'|5(?' - .'|645a/([^/]++)/([^/]++)/([^/]++)/45645a(*:48783)' - .'|58db/([^/]++)/([^/]++)/([^/]++)/4558db(*:48831)' + .'|645a/([^/]++)/([^/]++)/([^/]++)/45645a(*:48775)' + .'|58db/([^/]++)/([^/]++)/([^/]++)/4558db(*:48823)' .')' - .'|2e77b/([^/]++)/([^/]++)/([^/]++)/42e77b(*:48881)' - .'|c27ce/([^/]++)/([^/]++)/([^/]++)/4c27ce(*:48930)' + .'|2e77b/([^/]++)/([^/]++)/([^/]++)/42e77b(*:48873)' + .'|c27ce/([^/]++)/([^/]++)/([^/]++)/4c27ce(*:48922)' .'|f(?' - .'|fce0/([^/]++)/([^/]++)/([^/]++)/4ffce0(*:48982)' - .'|ac9b/([^/]++)/([^/]++)/([^/]++)/4fac9b(*:49030)' + .'|fce0/([^/]++)/([^/]++)/([^/]++)/4ffce0(*:48974)' + .'|ac9b/([^/]++)/([^/]++)/([^/]++)/4fac9b(*:49022)' .')' - .'|a47d2/([^/]++)/([^/]++)/([^/]++)/4a47d2(*:49080)' - .'|70e7a/([^/]++)/([^/]++)/([^/]++)/470e7a(*:49129)' + .'|a47d2/([^/]++)/([^/]++)/([^/]++)/4a47d2(*:49072)' + .'|70e7a/([^/]++)/([^/]++)/([^/]++)/470e7a(*:49121)' .'|b(?' .'|0(?' - .'|4a6/([^/]++)/([^/]++)/([^/]++)/4b04a6(*:49184)' - .'|a59/([^/]++)/([^/]++)/([^/]++)/4b0a59(*:49231)' - .'|250/([^/]++)/([^/]++)/([^/]++)/4b0250(*:49278)' + .'|4a6/([^/]++)/([^/]++)/([^/]++)/4b04a6(*:49176)' + .'|a59/([^/]++)/([^/]++)/([^/]++)/4b0a59(*:49223)' + .'|250/([^/]++)/([^/]++)/([^/]++)/4b0250(*:49270)' .')' - .'|6538/([^/]++)/([^/]++)/([^/]++)/4b6538(*:49327)' + .'|6538/([^/]++)/([^/]++)/([^/]++)/4b6538(*:49319)' .')' .'|3(?' .'|f(?' - .'|a7f/([^/]++)/([^/]++)/([^/]++)/43fa7f(*:49383)' - .'|eae/([^/]++)/([^/]++)/([^/]++)/43feae(*:49430)' + .'|a7f/([^/]++)/([^/]++)/([^/]++)/43fa7f(*:49375)' + .'|eae/([^/]++)/([^/]++)/([^/]++)/43feae(*:49422)' .')' - .'|0c36/([^/]++)/([^/]++)/([^/]++)/430c36(*:49479)' - .'|7d7d/([^/]++)/([^/]++)/([^/]++)/437d7d(*:49527)' - .'|1135/([^/]++)/([^/]++)/([^/]++)/431135(*:49575)' + .'|0c36/([^/]++)/([^/]++)/([^/]++)/430c36(*:49471)' + .'|7d7d/([^/]++)/([^/]++)/([^/]++)/437d7d(*:49519)' + .'|1135/([^/]++)/([^/]++)/([^/]++)/431135(*:49567)' .')' .'|d(?' - .'|5b99/([^/]++)/([^/]++)/([^/]++)/4d5b99(*:49628)' - .'|aa3d/([^/]++)/([^/]++)/([^/]++)/4daa3d(*:49676)' + .'|5b99/([^/]++)/([^/]++)/([^/]++)/4d5b99(*:49620)' + .'|aa3d/([^/]++)/([^/]++)/([^/]++)/4daa3d(*:49668)' .')' - .'|9c9ad/([^/]++)/([^/]++)/([^/]++)/49c9ad(*:49726)' + .'|9c9ad/([^/]++)/([^/]++)/([^/]++)/49c9ad(*:49718)' .')' .')$}sD', ); @@ -2290,505 +2290,505 @@ public function match($rawPathinfo) 24688 => array(array('_route' => '_391'), array('a', 'b', 'c'), null, null), 24737 => array(array('_route' => '_462'), array('a', 'b', 'c'), null, null), 24786 => array(array('_route' => '_476'), array('a', 'b', 'c'), null, null), - 24845 => array(array('_route' => '_501'), array('a', 'b', 'c'), null, null), - 24897 => array(array('_route' => '_514'), array('a', 'b', 'c'), null, null), - 24945 => array(array('_route' => '_731'), array('a', 'b', 'c'), null, null), - 24998 => array(array('_route' => '_522'), array('a', 'b', 'c'), null, null), - 25046 => array(array('_route' => '_693'), array('a', 'b', 'c'), null, null), - 25099 => array(array('_route' => '_537'), array('a', 'b', 'c'), null, null), - 25147 => array(array('_route' => '_554'), array('a', 'b', 'c'), null, null), - 25195 => array(array('_route' => '_645'), array('a', 'b', 'c'), null, null), - 25243 => array(array('_route' => '_862'), array('a', 'b', 'c'), null, null), - 25296 => array(array('_route' => '_539'), array('a', 'b', 'c'), null, null), - 25344 => array(array('_route' => '_729'), array('a', 'b', 'c'), null, null), - 25392 => array(array('_route' => '_897'), array('a', 'b', 'c'), null, null), - 25445 => array(array('_route' => '_561'), array('a', 'b', 'c'), null, null), - 25493 => array(array('_route' => '_615'), array('a', 'b', 'c'), null, null), - 25541 => array(array('_route' => '_764'), array('a', 'b', 'c'), null, null), - 25589 => array(array('_route' => '_948'), array('a', 'b', 'c'), null, null), - 25642 => array(array('_route' => '_617'), array('a', 'b', 'c'), null, null), - 25690 => array(array('_route' => '_671'), array('a', 'b', 'c'), null, null), - 25743 => array(array('_route' => '_649'), array('a', 'b', 'c'), null, null), - 25791 => array(array('_route' => '_651'), array('a', 'b', 'c'), null, null), - 25839 => array(array('_route' => '_684'), array('a', 'b', 'c'), null, null), - 25892 => array(array('_route' => '_669'), array('a', 'b', 'c'), null, null), - 25940 => array(array('_route' => '_743'), array('a', 'b', 'c'), null, null), - 25988 => array(array('_route' => '_962'), array('a', 'b', 'c'), null, null), - 26041 => array(array('_route' => '_694'), array('a', 'b', 'c'), null, null), - 26089 => array(array('_route' => '_985'), array('a', 'b', 'c'), null, null), - 26142 => array(array('_route' => '_707'), array('a', 'b', 'c'), null, null), - 26190 => array(array('_route' => '_718'), array('a', 'b', 'c'), null, null), - 26243 => array(array('_route' => '_720'), array('a', 'b', 'c'), null, null), - 26291 => array(array('_route' => '_745'), array('a', 'b', 'c'), null, null), - 26341 => array(array('_route' => '_874'), array('a', 'b', 'c'), null, null), - 26399 => array(array('_route' => '_502'), array('a', 'b', 'c'), null, null), - 26447 => array(array('_route' => '_667'), array('a', 'b', 'c'), null, null), - 26495 => array(array('_route' => '_911'), array('a', 'b', 'c'), null, null), - 26543 => array(array('_route' => '_942'), array('a', 'b', 'c'), null, null), - 26593 => array(array('_route' => '_504'), array('a', 'b', 'c'), null, null), - 26645 => array(array('_route' => '_524'), array('a', 'b', 'c'), null, null), - 26693 => array(array('_route' => '_732'), array('a', 'b', 'c'), null, null), - 26746 => array(array('_route' => '_596'), array('a', 'b', 'c'), null, null), - 26794 => array(array('_route' => '_601'), array('a', 'b', 'c'), null, null), - 26847 => array(array('_route' => '_620'), array('a', 'b', 'c'), null, null), - 26895 => array(array('_route' => '_631'), array('a', 'b', 'c'), null, null), - 26943 => array(array('_route' => '_771'), array('a', 'b', 'c'), null, null), - 26991 => array(array('_route' => '_937'), array('a', 'b', 'c'), null, null), - 27039 => array(array('_route' => '_999'), array('a', 'b', 'c'), null, null), - 27092 => array(array('_route' => '_657'), array('a', 'b', 'c'), null, null), - 27140 => array(array('_route' => '_701'), array('a', 'b', 'c'), null, null), - 27193 => array(array('_route' => '_662'), array('a', 'b', 'c'), null, null), - 27241 => array(array('_route' => '_797'), array('a', 'b', 'c'), null, null), - 27289 => array(array('_route' => '_924'), array('a', 'b', 'c'), null, null), - 27342 => array(array('_route' => '_702'), array('a', 'b', 'c'), null, null), - 27390 => array(array('_route' => '_750'), array('a', 'b', 'c'), null, null), - 27443 => array(array('_route' => '_749'), array('a', 'b', 'c'), null, null), - 27491 => array(array('_route' => '_837'), array('a', 'b', 'c'), null, null), - 27541 => array(array('_route' => '_758'), array('a', 'b', 'c'), null, null), - 27593 => array(array('_route' => '_810'), array('a', 'b', 'c'), null, null), - 27641 => array(array('_route' => '_902'), array('a', 'b', 'c'), null, null), - 27691 => array(array('_route' => '_845'), array('a', 'b', 'c'), null, null), - 27749 => array(array('_route' => '_503'), array('a', 'b', 'c'), null, null), - 27800 => array(array('_route' => '_756'), array('a', 'b', 'c'), null, null), - 27847 => array(array('_route' => '_799'), array('a', 'b', 'c'), null, null), - 27896 => array(array('_route' => '_769'), array('a', 'b', 'c'), null, null), - 27944 => array(array('_route' => '_981'), array('a', 'b', 'c'), null, null), - 27997 => array(array('_route' => '_507'), array('a', 'b', 'c'), null, null), - 28045 => array(array('_route' => '_672'), array('a', 'b', 'c'), null, null), - 28093 => array(array('_route' => '_790'), array('a', 'b', 'c'), null, null), - 28146 => array(array('_route' => '_515'), array('a', 'b', 'c'), null, null), - 28194 => array(array('_route' => '_523'), array('a', 'b', 'c'), null, null), - 28242 => array(array('_route' => '_957'), array('a', 'b', 'c'), null, null), - 28290 => array(array('_route' => '_995'), array('a', 'b', 'c'), null, null), - 28343 => array(array('_route' => '_532'), array('a', 'b', 'c'), null, null), - 28391 => array(array('_route' => '_642'), array('a', 'b', 'c'), null, null), - 28441 => array(array('_route' => '_579'), array('a', 'b', 'c'), null, null), - 28493 => array(array('_route' => '_625'), array('a', 'b', 'c'), null, null), - 28541 => array(array('_route' => '_916'), array('a', 'b', 'c'), null, null), - 28594 => array(array('_route' => '_633'), array('a', 'b', 'c'), null, null), - 28642 => array(array('_route' => '_656'), array('a', 'b', 'c'), null, null), - 28695 => array(array('_route' => '_658'), array('a', 'b', 'c'), null, null), - 28743 => array(array('_route' => '_943'), array('a', 'b', 'c'), null, null), - 28796 => array(array('_route' => '_664'), array('a', 'b', 'c'), null, null), - 28844 => array(array('_route' => '_852'), array('a', 'b', 'c'), null, null), - 28892 => array(array('_route' => '_870'), array('a', 'b', 'c'), null, null), - 28945 => array(array('_route' => '_683'), array('a', 'b', 'c'), null, null), - 28993 => array(array('_route' => '_915'), array('a', 'b', 'c'), null, null), - 29046 => array(array('_route' => '_719'), array('a', 'b', 'c'), null, null), - 29094 => array(array('_route' => '_859'), array('a', 'b', 'c'), null, null), - 29142 => array(array('_route' => '_912'), array('a', 'b', 'c'), null, null), - 29190 => array(array('_route' => '_978'), array('a', 'b', 'c'), null, null), - 29243 => array(array('_route' => '_738'), array('a', 'b', 'c'), null, null), - 29291 => array(array('_route' => '_883'), array('a', 'b', 'c'), null, null), - 29341 => array(array('_route' => '_741'), array('a', 'b', 'c'), null, null), - 29390 => array(array('_route' => '_760'), array('a', 'b', 'c'), null, null), - 29439 => array(array('_route' => '_895'), array('a', 'b', 'c'), null, null), - 29497 => array(array('_route' => '_505'), array('a', 'b', 'c'), null, null), - 29545 => array(array('_route' => '_935'), array('a', 'b', 'c'), null, null), - 29598 => array(array('_route' => '_509'), array('a', 'b', 'c'), null, null), - 29646 => array(array('_route' => '_820'), array('a', 'b', 'c'), null, null), - 29694 => array(array('_route' => '_910'), array('a', 'b', 'c'), null, null), - 29747 => array(array('_route' => '_518'), array('a', 'b', 'c'), null, null), - 29795 => array(array('_route' => '_618'), array('a', 'b', 'c'), null, null), - 29848 => array(array('_route' => '_546'), array('a', 'b', 'c'), null, null), - 29896 => array(array('_route' => '_740'), array('a', 'b', 'c'), null, null), - 29944 => array(array('_route' => '_867'), array('a', 'b', 'c'), null, null), - 29997 => array(array('_route' => '_572'), array('a', 'b', 'c'), null, null), - 30045 => array(array('_route' => '_952'), array('a', 'b', 'c'), null, null), - 30098 => array(array('_route' => '_573'), array('a', 'b', 'c'), null, null), - 30146 => array(array('_route' => '_692'), array('a', 'b', 'c'), null, null), - 30194 => array(array('_route' => '_700'), array('a', 'b', 'c'), null, null), - 30242 => array(array('_route' => '_772'), array('a', 'b', 'c'), null, null), - 30292 => array(array('_route' => '_653'), array('a', 'b', 'c'), null, null), - 30344 => array(array('_route' => '_695'), array('a', 'b', 'c'), null, null), - 30392 => array(array('_route' => '_748'), array('a', 'b', 'c'), null, null), - 30445 => array(array('_route' => '_710'), array('a', 'b', 'c'), null, null), - 30493 => array(array('_route' => '_716'), array('a', 'b', 'c'), null, null), - 30541 => array(array('_route' => '_969'), array('a', 'b', 'c'), null, null), - 30594 => array(array('_route' => '_734'), array('a', 'b', 'c'), null, null), - 30642 => array(array('_route' => '_742'), array('a', 'b', 'c'), null, null), - 30690 => array(array('_route' => '_844'), array('a', 'b', 'c'), null, null), - 30743 => array(array('_route' => '_763'), array('a', 'b', 'c'), null, null), - 30791 => array(array('_route' => '_965'), array('a', 'b', 'c'), null, null), - 30844 => array(array('_route' => '_778'), array('a', 'b', 'c'), null, null), - 30892 => array(array('_route' => '_813'), array('a', 'b', 'c'), null, null), - 30940 => array(array('_route' => '_831'), array('a', 'b', 'c'), null, null), - 30990 => array(array('_route' => '_955'), array('a', 'b', 'c'), null, null), - 31039 => array(array('_route' => '_997'), array('a', 'b', 'c'), null, null), - 31097 => array(array('_route' => '_506'), array('a', 'b', 'c'), null, null), - 31145 => array(array('_route' => '_575'), array('a', 'b', 'c'), null, null), - 31198 => array(array('_route' => '_516'), array('a', 'b', 'c'), null, null), - 31246 => array(array('_route' => '_553'), array('a', 'b', 'c'), null, null), - 31299 => array(array('_route' => '_528'), array('a', 'b', 'c'), null, null), - 31347 => array(array('_route' => '_847'), array('a', 'b', 'c'), null, null), - 31395 => array(array('_route' => '_904'), array('a', 'b', 'c'), null, null), - 31448 => array(array('_route' => '_574'), array('a', 'b', 'c'), null, null), - 31496 => array(array('_route' => '_818'), array('a', 'b', 'c'), null, null), - 31546 => array(array('_route' => '_577'), array('a', 'b', 'c'), null, null), - 31598 => array(array('_route' => '_584'), array('a', 'b', 'c'), null, null), - 31646 => array(array('_route' => '_905'), array('a', 'b', 'c'), null, null), - 31699 => array(array('_route' => '_612'), array('a', 'b', 'c'), null, null), - 31747 => array(array('_route' => '_688'), array('a', 'b', 'c'), null, null), - 31795 => array(array('_route' => '_854'), array('a', 'b', 'c'), null, null), - 31848 => array(array('_route' => '_613'), array('a', 'b', 'c'), null, null), - 31896 => array(array('_route' => '_767'), array('a', 'b', 'c'), null, null), - 31949 => array(array('_route' => '_666'), array('a', 'b', 'c'), null, null), - 31997 => array(array('_route' => '_759'), array('a', 'b', 'c'), null, null), - 32045 => array(array('_route' => '_827'), array('a', 'b', 'c'), null, null), - 32093 => array(array('_route' => '_840'), array('a', 'b', 'c'), null, null), - 32146 => array(array('_route' => '_680'), array('a', 'b', 'c'), null, null), - 32194 => array(array('_route' => '_784'), array('a', 'b', 'c'), null, null), - 32242 => array(array('_route' => '_842'), array('a', 'b', 'c'), null, null), - 32290 => array(array('_route' => '_860'), array('a', 'b', 'c'), null, null), - 32340 => array(array('_route' => '_704'), array('a', 'b', 'c'), null, null), - 32389 => array(array('_route' => '_727'), array('a', 'b', 'c'), null, null), - 32438 => array(array('_route' => '_777'), array('a', 'b', 'c'), null, null), - 32490 => array(array('_route' => '_838'), array('a', 'b', 'c'), null, null), - 32538 => array(array('_route' => '_861'), array('a', 'b', 'c'), null, null), - 32591 => array(array('_route' => '_849'), array('a', 'b', 'c'), null, null), - 32639 => array(array('_route' => '_982'), array('a', 'b', 'c'), null, null), - 32687 => array(array('_route' => '_986'), array('a', 'b', 'c'), null, null), - 32749 => array(array('_route' => '_508'), array('a', 'b', 'c'), null, null), - 32796 => array(array('_route' => '_517'), array('a', 'b', 'c'), null, null), - 32845 => array(array('_route' => '_622'), array('a', 'b', 'c'), null, null), - 32898 => array(array('_route' => '_513'), array('a', 'b', 'c'), null, null), - 32946 => array(array('_route' => '_655'), array('a', 'b', 'c'), null, null), - 32994 => array(array('_route' => '_843'), array('a', 'b', 'c'), null, null), - 33042 => array(array('_route' => '_939'), array('a', 'b', 'c'), null, null), - 33092 => array(array('_route' => '_529'), array('a', 'b', 'c'), null, null), - 33144 => array(array('_route' => '_535'), array('a', 'b', 'c'), null, null), - 33192 => array(array('_route' => '_685'), array('a', 'b', 'c'), null, null), - 33248 => array(array('_route' => '_559'), array('a', 'b', 'c'), null, null), - 33295 => array(array('_route' => '_661'), array('a', 'b', 'c'), null, null), - 33344 => array(array('_route' => '_768'), array('a', 'b', 'c'), null, null), - 33397 => array(array('_route' => '_589'), array('a', 'b', 'c'), null, null), - 33445 => array(array('_route' => '_647'), array('a', 'b', 'c'), null, null), - 33493 => array(array('_route' => '_652'), array('a', 'b', 'c'), null, null), - 33541 => array(array('_route' => '_834'), array('a', 'b', 'c'), null, null), - 33594 => array(array('_route' => '_591'), array('a', 'b', 'c'), null, null), - 33642 => array(array('_route' => '_599'), array('a', 'b', 'c'), null, null), - 33695 => array(array('_route' => '_787'), array('a', 'b', 'c'), null, null), - 33742 => array(array('_route' => '_848'), array('a', 'b', 'c'), null, null), - 33795 => array(array('_route' => '_796'), array('a', 'b', 'c'), null, null), - 33843 => array(array('_route' => '_877'), array('a', 'b', 'c'), null, null), - 33893 => array(array('_route' => '_809'), array('a', 'b', 'c'), null, null), - 33942 => array(array('_route' => '_817'), array('a', 'b', 'c'), null, null), - 33994 => array(array('_route' => '_819'), array('a', 'b', 'c'), null, null), - 34042 => array(array('_route' => '_865'), array('a', 'b', 'c'), null, null), - 34092 => array(array('_route' => '_919'), array('a', 'b', 'c'), null, null), - 34141 => array(array('_route' => '_949'), array('a', 'b', 'c'), null, null), - 34199 => array(array('_route' => '_510'), array('a', 'b', 'c'), null, null), - 34247 => array(array('_route' => '_590'), array('a', 'b', 'c'), null, null), - 34295 => array(array('_route' => '_597'), array('a', 'b', 'c'), null, null), - 34343 => array(array('_route' => '_682'), array('a', 'b', 'c'), null, null), - 34391 => array(array('_route' => '_723'), array('a', 'b', 'c'), null, null), - 34444 => array(array('_route' => '_521'), array('a', 'b', 'c'), null, null), - 34492 => array(array('_route' => '_594'), array('a', 'b', 'c'), null, null), - 34540 => array(array('_route' => '_689'), array('a', 'b', 'c'), null, null), - 34588 => array(array('_route' => '_713'), array('a', 'b', 'c'), null, null), - 34636 => array(array('_route' => '_889'), array('a', 'b', 'c'), null, null), - 34689 => array(array('_route' => '_531'), array('a', 'b', 'c'), null, null), - 34737 => array(array('_route' => '_639'), array('a', 'b', 'c'), null, null), - 34788 => array(array('_route' => '_646'), array('a', 'b', 'c'), null, null), - 34835 => array(array('_route' => '_659'), array('a', 'b', 'c'), null, null), - 34884 => array(array('_route' => '_959'), array('a', 'b', 'c'), null, null), - 34937 => array(array('_route' => '_550'), array('a', 'b', 'c'), null, null), - 34985 => array(array('_route' => '_833'), array('a', 'b', 'c'), null, null), - 35033 => array(array('_route' => '_899'), array('a', 'b', 'c'), null, null), - 35089 => array(array('_route' => '_580'), array('a', 'b', 'c'), null, null), - 35136 => array(array('_route' => '_762'), array('a', 'b', 'c'), null, null), - 35185 => array(array('_route' => '_896'), array('a', 'b', 'c'), null, null), - 35238 => array(array('_route' => '_595'), array('a', 'b', 'c'), null, null), - 35286 => array(array('_route' => '_933'), array('a', 'b', 'c'), null, null), - 35336 => array(array('_route' => '_610'), array('a', 'b', 'c'), null, null), - 35388 => array(array('_route' => '_629'), array('a', 'b', 'c'), null, null), - 35436 => array(array('_route' => '_744'), array('a', 'b', 'c'), null, null), - 35489 => array(array('_route' => '_674'), array('a', 'b', 'c'), null, null), - 35537 => array(array('_route' => '_726'), array('a', 'b', 'c'), null, null), - 35585 => array(array('_route' => '_929'), array('a', 'b', 'c'), null, null), - 35635 => array(array('_route' => '_696'), array('a', 'b', 'c'), null, null), - 35687 => array(array('_route' => '_841'), array('a', 'b', 'c'), null, null), - 35735 => array(array('_route' => '_890'), array('a', 'b', 'c'), null, null), - 35785 => array(array('_route' => '_885'), array('a', 'b', 'c'), null, null), - 35834 => array(array('_route' => '_888'), array('a', 'b', 'c'), null, null), - 35883 => array(array('_route' => '_996'), array('a', 'b', 'c'), null, null), - 35941 => array(array('_route' => '_511'), array('a', 'b', 'c'), null, null), - 35989 => array(array('_route' => '_576'), array('a', 'b', 'c'), null, null), - 36037 => array(array('_route' => '_623'), array('a', 'b', 'c'), null, null), - 36090 => array(array('_route' => '_560'), array('a', 'b', 'c'), null, null), - 36137 => array(array('_route' => '_585'), array('a', 'b', 'c'), null, null), - 36190 => array(array('_route' => '_570'), array('a', 'b', 'c'), null, null), - 36238 => array(array('_route' => '_578'), array('a', 'b', 'c'), null, null), - 36289 => array(array('_route' => '_780'), array('a', 'b', 'c'), null, null), - 36336 => array(array('_route' => '_808'), array('a', 'b', 'c'), null, null), - 36390 => array(array('_route' => '_593'), array('a', 'b', 'c'), null, null), - 36438 => array(array('_route' => '_900'), array('a', 'b', 'c'), null, null), - 36491 => array(array('_route' => '_632'), array('a', 'b', 'c'), null, null), - 36539 => array(array('_route' => '_654'), array('a', 'b', 'c'), null, null), - 36587 => array(array('_route' => '_721'), array('a', 'b', 'c'), null, null), - 36635 => array(array('_route' => '_836'), array('a', 'b', 'c'), null, null), - 36688 => array(array('_route' => '_637'), array('a', 'b', 'c'), null, null), - 36736 => array(array('_route' => '_737'), array('a', 'b', 'c'), null, null), - 36792 => array(array('_route' => '_699'), array('a', 'b', 'c'), null, null), - 36839 => array(array('_route' => '_822'), array('a', 'b', 'c'), null, null), - 36888 => array(array('_route' => '_853'), array('a', 'b', 'c'), null, null), - 36941 => array(array('_route' => '_708'), array('a', 'b', 'c'), null, null), - 36989 => array(array('_route' => '_871'), array('a', 'b', 'c'), null, null), - 37042 => array(array('_route' => '_752'), array('a', 'b', 'c'), null, null), - 37090 => array(array('_route' => '_989'), array('a', 'b', 'c'), null, null), - 37140 => array(array('_route' => '_855'), array('a', 'b', 'c'), null, null), - 37192 => array(array('_route' => '_858'), array('a', 'b', 'c'), null, null), - 37240 => array(array('_route' => '_898'), array('a', 'b', 'c'), null, null), - 37290 => array(array('_route' => '_903'), array('a', 'b', 'c'), null, null), - 37339 => array(array('_route' => '_909'), array('a', 'b', 'c'), null, null), - 37388 => array(array('_route' => '_950'), array('a', 'b', 'c'), null, null), - 37449 => array(array('_route' => '_512'), array('a', 'b', 'c'), null, null), - 37496 => array(array('_route' => '_691'), array('a', 'b', 'c'), null, null), - 37545 => array(array('_route' => '_686'), array('a', 'b', 'c'), null, null), - 37595 => array(array('_route' => '_527'), array('a', 'b', 'c'), null, null), - 37647 => array(array('_route' => '_541'), array('a', 'b', 'c'), null, null), - 37695 => array(array('_route' => '_956'), array('a', 'b', 'c'), null, null), - 37748 => array(array('_route' => '_555'), array('a', 'b', 'c'), null, null), - 37796 => array(array('_route' => '_681'), array('a', 'b', 'c'), null, null), - 37849 => array(array('_route' => '_556'), array('a', 'b', 'c'), null, null), - 37897 => array(array('_route' => '_802'), array('a', 'b', 'c'), null, null), - 37947 => array(array('_route' => '_558'), array('a', 'b', 'c'), null, null), - 37999 => array(array('_route' => '_564'), array('a', 'b', 'c'), null, null), - 38047 => array(array('_route' => '_670'), array('a', 'b', 'c'), null, null), - 38095 => array(array('_route' => '_884'), array('a', 'b', 'c'), null, null), - 38148 => array(array('_route' => '_627'), array('a', 'b', 'c'), null, null), - 38195 => array(array('_route' => '_746'), array('a', 'b', 'c'), null, null), - 38248 => array(array('_route' => '_668'), array('a', 'b', 'c'), null, null), - 38299 => array(array('_route' => '_712'), array('a', 'b', 'c'), null, null), - 38346 => array(array('_route' => '_863'), array('a', 'b', 'c'), null, null), - 38395 => array(array('_route' => '_801'), array('a', 'b', 'c'), null, null), - 38448 => array(array('_route' => '_709'), array('a', 'b', 'c'), null, null), - 38496 => array(array('_route' => '_850'), array('a', 'b', 'c'), null, null), - 38544 => array(array('_route' => '_918'), array('a', 'b', 'c'), null, null), - 38594 => array(array('_route' => '_803'), array('a', 'b', 'c'), null, null), - 38646 => array(array('_route' => '_864'), array('a', 'b', 'c'), null, null), - 38694 => array(array('_route' => '_880'), array('a', 'b', 'c'), null, null), - 38742 => array(array('_route' => '_927'), array('a', 'b', 'c'), null, null), - 38795 => array(array('_route' => '_930'), array('a', 'b', 'c'), null, null), - 38843 => array(array('_route' => '_951'), array('a', 'b', 'c'), null, null), - 38891 => array(array('_route' => '_963'), array('a', 'b', 'c'), null, null), - 38950 => array(array('_route' => '_519'), array('a', 'b', 'c'), null, null), - 38998 => array(array('_route' => '_823'), array('a', 'b', 'c'), null, null), - 39046 => array(array('_route' => '_954'), array('a', 'b', 'c'), null, null), - 39099 => array(array('_route' => '_525'), array('a', 'b', 'c'), null, null), - 39147 => array(array('_route' => '_991'), array('a', 'b', 'c'), null, null), - 39197 => array(array('_route' => '_536'), array('a', 'b', 'c'), null, null), - 39249 => array(array('_route' => '_545'), array('a', 'b', 'c'), null, null), - 39297 => array(array('_route' => '_944'), array('a', 'b', 'c'), null, null), - 39350 => array(array('_route' => '_557'), array('a', 'b', 'c'), null, null), - 39398 => array(array('_route' => '_783'), array('a', 'b', 'c'), null, null), - 39446 => array(array('_route' => '_807'), array('a', 'b', 'c'), null, null), - 39499 => array(array('_route' => '_586'), array('a', 'b', 'c'), null, null), - 39547 => array(array('_route' => '_711'), array('a', 'b', 'c'), null, null), - 39600 => array(array('_route' => '_598'), array('a', 'b', 'c'), null, null), - 39648 => array(array('_route' => '_635'), array('a', 'b', 'c'), null, null), - 39696 => array(array('_route' => '_983'), array('a', 'b', 'c'), null, null), - 39749 => array(array('_route' => '_634'), array('a', 'b', 'c'), null, null), - 39797 => array(array('_route' => '_641'), array('a', 'b', 'c'), null, null), - 39848 => array(array('_route' => '_779'), array('a', 'b', 'c'), null, null), - 39895 => array(array('_route' => '_876'), array('a', 'b', 'c'), null, null), - 39944 => array(array('_route' => '_811'), array('a', 'b', 'c'), null, null), - 39992 => array(array('_route' => '_824'), array('a', 'b', 'c'), null, null), - 40045 => array(array('_route' => '_660'), array('a', 'b', 'c'), null, null), - 40093 => array(array('_route' => '_789'), array('a', 'b', 'c'), null, null), - 40146 => array(array('_route' => '_733'), array('a', 'b', 'c'), null, null), - 40194 => array(array('_route' => '_735'), array('a', 'b', 'c'), null, null), - 40242 => array(array('_route' => '_882'), array('a', 'b', 'c'), null, null), - 40290 => array(array('_route' => '_967'), array('a', 'b', 'c'), null, null), - 40340 => array(array('_route' => '_736'), array('a', 'b', 'c'), null, null), - 40389 => array(array('_route' => '_753'), array('a', 'b', 'c'), null, null), - 40438 => array(array('_route' => '_786'), array('a', 'b', 'c'), null, null), - 40487 => array(array('_route' => '_907'), array('a', 'b', 'c'), null, null), - 40536 => array(array('_route' => '_920'), array('a', 'b', 'c'), null, null), - 40585 => array(array('_route' => '_971'), array('a', 'b', 'c'), null, null), - 40643 => array(array('_route' => '_520'), array('a', 'b', 'c'), null, null), - 40691 => array(array('_route' => '_891'), array('a', 'b', 'c'), null, null), - 40747 => array(array('_route' => '_534'), array('a', 'b', 'c'), null, null), - 40793 => array(array('_route' => '_602'), array('a', 'b', 'c'), null, null), - 40842 => array(array('_route' => '_605'), array('a', 'b', 'c'), null, null), - 40890 => array(array('_route' => '_979'), array('a', 'b', 'c'), null, null), - 40940 => array(array('_route' => '_547'), array('a', 'b', 'c'), null, null), - 40995 => array(array('_route' => '_549'), array('a', 'b', 'c'), null, null), - 41042 => array(array('_route' => '_755'), array('a', 'b', 'c'), null, null), - 41091 => array(array('_route' => '_922'), array('a', 'b', 'c'), null, null), - 41139 => array(array('_route' => '_977'), array('a', 'b', 'c'), null, null), - 41192 => array(array('_route' => '_565'), array('a', 'b', 'c'), null, null), - 41240 => array(array('_route' => '_926'), array('a', 'b', 'c'), null, null), - 41290 => array(array('_route' => '_571'), array('a', 'b', 'c'), null, null), - 41339 => array(array('_route' => '_581'), array('a', 'b', 'c'), null, null), - 41388 => array(array('_route' => '_619'), array('a', 'b', 'c'), null, null), - 41437 => array(array('_route' => '_636'), array('a', 'b', 'c'), null, null), - 41489 => array(array('_route' => '_679'), array('a', 'b', 'c'), null, null), - 41537 => array(array('_route' => '_866'), array('a', 'b', 'c'), null, null), - 41585 => array(array('_route' => '_973'), array('a', 'b', 'c'), null, null), - 41638 => array(array('_route' => '_690'), array('a', 'b', 'c'), null, null), - 41686 => array(array('_route' => '_775'), array('a', 'b', 'c'), null, null), - 41739 => array(array('_route' => '_722'), array('a', 'b', 'c'), null, null), - 41787 => array(array('_route' => '_906'), array('a', 'b', 'c'), null, null), - 41835 => array(array('_route' => '_946'), array('a', 'b', 'c'), null, null), - 41885 => array(array('_route' => '_788'), array('a', 'b', 'c'), null, null), - 41937 => array(array('_route' => '_828'), array('a', 'b', 'c'), null, null), - 41985 => array(array('_route' => '_892'), array('a', 'b', 'c'), null, null), - 42033 => array(array('_route' => '_972'), array('a', 'b', 'c'), null, null), - 42083 => array(array('_route' => '_829'), array('a', 'b', 'c'), null, null), - 42135 => array(array('_route' => '_923'), array('a', 'b', 'c'), null, null), - 42183 => array(array('_route' => '_947'), array('a', 'b', 'c'), null, null), - 42242 => array(array('_route' => '_526'), array('a', 'b', 'c'), null, null), - 42290 => array(array('_route' => '_614'), array('a', 'b', 'c'), null, null), - 42338 => array(array('_route' => '_621'), array('a', 'b', 'c'), null, null), - 42391 => array(array('_route' => '_543'), array('a', 'b', 'c'), null, null), - 42439 => array(array('_route' => '_812'), array('a', 'b', 'c'), null, null), - 42495 => array(array('_route' => '_548'), array('a', 'b', 'c'), null, null), - 42542 => array(array('_route' => '_747'), array('a', 'b', 'c'), null, null), - 42591 => array(array('_route' => '_715'), array('a', 'b', 'c'), null, null), - 42639 => array(array('_route' => '_940'), array('a', 'b', 'c'), null, null), - 42692 => array(array('_route' => '_563'), array('a', 'b', 'c'), null, null), - 42740 => array(array('_route' => '_611'), array('a', 'b', 'c'), null, null), - 42788 => array(array('_route' => '_830'), array('a', 'b', 'c'), null, null), - 42841 => array(array('_route' => '_569'), array('a', 'b', 'c'), null, null), - 42889 => array(array('_route' => '_908'), array('a', 'b', 'c'), null, null), - 42937 => array(array('_route' => '_913'), array('a', 'b', 'c'), null, null), - 42990 => array(array('_route' => '_644'), array('a', 'b', 'c'), null, null), - 43038 => array(array('_route' => '_776'), array('a', 'b', 'c'), null, null), - 43086 => array(array('_route' => '_856'), array('a', 'b', 'c'), null, null), - 43139 => array(array('_route' => '_650'), array('a', 'b', 'c'), null, null), - 43187 => array(array('_route' => '_761'), array('a', 'b', 'c'), null, null), - 43240 => array(array('_route' => '_663'), array('a', 'b', 'c'), null, null), - 43288 => array(array('_route' => '_754'), array('a', 'b', 'c'), null, null), - 43341 => array(array('_route' => '_665'), array('a', 'b', 'c'), null, null), - 43389 => array(array('_route' => '_805'), array('a', 'b', 'c'), null, null), - 43437 => array(array('_route' => '_846'), array('a', 'b', 'c'), null, null), - 43485 => array(array('_route' => '_857'), array('a', 'b', 'c'), null, null), - 43538 => array(array('_route' => '_675'), array('a', 'b', 'c'), null, null), - 43586 => array(array('_route' => '_839'), array('a', 'b', 'c'), null, null), - 43634 => array(array('_route' => '_968'), array('a', 'b', 'c'), null, null), - 43684 => array(array('_route' => '_697'), array('a', 'b', 'c'), null, null), - 43736 => array(array('_route' => '_725'), array('a', 'b', 'c'), null, null), - 43784 => array(array('_route' => '_794'), array('a', 'b', 'c'), null, null), - 43837 => array(array('_route' => '_773'), array('a', 'b', 'c'), null, null), - 43885 => array(array('_route' => '_992'), array('a', 'b', 'c'), null, null), - 43938 => array(array('_route' => '_901'), array('a', 'b', 'c'), null, null), - 43986 => array(array('_route' => '_970'), array('a', 'b', 'c'), null, null), - 44036 => array(array('_route' => '_964'), array('a', 'b', 'c'), null, null), - 44094 => array(array('_route' => '_530'), array('a', 'b', 'c'), null, null), - 44142 => array(array('_route' => '_703'), array('a', 'b', 'c'), null, null), - 44195 => array(array('_route' => '_533'), array('a', 'b', 'c'), null, null), - 44243 => array(array('_route' => '_739'), array('a', 'b', 'c'), null, null), - 44291 => array(array('_route' => '_791'), array('a', 'b', 'c'), null, null), - 44339 => array(array('_route' => '_987'), array('a', 'b', 'c'), null, null), - 44392 => array(array('_route' => '_566'), array('a', 'b', 'c'), null, null), - 44440 => array(array('_route' => '_592'), array('a', 'b', 'c'), null, null), - 44496 => array(array('_route' => '_568'), array('a', 'b', 'c'), null, null), - 44542 => array(array('_route' => '_868'), array('a', 'b', 'c'), null, null), - 44591 => array(array('_route' => '_878'), array('a', 'b', 'c'), null, null), - 44644 => array(array('_route' => '_588'), array('a', 'b', 'c'), null, null), - 44692 => array(array('_route' => '_793'), array('a', 'b', 'c'), null, null), - 44740 => array(array('_route' => '_917'), array('a', 'b', 'c'), null, null), - 44793 => array(array('_route' => '_600'), array('a', 'b', 'c'), null, null), - 44841 => array(array('_route' => '_728'), array('a', 'b', 'c'), null, null), - 44894 => array(array('_route' => '_603'), array('a', 'b', 'c'), null, null), - 44942 => array(array('_route' => '_765'), array('a', 'b', 'c'), null, null), - 44995 => array(array('_route' => '_607'), array('a', 'b', 'c'), null, null), - 45043 => array(array('_route' => '_676'), array('a', 'b', 'c'), null, null), - 45091 => array(array('_route' => '_804'), array('a', 'b', 'c'), null, null), - 45144 => array(array('_route' => '_609'), array('a', 'b', 'c'), null, null), - 45192 => array(array('_route' => '_961'), array('a', 'b', 'c'), null, null), - 45240 => array(array('_route' => '_980'), array('a', 'b', 'c'), null, null), - 45290 => array(array('_route' => '_714'), array('a', 'b', 'c'), null, null), - 45342 => array(array('_route' => '_730'), array('a', 'b', 'c'), null, null), - 45390 => array(array('_route' => '_806'), array('a', 'b', 'c'), null, null), - 45438 => array(array('_route' => '_825'), array('a', 'b', 'c'), null, null), - 45486 => array(array('_route' => '_879'), array('a', 'b', 'c'), null, null), - 45534 => array(array('_route' => '_893'), array('a', 'b', 'c'), null, null), - 45584 => array(array('_route' => '_928'), array('a', 'b', 'c'), null, null), - 45636 => array(array('_route' => '_932'), array('a', 'b', 'c'), null, null), - 45684 => array(array('_route' => '_958'), array('a', 'b', 'c'), null, null), - 45734 => array(array('_route' => '_984'), array('a', 'b', 'c'), null, null), - 45792 => array(array('_route' => '_538'), array('a', 'b', 'c'), null, null), - 45840 => array(array('_route' => '_993'), array('a', 'b', 'c'), null, null), - 45890 => array(array('_route' => '_542'), array('a', 'b', 'c'), null, null), - 45942 => array(array('_route' => '_551'), array('a', 'b', 'c'), null, null), - 45990 => array(array('_route' => '_687'), array('a', 'b', 'c'), null, null), - 46038 => array(array('_route' => '_724'), array('a', 'b', 'c'), null, null), - 46086 => array(array('_route' => '_925'), array('a', 'b', 'c'), null, null), - 46139 => array(array('_route' => '_587'), array('a', 'b', 'c'), null, null), - 46187 => array(array('_route' => '_914'), array('a', 'b', 'c'), null, null), - 46237 => array(array('_route' => '_616'), array('a', 'b', 'c'), null, null), - 46292 => array(array('_route' => '_677'), array('a', 'b', 'c'), null, null), - 46339 => array(array('_route' => '_815'), array('a', 'b', 'c'), null, null), - 46388 => array(array('_route' => '_781'), array('a', 'b', 'c'), null, null), - 46438 => array(array('_route' => '_717'), array('a', 'b', 'c'), null, null), - 46490 => array(array('_route' => '_782'), array('a', 'b', 'c'), null, null), - 46538 => array(array('_route' => '_832'), array('a', 'b', 'c'), null, null), - 46591 => array(array('_route' => '_795'), array('a', 'b', 'c'), null, null), - 46639 => array(array('_route' => '_887'), array('a', 'b', 'c'), null, null), - 46689 => array(array('_route' => '_800'), array('a', 'b', 'c'), null, null), - 46738 => array(array('_route' => '_826'), array('a', 'b', 'c'), null, null), - 46787 => array(array('_route' => '_881'), array('a', 'b', 'c'), null, null), - 46836 => array(array('_route' => '_886'), array('a', 'b', 'c'), null, null), - 46885 => array(array('_route' => '_938'), array('a', 'b', 'c'), null, null), - 46943 => array(array('_route' => '_540'), array('a', 'b', 'c'), null, null), - 46991 => array(array('_route' => '_643'), array('a', 'b', 'c'), null, null), - 47041 => array(array('_route' => '_544'), array('a', 'b', 'c'), null, null), - 47090 => array(array('_route' => '_552'), array('a', 'b', 'c'), null, null), - 47142 => array(array('_route' => '_567'), array('a', 'b', 'c'), null, null), - 47190 => array(array('_route' => '_608'), array('a', 'b', 'c'), null, null), - 47238 => array(array('_route' => '_698'), array('a', 'b', 'c'), null, null), - 47286 => array(array('_route' => '_988'), array('a', 'b', 'c'), null, null), - 47339 => array(array('_route' => '_583'), array('a', 'b', 'c'), null, null), - 47387 => array(array('_route' => '_998'), array('a', 'b', 'c'), null, null), - 47440 => array(array('_route' => '_604'), array('a', 'b', 'c'), null, null), - 47488 => array(array('_route' => '_630'), array('a', 'b', 'c'), null, null), - 47536 => array(array('_route' => '_706'), array('a', 'b', 'c'), null, null), - 47584 => array(array('_route' => '_976'), array('a', 'b', 'c'), null, null), - 47637 => array(array('_route' => '_673'), array('a', 'b', 'c'), null, null), - 47685 => array(array('_route' => '_678'), array('a', 'b', 'c'), null, null), - 47733 => array(array('_route' => '_931'), array('a', 'b', 'c'), null, null), - 47783 => array(array('_route' => '_751'), array('a', 'b', 'c'), null, null), - 47832 => array(array('_route' => '_766'), array('a', 'b', 'c'), null, null), - 47884 => array(array('_route' => '_792'), array('a', 'b', 'c'), null, null), - 47932 => array(array('_route' => '_814'), array('a', 'b', 'c'), null, null), - 47982 => array(array('_route' => '_798'), array('a', 'b', 'c'), null, null), - 48034 => array(array('_route' => '_851'), array('a', 'b', 'c'), null, null), - 48082 => array(array('_route' => '_941'), array('a', 'b', 'c'), null, null), - 48130 => array(array('_route' => '_953'), array('a', 'b', 'c'), null, null), - 48178 => array(array('_route' => '_975'), array('a', 'b', 'c'), null, null), - 48228 => array(array('_route' => '_873'), array('a', 'b', 'c'), null, null), - 48277 => array(array('_route' => '_936'), array('a', 'b', 'c'), null, null), - 48326 => array(array('_route' => '_994'), array('a', 'b', 'c'), null, null), - 48384 => array(array('_route' => '_562'), array('a', 'b', 'c'), null, null), - 48432 => array(array('_route' => '_770'), array('a', 'b', 'c'), null, null), - 48483 => array(array('_route' => '_774'), array('a', 'b', 'c'), null, null), - 48530 => array(array('_route' => '_966'), array('a', 'b', 'c'), null, null), - 48581 => array(array('_route' => '_582'), array('a', 'b', 'c'), null, null), - 48633 => array(array('_route' => '_606'), array('a', 'b', 'c'), null, null), - 48681 => array(array('_route' => '_648'), array('a', 'b', 'c'), null, null), - 48731 => array(array('_route' => '_624'), array('a', 'b', 'c'), null, null), - 48783 => array(array('_route' => '_626'), array('a', 'b', 'c'), null, null), - 48831 => array(array('_route' => '_821'), array('a', 'b', 'c'), null, null), - 48881 => array(array('_route' => '_628'), array('a', 'b', 'c'), null, null), - 48930 => array(array('_route' => '_638'), array('a', 'b', 'c'), null, null), - 48982 => array(array('_route' => '_640'), array('a', 'b', 'c'), null, null), - 49030 => array(array('_route' => '_990'), array('a', 'b', 'c'), null, null), - 49080 => array(array('_route' => '_705'), array('a', 'b', 'c'), null, null), - 49129 => array(array('_route' => '_757'), array('a', 'b', 'c'), null, null), - 49184 => array(array('_route' => '_785'), array('a', 'b', 'c'), null, null), - 49231 => array(array('_route' => '_875'), array('a', 'b', 'c'), null, null), - 49278 => array(array('_route' => '_894'), array('a', 'b', 'c'), null, null), - 49327 => array(array('_route' => '_945'), array('a', 'b', 'c'), null, null), - 49383 => array(array('_route' => '_816'), array('a', 'b', 'c'), null, null), - 49430 => array(array('_route' => '_872'), array('a', 'b', 'c'), null, null), - 49479 => array(array('_route' => '_921'), array('a', 'b', 'c'), null, null), - 49527 => array(array('_route' => '_960'), array('a', 'b', 'c'), null, null), - 49575 => array(array('_route' => '_974'), array('a', 'b', 'c'), null, null), - 49628 => array(array('_route' => '_835'), array('a', 'b', 'c'), null, null), - 49676 => array(array('_route' => '_934'), array('a', 'b', 'c'), null, null), - 49726 => array(array('_route' => '_869'), array('a', 'b', 'c'), null, null), + 24837 => array(array('_route' => '_501'), array('a', 'b', 'c'), null, null), + 24889 => array(array('_route' => '_514'), array('a', 'b', 'c'), null, null), + 24937 => array(array('_route' => '_731'), array('a', 'b', 'c'), null, null), + 24990 => array(array('_route' => '_522'), array('a', 'b', 'c'), null, null), + 25038 => array(array('_route' => '_693'), array('a', 'b', 'c'), null, null), + 25091 => array(array('_route' => '_537'), array('a', 'b', 'c'), null, null), + 25139 => array(array('_route' => '_554'), array('a', 'b', 'c'), null, null), + 25187 => array(array('_route' => '_645'), array('a', 'b', 'c'), null, null), + 25235 => array(array('_route' => '_862'), array('a', 'b', 'c'), null, null), + 25288 => array(array('_route' => '_539'), array('a', 'b', 'c'), null, null), + 25336 => array(array('_route' => '_729'), array('a', 'b', 'c'), null, null), + 25384 => array(array('_route' => '_897'), array('a', 'b', 'c'), null, null), + 25437 => array(array('_route' => '_561'), array('a', 'b', 'c'), null, null), + 25485 => array(array('_route' => '_615'), array('a', 'b', 'c'), null, null), + 25533 => array(array('_route' => '_764'), array('a', 'b', 'c'), null, null), + 25581 => array(array('_route' => '_948'), array('a', 'b', 'c'), null, null), + 25634 => array(array('_route' => '_617'), array('a', 'b', 'c'), null, null), + 25682 => array(array('_route' => '_671'), array('a', 'b', 'c'), null, null), + 25735 => array(array('_route' => '_649'), array('a', 'b', 'c'), null, null), + 25783 => array(array('_route' => '_651'), array('a', 'b', 'c'), null, null), + 25831 => array(array('_route' => '_684'), array('a', 'b', 'c'), null, null), + 25884 => array(array('_route' => '_669'), array('a', 'b', 'c'), null, null), + 25932 => array(array('_route' => '_743'), array('a', 'b', 'c'), null, null), + 25980 => array(array('_route' => '_962'), array('a', 'b', 'c'), null, null), + 26033 => array(array('_route' => '_694'), array('a', 'b', 'c'), null, null), + 26081 => array(array('_route' => '_985'), array('a', 'b', 'c'), null, null), + 26134 => array(array('_route' => '_707'), array('a', 'b', 'c'), null, null), + 26182 => array(array('_route' => '_718'), array('a', 'b', 'c'), null, null), + 26235 => array(array('_route' => '_720'), array('a', 'b', 'c'), null, null), + 26283 => array(array('_route' => '_745'), array('a', 'b', 'c'), null, null), + 26333 => array(array('_route' => '_874'), array('a', 'b', 'c'), null, null), + 26391 => array(array('_route' => '_502'), array('a', 'b', 'c'), null, null), + 26439 => array(array('_route' => '_667'), array('a', 'b', 'c'), null, null), + 26487 => array(array('_route' => '_911'), array('a', 'b', 'c'), null, null), + 26535 => array(array('_route' => '_942'), array('a', 'b', 'c'), null, null), + 26585 => array(array('_route' => '_504'), array('a', 'b', 'c'), null, null), + 26637 => array(array('_route' => '_524'), array('a', 'b', 'c'), null, null), + 26685 => array(array('_route' => '_732'), array('a', 'b', 'c'), null, null), + 26738 => array(array('_route' => '_596'), array('a', 'b', 'c'), null, null), + 26786 => array(array('_route' => '_601'), array('a', 'b', 'c'), null, null), + 26839 => array(array('_route' => '_620'), array('a', 'b', 'c'), null, null), + 26887 => array(array('_route' => '_631'), array('a', 'b', 'c'), null, null), + 26935 => array(array('_route' => '_771'), array('a', 'b', 'c'), null, null), + 26983 => array(array('_route' => '_937'), array('a', 'b', 'c'), null, null), + 27031 => array(array('_route' => '_999'), array('a', 'b', 'c'), null, null), + 27084 => array(array('_route' => '_657'), array('a', 'b', 'c'), null, null), + 27132 => array(array('_route' => '_701'), array('a', 'b', 'c'), null, null), + 27185 => array(array('_route' => '_662'), array('a', 'b', 'c'), null, null), + 27233 => array(array('_route' => '_797'), array('a', 'b', 'c'), null, null), + 27281 => array(array('_route' => '_924'), array('a', 'b', 'c'), null, null), + 27334 => array(array('_route' => '_702'), array('a', 'b', 'c'), null, null), + 27382 => array(array('_route' => '_750'), array('a', 'b', 'c'), null, null), + 27435 => array(array('_route' => '_749'), array('a', 'b', 'c'), null, null), + 27483 => array(array('_route' => '_837'), array('a', 'b', 'c'), null, null), + 27533 => array(array('_route' => '_758'), array('a', 'b', 'c'), null, null), + 27585 => array(array('_route' => '_810'), array('a', 'b', 'c'), null, null), + 27633 => array(array('_route' => '_902'), array('a', 'b', 'c'), null, null), + 27683 => array(array('_route' => '_845'), array('a', 'b', 'c'), null, null), + 27741 => array(array('_route' => '_503'), array('a', 'b', 'c'), null, null), + 27792 => array(array('_route' => '_756'), array('a', 'b', 'c'), null, null), + 27839 => array(array('_route' => '_799'), array('a', 'b', 'c'), null, null), + 27888 => array(array('_route' => '_769'), array('a', 'b', 'c'), null, null), + 27936 => array(array('_route' => '_981'), array('a', 'b', 'c'), null, null), + 27989 => array(array('_route' => '_507'), array('a', 'b', 'c'), null, null), + 28037 => array(array('_route' => '_672'), array('a', 'b', 'c'), null, null), + 28085 => array(array('_route' => '_790'), array('a', 'b', 'c'), null, null), + 28138 => array(array('_route' => '_515'), array('a', 'b', 'c'), null, null), + 28186 => array(array('_route' => '_523'), array('a', 'b', 'c'), null, null), + 28234 => array(array('_route' => '_957'), array('a', 'b', 'c'), null, null), + 28282 => array(array('_route' => '_995'), array('a', 'b', 'c'), null, null), + 28335 => array(array('_route' => '_532'), array('a', 'b', 'c'), null, null), + 28383 => array(array('_route' => '_642'), array('a', 'b', 'c'), null, null), + 28433 => array(array('_route' => '_579'), array('a', 'b', 'c'), null, null), + 28485 => array(array('_route' => '_625'), array('a', 'b', 'c'), null, null), + 28533 => array(array('_route' => '_916'), array('a', 'b', 'c'), null, null), + 28586 => array(array('_route' => '_633'), array('a', 'b', 'c'), null, null), + 28634 => array(array('_route' => '_656'), array('a', 'b', 'c'), null, null), + 28687 => array(array('_route' => '_658'), array('a', 'b', 'c'), null, null), + 28735 => array(array('_route' => '_943'), array('a', 'b', 'c'), null, null), + 28788 => array(array('_route' => '_664'), array('a', 'b', 'c'), null, null), + 28836 => array(array('_route' => '_852'), array('a', 'b', 'c'), null, null), + 28884 => array(array('_route' => '_870'), array('a', 'b', 'c'), null, null), + 28937 => array(array('_route' => '_683'), array('a', 'b', 'c'), null, null), + 28985 => array(array('_route' => '_915'), array('a', 'b', 'c'), null, null), + 29038 => array(array('_route' => '_719'), array('a', 'b', 'c'), null, null), + 29086 => array(array('_route' => '_859'), array('a', 'b', 'c'), null, null), + 29134 => array(array('_route' => '_912'), array('a', 'b', 'c'), null, null), + 29182 => array(array('_route' => '_978'), array('a', 'b', 'c'), null, null), + 29235 => array(array('_route' => '_738'), array('a', 'b', 'c'), null, null), + 29283 => array(array('_route' => '_883'), array('a', 'b', 'c'), null, null), + 29333 => array(array('_route' => '_741'), array('a', 'b', 'c'), null, null), + 29382 => array(array('_route' => '_760'), array('a', 'b', 'c'), null, null), + 29431 => array(array('_route' => '_895'), array('a', 'b', 'c'), null, null), + 29489 => array(array('_route' => '_505'), array('a', 'b', 'c'), null, null), + 29537 => array(array('_route' => '_935'), array('a', 'b', 'c'), null, null), + 29590 => array(array('_route' => '_509'), array('a', 'b', 'c'), null, null), + 29638 => array(array('_route' => '_820'), array('a', 'b', 'c'), null, null), + 29686 => array(array('_route' => '_910'), array('a', 'b', 'c'), null, null), + 29739 => array(array('_route' => '_518'), array('a', 'b', 'c'), null, null), + 29787 => array(array('_route' => '_618'), array('a', 'b', 'c'), null, null), + 29840 => array(array('_route' => '_546'), array('a', 'b', 'c'), null, null), + 29888 => array(array('_route' => '_740'), array('a', 'b', 'c'), null, null), + 29936 => array(array('_route' => '_867'), array('a', 'b', 'c'), null, null), + 29989 => array(array('_route' => '_572'), array('a', 'b', 'c'), null, null), + 30037 => array(array('_route' => '_952'), array('a', 'b', 'c'), null, null), + 30090 => array(array('_route' => '_573'), array('a', 'b', 'c'), null, null), + 30138 => array(array('_route' => '_692'), array('a', 'b', 'c'), null, null), + 30186 => array(array('_route' => '_700'), array('a', 'b', 'c'), null, null), + 30234 => array(array('_route' => '_772'), array('a', 'b', 'c'), null, null), + 30284 => array(array('_route' => '_653'), array('a', 'b', 'c'), null, null), + 30336 => array(array('_route' => '_695'), array('a', 'b', 'c'), null, null), + 30384 => array(array('_route' => '_748'), array('a', 'b', 'c'), null, null), + 30437 => array(array('_route' => '_710'), array('a', 'b', 'c'), null, null), + 30485 => array(array('_route' => '_716'), array('a', 'b', 'c'), null, null), + 30533 => array(array('_route' => '_969'), array('a', 'b', 'c'), null, null), + 30586 => array(array('_route' => '_734'), array('a', 'b', 'c'), null, null), + 30634 => array(array('_route' => '_742'), array('a', 'b', 'c'), null, null), + 30682 => array(array('_route' => '_844'), array('a', 'b', 'c'), null, null), + 30735 => array(array('_route' => '_763'), array('a', 'b', 'c'), null, null), + 30783 => array(array('_route' => '_965'), array('a', 'b', 'c'), null, null), + 30836 => array(array('_route' => '_778'), array('a', 'b', 'c'), null, null), + 30884 => array(array('_route' => '_813'), array('a', 'b', 'c'), null, null), + 30932 => array(array('_route' => '_831'), array('a', 'b', 'c'), null, null), + 30982 => array(array('_route' => '_955'), array('a', 'b', 'c'), null, null), + 31031 => array(array('_route' => '_997'), array('a', 'b', 'c'), null, null), + 31089 => array(array('_route' => '_506'), array('a', 'b', 'c'), null, null), + 31137 => array(array('_route' => '_575'), array('a', 'b', 'c'), null, null), + 31190 => array(array('_route' => '_516'), array('a', 'b', 'c'), null, null), + 31238 => array(array('_route' => '_553'), array('a', 'b', 'c'), null, null), + 31291 => array(array('_route' => '_528'), array('a', 'b', 'c'), null, null), + 31339 => array(array('_route' => '_847'), array('a', 'b', 'c'), null, null), + 31387 => array(array('_route' => '_904'), array('a', 'b', 'c'), null, null), + 31440 => array(array('_route' => '_574'), array('a', 'b', 'c'), null, null), + 31488 => array(array('_route' => '_818'), array('a', 'b', 'c'), null, null), + 31538 => array(array('_route' => '_577'), array('a', 'b', 'c'), null, null), + 31590 => array(array('_route' => '_584'), array('a', 'b', 'c'), null, null), + 31638 => array(array('_route' => '_905'), array('a', 'b', 'c'), null, null), + 31691 => array(array('_route' => '_612'), array('a', 'b', 'c'), null, null), + 31739 => array(array('_route' => '_688'), array('a', 'b', 'c'), null, null), + 31787 => array(array('_route' => '_854'), array('a', 'b', 'c'), null, null), + 31840 => array(array('_route' => '_613'), array('a', 'b', 'c'), null, null), + 31888 => array(array('_route' => '_767'), array('a', 'b', 'c'), null, null), + 31941 => array(array('_route' => '_666'), array('a', 'b', 'c'), null, null), + 31989 => array(array('_route' => '_759'), array('a', 'b', 'c'), null, null), + 32037 => array(array('_route' => '_827'), array('a', 'b', 'c'), null, null), + 32085 => array(array('_route' => '_840'), array('a', 'b', 'c'), null, null), + 32138 => array(array('_route' => '_680'), array('a', 'b', 'c'), null, null), + 32186 => array(array('_route' => '_784'), array('a', 'b', 'c'), null, null), + 32234 => array(array('_route' => '_842'), array('a', 'b', 'c'), null, null), + 32282 => array(array('_route' => '_860'), array('a', 'b', 'c'), null, null), + 32332 => array(array('_route' => '_704'), array('a', 'b', 'c'), null, null), + 32381 => array(array('_route' => '_727'), array('a', 'b', 'c'), null, null), + 32430 => array(array('_route' => '_777'), array('a', 'b', 'c'), null, null), + 32482 => array(array('_route' => '_838'), array('a', 'b', 'c'), null, null), + 32530 => array(array('_route' => '_861'), array('a', 'b', 'c'), null, null), + 32583 => array(array('_route' => '_849'), array('a', 'b', 'c'), null, null), + 32631 => array(array('_route' => '_982'), array('a', 'b', 'c'), null, null), + 32679 => array(array('_route' => '_986'), array('a', 'b', 'c'), null, null), + 32741 => array(array('_route' => '_508'), array('a', 'b', 'c'), null, null), + 32788 => array(array('_route' => '_517'), array('a', 'b', 'c'), null, null), + 32837 => array(array('_route' => '_622'), array('a', 'b', 'c'), null, null), + 32890 => array(array('_route' => '_513'), array('a', 'b', 'c'), null, null), + 32938 => array(array('_route' => '_655'), array('a', 'b', 'c'), null, null), + 32986 => array(array('_route' => '_843'), array('a', 'b', 'c'), null, null), + 33034 => array(array('_route' => '_939'), array('a', 'b', 'c'), null, null), + 33084 => array(array('_route' => '_529'), array('a', 'b', 'c'), null, null), + 33136 => array(array('_route' => '_535'), array('a', 'b', 'c'), null, null), + 33184 => array(array('_route' => '_685'), array('a', 'b', 'c'), null, null), + 33240 => array(array('_route' => '_559'), array('a', 'b', 'c'), null, null), + 33287 => array(array('_route' => '_661'), array('a', 'b', 'c'), null, null), + 33336 => array(array('_route' => '_768'), array('a', 'b', 'c'), null, null), + 33389 => array(array('_route' => '_589'), array('a', 'b', 'c'), null, null), + 33437 => array(array('_route' => '_647'), array('a', 'b', 'c'), null, null), + 33485 => array(array('_route' => '_652'), array('a', 'b', 'c'), null, null), + 33533 => array(array('_route' => '_834'), array('a', 'b', 'c'), null, null), + 33586 => array(array('_route' => '_591'), array('a', 'b', 'c'), null, null), + 33634 => array(array('_route' => '_599'), array('a', 'b', 'c'), null, null), + 33687 => array(array('_route' => '_787'), array('a', 'b', 'c'), null, null), + 33734 => array(array('_route' => '_848'), array('a', 'b', 'c'), null, null), + 33787 => array(array('_route' => '_796'), array('a', 'b', 'c'), null, null), + 33835 => array(array('_route' => '_877'), array('a', 'b', 'c'), null, null), + 33885 => array(array('_route' => '_809'), array('a', 'b', 'c'), null, null), + 33934 => array(array('_route' => '_817'), array('a', 'b', 'c'), null, null), + 33986 => array(array('_route' => '_819'), array('a', 'b', 'c'), null, null), + 34034 => array(array('_route' => '_865'), array('a', 'b', 'c'), null, null), + 34084 => array(array('_route' => '_919'), array('a', 'b', 'c'), null, null), + 34133 => array(array('_route' => '_949'), array('a', 'b', 'c'), null, null), + 34191 => array(array('_route' => '_510'), array('a', 'b', 'c'), null, null), + 34239 => array(array('_route' => '_590'), array('a', 'b', 'c'), null, null), + 34287 => array(array('_route' => '_597'), array('a', 'b', 'c'), null, null), + 34335 => array(array('_route' => '_682'), array('a', 'b', 'c'), null, null), + 34383 => array(array('_route' => '_723'), array('a', 'b', 'c'), null, null), + 34436 => array(array('_route' => '_521'), array('a', 'b', 'c'), null, null), + 34484 => array(array('_route' => '_594'), array('a', 'b', 'c'), null, null), + 34532 => array(array('_route' => '_689'), array('a', 'b', 'c'), null, null), + 34580 => array(array('_route' => '_713'), array('a', 'b', 'c'), null, null), + 34628 => array(array('_route' => '_889'), array('a', 'b', 'c'), null, null), + 34681 => array(array('_route' => '_531'), array('a', 'b', 'c'), null, null), + 34729 => array(array('_route' => '_639'), array('a', 'b', 'c'), null, null), + 34780 => array(array('_route' => '_646'), array('a', 'b', 'c'), null, null), + 34827 => array(array('_route' => '_659'), array('a', 'b', 'c'), null, null), + 34876 => array(array('_route' => '_959'), array('a', 'b', 'c'), null, null), + 34929 => array(array('_route' => '_550'), array('a', 'b', 'c'), null, null), + 34977 => array(array('_route' => '_833'), array('a', 'b', 'c'), null, null), + 35025 => array(array('_route' => '_899'), array('a', 'b', 'c'), null, null), + 35081 => array(array('_route' => '_580'), array('a', 'b', 'c'), null, null), + 35128 => array(array('_route' => '_762'), array('a', 'b', 'c'), null, null), + 35177 => array(array('_route' => '_896'), array('a', 'b', 'c'), null, null), + 35230 => array(array('_route' => '_595'), array('a', 'b', 'c'), null, null), + 35278 => array(array('_route' => '_933'), array('a', 'b', 'c'), null, null), + 35328 => array(array('_route' => '_610'), array('a', 'b', 'c'), null, null), + 35380 => array(array('_route' => '_629'), array('a', 'b', 'c'), null, null), + 35428 => array(array('_route' => '_744'), array('a', 'b', 'c'), null, null), + 35481 => array(array('_route' => '_674'), array('a', 'b', 'c'), null, null), + 35529 => array(array('_route' => '_726'), array('a', 'b', 'c'), null, null), + 35577 => array(array('_route' => '_929'), array('a', 'b', 'c'), null, null), + 35627 => array(array('_route' => '_696'), array('a', 'b', 'c'), null, null), + 35679 => array(array('_route' => '_841'), array('a', 'b', 'c'), null, null), + 35727 => array(array('_route' => '_890'), array('a', 'b', 'c'), null, null), + 35777 => array(array('_route' => '_885'), array('a', 'b', 'c'), null, null), + 35826 => array(array('_route' => '_888'), array('a', 'b', 'c'), null, null), + 35875 => array(array('_route' => '_996'), array('a', 'b', 'c'), null, null), + 35933 => array(array('_route' => '_511'), array('a', 'b', 'c'), null, null), + 35981 => array(array('_route' => '_576'), array('a', 'b', 'c'), null, null), + 36029 => array(array('_route' => '_623'), array('a', 'b', 'c'), null, null), + 36082 => array(array('_route' => '_560'), array('a', 'b', 'c'), null, null), + 36129 => array(array('_route' => '_585'), array('a', 'b', 'c'), null, null), + 36182 => array(array('_route' => '_570'), array('a', 'b', 'c'), null, null), + 36230 => array(array('_route' => '_578'), array('a', 'b', 'c'), null, null), + 36281 => array(array('_route' => '_780'), array('a', 'b', 'c'), null, null), + 36328 => array(array('_route' => '_808'), array('a', 'b', 'c'), null, null), + 36382 => array(array('_route' => '_593'), array('a', 'b', 'c'), null, null), + 36430 => array(array('_route' => '_900'), array('a', 'b', 'c'), null, null), + 36483 => array(array('_route' => '_632'), array('a', 'b', 'c'), null, null), + 36531 => array(array('_route' => '_654'), array('a', 'b', 'c'), null, null), + 36579 => array(array('_route' => '_721'), array('a', 'b', 'c'), null, null), + 36627 => array(array('_route' => '_836'), array('a', 'b', 'c'), null, null), + 36680 => array(array('_route' => '_637'), array('a', 'b', 'c'), null, null), + 36728 => array(array('_route' => '_737'), array('a', 'b', 'c'), null, null), + 36784 => array(array('_route' => '_699'), array('a', 'b', 'c'), null, null), + 36831 => array(array('_route' => '_822'), array('a', 'b', 'c'), null, null), + 36880 => array(array('_route' => '_853'), array('a', 'b', 'c'), null, null), + 36933 => array(array('_route' => '_708'), array('a', 'b', 'c'), null, null), + 36981 => array(array('_route' => '_871'), array('a', 'b', 'c'), null, null), + 37034 => array(array('_route' => '_752'), array('a', 'b', 'c'), null, null), + 37082 => array(array('_route' => '_989'), array('a', 'b', 'c'), null, null), + 37132 => array(array('_route' => '_855'), array('a', 'b', 'c'), null, null), + 37184 => array(array('_route' => '_858'), array('a', 'b', 'c'), null, null), + 37232 => array(array('_route' => '_898'), array('a', 'b', 'c'), null, null), + 37282 => array(array('_route' => '_903'), array('a', 'b', 'c'), null, null), + 37331 => array(array('_route' => '_909'), array('a', 'b', 'c'), null, null), + 37380 => array(array('_route' => '_950'), array('a', 'b', 'c'), null, null), + 37441 => array(array('_route' => '_512'), array('a', 'b', 'c'), null, null), + 37488 => array(array('_route' => '_691'), array('a', 'b', 'c'), null, null), + 37537 => array(array('_route' => '_686'), array('a', 'b', 'c'), null, null), + 37587 => array(array('_route' => '_527'), array('a', 'b', 'c'), null, null), + 37639 => array(array('_route' => '_541'), array('a', 'b', 'c'), null, null), + 37687 => array(array('_route' => '_956'), array('a', 'b', 'c'), null, null), + 37740 => array(array('_route' => '_555'), array('a', 'b', 'c'), null, null), + 37788 => array(array('_route' => '_681'), array('a', 'b', 'c'), null, null), + 37841 => array(array('_route' => '_556'), array('a', 'b', 'c'), null, null), + 37889 => array(array('_route' => '_802'), array('a', 'b', 'c'), null, null), + 37939 => array(array('_route' => '_558'), array('a', 'b', 'c'), null, null), + 37991 => array(array('_route' => '_564'), array('a', 'b', 'c'), null, null), + 38039 => array(array('_route' => '_670'), array('a', 'b', 'c'), null, null), + 38087 => array(array('_route' => '_884'), array('a', 'b', 'c'), null, null), + 38140 => array(array('_route' => '_627'), array('a', 'b', 'c'), null, null), + 38187 => array(array('_route' => '_746'), array('a', 'b', 'c'), null, null), + 38240 => array(array('_route' => '_668'), array('a', 'b', 'c'), null, null), + 38291 => array(array('_route' => '_712'), array('a', 'b', 'c'), null, null), + 38338 => array(array('_route' => '_863'), array('a', 'b', 'c'), null, null), + 38387 => array(array('_route' => '_801'), array('a', 'b', 'c'), null, null), + 38440 => array(array('_route' => '_709'), array('a', 'b', 'c'), null, null), + 38488 => array(array('_route' => '_850'), array('a', 'b', 'c'), null, null), + 38536 => array(array('_route' => '_918'), array('a', 'b', 'c'), null, null), + 38586 => array(array('_route' => '_803'), array('a', 'b', 'c'), null, null), + 38638 => array(array('_route' => '_864'), array('a', 'b', 'c'), null, null), + 38686 => array(array('_route' => '_880'), array('a', 'b', 'c'), null, null), + 38734 => array(array('_route' => '_927'), array('a', 'b', 'c'), null, null), + 38787 => array(array('_route' => '_930'), array('a', 'b', 'c'), null, null), + 38835 => array(array('_route' => '_951'), array('a', 'b', 'c'), null, null), + 38883 => array(array('_route' => '_963'), array('a', 'b', 'c'), null, null), + 38942 => array(array('_route' => '_519'), array('a', 'b', 'c'), null, null), + 38990 => array(array('_route' => '_823'), array('a', 'b', 'c'), null, null), + 39038 => array(array('_route' => '_954'), array('a', 'b', 'c'), null, null), + 39091 => array(array('_route' => '_525'), array('a', 'b', 'c'), null, null), + 39139 => array(array('_route' => '_991'), array('a', 'b', 'c'), null, null), + 39189 => array(array('_route' => '_536'), array('a', 'b', 'c'), null, null), + 39241 => array(array('_route' => '_545'), array('a', 'b', 'c'), null, null), + 39289 => array(array('_route' => '_944'), array('a', 'b', 'c'), null, null), + 39342 => array(array('_route' => '_557'), array('a', 'b', 'c'), null, null), + 39390 => array(array('_route' => '_783'), array('a', 'b', 'c'), null, null), + 39438 => array(array('_route' => '_807'), array('a', 'b', 'c'), null, null), + 39491 => array(array('_route' => '_586'), array('a', 'b', 'c'), null, null), + 39539 => array(array('_route' => '_711'), array('a', 'b', 'c'), null, null), + 39592 => array(array('_route' => '_598'), array('a', 'b', 'c'), null, null), + 39640 => array(array('_route' => '_635'), array('a', 'b', 'c'), null, null), + 39688 => array(array('_route' => '_983'), array('a', 'b', 'c'), null, null), + 39741 => array(array('_route' => '_634'), array('a', 'b', 'c'), null, null), + 39789 => array(array('_route' => '_641'), array('a', 'b', 'c'), null, null), + 39840 => array(array('_route' => '_779'), array('a', 'b', 'c'), null, null), + 39887 => array(array('_route' => '_876'), array('a', 'b', 'c'), null, null), + 39936 => array(array('_route' => '_811'), array('a', 'b', 'c'), null, null), + 39984 => array(array('_route' => '_824'), array('a', 'b', 'c'), null, null), + 40037 => array(array('_route' => '_660'), array('a', 'b', 'c'), null, null), + 40085 => array(array('_route' => '_789'), array('a', 'b', 'c'), null, null), + 40138 => array(array('_route' => '_733'), array('a', 'b', 'c'), null, null), + 40186 => array(array('_route' => '_735'), array('a', 'b', 'c'), null, null), + 40234 => array(array('_route' => '_882'), array('a', 'b', 'c'), null, null), + 40282 => array(array('_route' => '_967'), array('a', 'b', 'c'), null, null), + 40332 => array(array('_route' => '_736'), array('a', 'b', 'c'), null, null), + 40381 => array(array('_route' => '_753'), array('a', 'b', 'c'), null, null), + 40430 => array(array('_route' => '_786'), array('a', 'b', 'c'), null, null), + 40479 => array(array('_route' => '_907'), array('a', 'b', 'c'), null, null), + 40528 => array(array('_route' => '_920'), array('a', 'b', 'c'), null, null), + 40577 => array(array('_route' => '_971'), array('a', 'b', 'c'), null, null), + 40635 => array(array('_route' => '_520'), array('a', 'b', 'c'), null, null), + 40683 => array(array('_route' => '_891'), array('a', 'b', 'c'), null, null), + 40739 => array(array('_route' => '_534'), array('a', 'b', 'c'), null, null), + 40785 => array(array('_route' => '_602'), array('a', 'b', 'c'), null, null), + 40834 => array(array('_route' => '_605'), array('a', 'b', 'c'), null, null), + 40882 => array(array('_route' => '_979'), array('a', 'b', 'c'), null, null), + 40932 => array(array('_route' => '_547'), array('a', 'b', 'c'), null, null), + 40987 => array(array('_route' => '_549'), array('a', 'b', 'c'), null, null), + 41034 => array(array('_route' => '_755'), array('a', 'b', 'c'), null, null), + 41083 => array(array('_route' => '_922'), array('a', 'b', 'c'), null, null), + 41131 => array(array('_route' => '_977'), array('a', 'b', 'c'), null, null), + 41184 => array(array('_route' => '_565'), array('a', 'b', 'c'), null, null), + 41232 => array(array('_route' => '_926'), array('a', 'b', 'c'), null, null), + 41282 => array(array('_route' => '_571'), array('a', 'b', 'c'), null, null), + 41331 => array(array('_route' => '_581'), array('a', 'b', 'c'), null, null), + 41380 => array(array('_route' => '_619'), array('a', 'b', 'c'), null, null), + 41429 => array(array('_route' => '_636'), array('a', 'b', 'c'), null, null), + 41481 => array(array('_route' => '_679'), array('a', 'b', 'c'), null, null), + 41529 => array(array('_route' => '_866'), array('a', 'b', 'c'), null, null), + 41577 => array(array('_route' => '_973'), array('a', 'b', 'c'), null, null), + 41630 => array(array('_route' => '_690'), array('a', 'b', 'c'), null, null), + 41678 => array(array('_route' => '_775'), array('a', 'b', 'c'), null, null), + 41731 => array(array('_route' => '_722'), array('a', 'b', 'c'), null, null), + 41779 => array(array('_route' => '_906'), array('a', 'b', 'c'), null, null), + 41827 => array(array('_route' => '_946'), array('a', 'b', 'c'), null, null), + 41877 => array(array('_route' => '_788'), array('a', 'b', 'c'), null, null), + 41929 => array(array('_route' => '_828'), array('a', 'b', 'c'), null, null), + 41977 => array(array('_route' => '_892'), array('a', 'b', 'c'), null, null), + 42025 => array(array('_route' => '_972'), array('a', 'b', 'c'), null, null), + 42075 => array(array('_route' => '_829'), array('a', 'b', 'c'), null, null), + 42127 => array(array('_route' => '_923'), array('a', 'b', 'c'), null, null), + 42175 => array(array('_route' => '_947'), array('a', 'b', 'c'), null, null), + 42234 => array(array('_route' => '_526'), array('a', 'b', 'c'), null, null), + 42282 => array(array('_route' => '_614'), array('a', 'b', 'c'), null, null), + 42330 => array(array('_route' => '_621'), array('a', 'b', 'c'), null, null), + 42383 => array(array('_route' => '_543'), array('a', 'b', 'c'), null, null), + 42431 => array(array('_route' => '_812'), array('a', 'b', 'c'), null, null), + 42487 => array(array('_route' => '_548'), array('a', 'b', 'c'), null, null), + 42534 => array(array('_route' => '_747'), array('a', 'b', 'c'), null, null), + 42583 => array(array('_route' => '_715'), array('a', 'b', 'c'), null, null), + 42631 => array(array('_route' => '_940'), array('a', 'b', 'c'), null, null), + 42684 => array(array('_route' => '_563'), array('a', 'b', 'c'), null, null), + 42732 => array(array('_route' => '_611'), array('a', 'b', 'c'), null, null), + 42780 => array(array('_route' => '_830'), array('a', 'b', 'c'), null, null), + 42833 => array(array('_route' => '_569'), array('a', 'b', 'c'), null, null), + 42881 => array(array('_route' => '_908'), array('a', 'b', 'c'), null, null), + 42929 => array(array('_route' => '_913'), array('a', 'b', 'c'), null, null), + 42982 => array(array('_route' => '_644'), array('a', 'b', 'c'), null, null), + 43030 => array(array('_route' => '_776'), array('a', 'b', 'c'), null, null), + 43078 => array(array('_route' => '_856'), array('a', 'b', 'c'), null, null), + 43131 => array(array('_route' => '_650'), array('a', 'b', 'c'), null, null), + 43179 => array(array('_route' => '_761'), array('a', 'b', 'c'), null, null), + 43232 => array(array('_route' => '_663'), array('a', 'b', 'c'), null, null), + 43280 => array(array('_route' => '_754'), array('a', 'b', 'c'), null, null), + 43333 => array(array('_route' => '_665'), array('a', 'b', 'c'), null, null), + 43381 => array(array('_route' => '_805'), array('a', 'b', 'c'), null, null), + 43429 => array(array('_route' => '_846'), array('a', 'b', 'c'), null, null), + 43477 => array(array('_route' => '_857'), array('a', 'b', 'c'), null, null), + 43530 => array(array('_route' => '_675'), array('a', 'b', 'c'), null, null), + 43578 => array(array('_route' => '_839'), array('a', 'b', 'c'), null, null), + 43626 => array(array('_route' => '_968'), array('a', 'b', 'c'), null, null), + 43676 => array(array('_route' => '_697'), array('a', 'b', 'c'), null, null), + 43728 => array(array('_route' => '_725'), array('a', 'b', 'c'), null, null), + 43776 => array(array('_route' => '_794'), array('a', 'b', 'c'), null, null), + 43829 => array(array('_route' => '_773'), array('a', 'b', 'c'), null, null), + 43877 => array(array('_route' => '_992'), array('a', 'b', 'c'), null, null), + 43930 => array(array('_route' => '_901'), array('a', 'b', 'c'), null, null), + 43978 => array(array('_route' => '_970'), array('a', 'b', 'c'), null, null), + 44028 => array(array('_route' => '_964'), array('a', 'b', 'c'), null, null), + 44086 => array(array('_route' => '_530'), array('a', 'b', 'c'), null, null), + 44134 => array(array('_route' => '_703'), array('a', 'b', 'c'), null, null), + 44187 => array(array('_route' => '_533'), array('a', 'b', 'c'), null, null), + 44235 => array(array('_route' => '_739'), array('a', 'b', 'c'), null, null), + 44283 => array(array('_route' => '_791'), array('a', 'b', 'c'), null, null), + 44331 => array(array('_route' => '_987'), array('a', 'b', 'c'), null, null), + 44384 => array(array('_route' => '_566'), array('a', 'b', 'c'), null, null), + 44432 => array(array('_route' => '_592'), array('a', 'b', 'c'), null, null), + 44488 => array(array('_route' => '_568'), array('a', 'b', 'c'), null, null), + 44534 => array(array('_route' => '_868'), array('a', 'b', 'c'), null, null), + 44583 => array(array('_route' => '_878'), array('a', 'b', 'c'), null, null), + 44636 => array(array('_route' => '_588'), array('a', 'b', 'c'), null, null), + 44684 => array(array('_route' => '_793'), array('a', 'b', 'c'), null, null), + 44732 => array(array('_route' => '_917'), array('a', 'b', 'c'), null, null), + 44785 => array(array('_route' => '_600'), array('a', 'b', 'c'), null, null), + 44833 => array(array('_route' => '_728'), array('a', 'b', 'c'), null, null), + 44886 => array(array('_route' => '_603'), array('a', 'b', 'c'), null, null), + 44934 => array(array('_route' => '_765'), array('a', 'b', 'c'), null, null), + 44987 => array(array('_route' => '_607'), array('a', 'b', 'c'), null, null), + 45035 => array(array('_route' => '_676'), array('a', 'b', 'c'), null, null), + 45083 => array(array('_route' => '_804'), array('a', 'b', 'c'), null, null), + 45136 => array(array('_route' => '_609'), array('a', 'b', 'c'), null, null), + 45184 => array(array('_route' => '_961'), array('a', 'b', 'c'), null, null), + 45232 => array(array('_route' => '_980'), array('a', 'b', 'c'), null, null), + 45282 => array(array('_route' => '_714'), array('a', 'b', 'c'), null, null), + 45334 => array(array('_route' => '_730'), array('a', 'b', 'c'), null, null), + 45382 => array(array('_route' => '_806'), array('a', 'b', 'c'), null, null), + 45430 => array(array('_route' => '_825'), array('a', 'b', 'c'), null, null), + 45478 => array(array('_route' => '_879'), array('a', 'b', 'c'), null, null), + 45526 => array(array('_route' => '_893'), array('a', 'b', 'c'), null, null), + 45576 => array(array('_route' => '_928'), array('a', 'b', 'c'), null, null), + 45628 => array(array('_route' => '_932'), array('a', 'b', 'c'), null, null), + 45676 => array(array('_route' => '_958'), array('a', 'b', 'c'), null, null), + 45726 => array(array('_route' => '_984'), array('a', 'b', 'c'), null, null), + 45784 => array(array('_route' => '_538'), array('a', 'b', 'c'), null, null), + 45832 => array(array('_route' => '_993'), array('a', 'b', 'c'), null, null), + 45882 => array(array('_route' => '_542'), array('a', 'b', 'c'), null, null), + 45934 => array(array('_route' => '_551'), array('a', 'b', 'c'), null, null), + 45982 => array(array('_route' => '_687'), array('a', 'b', 'c'), null, null), + 46030 => array(array('_route' => '_724'), array('a', 'b', 'c'), null, null), + 46078 => array(array('_route' => '_925'), array('a', 'b', 'c'), null, null), + 46131 => array(array('_route' => '_587'), array('a', 'b', 'c'), null, null), + 46179 => array(array('_route' => '_914'), array('a', 'b', 'c'), null, null), + 46229 => array(array('_route' => '_616'), array('a', 'b', 'c'), null, null), + 46284 => array(array('_route' => '_677'), array('a', 'b', 'c'), null, null), + 46331 => array(array('_route' => '_815'), array('a', 'b', 'c'), null, null), + 46380 => array(array('_route' => '_781'), array('a', 'b', 'c'), null, null), + 46430 => array(array('_route' => '_717'), array('a', 'b', 'c'), null, null), + 46482 => array(array('_route' => '_782'), array('a', 'b', 'c'), null, null), + 46530 => array(array('_route' => '_832'), array('a', 'b', 'c'), null, null), + 46583 => array(array('_route' => '_795'), array('a', 'b', 'c'), null, null), + 46631 => array(array('_route' => '_887'), array('a', 'b', 'c'), null, null), + 46681 => array(array('_route' => '_800'), array('a', 'b', 'c'), null, null), + 46730 => array(array('_route' => '_826'), array('a', 'b', 'c'), null, null), + 46779 => array(array('_route' => '_881'), array('a', 'b', 'c'), null, null), + 46828 => array(array('_route' => '_886'), array('a', 'b', 'c'), null, null), + 46877 => array(array('_route' => '_938'), array('a', 'b', 'c'), null, null), + 46935 => array(array('_route' => '_540'), array('a', 'b', 'c'), null, null), + 46983 => array(array('_route' => '_643'), array('a', 'b', 'c'), null, null), + 47033 => array(array('_route' => '_544'), array('a', 'b', 'c'), null, null), + 47082 => array(array('_route' => '_552'), array('a', 'b', 'c'), null, null), + 47134 => array(array('_route' => '_567'), array('a', 'b', 'c'), null, null), + 47182 => array(array('_route' => '_608'), array('a', 'b', 'c'), null, null), + 47230 => array(array('_route' => '_698'), array('a', 'b', 'c'), null, null), + 47278 => array(array('_route' => '_988'), array('a', 'b', 'c'), null, null), + 47331 => array(array('_route' => '_583'), array('a', 'b', 'c'), null, null), + 47379 => array(array('_route' => '_998'), array('a', 'b', 'c'), null, null), + 47432 => array(array('_route' => '_604'), array('a', 'b', 'c'), null, null), + 47480 => array(array('_route' => '_630'), array('a', 'b', 'c'), null, null), + 47528 => array(array('_route' => '_706'), array('a', 'b', 'c'), null, null), + 47576 => array(array('_route' => '_976'), array('a', 'b', 'c'), null, null), + 47629 => array(array('_route' => '_673'), array('a', 'b', 'c'), null, null), + 47677 => array(array('_route' => '_678'), array('a', 'b', 'c'), null, null), + 47725 => array(array('_route' => '_931'), array('a', 'b', 'c'), null, null), + 47775 => array(array('_route' => '_751'), array('a', 'b', 'c'), null, null), + 47824 => array(array('_route' => '_766'), array('a', 'b', 'c'), null, null), + 47876 => array(array('_route' => '_792'), array('a', 'b', 'c'), null, null), + 47924 => array(array('_route' => '_814'), array('a', 'b', 'c'), null, null), + 47974 => array(array('_route' => '_798'), array('a', 'b', 'c'), null, null), + 48026 => array(array('_route' => '_851'), array('a', 'b', 'c'), null, null), + 48074 => array(array('_route' => '_941'), array('a', 'b', 'c'), null, null), + 48122 => array(array('_route' => '_953'), array('a', 'b', 'c'), null, null), + 48170 => array(array('_route' => '_975'), array('a', 'b', 'c'), null, null), + 48220 => array(array('_route' => '_873'), array('a', 'b', 'c'), null, null), + 48269 => array(array('_route' => '_936'), array('a', 'b', 'c'), null, null), + 48318 => array(array('_route' => '_994'), array('a', 'b', 'c'), null, null), + 48376 => array(array('_route' => '_562'), array('a', 'b', 'c'), null, null), + 48424 => array(array('_route' => '_770'), array('a', 'b', 'c'), null, null), + 48475 => array(array('_route' => '_774'), array('a', 'b', 'c'), null, null), + 48522 => array(array('_route' => '_966'), array('a', 'b', 'c'), null, null), + 48573 => array(array('_route' => '_582'), array('a', 'b', 'c'), null, null), + 48625 => array(array('_route' => '_606'), array('a', 'b', 'c'), null, null), + 48673 => array(array('_route' => '_648'), array('a', 'b', 'c'), null, null), + 48723 => array(array('_route' => '_624'), array('a', 'b', 'c'), null, null), + 48775 => array(array('_route' => '_626'), array('a', 'b', 'c'), null, null), + 48823 => array(array('_route' => '_821'), array('a', 'b', 'c'), null, null), + 48873 => array(array('_route' => '_628'), array('a', 'b', 'c'), null, null), + 48922 => array(array('_route' => '_638'), array('a', 'b', 'c'), null, null), + 48974 => array(array('_route' => '_640'), array('a', 'b', 'c'), null, null), + 49022 => array(array('_route' => '_990'), array('a', 'b', 'c'), null, null), + 49072 => array(array('_route' => '_705'), array('a', 'b', 'c'), null, null), + 49121 => array(array('_route' => '_757'), array('a', 'b', 'c'), null, null), + 49176 => array(array('_route' => '_785'), array('a', 'b', 'c'), null, null), + 49223 => array(array('_route' => '_875'), array('a', 'b', 'c'), null, null), + 49270 => array(array('_route' => '_894'), array('a', 'b', 'c'), null, null), + 49319 => array(array('_route' => '_945'), array('a', 'b', 'c'), null, null), + 49375 => array(array('_route' => '_816'), array('a', 'b', 'c'), null, null), + 49422 => array(array('_route' => '_872'), array('a', 'b', 'c'), null, null), + 49471 => array(array('_route' => '_921'), array('a', 'b', 'c'), null, null), + 49519 => array(array('_route' => '_960'), array('a', 'b', 'c'), null, null), + 49567 => array(array('_route' => '_974'), array('a', 'b', 'c'), null, null), + 49620 => array(array('_route' => '_835'), array('a', 'b', 'c'), null, null), + 49668 => array(array('_route' => '_934'), array('a', 'b', 'c'), null, null), + 49718 => array(array('_route' => '_869'), array('a', 'b', 'c'), null, null), ); list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m]; @@ -2814,7 +2814,7 @@ public function match($rawPathinfo) return $ret; } - if (49726 === $m) { + if (49718 === $m) { break; } $regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m)); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php index 7571aa75d1d3..02f6ac949eb2 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher12.php @@ -29,13 +29,21 @@ public function match($rawPathinfo) $matchedPathinfo = $pathinfo; $regexList = array( 0 => '{^(?' - .'|/abc(?' - .'|([^/]++)/1(*:24)' - .'|([^/]++)/2(*:41)' - .'|([^/]++)/10(*:59)' - .'|([^/]++)/20(*:77)' - .'|([^/]++)/100(*:96)' - .'|([^/]++)/200(*:115)' + .'|/abc([^/]++)/(?' + .'|1(?' + .'|(*:27)' + .'|0(?' + .'|(*:38)' + .'|0(*:46)' + .')' + .')' + .'|2(?' + .'|(*:59)' + .'|0(?' + .'|(*:70)' + .'|0(*:78)' + .')' + .')' .')' .')$}sD', ); @@ -45,12 +53,12 @@ public function match($rawPathinfo) switch ($m = (int) $matches['MARK']) { default: $routes = array( - 24 => array(array('_route' => 'r1'), array('foo'), null, null), - 41 => array(array('_route' => 'r2'), array('foo'), null, null), - 59 => array(array('_route' => 'r10'), array('foo'), null, null), - 77 => array(array('_route' => 'r20'), array('foo'), null, null), - 96 => array(array('_route' => 'r100'), array('foo'), null, null), - 115 => array(array('_route' => 'r200'), array('foo'), null, null), + 27 => array(array('_route' => 'r1'), array('foo'), null, null), + 38 => array(array('_route' => 'r10'), array('foo'), null, null), + 46 => array(array('_route' => 'r100'), array('foo'), null, null), + 59 => array(array('_route' => 'r2'), array('foo'), null, null), + 70 => array(array('_route' => 'r20'), array('foo'), null, null), + 78 => array(array('_route' => 'r200'), array('foo'), null, null), ); list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m]; @@ -76,7 +84,7 @@ public function match($rawPathinfo) return $ret; } - if (115 === $m) { + if (78 === $m) { break; } $regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m)); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php index a7ff452cc6ef..b4457d7cdc7e 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher13.php @@ -27,12 +27,12 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - $matchedPathinfo = $host.$pathinfo; + $matchedPathinfo = $host.'.'.$pathinfo; $regexList = array( 0 => '{^(?' - .'|(?i:([^\\.]++)\\.exampple\\.com)(?' + .'|(?i:([^\\.]++)\\.exampple\\.com)\\.(?' .'|/abc([^/]++)(?' - .'|(*:54)' + .'|(*:56)' .')' .')' .')$}sD', @@ -41,7 +41,7 @@ public function match($rawPathinfo) foreach ($regexList as $offset => $regex) { while (preg_match($regex, $matchedPathinfo, $matches)) { switch ($m = (int) $matches['MARK']) { - case 54: + case 56: $matches = array('foo' => $matches[1] ?? null, 'foo' => $matches[2] ?? null); // r1 @@ -53,7 +53,7 @@ public function match($rawPathinfo) break; } - if (54 === $m) { + if (56 === $m) { break; } $regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m)); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index c33e1846a8cf..79b650eb5b26 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -116,50 +116,50 @@ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$a return $ret; } - $matchedPathinfo = $host.$pathinfo; + $matchedPathinfo = $host.'.'.$pathinfo; $regexList = array( 0 => '{^(?' - .'|[^/]*+(?' - .'|/foo/(baz|symfony)(*:34)' + .'|(?:(?:[^.]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:46)' .'|/bar(?' - .'|/([^/]++)(*:57)' - .'|head/([^/]++)(*:77)' + .'|/([^/]++)(*:69)' + .'|head/([^/]++)(*:89)' .')' .'|/test/([^/]++)/(?' - .'|(*:103)' + .'|(*:115)' .')' - .'|/([\']+)(*:119)' + .'|/([\']+)(*:131)' .'|/a/(?' .'|b\'b/([^/]++)(?' - .'|(*:148)' - .'|(*:156)' + .'|(*:160)' + .'|(*:168)' .')' - .'|(.*)(*:169)' + .'|(.*)(*:181)' .'|b\'b/([^/]++)(?' - .'|(*:192)' - .'|(*:200)' + .'|(*:204)' + .'|(*:212)' .')' .')' - .'|/multi/hello(?:/([^/]++))?(*:236)' + .'|/multi/hello(?:/([^/]++))?(*:248)' .'|/([^/]++)/b/([^/]++)(?' - .'|(*:267)' - .'|(*:275)' + .'|(*:279)' + .'|(*:287)' .')' - .'|/aba/([^/]++)(*:297)' - .')|(?i:([^\\.]++)\\.example\\.com)(?' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' .'|/route1(?' - .'|3/([^/]++)(*:357)' - .'|4/([^/]++)(*:375)' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' .')' - .')|(?i:c\\.example\\.com)(?' - .'|/route15/([^/]++)(*:425)' - .')|[^/]*+(?' - .'|/route16/([^/]++)(*:460)' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^.]*+\\.)++)(?' + .'|/route16/([^/]++)(*:488)' .'|/a/(?' - .'|a\\.\\.\\.(*:481)' + .'|a\\.\\.\\.(*:509)' .'|b/(?' - .'|([^/]++)(*:502)' - .'|c/([^/]++)(*:520)' + .'|([^/]++)(*:530)' + .'|c/([^/]++)(*:548)' .')' .')' .')' @@ -169,7 +169,7 @@ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$a foreach ($regexList as $offset => $regex) { while (preg_match($regex, $matchedPathinfo, $matches)) { switch ($m = (int) $matches['MARK']) { - case 103: + case 115: $matches = array('foo' => $matches[1] ?? null); // baz4 @@ -196,7 +196,7 @@ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$a not_bazbaz6: break; - case 148: + case 160: $matches = array('foo' => $matches[1] ?? null); // foo1 @@ -210,14 +210,14 @@ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$a not_foo1: break; - case 192: + case 204: $matches = array('foo1' => $matches[1] ?? null); // foo2 return $this->mergeDefaults(array('_route' => 'foo2') + $matches, array()); break; - case 267: + case 279: $matches = array('_locale' => $matches[1] ?? null, 'foo' => $matches[2] ?? null); // foo3 @@ -226,23 +226,23 @@ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$a break; default: $routes = array( - 34 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null), - 57 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null), - 77 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null), - 119 => array(array('_route' => 'quoter'), array('quoter'), null, null), - 156 => array(array('_route' => 'bar1'), array('bar'), null, null), - 169 => array(array('_route' => 'overridden'), array('var'), null, null), - 200 => array(array('_route' => 'bar2'), array('bar1'), null, null), - 236 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null), - 275 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null), - 297 => array(array('_route' => 'foo4'), array('foo'), null, null), - 357 => array(array('_route' => 'route13'), array('var1', 'name'), null, null), - 375 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null), - 425 => array(array('_route' => 'route15'), array('name'), null, null), - 460 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null), - 481 => array(array('_route' => 'a'), array(), null, null), - 502 => array(array('_route' => 'b'), array('var'), null, null), - 520 => array(array('_route' => 'c'), array('var'), null, null), + 46 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null), + 69 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null), + 89 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null), + 131 => array(array('_route' => 'quoter'), array('quoter'), null, null), + 168 => array(array('_route' => 'bar1'), array('bar'), null, null), + 181 => array(array('_route' => 'overridden'), array('var'), null, null), + 212 => array(array('_route' => 'bar2'), array('bar1'), null, null), + 248 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null), + 287 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null), + 309 => array(array('_route' => 'foo4'), array('foo'), null, null), + 371 => array(array('_route' => 'route13'), array('var1', 'name'), null, null), + 389 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null), + 441 => array(array('_route' => 'route15'), array('name'), null, null), + 488 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null), + 509 => array(array('_route' => 'a'), array(), null, null), + 530 => array(array('_route' => 'b'), array('var'), null, null), + 548 => array(array('_route' => 'c'), array('var'), null, null), ); list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m]; @@ -268,7 +268,7 @@ private function doMatch(string $rawPathinfo, array &$allow = array(), array &$a return $ret; } - if (520 === $m) { + if (548 === $m) { break; } $regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m)); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php index f3163063c432..0f2ce53fed0b 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher8.php @@ -32,10 +32,10 @@ public function match($rawPathinfo) .'|/(a)(*:11)' .')$}sD', 11 => '{^(?' - .'|/(.)(*:26)' + .'|/(.)(*:22)' .')$}sDu', - 26 => '{^(?' - .'|/(.)(*:41)' + 22 => '{^(?' + .'|/(.)(*:33)' .')$}sD', ); @@ -45,8 +45,8 @@ public function match($rawPathinfo) default: $routes = array( 11 => array(array('_route' => 'a'), array('a'), null, null), - 26 => array(array('_route' => 'b'), array('a'), null, null), - 41 => array(array('_route' => 'c'), array('a'), null, null), + 22 => array(array('_route' => 'b'), array('a'), null, null), + 33 => array(array('_route' => 'c'), array('a'), null, null), ); list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m]; @@ -72,7 +72,7 @@ public function match($rawPathinfo) return $ret; } - if (41 === $m) { + if (33 === $m) { break; } $regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m)); diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 1e13f0883e9d..f0013d7bc3d1 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -633,6 +633,43 @@ public function testDotAllWithCatchAll() $this->assertEquals(array('_route' => 'a', 'id' => 'foo/bar'), $matcher->match('/foo/bar.html')); } + public function testHostPattern() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{app}/{action}/{unused}', array(), array(), array(), '{host}')); + + $expected = array( + '_route' => 'a', + 'app' => 'an_app', + 'action' => 'an_action', + 'unused' => 'unused', + 'host' => 'foo', + ); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo')); + $this->assertEquals($expected, $matcher->match('/an_app/an_action/unused')); + } + + public function testUtf8Prefix() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/é{foo}', array(), array(), array('utf8' => true))); + $coll->add('b', new Route('/è{bar}', array(), array(), array('utf8' => true))); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals('a', $matcher->match('/éo')['_route']); + } + + public function testUtf8AndMethodMatching() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/admin/api/list/{shortClassName}/{id}.{_format}', array(), array(), array('utf8' => true), '', array(), array('PUT'))); + $coll->add('b', new Route('/admin/api/package.{_format}', array(), array(), array(), '', array(), array('POST'))); + $coll->add('c', new Route('/admin/api/package.{_format}', array('_format' => 'json'), array(), array(), '', array(), array('GET'))); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals('c', $matcher->match('/admin/api/package.json')['_route']); + } + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) { return new UrlMatcher($routes, $context ?: new RequestContext()); diff --git a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php index 1ce132b4d21a..04bcdac918ac 100644 --- a/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteCompilerTest.php @@ -398,6 +398,7 @@ public function provideRemoveCapturingGroup() yield array('#^/(?P(?:b))$#sD', '(?:b)'); yield array('#^/(?P(?(b)b))$#sD', '(?(b)b)'); yield array('#^/(?P(*F))$#sD', '(*F)'); + yield array('#^/(?P(?:(?:foo)))$#sD', '((foo))'); } } From 322f58b334105e09330809e91e9b09e27b7c1e99 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 9 Jun 2018 21:00:10 +0200 Subject: [PATCH 2/9] [DI] Deduplicate generated proxy classes --- .../DependencyInjection/Dumper/PhpDumper.php | 7 +- .../Tests/Dumper/PhpDumperTest.php | 13 +++ .../Tests/Fixtures/includes/classes.php | 4 +- .../php/services_dedup_lazy_proxy.php | 88 +++++++++++++++++++ .../Fixtures/php/services_non_shared_lazy.php | 4 +- 5 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy_proxy.php diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index d640b9a2351d..560b2516bb3c 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -396,6 +396,7 @@ private function collectLineage($class, array &$lineage) private function generateProxyClasses() { + $alreadyGenerated = array(); $definitions = $this->container->getDefinitions(); $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments'); $proxyDumper = $this->getProxyDumper(); @@ -404,8 +405,12 @@ private function generateProxyClasses() if (!$proxyDumper->isProxyCandidate($definition)) { continue; } + if (isset($alreadyGenerated[$class = $definition->getClass()])) { + continue; + } + $alreadyGenerated[$class] = true; // register class' reflector for resource tracking - $this->container->getReflectionClass($definition->getClass()); + $this->container->getReflectionClass($class); $proxyCode = "\n".$proxyDumper->getProxyCode($definition); if ($strip) { $proxyCode = "addToAssertionCount(1); } + public function testDedupLazyProxy() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass')->setLazy(true)->setPublic(true); + $container->register('bar', 'stdClass')->setLazy(true)->setPublic(true); + $container->compile(); + + $dumper = new PhpDumper($container); + $dumper->setProxyDumper(new \DummyProxyDumper()); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dedup_lazy_proxy.php', $dumper->dump()); + } + public function testLazyArgumentProvideGenerator() { require_once self::$fixturesPath.'/includes/classes.php'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index bced911043c5..33b043fa3f38 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -90,12 +90,12 @@ public function isProxyCandidate(Definition $definition) public function getProxyFactoryCode(Definition $definition, $id, $factoryCall = null) { - return " // lazy factory\n\n"; + return " // lazy factory for {$definition->getClass()}\n\n"; } public function getProxyCode(Definition $definition) { - return "// proxy code\n"; + return "// proxy code for {$definition->getClass()}\n"; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy_proxy.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy_proxy.php new file mode 100644 index 000000000000..73a7f259f86b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dedup_lazy_proxy.php @@ -0,0 +1,88 @@ +services = array(); + $this->methodMap = array( + 'bar' => 'getBarService', + 'foo' => 'getFooService', + ); + + $this->aliases = array(); + } + + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + public function isCompiled() + { + return true; + } + + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + protected function createProxy($class, \Closure $factory) + { + return $factory(); + } + + /** + * Gets the public 'bar' shared service. + * + * @return \stdClass + */ + protected function getBarService($lazyLoad = true) + { + // lazy factory for stdClass + + return new \stdClass(); + } + + /** + * Gets the public 'foo' shared service. + * + * @return \stdClass + */ + protected function getFooService($lazyLoad = true) + { + // lazy factory for stdClass + + return new \stdClass(); + } +} + +// proxy code for stdClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy.php index 9e2f1ab915f8..6c3b1405069f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_non_shared_lazy.php @@ -83,10 +83,10 @@ protected function getBarService() */ protected function getFooService($lazyLoad = true) { - // lazy factory + // lazy factory for stdClass return new \stdClass(); } } -// proxy code +// proxy code for stdClass From 50979b5ea47336e5a052bba88df3746e4e7fb775 Mon Sep 17 00:00:00 2001 From: nsbx Date: Sat, 9 Jun 2018 15:16:17 +0200 Subject: [PATCH 3/9] [PhpUnitBridge] Fix error on some Windows OS --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 552d5abb36b5..197650915fe9 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -70,6 +70,8 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ throw new \RuntimeException("Could not find $remoteZip"); } stream_copy_to_stream($remoteZipStream, fopen("$PHPUNIT_VERSION.zip", 'wb')); + } elseif ('\\' === DIRECTORY_SEPARATOR) { + passthru("certutil -urlcache -split -f \"https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip\" $PHPUNIT_VERSION.zip"); } else { @unlink("$PHPUNIT_VERSION.zip"); passthru("wget -q https://github.com/sebastianbergmann/phpunit/archive/$PHPUNIT_VERSION.zip"); From 85b832bcc9d862d6e372acd19f5d5ef23e46d7fb Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 9 Jun 2018 09:49:02 +0200 Subject: [PATCH 4/9] [HttpKernel] Log/Collect exceptions at prio 0 --- src/Symfony/Component/HttpKernel/CHANGELOG.md | 2 +- .../Component/HttpKernel/EventListener/ExceptionListener.php | 3 +-- .../Component/HttpKernel/EventListener/ProfilerListener.php | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index f64905cbe086..c98d2235e333 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -5,7 +5,7 @@ CHANGELOG ----- * added orphaned events support to `EventDataCollector` - * `ExceptionListener` now logs and collects exceptions at priority `2048` (previously logged at `-128` and collected at `0`) + * `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`) * Deprecated `service:action` syntax with a single colon to reference controllers. Use `service::method` instead. * Added the ability to profile individual argument value resolvers via the `Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver` diff --git a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php index fc749de599a4..4812f426951c 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php @@ -44,7 +44,6 @@ public function __construct($controller, LoggerInterface $logger = null, $debug public function logKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); - $request = $event->getRequest(); $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine())); } @@ -90,7 +89,7 @@ public static function getSubscribedEvents() { return array( KernelEvents::EXCEPTION => array( - array('logKernelException', 2048), + array('logKernelException', 0), array('onKernelException', -128), ), ); diff --git a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php index 9cc554db72ab..045e08347ff8 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php @@ -121,7 +121,7 @@ public static function getSubscribedEvents() { return array( KernelEvents::RESPONSE => array('onKernelResponse', -100), - KernelEvents::EXCEPTION => array('onKernelException', 2048), + KernelEvents::EXCEPTION => array('onKernelException', 0), KernelEvents::TERMINATE => array('onKernelTerminate', -1024), ); } From 1f346f446d462e5d0b79bf0642ed4b89621a1684 Mon Sep 17 00:00:00 2001 From: Webnet team Date: Mon, 21 May 2018 12:07:14 +0200 Subject: [PATCH 5/9] [Serializer] deserialize from xml: Fix a collection that contains the only one element --- .../Normalizer/AbstractObjectNormalizer.php | 6 + .../AbstractObjectNormalizerTest.php | 196 ++++++++++++++++++ 2 files changed, 202 insertions(+) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 251ec5fac05e..020b3d5317a7 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -255,6 +255,12 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma $builtinType = Type::BUILTIN_TYPE_OBJECT; $class = $collectionValueType->getClassName().'[]'; + // Fix a collection that contains the only one element + // This is special to xml format only + if ('xml' === $format && !is_int(key($data))) { + $data = array($data); + } + if (null !== $collectionKeyType = $type->getCollectionKeyType()) { $context['key_type'] = $collectionKeyType; } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 3ca418d55ed6..b1d40dcee3e1 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -13,9 +13,13 @@ use Doctrine\Common\Annotations\AnnotationReader; use PHPUnit\Framework\TestCase; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +use Symfony\Component\Serializer\SerializerAwareInterface; +use Symfony\Component\Serializer\SerializerInterface; class AbstractObjectNormalizerTest extends TestCase { @@ -69,6 +73,75 @@ public function testDenormalizeWithExtraAttributesAndNoGroupsWithMetadataFactory array('allow_extra_attributes' => false) ); } + + public function testDenormalizeCollectionDecodedFromXmlWithOneChild() + { + $denormalizer = $this->getDenormalizerForDummyCollection(); + + $dummyCollection = $denormalizer->denormalize( + array( + 'children' => array( + 'bar' => 'first', + ), + ), + DummyCollection::class, + 'xml' + ); + + $this->assertInstanceOf(DummyCollection::class, $dummyCollection); + $this->assertInternalType('array', $dummyCollection->children); + $this->assertCount(1, $dummyCollection->children); + $this->assertInstanceOf(DummyChild::class, $dummyCollection->children[0]); + } + + public function testDenormalizeCollectionDecodedFromXmlWithTwoChildren() + { + $denormalizer = $this->getDenormalizerForDummyCollection(); + + $dummyCollection = $denormalizer->denormalize( + array( + 'children' => array( + array('bar' => 'first'), + array('bar' => 'second'), + ), + ), + DummyCollection::class, + 'xml' + ); + + $this->assertInstanceOf(DummyCollection::class, $dummyCollection); + $this->assertInternalType('array', $dummyCollection->children); + $this->assertCount(2, $dummyCollection->children); + $this->assertInstanceOf(DummyChild::class, $dummyCollection->children[0]); + $this->assertInstanceOf(DummyChild::class, $dummyCollection->children[1]); + } + + private function getDenormalizerForDummyCollection() + { + $extractor = $this->getMockBuilder('Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor')->getMock(); + $extractor->method('getTypes') + ->will($this->onConsecutiveCalls( + array( + new \Symfony\Component\PropertyInfo\Type( + 'array', + false, + null, + true, + new \Symfony\Component\PropertyInfo\Type('int'), + new \Symfony\Component\PropertyInfo\Type('object', false, DummyChild::class) + ), + ), + null + )); + + $denormalizer = new AbstractObjectNormalizerCollectionDummy(null, null, $extractor); + $arrayDenormalizer = new ArrayDenormalizerDummy(); + $serializer = new SerializerCollectionDummy(array($arrayDenormalizer, $denormalizer)); + $arrayDenormalizer->setSerializer($serializer); + $denormalizer->setSerializer($serializer); + + return $denormalizer; + } } class AbstractObjectNormalizerDummy extends AbstractObjectNormalizer @@ -124,3 +197,126 @@ protected function setAttributeValue($object, $attribute, $value, $format = null $object->$attribute = $value; } } + +class DummyCollection +{ + /** @var DummyChild[] */ + public $children; +} + +class DummyChild +{ + public $bar; +} + +class SerializerCollectionDummy implements \Symfony\Component\Serializer\SerializerInterface, \Symfony\Component\Serializer\Normalizer\DenormalizerInterface +{ + /** @var \Symfony\Component\Serializer\Normalizer\DenormalizerInterface */ + private $normalizers; + + /** + * @param $normalizers + */ + public function __construct($normalizers) + { + $this->normalizers = $normalizers; + } + + public function serialize($data, $format, array $context = array()) + { + } + + public function deserialize($data, $type, $format, array $context = array()) + { + } + + public function denormalize($data, $type, $format = null, array $context = array()) + { + foreach ($this->normalizers as $normalizer) { + if ($normalizer instanceof \Symfony\Component\Serializer\Normalizer\DenormalizerInterface && $normalizer->supportsDenormalization($data, $type, $format, $context)) { + return $normalizer->denormalize($data, $type, $format, $context); + } + } + } + + public function supportsDenormalization($data, $type, $format = null) + { + return true; + } +} + +class AbstractObjectNormalizerCollectionDummy extends \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer +{ + protected function extractAttributes($object, $format = null, array $context = array()) + { + } + + protected function getAttributeValue($object, $attribute, $format = null, array $context = array()) + { + } + + protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = array()) + { + $object->$attribute = $value; + } + + protected function isAllowedAttribute($classOrObject, $attribute, $format = null, array $context = array()) + { + return true; + } + + public function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, $format = null) + { + return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format); + } + + public function serialize($data, $format, array $context = array()) + { + } + + public function deserialize($data, $type, $format, array $context = array()) + { + } +} + +class ArrayDenormalizerDummy implements DenormalizerInterface, SerializerAwareInterface +{ + /** + * @var SerializerInterface|DenormalizerInterface + */ + private $serializer; + + /** + * {@inheritdoc} + * + * @throws NotNormalizableValueException + */ + public function denormalize($data, $class, $format = null, array $context = array()) + { + $serializer = $this->serializer; + $class = substr($class, 0, -2); + + foreach ($data as $key => $value) { + $data[$key] = $serializer->denormalize($value, $class, $format, $context); + } + + return $data; + } + + /** + * {@inheritdoc} + */ + public function supportsDenormalization($data, $type, $format = null, array $context = array()) + { + return '[]' === substr($type, -2) + && $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); + } + + /** + * {@inheritdoc} + */ + public function setSerializer(SerializerInterface $serializer) + { + $this->serializer = $serializer; + } +} From cca73bb564adae22d0e9dd0c6dafbf1466a555c1 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 30 May 2018 10:06:54 -0400 Subject: [PATCH 6/9] Avoid migration on stateless firewalls --- .../Factory/GuardAuthenticationFactory.php | 1 + .../Security/Factory/HttpBasicFactory.php | 1 + .../Security/Factory/HttpDigestFactory.php | 1 + .../Security/Factory/RemoteUserFactory.php | 1 + .../SimplePreAuthenticationFactory.php | 1 + .../Security/Factory/X509Factory.php | 1 + .../DependencyInjection/SecurityExtension.php | 4 ++ .../Resources/config/security.xml | 4 ++ .../Bundle/SecurityBundle/composer.json | 2 +- .../Guard/GuardAuthenticatorHandler.php | 24 ++++++++---- .../Tests/GuardAuthenticatorHandlerTest.php | 37 +++++++++++++++++++ .../AbstractPreAuthenticatedListener.php | 24 ++++++++---- .../Firewall/BasicAuthenticationListener.php | 24 ++++++++---- .../Firewall/DigestAuthenticationListener.php | 27 ++++++++++---- .../SimplePreAuthenticationListener.php | 24 ++++++++---- 15 files changed, 138 insertions(+), 38 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php index 533560d6d986..bd49cbc93208 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php @@ -77,6 +77,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.guard')); $listener->replaceArgument(2, $id); $listener->replaceArgument(3, $authenticatorReferences); + $listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id))); // determine the entryPointId to use $entryPointId = $this->determineEntryPoint($defaultEntryPoint, $config); diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php index 162ea0515798..f09636ec71c0 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicFactory.php @@ -41,6 +41,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.basic')); $listener->replaceArgument(2, $id); $listener->replaceArgument(3, new Reference($entryPointId)); + $listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id))); return array($provider, $listenerId, $entryPointId); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php index 4cfb79653c05..944a9100f389 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php @@ -42,6 +42,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $listener->replaceArgument(1, new Reference($userProvider)); $listener->replaceArgument(2, $id); $listener->replaceArgument(3, new Reference($entryPointId)); + $listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id))); return array($provider, $listenerId, $entryPointId); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php index cf2e2ed71b16..5be068e6c487 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RemoteUserFactory.php @@ -38,6 +38,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.remote_user')); $listener->replaceArgument(2, $id); $listener->replaceArgument(3, $config['user']); + $listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id))); return array($providerId, $listenerId, $defaultEntryPoint); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php index c1c6e4808385..03fca8d6a25d 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimplePreAuthenticationFactory.php @@ -57,6 +57,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.simple_preauth')); $listener->replaceArgument(2, $id); $listener->replaceArgument(3, new Reference($config['authenticator'])); + $listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id))); return array($provider, $listenerId, null); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php index 0467ef2ba2c7..a745de9b2d78 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/X509Factory.php @@ -39,6 +39,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $listener->replaceArgument(2, $id); $listener->replaceArgument(3, $config['user']); $listener->replaceArgument(4, $config['credentials']); + $listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id))); return array($providerId, $listenerId, $defaultEntryPoint); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 34276e95e79f..5138eff36719 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -285,7 +285,11 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a } $listeners[] = new Reference($this->createContextListener($container, $contextKey)); + $sessionStrategyId = 'security.authentication.session_strategy'; + } else { + $sessionStrategyId = 'security.authentication.session_strategy_noop'; } + $container->setAlias(new Alias('security.authentication.session_strategy.'.$id, false), $sessionStrategyId); // Logout listener $logoutListenerId = null; diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 029395de9dea..74b097aa4c2b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -84,6 +84,10 @@ %security.authentication.session_strategy.strategy% + + none + + diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index f588b0488816..c0508ea29b02 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.9", "ext-xml": "*", - "symfony/security": "^2.8.41|^3.4.11", + "symfony/security": "^2.8.42|^3.4.12", "symfony/security-acl": "~2.7|~3.0.0", "symfony/http-kernel": "~2.7|~3.0.0", "symfony/polyfill-php70": "~1.0" diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php index 5e6eba339bf6..0164ba923526 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -20,6 +20,7 @@ use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; +use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; /** * A utility class that does much of the *work* during the guard authentication process. @@ -32,8 +33,8 @@ class GuardAuthenticatorHandler { private $tokenStorage; - private $dispatcher; + private $sessionStrategy; public function __construct(TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher = null) { @@ -46,7 +47,7 @@ public function __construct(TokenStorageInterface $tokenStorage, EventDispatcher */ public function authenticateWithToken(TokenInterface $token, Request $request) { - $this->migrateSession($request); + $this->migrateSession($request, $token); $this->tokenStorage->setToken($token); if (null !== $this->dispatcher) { @@ -129,15 +130,22 @@ public function handleAuthenticationFailure(AuthenticationException $authenticat )); } - private function migrateSession(Request $request) + /** + * Call this method if your authentication token is stored to a session. + * + * @final since version 2.8 + */ + public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) + { + $this->sessionStrategy = $sessionStrategy; + } + + private function migrateSession(Request $request, TokenInterface $token) { - if (!$request->hasSession() || !$request->hasPreviousSession()) { + if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) { return; } - // Destroying the old session is broken in php 5.4.0 - 5.4.10 - // See https://bugs.php.net/63379 - $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; - $request->getSession()->migrate($destroy); + $this->sessionStrategy->onAuthentication($request, $token); } } diff --git a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php index 662bace30877..49ce6548acab 100644 --- a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php @@ -25,6 +25,7 @@ class GuardAuthenticatorHandlerTest extends TestCase private $dispatcher; private $token; private $request; + private $sessionStrategy; private $guardAuthenticator; public function testAuthenticateWithToken() @@ -117,12 +118,38 @@ public function getTokenClearingTests() return $tests; } + public function testNoFailureIfSessionStrategyNotPassed() + { + $this->configurePreviousSession(); + + $this->tokenStorage->expects($this->once()) + ->method('setToken') + ->with($this->token); + + $handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher); + $handler->authenticateWithToken($this->token, $this->request); + } + + public function testSessionStrategyIsCalled() + { + $this->configurePreviousSession(); + + $this->sessionStrategy->expects($this->once()) + ->method('onAuthentication') + ->with($this->request, $this->token); + + $handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher); + $handler->setSessionAuthenticationStrategy($this->sessionStrategy); + $handler->authenticateWithToken($this->token, $this->request); + } + protected function setUp() { $this->tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(); $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); $this->request = new Request(array(), array(), array(), array(), array(), array()); + $this->sessionStrategy = $this->getMockBuilder('Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface')->getMock(); $this->guardAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); } @@ -134,4 +161,14 @@ protected function tearDown() $this->request = null; $this->guardAuthenticator = null; } + + private function configurePreviousSession() + { + $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock(); + $session->expects($this->any()) + ->method('getName') + ->willReturn('test_session_name'); + $this->request->setSession($session); + $this->request->cookies->set('test_session_name', 'session_cookie_val'); + } } diff --git a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php index 2054c4aa0774..6451d882e8b9 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php @@ -14,6 +14,7 @@ use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; @@ -22,6 +23,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; +use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; /** * AbstractPreAuthenticatedListener is the base class for all listener that @@ -37,6 +39,7 @@ abstract class AbstractPreAuthenticatedListener implements ListenerInterface private $authenticationManager; private $providerKey; private $dispatcher; + private $sessionStrategy; public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, $providerKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null) { @@ -83,7 +86,7 @@ final public function handle(GetResponseEvent $event) $this->logger->info('Pre-authentication successful.', array('token' => (string) $token)); } - $this->migrateSession($request); + $this->migrateSession($request, $token); $this->tokenStorage->setToken($token); @@ -96,6 +99,16 @@ final public function handle(GetResponseEvent $event) } } + /** + * Call this method if your authentication token is stored to a session. + * + * @final since version 2.8 + */ + public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) + { + $this->sessionStrategy = $sessionStrategy; + } + /** * Clears a PreAuthenticatedToken for this provider (if present). */ @@ -118,15 +131,12 @@ private function clearToken(AuthenticationException $exception) */ abstract protected function getPreAuthenticatedData(Request $request); - private function migrateSession(Request $request) + private function migrateSession(Request $request, TokenInterface $token) { - if (!$request->hasSession() || !$request->hasPreviousSession()) { + if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) { return; } - // Destroying the old session is broken in php 5.4.0 - 5.4.10 - // See https://bugs.php.net/63379 - $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; - $request->getSession()->migrate($destroy); + $this->sessionStrategy->onAuthentication($request, $token); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php index 63bd013c64e3..4b14a842dc13 100644 --- a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php @@ -14,11 +14,13 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; /** * BasicAuthenticationListener implements Basic HTTP authentication. @@ -33,6 +35,7 @@ class BasicAuthenticationListener implements ListenerInterface private $authenticationEntryPoint; private $logger; private $ignoreFailure; + private $sessionStrategy; public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, $providerKey, AuthenticationEntryPointInterface $authenticationEntryPoint, LoggerInterface $logger = null) { @@ -72,7 +75,7 @@ public function handle(GetResponseEvent $event) try { $token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey)); - $this->migrateSession($request); + $this->migrateSession($request, $token); $this->tokenStorage->setToken($token); } catch (AuthenticationException $e) { @@ -93,15 +96,22 @@ public function handle(GetResponseEvent $event) } } - private function migrateSession(Request $request) + /** + * Call this method if your authentication token is stored to a session. + * + * @final since version 2.8 + */ + public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) + { + $this->sessionStrategy = $sessionStrategy; + } + + private function migrateSession(Request $request, TokenInterface $token) { - if (!$request->hasSession() || !$request->hasPreviousSession()) { + if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) { return; } - // Destroying the old session is broken in php 5.4.0 - 5.4.10 - // See https://bugs.php.net/63379 - $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; - $request->getSession()->migrate($destroy); + $this->sessionStrategy->onAuthentication($request, $token); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php index 5655315a8b0c..b4853931ca4b 100644 --- a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Http\Firewall; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; use Psr\Log\LoggerInterface; @@ -23,6 +24,7 @@ use Symfony\Component\Security\Core\Exception\NonceExpiredException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; /** * DigestAuthenticationListener implements Digest HTTP authentication. @@ -36,6 +38,7 @@ class DigestAuthenticationListener implements ListenerInterface private $providerKey; private $authenticationEntryPoint; private $logger; + private $sessionStrategy; public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null) { @@ -117,9 +120,20 @@ public function handle(GetResponseEvent $event) $this->logger->info('Digest authentication successful.', array('username' => $digestAuth->getUsername(), 'received' => $digestAuth->getResponse())); } - $this->migrateSession($request); + $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey); + $this->migrateSession($request, $token); - $this->tokenStorage->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey)); + $this->tokenStorage->setToken($token); + } + + /** + * Call this method if your authentication token is stored to a session. + * + * @final since version 2.8 + */ + public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) + { + $this->sessionStrategy = $sessionStrategy; } private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException) @@ -136,16 +150,13 @@ private function fail(GetResponseEvent $event, Request $request, AuthenticationE $event->setResponse($this->authenticationEntryPoint->start($request, $authException)); } - private function migrateSession(Request $request) + private function migrateSession(Request $request, TokenInterface $token) { - if (!$request->hasSession() || !$request->hasPreviousSession()) { + if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) { return; } - // Destroying the old session is broken in php 5.4.0 - 5.4.10 - // See https://bugs.php.net/63379 - $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; - $request->getSession()->migrate($destroy); + $this->sessionStrategy->onAuthentication($request, $token); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php index 23e517969f4e..cdfb06d4fa2e 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php @@ -19,12 +19,14 @@ use Symfony\Component\Security\Core\Authentication\SimplePreAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface; use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; /** * SimplePreAuthenticationListener implements simple proxying to an authenticator. @@ -39,6 +41,7 @@ class SimplePreAuthenticationListener implements ListenerInterface private $simpleAuthenticator; private $logger; private $dispatcher; + private $sessionStrategy; /** * @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance @@ -62,6 +65,16 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationM $this->dispatcher = $dispatcher; } + /** + * Call this method if your authentication token is stored to a session. + * + * @final since version 2.8 + */ + public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) + { + $this->sessionStrategy = $sessionStrategy; + } + /** * Handles basic authentication. */ @@ -87,7 +100,7 @@ public function handle(GetResponseEvent $event) $token = $this->authenticationManager->authenticate($token); - $this->migrateSession($request); + $this->migrateSession($request, $token); $this->tokenStorage->setToken($token); @@ -124,15 +137,12 @@ public function handle(GetResponseEvent $event) } } - private function migrateSession(Request $request) + private function migrateSession(Request $request, TokenInterface $token) { - if (!$request->hasSession() || !$request->hasPreviousSession()) { + if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) { return; } - // Destroying the old session is broken in php 5.4.0 - 5.4.10 - // See https://bugs.php.net/63379 - $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; - $request->getSession()->migrate($destroy); + $this->sessionStrategy->onAuthentication($request, $token); } } From 5c2b2bb2ce38b4055f35ffc08984a49694a8f79f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 10 Jun 2018 12:30:11 +0200 Subject: [PATCH 7/9] fixed CS --- .../Component/Security/Guard/GuardAuthenticatorHandler.php | 2 +- .../Security/Http/Firewall/AbstractPreAuthenticatedListener.php | 2 +- .../Security/Http/Firewall/BasicAuthenticationListener.php | 2 +- .../Security/Http/Firewall/DigestAuthenticationListener.php | 2 +- .../Security/Http/Firewall/SimplePreAuthenticationListener.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php index 0164ba923526..7b340a2601ce 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -133,7 +133,7 @@ public function handleAuthenticationFailure(AuthenticationException $authenticat /** * Call this method if your authentication token is stored to a session. * - * @final since version 2.8 + * @final */ public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) { diff --git a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php index 6451d882e8b9..062f4521cfba 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AbstractPreAuthenticatedListener.php @@ -102,7 +102,7 @@ final public function handle(GetResponseEvent $event) /** * Call this method if your authentication token is stored to a session. * - * @final since version 2.8 + * @final */ public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) { diff --git a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php index 4b14a842dc13..bfc61f3faacf 100644 --- a/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php @@ -99,7 +99,7 @@ public function handle(GetResponseEvent $event) /** * Call this method if your authentication token is stored to a session. * - * @final since version 2.8 + * @final */ public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) { diff --git a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php index b4853931ca4b..5bc3c5ea94df 100644 --- a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php @@ -129,7 +129,7 @@ public function handle(GetResponseEvent $event) /** * Call this method if your authentication token is stored to a session. * - * @final since version 2.8 + * @final */ public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) { diff --git a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php index cdfb06d4fa2e..9cb90edbe65f 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php @@ -68,7 +68,7 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationM /** * Call this method if your authentication token is stored to a session. * - * @final since version 2.8 + * @final */ public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) { From c06f3229decae3950d52b76d5e262d8a6b54a23e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 8 Jun 2018 09:36:24 -0400 Subject: [PATCH 8/9] Avoiding session migration for stateless firewall UsernamePasswordJsonAuthenticationListener --- .../Security/Factory/JsonLoginFactory.php | 1 + .../DependencyInjection/SecurityExtension.php | 4 ++ .../Resources/config/security.xml | 3 ++ .../Bundle/SecurityBundle/composer.json | 2 +- ...namePasswordJsonAuthenticationListener.php | 20 ++++++++-- ...PasswordJsonAuthenticationListenerTest.php | 38 +++++++++++++++++++ 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php index 5a391ffacaea..6c7adb032395 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php @@ -89,6 +89,7 @@ protected function createListener($container, $id, $config, $userProvider) $listener->replaceArgument(4, isset($config['success_handler']) ? new Reference($this->createAuthenticationSuccessHandler($container, $id, $config)) : null); $listener->replaceArgument(5, isset($config['failure_handler']) ? new Reference($this->createAuthenticationFailureHandler($container, $id, $config)) : null); $listener->replaceArgument(6, array_intersect_key($config, $this->options)); + $listener->addMethodCall('setSessionAuthenticationStrategy', array(new Reference('security.authentication.session_strategy.'.$id))); $listenerId .= '.'.$id; $container->setDefinition($listenerId, $listener); diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index d8f1db8dd96f..b17c93f3e90c 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -377,7 +377,11 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a $this->logoutOnUserChangeByContextKey[$contextKey] = array($id, $logoutOnUserChange); $listeners[] = new Reference($this->createContextListener($container, $contextKey, $logoutOnUserChange)); + $sessionStrategyId = 'security.authentication.session_strategy'; + } else { + $sessionStrategyId = 'security.authentication.session_strategy_noop'; } + $container->setAlias(new Alias('security.authentication.session_strategy.'.$id, false), $sessionStrategyId); $config->replaceArgument(6, $contextKey); diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 515f56db6e8c..dea2481df457 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -62,6 +62,9 @@ %security.authentication.session_strategy.strategy% + + none + diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index cc46a01f0f67..ebf39d1beea5 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^5.5.9|>=7.0.8", "ext-xml": "*", - "symfony/security": "~3.4.11|^4.0.11", + "symfony/security": "~3.4.12|^4.0.12|^4.1.1", "symfony/dependency-injection": "^3.4.3|^4.0.3", "symfony/http-kernel": "~3.4|~4.0", "symfony/polyfill-php70": "~1.0" diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php index 8bde1e00151e..d83e94d4b2ef 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php @@ -33,6 +33,7 @@ use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; use Symfony\Component\Security\Http\HttpUtils; use Symfony\Component\Security\Http\SecurityEvents; +use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface; /** * UsernamePasswordJsonAuthenticationListener is a stateless implementation of @@ -52,6 +53,7 @@ class UsernamePasswordJsonAuthenticationListener implements ListenerInterface private $logger; private $eventDispatcher; private $propertyAccessor; + private $sessionStrategy; public function __construct(TokenStorageInterface $tokenStorage, AuthenticationManagerInterface $authenticationManager, HttpUtils $httpUtils, $providerKey, AuthenticationSuccessHandlerInterface $successHandler = null, AuthenticationFailureHandlerInterface $failureHandler = null, array $options = array(), LoggerInterface $logger = null, EventDispatcherInterface $eventDispatcher = null, PropertyAccessorInterface $propertyAccessor = null) { @@ -139,7 +141,7 @@ private function onSuccess(Request $request, TokenInterface $token) $this->logger->info('User has been authenticated successfully.', array('username' => $token->getUsername())); } - $this->migrateSession($request); + $this->migrateSession($request, $token); $this->tokenStorage->setToken($token); @@ -185,11 +187,21 @@ private function onFailure(Request $request, AuthenticationException $failed) return $response; } - private function migrateSession(Request $request) + /** + * Call this method if your authentication token is stored to a session. + * + * @final since version 3.4 + */ + public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) + { + $this->sessionStrategy = $sessionStrategy; + } + + private function migrateSession(Request $request, TokenInterface $token) { - if (!$request->hasSession() || !$request->hasPreviousSession()) { + if (!$this->sessionStrategy || !$request->hasSession() || !$request->hasPreviousSession()) { return; } - $request->getSession()->migrate(true); + $this->sessionStrategy->onAuthentication($request, $token); } } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php index 74526fcd543e..d8bb77bb9e81 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/UsernamePasswordJsonAuthenticationListenerTest.php @@ -212,4 +212,42 @@ public function testAttemptAuthenticationIfRequestPathMatchesCheckPath() $this->listener->handle($event); $this->assertSame('ok', $event->getResponse()->getContent()); } + + public function testNoErrorOnMissingSessionStrategy() + { + $this->createListener(); + $request = new Request(array(), array(), array(), array(), array(), array('HTTP_CONTENT_TYPE' => 'application/json'), '{"username": "dunglas", "password": "foo"}'); + $this->configurePreviousSession($request); + $event = new GetResponseEvent($this->getMockBuilder(KernelInterface::class)->getMock(), $request, KernelInterface::MASTER_REQUEST); + + $this->listener->handle($event); + $this->assertEquals('ok', $event->getResponse()->getContent()); + } + + public function testMigratesViaSessionStrategy() + { + $this->createListener(); + $request = new Request(array(), array(), array(), array(), array(), array('HTTP_CONTENT_TYPE' => 'application/json'), '{"username": "dunglas", "password": "foo"}'); + $this->configurePreviousSession($request); + $event = new GetResponseEvent($this->getMockBuilder(KernelInterface::class)->getMock(), $request, KernelInterface::MASTER_REQUEST); + + $sessionStrategy = $this->getMockBuilder('Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface')->getMock(); + $sessionStrategy->expects($this->once()) + ->method('onAuthentication') + ->with($request, $this->isInstanceOf(TokenInterface::class)); + $this->listener->setSessionAuthenticationStrategy($sessionStrategy); + + $this->listener->handle($event); + $this->assertEquals('ok', $event->getResponse()->getContent()); + } + + private function configurePreviousSession(Request $request) + { + $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock(); + $session->expects($this->any()) + ->method('getName') + ->willReturn('test_session_name'); + $request->setSession($session); + $request->cookies->set('test_session_name', 'session_cookie_val'); + } } From 697a6a0ae4db1c613b47af2f465746b051351e3e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 10 Jun 2018 12:33:24 +0200 Subject: [PATCH 9/9] fixed CS --- .../Firewall/UsernamePasswordJsonAuthenticationListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php index d83e94d4b2ef..61a14823d999 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php @@ -190,7 +190,7 @@ private function onFailure(Request $request, AuthenticationException $failed) /** * Call this method if your authentication token is stored to a session. * - * @final since version 3.4 + * @final */ public function setSessionAuthenticationStrategy(SessionAuthenticationStrategyInterface $sessionStrategy) {