This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace MJanssen\Provider; |
||
3 | |||
4 | use InvalidArgumentException; |
||
5 | use Silex\Application; |
||
6 | use Silex\Controller; |
||
7 | use Silex\Route; |
||
8 | use Pimple\ServiceProviderInterface; |
||
9 | use Pimple\Container; |
||
10 | use Silex\Api\BootableProviderInterface; |
||
11 | use Silex\Api\EventListenerProviderInterface; |
||
12 | use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
||
13 | |||
14 | /** |
||
15 | * Class RoutingServiceProvider |
||
16 | * @package MJanssen\Provider |
||
17 | */ |
||
18 | class RoutingServiceProvider implements |
||
19 | ServiceProviderInterface, |
||
20 | BootableProviderInterface, |
||
21 | EventListenerProviderInterface |
||
22 | { |
||
23 | /** |
||
24 | * @var |
||
25 | */ |
||
26 | protected $appRoutingKey; |
||
27 | |||
28 | /** |
||
29 | * @param string $appRoutingKey |
||
30 | */ |
||
31 | public function __construct($appRoutingKey = 'config.routes') |
||
32 | { |
||
33 | $this->appRoutingKey = $appRoutingKey; |
||
34 | } |
||
35 | |||
36 | /** |
||
37 | * @param Container $app |
||
38 | * @throws \InvalidArgumentException |
||
39 | */ |
||
40 | public function register(Container $app) |
||
41 | { |
||
42 | if (isset($app[$this->appRoutingKey])) { |
||
43 | if (is_array($app[$this->appRoutingKey])) { |
||
44 | $this->addRoutes($app, $app[$this->appRoutingKey]); |
||
45 | } else { |
||
46 | throw new InvalidArgumentException('config.routes must be of type Array'); |
||
47 | } |
||
48 | } |
||
49 | } |
||
50 | |||
51 | /** |
||
52 | * @param Application $app |
||
53 | * @codeCoverageIgnore |
||
54 | */ |
||
55 | public function boot(Application $app) |
||
56 | { |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * @param Container $app |
||
61 | * @param EventDispatcherInterface $dispatcher |
||
62 | * @codeCoverageIgnore |
||
63 | */ |
||
64 | public function subscribe(Container $app, EventDispatcherInterface $dispatcher) |
||
65 | { |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Adds all routes |
||
70 | * |
||
71 | * @param Container $app |
||
72 | * @param $routes |
||
73 | */ |
||
74 | public function addRoutes(Container $app, $routes) |
||
75 | { |
||
76 | foreach ($routes as $name => $route) { |
||
77 | |||
78 | if (is_numeric($name)) { |
||
79 | $name = ''; |
||
80 | } |
||
81 | |||
82 | $this->addRoute($app, $route, $name); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Adds a route, a given route-name (for named routes) and all of its methods |
||
88 | * |
||
89 | * @param Container $app |
||
90 | * @param array $route |
||
91 | * @throws InvalidArgumentException |
||
92 | */ |
||
93 | public function addRoute(Container $app, array $route, $name = '') |
||
94 | { |
||
95 | if (isset($route['method']) && is_string($route['method'])) { |
||
96 | $route['method'] = array($route['method']); |
||
97 | } |
||
98 | |||
99 | $this->validateRoute($route); |
||
100 | |||
101 | if (array_key_exists('name', $route)) { |
||
102 | $name = $route['name']; |
||
103 | } |
||
104 | |||
105 | $controller = $app->match( |
||
0 ignored issues
–
show
|
|||
106 | $route['pattern'], |
||
107 | $route['controller']) |
||
108 | ->bind( |
||
109 | $this->sanitizeRouteName($name) |
||
110 | )->method( |
||
111 | join('|', array_map('strtoupper', $route['method'])) |
||
112 | ); |
||
113 | |||
114 | $supportedProperties = array('value', 'assert', 'convert', 'before', 'after', 'secure'); |
||
115 | foreach ($supportedProperties AS $property) { |
||
116 | if (isset($route[$property])) { |
||
117 | $this->addActions($controller, $route[$property], $property); |
||
118 | } |
||
119 | } |
||
120 | |||
121 | if (isset($route['scheme'])) { |
||
122 | if ('https' === $route['scheme']) { |
||
123 | $controller->requireHttps(); |
||
124 | } |
||
125 | } |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Validates the given methods. Only get, put, post, delete, options, head |
||
130 | * are allowed |
||
131 | * |
||
132 | * @param array $methods |
||
133 | */ |
||
134 | protected function validateMethods(Array $methods) |
||
135 | { |
||
136 | $availableMethods = array('get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'purge', 'options', 'trace', 'connect'); |
||
137 | foreach (array_map('strtolower', $methods) as $method) { |
||
138 | if (!in_array($method, $availableMethods)) { |
||
139 | throw new InvalidArgumentException('Method "' . $method . '" is not valid, only the following methods are allowed: ' . join(', ', $availableMethods)); |
||
140 | } |
||
141 | } |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Validates the given $route Array |
||
146 | * |
||
147 | * @param $route |
||
148 | * @throws \InvalidArgumentException |
||
149 | */ |
||
150 | protected function validateRoute($route) |
||
151 | { |
||
152 | if (!isset($route['pattern']) || !isset($route['method']) || !isset($route['controller'])) { |
||
153 | throw new InvalidArgumentException('Required parameter (pattern/method/controller) is not set.'); |
||
154 | } |
||
155 | |||
156 | $arrayParameters = array('method', 'assert', 'value'); |
||
157 | |||
158 | foreach ($arrayParameters as $parameter) { |
||
159 | if (isset($route[$parameter]) && !is_array($route[$parameter])) { |
||
160 | throw new InvalidArgumentException(sprintf( |
||
161 | '%s is not of type Array (%s)', |
||
162 | $parameter, gettype($route[$parameter]) |
||
163 | )); |
||
164 | } |
||
165 | } |
||
166 | |||
167 | $this->validateMethods($route['method']); |
||
168 | } |
||
169 | |||
170 | |||
171 | /** |
||
172 | * Sanitizes the routeName for named route: |
||
173 | * |
||
174 | * - replaces '/', ':', '|', '-' with '_' |
||
175 | * - removes special characters |
||
176 | * |
||
177 | * Algorithm copied from \Silex\Controller->generateRouteName |
||
178 | * see: https://github.com/silexphp/Silex/blob/1.2/src/Silex/Controller.php |
||
179 | * |
||
180 | * @param string $routeName |
||
181 | * @return string |
||
182 | */ |
||
183 | protected function sanitizeRouteName($routeName) |
||
184 | { |
||
185 | if (empty($routeName)) { |
||
186 | //If no routeName is specified, |
||
187 | //we set an empty route name to force the default route name e.g. "GET_myRouteName" |
||
188 | return ''; |
||
189 | } |
||
190 | |||
191 | $routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName); |
||
192 | $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); |
||
193 | |||
194 | return $routeName; |
||
195 | } |
||
196 | |||
197 | /** |
||
198 | * @param Controller $controller |
||
199 | * @param $actions |
||
200 | * @param $type |
||
201 | * @throws \InvalidArgumentException |
||
202 | */ |
||
203 | protected function addActions(Controller $controller, $actions, $type) |
||
204 | { |
||
205 | if (!is_array($actions)){ |
||
206 | if ($type === 'before' || $type === 'after') { |
||
207 | $actions = array($actions); |
||
208 | } else { |
||
209 | throw new InvalidArgumentException( |
||
210 | sprintf( |
||
211 | 'Action %s is not of type Array (%s)', |
||
212 | $type, gettype($actions) |
||
213 | ) |
||
214 | ); |
||
215 | } |
||
216 | } |
||
217 | |||
218 | foreach ($actions as $name => $value) { |
||
219 | switch ($type) { |
||
220 | case 'after': |
||
221 | $this->addBeforeAfterMiddleware($controller, $type, $value); |
||
222 | break; |
||
223 | case 'before': |
||
224 | $this->addBeforeAfterMiddleware($controller, $type, $value); |
||
225 | break; |
||
226 | case 'secure': |
||
227 | $this->addSecure($controller, $type, $actions); |
||
228 | break; |
||
229 | default: |
||
230 | $this->addAction($controller, $name, $value, $type); |
||
231 | break; |
||
232 | } |
||
233 | } |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * @param Controller $controller |
||
238 | * @param $name |
||
239 | * @param $value |
||
240 | * @param $type |
||
241 | */ |
||
242 | protected function addAction(Controller $controller, $name, $value, $type) |
||
243 | { |
||
244 | call_user_func_array(array($controller, $type), array($name, $value)); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * @param Controller $controller |
||
249 | * @param $type |
||
250 | * @param array $values |
||
251 | */ |
||
252 | protected function addSecure(Controller $controller, $type, Array $values) |
||
253 | { |
||
254 | call_user_func_array(array($controller, $type), $values); |
||
255 | } |
||
256 | |||
257 | protected function isClosure($param) |
||
258 | { |
||
259 | return is_object($param) && is_callable($param); |
||
260 | } |
||
261 | |||
262 | /** |
||
263 | * Adds a middleware (before/after) |
||
264 | * |
||
265 | * @param Controller $controller |
||
266 | * @param string $type | 'before' or 'after' |
||
267 | * @param $value |
||
268 | */ |
||
269 | protected function addBeforeAfterMiddleware(Controller $controller, $type, $value) |
||
270 | { |
||
271 | $supportedMWTypes = ['before', 'after']; |
||
272 | |||
273 | if (!in_array($type, $supportedMWTypes)) { |
||
274 | throw new \UnexpectedValueException( |
||
275 | sprintf( |
||
276 | 'type %s not supported', |
||
277 | $type |
||
278 | ) |
||
279 | ); |
||
280 | } |
||
281 | |||
282 | if ($this->isClosure($value)) { |
||
283 | //When a closure is provided, we will just load it as a middleware type |
||
284 | $controller->$type($value); |
||
285 | } else { |
||
286 | //In this case a yaml/xml configuration was used |
||
287 | $this->addMiddlewareFromConfig($controller, $type, $value); |
||
288 | } |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * Adds a before/after middleware by its configuration |
||
293 | * |
||
294 | * @param Controller $controller |
||
295 | * @param $type |
||
296 | * @param $value |
||
297 | */ |
||
298 | protected function addMiddlewareFromConfig(Controller $controller, $type, $value) |
||
299 | { |
||
300 | if (!is_string($value) || strpos($value, '::') === FALSE) { |
||
301 | throw new InvalidArgumentException( |
||
302 | sprintf( |
||
303 | '%s is no valid Middleware callback. Please provide the following syntax: NamespaceName\SubNamespaceName\ClassName::methodName', |
||
304 | $value |
||
305 | ) |
||
306 | ); |
||
307 | } |
||
308 | |||
309 | list($class, $method) = explode('::', $value, 2); |
||
310 | |||
311 | if ($class && $method) { |
||
312 | |||
313 | if (!method_exists($class, $method)) { |
||
314 | throw new \BadMethodCallException(sprintf('Method "%s::%s" does not exist.', $class, $method)); |
||
315 | } |
||
316 | |||
317 | $controller->$type([new $class, $method]); |
||
318 | } |
||
319 | } |
||
320 | } |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: