Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: throws exception when controller name in routes contains / #5885

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions system/Language/en/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@
'invalidParameter' => 'A parameter does not match the expected type.',
'missingDefaultRoute' => 'Unable to determine what should be displayed. A default route has not been specified in the routing file.',
'invalidDynamicController' => 'A dynamic controller is not allowed for security reasons. Route handler: {0}',
'invalidControllerName' => 'The namespace delimiter is a backslash (\), not a slash (/). Route handler: {0}',
];
10 changes: 10 additions & 0 deletions system/Router/Exceptions/RouterException.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,14 @@ public static function forDynamicController(string $handler)
{
return new static(lang('Router.invalidDynamicController', [$handler]));
}

/**
* Throw when controller name has `/`.
*
* @return RouterException
*/
public static function forInvalidControllerName(string $handler)
{
return new static(lang('Router.invalidControllerName', [$handler]));
}
}
5 changes: 5 additions & 0 deletions system/Router/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,11 @@ protected function checkRoutes(string $uri): bool
throw RouterException::forDynamicController($handler);
}

// Checks `/` in controller name
if (strpos($controller, '/') !== false) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to find parameters for "valid PHP class names", but would it make sense to expand this out to a regex and fail anything that didn't fit?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admin/AdminGlavni is not a valid PHP class name.
Because / is wrong.

Many users write like 'Admin/AdminGlavni::cam_edit_show/$1' and CI4 causes errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I get that. My question was: is there any reason why not to make this check for all class names? Admin\Admin-Glavni is also not valid. This could be implemented as a filter and the error as "Your controller contains the following invalid characters: -"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it is a breaking change.
Admin/AdminGlavni is not valid, but works now.

throw RouterException::forInvalidControllerName($handler);
}

if (strpos($routeKey, '/') !== false) {
$replacekey = str_replace('/(.*)', '', $routeKey);
$handler = preg_replace('#^' . $routeKey . '$#u', $handler, $uri);
Expand Down
12 changes: 12 additions & 0 deletions tests/system/Router/RouterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ protected function setUp(): void
'closure/(:num)/(:alpha)' => static fn ($num, $str) => $num . '-' . $str,
'{locale}/pages' => 'App\Pages::list_all',
'admin/admins' => 'App\Admin\Admins::list_all',
'admin/admins/edit/(:any)' => 'App/Admin/Admins::edit_show/$1',
'/some/slash' => 'App\Slash::index',
'objects/(:segment)/sort/(:segment)/([A-Z]{3,7})' => 'AdminList::objectsSortCreate/$1/$2/$3',
'(:segment)/(:segment)/(:segment)' => '$2::$3/$1',
Expand Down Expand Up @@ -402,6 +403,17 @@ public function testRouteResource()
$this->assertSame('list_all', $router->methodName());
}

public function testRouteWithSlashInControllerName()
{
$this->expectExceptionMessage(
'The namespace delimiter is a backslash (\), not a slash (/). Route handler: \App/Admin/Admins::edit_show/$1'
);

$router = new Router($this->collection, $this->request);

$router->handle('admin/admins/edit/1');
}

public function testRouteWithLeadingSlash()
{
$router = new Router($this->collection, $this->request);
Expand Down