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.
Check for implicit conversion of array to boolean.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the FOSRestBundle package. |
||
5 | * |
||
6 | * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace FOS\RestBundle\DependencyInjection; |
||
13 | |||
14 | use FOS\RestBundle\ErrorRenderer\SerializerErrorRenderer; |
||
15 | use FOS\RestBundle\EventListener\ResponseStatusCodeListener; |
||
16 | use FOS\RestBundle\View\ViewHandler; |
||
17 | use Symfony\Component\Config\FileLocator; |
||
18 | use Symfony\Component\DependencyInjection\Alias; |
||
19 | use Symfony\Component\DependencyInjection\ChildDefinition; |
||
20 | use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; |
||
21 | use Symfony\Component\DependencyInjection\ContainerBuilder; |
||
22 | use Symfony\Component\DependencyInjection\ContainerInterface; |
||
23 | use Symfony\Component\DependencyInjection\Definition; |
||
24 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; |
||
25 | use Symfony\Component\DependencyInjection\Reference; |
||
26 | use Symfony\Component\Form\Extension\Core\Type\FormType; |
||
27 | use Symfony\Component\HttpFoundation\Response; |
||
28 | use Symfony\Component\HttpKernel\DependencyInjection\Extension; |
||
29 | use Symfony\Component\Validator\Constraint; |
||
30 | |||
31 | /** |
||
32 | * @internal |
||
33 | */ |
||
34 | class FOSRestExtension extends Extension |
||
35 | { |
||
36 | /** |
||
37 | * {@inheritdoc} |
||
38 | */ |
||
39 | 14 | public function getConfiguration(array $config, ContainerBuilder $container): Configuration |
|
40 | { |
||
41 | 14 | return new Configuration($container->getParameter('kernel.debug')); |
|
42 | } |
||
43 | |||
44 | 49 | public function load(array $configs, ContainerBuilder $container): void |
|
45 | { |
||
46 | 49 | $configuration = new Configuration($container->getParameter('kernel.debug')); |
|
47 | 49 | $config = $this->processConfiguration($configuration, $configs); |
|
48 | |||
49 | 44 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); |
|
50 | 44 | $loader->load('view.xml'); |
|
51 | 44 | $loader->load('request.xml'); |
|
52 | 44 | $loader->load('serializer.xml'); |
|
53 | |||
54 | 44 | foreach ($config['service'] as $key => $service) { |
|
55 | 44 | if ('validator' === $service && empty($config['body_converter']['validate'])) { |
|
56 | 43 | continue; |
|
57 | } |
||
58 | |||
59 | 44 | if (null !== $service) { |
|
60 | 44 | if ('view_handler' === $key) { |
|
61 | 44 | $container->setAlias('fos_rest.'.$key, new Alias($service, true)); |
|
62 | } else { |
||
63 | 1 | $container->setAlias('fos_rest.'.$key, $service); |
|
64 | } |
||
65 | } |
||
66 | } |
||
67 | |||
68 | 44 | $this->loadForm($config, $loader, $container); |
|
69 | 44 | $this->loadException($config, $loader, $container); |
|
70 | 44 | $this->loadBodyConverter($config, $loader, $container); |
|
71 | 44 | $this->loadView($config, $loader, $container); |
|
72 | |||
73 | 44 | $this->loadBodyListener($config, $loader, $container); |
|
74 | 44 | $this->loadFormatListener($config, $loader, $container); |
|
75 | 44 | $this->loadVersioning($config, $loader, $container); |
|
76 | 44 | $this->loadParamFetcherListener($config, $loader, $container); |
|
77 | 44 | $this->loadAllowedMethodsListener($config, $loader, $container); |
|
78 | 44 | $this->loadZoneMatcherListener($config, $loader, $container); |
|
79 | |||
80 | // Needs RequestBodyParamConverter and View Handler loaded. |
||
81 | 44 | $this->loadSerializer($config, $container); |
|
82 | 44 | } |
|
83 | |||
84 | 44 | private function loadForm(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
85 | { |
||
86 | 44 | if (!empty($config['disable_csrf_role'])) { |
|
87 | $loader->load('forms.xml'); |
||
88 | |||
89 | $definition = $container->getDefinition('fos_rest.form.extension.csrf_disable'); |
||
90 | $definition->replaceArgument(1, $config['disable_csrf_role']); |
||
91 | $definition->addTag('form.type_extension', ['extended_type' => FormType::class]); |
||
92 | } |
||
93 | 44 | } |
|
94 | |||
95 | 44 | private function loadAllowedMethodsListener(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
96 | { |
||
97 | 44 | if ($config['allowed_methods_listener']['enabled']) { |
|
98 | 1 | if (!empty($config['allowed_methods_listener']['service'])) { |
|
99 | $service = $container->getDefinition('fos_rest.allowed_methods_listener'); |
||
100 | $service->clearTag('kernel.event_listener'); |
||
101 | } |
||
102 | |||
103 | 1 | $loader->load('allowed_methods_listener.xml'); |
|
104 | |||
105 | 1 | $container->getDefinition('fos_rest.allowed_methods_loader')->replaceArgument(1, $config['cache_dir']); |
|
106 | } |
||
107 | 44 | } |
|
108 | |||
109 | 44 | private function loadBodyListener(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
110 | { |
||
111 | 44 | if ($config['body_listener']['enabled']) { |
|
112 | 5 | $loader->load('body_listener.xml'); |
|
113 | |||
114 | 5 | $service = $container->getDefinition('fos_rest.body_listener'); |
|
115 | |||
116 | 5 | if (!empty($config['body_listener']['service'])) { |
|
117 | $service->clearTag('kernel.event_listener'); |
||
118 | } |
||
119 | |||
120 | 5 | $service->replaceArgument(1, $config['body_listener']['throw_exception_on_unsupported_content_type']); |
|
121 | 5 | $service->addMethodCall('setDefaultFormat', array($config['body_listener']['default_format'])); |
|
122 | |||
123 | 5 | $container->getDefinition('fos_rest.decoder_provider')->replaceArgument(1, $config['body_listener']['decoders']); |
|
124 | |||
125 | 5 | $decoderServicesMap = array(); |
|
126 | |||
127 | 5 | foreach ($config['body_listener']['decoders'] as $id) { |
|
128 | 5 | $decoderServicesMap[$id] = new Reference($id); |
|
129 | } |
||
130 | |||
131 | 5 | $decodersServiceLocator = ServiceLocatorTagPass::register($container, $decoderServicesMap); |
|
132 | 5 | $container->getDefinition('fos_rest.decoder_provider')->replaceArgument(0, $decodersServiceLocator); |
|
133 | |||
134 | 5 | $arrayNormalizer = $config['body_listener']['array_normalizer']; |
|
135 | |||
136 | 5 | if (null !== $arrayNormalizer['service']) { |
|
137 | 3 | $bodyListener = $container->getDefinition('fos_rest.body_listener'); |
|
138 | 3 | $bodyListener->addArgument(new Reference($arrayNormalizer['service'])); |
|
139 | 3 | $bodyListener->addArgument($arrayNormalizer['forms']); |
|
140 | } |
||
141 | } |
||
142 | 44 | } |
|
143 | |||
144 | 44 | private function loadFormatListener(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
145 | { |
||
146 | 44 | if ($config['format_listener']['enabled'] && !empty($config['format_listener']['rules'])) { |
|
147 | 3 | $loader->load('format_listener.xml'); |
|
148 | |||
149 | 3 | if (!empty($config['format_listener']['service'])) { |
|
150 | $service = $container->getDefinition('fos_rest.format_listener'); |
||
151 | $service->clearTag('kernel.event_listener'); |
||
152 | } |
||
153 | |||
154 | 3 | $container->setParameter( |
|
155 | 3 | 'fos_rest.format_listener.rules', |
|
156 | 3 | $config['format_listener']['rules'] |
|
157 | ); |
||
158 | } |
||
159 | 44 | } |
|
160 | |||
161 | 44 | private function loadVersioning(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
162 | { |
||
163 | 44 | if (!empty($config['versioning']['enabled'])) { |
|
164 | $loader->load('versioning.xml'); |
||
165 | |||
166 | $versionListener = $container->getDefinition('fos_rest.versioning.listener'); |
||
167 | $versionListener->replaceArgument(1, $config['versioning']['default_version']); |
||
168 | |||
169 | $resolvers = []; |
||
170 | if ($config['versioning']['resolvers']['query']['enabled']) { |
||
171 | $resolvers['query'] = $container->getDefinition('fos_rest.versioning.query_parameter_resolver'); |
||
172 | $resolvers['query']->replaceArgument(0, $config['versioning']['resolvers']['query']['parameter_name']); |
||
173 | } |
||
174 | if ($config['versioning']['resolvers']['custom_header']['enabled']) { |
||
175 | $resolvers['custom_header'] = $container->getDefinition('fos_rest.versioning.header_resolver'); |
||
176 | $resolvers['custom_header']->replaceArgument(0, $config['versioning']['resolvers']['custom_header']['header_name']); |
||
177 | } |
||
178 | if ($config['versioning']['resolvers']['media_type']['enabled']) { |
||
179 | $resolvers['media_type'] = $container->getDefinition('fos_rest.versioning.media_type_resolver'); |
||
180 | $resolvers['media_type']->replaceArgument(0, $config['versioning']['resolvers']['media_type']['regex']); |
||
181 | } |
||
182 | |||
183 | $chainResolver = $container->getDefinition('fos_rest.versioning.chain_resolver'); |
||
184 | foreach ($config['versioning']['guessing_order'] as $resolver) { |
||
185 | if (isset($resolvers[$resolver])) { |
||
186 | $chainResolver->addMethodCall('addResolver', [$resolvers[$resolver]]); |
||
187 | } |
||
188 | } |
||
189 | } |
||
190 | 44 | } |
|
191 | |||
192 | 44 | private function loadParamFetcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
193 | { |
||
194 | 44 | if ($config['param_fetcher_listener']['enabled']) { |
|
195 | 3 | if (!class_exists(Constraint::class)) { |
|
196 | throw new \LogicException('Enabling the fos_rest.param_fetcher_listener option when the Symfony Validator component is not installed is not supported. Try installing the symfony/validator package.'); |
||
197 | } |
||
198 | |||
199 | 3 | $loader->load('param_fetcher_listener.xml'); |
|
200 | |||
201 | 3 | if (!empty($config['param_fetcher_listener']['service'])) { |
|
202 | $service = $container->getDefinition('fos_rest.param_fetcher_listener'); |
||
203 | $service->clearTag('kernel.event_listener'); |
||
204 | } |
||
205 | |||
206 | 3 | if ($config['param_fetcher_listener']['force']) { |
|
207 | 1 | $container->getDefinition('fos_rest.param_fetcher_listener')->replaceArgument(1, true); |
|
208 | } |
||
209 | } |
||
210 | 44 | } |
|
211 | |||
212 | 44 | private function loadBodyConverter(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
213 | { |
||
214 | 44 | if (!$this->isConfigEnabled($container, $config['body_converter'])) { |
|
215 | 40 | return; |
|
216 | } |
||
217 | |||
218 | 4 | $loader->load('request_body_param_converter.xml'); |
|
219 | |||
220 | 4 | if (!empty($config['body_converter']['validation_errors_argument'])) { |
|
221 | 4 | $container->getDefinition('fos_rest.converter.request_body')->replaceArgument(4, $config['body_converter']['validation_errors_argument']); |
|
222 | } |
||
223 | 4 | } |
|
224 | |||
225 | 44 | private function loadView(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
226 | { |
||
227 | 44 | if (!empty($config['view']['jsonp_handler'])) { |
|
228 | 1 | $handler = new ChildDefinition($config['service']['view_handler']); |
|
229 | 1 | $handler->setPublic(true); |
|
230 | |||
231 | 1 | $jsonpHandler = new Reference('fos_rest.view_handler.jsonp'); |
|
232 | 1 | $handler->addMethodCall('registerHandler', ['jsonp', [$jsonpHandler, 'createResponse']]); |
|
233 | 1 | $container->setDefinition('fos_rest.view_handler', $handler); |
|
234 | |||
235 | 1 | $container->getDefinition('fos_rest.view_handler.jsonp')->replaceArgument(0, $config['view']['jsonp_handler']['callback_param']); |
|
236 | |||
237 | 1 | if (empty($config['view']['mime_types']['jsonp'])) { |
|
238 | 1 | $config['view']['mime_types']['jsonp'] = $config['view']['jsonp_handler']['mime_type']; |
|
239 | } |
||
240 | } |
||
241 | |||
242 | 44 | if ($config['view']['mime_types']['enabled']) { |
|
243 | 1 | $loader->load('mime_type_listener.xml'); |
|
244 | |||
245 | 1 | if (!empty($config['mime_type_listener']['service'])) { |
|
246 | $service = $container->getDefinition('fos_rest.mime_type_listener'); |
||
247 | $service->clearTag('kernel.event_listener'); |
||
248 | } |
||
249 | |||
250 | 1 | $container->getDefinition('fos_rest.mime_type_listener')->replaceArgument(0, $config['view']['mime_types']['formats']); |
|
251 | } |
||
252 | |||
253 | 44 | if ($config['view']['view_response_listener']['enabled']) { |
|
254 | 5 | $loader->load('view_response_listener.xml'); |
|
255 | 5 | $service = $container->getDefinition('fos_rest.view_response_listener'); |
|
256 | |||
257 | 5 | if (!empty($config['view_response_listener']['service'])) { |
|
258 | $service->clearTag('kernel.event_listener'); |
||
259 | } |
||
260 | |||
261 | 5 | $service->replaceArgument(1, $config['view']['view_response_listener']['force']); |
|
262 | } |
||
263 | |||
264 | 44 | $formats = []; |
|
265 | 44 | foreach ($config['view']['formats'] as $format => $enabled) { |
|
266 | 44 | if ($enabled) { |
|
267 | 44 | $formats[$format] = false; |
|
268 | } |
||
269 | } |
||
270 | |||
271 | 44 | if (!is_numeric($config['view']['failed_validation'])) { |
|
272 | $config['view']['failed_validation'] = constant(sprintf('%s::%s', Response::class, $config['view']['failed_validation'])); |
||
273 | } |
||
274 | |||
275 | 44 | if (!is_numeric($config['view']['empty_content'])) { |
|
276 | $config['view']['empty_content'] = constant(sprintf('%s::%s', Response::class, $config['view']['empty_content'])); |
||
277 | } |
||
278 | |||
279 | 44 | $defaultViewHandler = $container->getDefinition('fos_rest.view_handler.default'); |
|
280 | 44 | $defaultViewHandler->setFactory([ViewHandler::class, 'create']); |
|
281 | 44 | $defaultViewHandler->setArguments([ |
|
282 | 44 | new Reference('router'), |
|
283 | 44 | new Reference('fos_rest.serializer'), |
|
284 | 44 | new Reference('request_stack'), |
|
285 | 44 | $formats, |
|
286 | 44 | $config['view']['failed_validation'], |
|
287 | 44 | $config['view']['empty_content'], |
|
288 | 44 | $config['view']['serialize_null'], |
|
289 | ]); |
||
290 | 44 | } |
|
291 | |||
292 | 44 | private function loadException(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
293 | { |
||
294 | 44 | if ($config['exception']['enabled']) { |
|
295 | 11 | $loader->load('exception.xml'); |
|
296 | |||
297 | 11 | if ($config['exception']['map_exception_codes']) { |
|
298 | 1 | $container->register('fos_rest.exception.response_status_code_listener', ResponseStatusCodeListener::class) |
|
299 | 1 | ->setArguments([ |
|
300 | 1 | new Reference('fos_rest.exception.codes_map'), |
|
301 | ]) |
||
302 | 1 | ->addTag('kernel.event_subscriber'); |
|
303 | } |
||
304 | |||
305 | 11 | $container->getDefinition('fos_rest.exception.codes_map') |
|
306 | 11 | ->replaceArgument(0, $config['exception']['codes']); |
|
307 | 11 | $container->getDefinition('fos_rest.exception.messages_map') |
|
308 | 11 | ->replaceArgument(0, $config['exception']['messages']); |
|
309 | |||
310 | 11 | $container->getDefinition('fos_rest.serializer.flatten_exception_handler') |
|
311 | 11 | ->replaceArgument(1, $config['exception']['debug']); |
|
312 | 11 | $container->getDefinition('fos_rest.serializer.flatten_exception_handler') |
|
313 | 11 | ->replaceArgument(2, 'rfc7807' === $config['exception']['flatten_exception_format']); |
|
314 | 11 | $container->getDefinition('fos_rest.serializer.flatten_exception_normalizer') |
|
315 | 11 | ->replaceArgument(1, $config['exception']['debug']); |
|
316 | 11 | $container->getDefinition('fos_rest.serializer.flatten_exception_normalizer') |
|
317 | 11 | ->replaceArgument(2, 'rfc7807' === $config['exception']['flatten_exception_format']); |
|
318 | |||
319 | 11 | if ($config['exception']['serializer_error_renderer']) { |
|
320 | 3 | $format = new Definition(); |
|
321 | 3 | $format->setFactory([SerializerErrorRenderer::class, 'getPreferredFormat']); |
|
322 | 3 | $format->setArguments([ |
|
323 | 3 | new Reference('request_stack'), |
|
324 | ]); |
||
325 | 3 | $debug = new Definition(); |
|
326 | 3 | $debug->setFactory([SerializerErrorRenderer::class, 'isDebug']); |
|
327 | 3 | $debug->setArguments([ |
|
328 | 3 | new Reference('request_stack'), |
|
329 | 3 | '%kernel.debug%', |
|
330 | ]); |
||
331 | 3 | $container->register('fos_rest.error_renderer.serializer', SerializerErrorRenderer::class) |
|
332 | 3 | ->setArguments([ |
|
333 | 3 | new Reference('fos_rest.serializer'), |
|
334 | 3 | $format, |
|
335 | 3 | new Reference('error_renderer.html', ContainerInterface::NULL_ON_INVALID_REFERENCE), |
|
336 | 3 | $debug, |
|
337 | ]); |
||
338 | 3 | $container->setAlias('error_renderer', 'fos_rest.error_renderer.serializer'); |
|
339 | } |
||
340 | } |
||
341 | 44 | } |
|
342 | |||
343 | 44 | private function loadSerializer(array $config, ContainerBuilder $container): void |
|
344 | { |
||
345 | 44 | $bodyConverter = $container->hasDefinition('fos_rest.converter.request_body') ? $container->getDefinition('fos_rest.converter.request_body') : null; |
|
346 | 44 | $viewHandler = $container->getDefinition('fos_rest.view_handler.default'); |
|
347 | 44 | $options = array(); |
|
348 | |||
349 | 44 | if (!empty($config['serializer']['version'])) { |
|
350 | 1 | if ($bodyConverter) { |
|
351 | $bodyConverter->replaceArgument(2, $config['serializer']['version']); |
||
352 | } |
||
353 | 1 | $options['exclusionStrategyVersion'] = $config['serializer']['version']; |
|
354 | } |
||
355 | |||
356 | 44 | if (!empty($config['serializer']['groups'])) { |
|
357 | 1 | if ($bodyConverter) { |
|
358 | $bodyConverter->replaceArgument(1, $config['serializer']['groups']); |
||
359 | } |
||
360 | 1 | $options['exclusionStrategyGroups'] = $config['serializer']['groups']; |
|
361 | } |
||
362 | |||
363 | 44 | $options['serializeNullStrategy'] = $config['serializer']['serialize_null']; |
|
364 | 44 | $viewHandler->addArgument($options); |
|
365 | 44 | } |
|
366 | |||
367 | 44 | private function loadZoneMatcherListener(array $config, XmlFileLoader $loader, ContainerBuilder $container): void |
|
368 | { |
||
369 | 44 | if (!empty($config['zone'])) { |
|
370 | 1 | $loader->load('zone_matcher_listener.xml'); |
|
371 | 1 | $zoneMatcherListener = $container->getDefinition('fos_rest.zone_matcher_listener'); |
|
372 | |||
373 | 1 | foreach ($config['zone'] as $zone) { |
|
374 | 1 | $matcher = $this->createZoneRequestMatcher( |
|
375 | 1 | $container, |
|
376 | 1 | $zone['path'], |
|
377 | 1 | $zone['host'], |
|
378 | 1 | $zone['methods'], |
|
379 | 1 | $zone['ips'] |
|
380 | ); |
||
381 | |||
382 | 1 | $zoneMatcherListener->addMethodCall('addRequestMatcher', array($matcher)); |
|
383 | } |
||
384 | } |
||
385 | 44 | } |
|
386 | |||
387 | 1 | private function createZoneRequestMatcher(ContainerBuilder $container, ?string $path = null, ?string $host = null, array $methods = array(), array $ips = null): Reference |
|
388 | { |
||
389 | 1 | if ($methods) { |
|
0 ignored issues
–
show
|
|||
390 | $methods = array_map('strtoupper', (array) $methods); |
||
391 | } |
||
392 | |||
393 | 1 | $serialized = serialize(array($path, $host, $methods, $ips)); |
|
394 | 1 | $id = 'fos_rest.zone_request_matcher.'.md5($serialized).sha1($serialized); |
|
395 | |||
396 | // only add arguments that are necessary |
||
397 | 1 | $arguments = array($path, $host, $methods, $ips); |
|
398 | 1 | while (count($arguments) > 0 && !end($arguments)) { |
|
399 | 1 | array_pop($arguments); |
|
400 | } |
||
401 | |||
402 | $container |
||
403 | 1 | ->setDefinition($id, new ChildDefinition('fos_rest.zone_request_matcher')) |
|
404 | 1 | ->setArguments($arguments) |
|
405 | ; |
||
406 | |||
407 | 1 | return new Reference($id); |
|
408 | } |
||
409 | } |
||
410 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.