Completed
Push — master ( 4a8862...9e8f45 )
by Philip
04:41
created

Controller::show()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 38
ccs 28
cts 28
cp 1
rs 8.6897
c 0
b 0
f 0
cc 6
nc 4
nop 2
crap 6
1
<?php
2
3
/*
4
 * This file is part of the CRUDlex package.
5
 *
6
 * (c) Philip Lehmann-Böhm <[email protected]>
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 CRUDlex;
13
14
use League\Flysystem\FilesystemInterface;
15
use League\Flysystem\Util\MimeType;
16
use Symfony\Component\HttpFoundation\RedirectResponse;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\HttpFoundation\Session\SessionInterface;
20
use Symfony\Component\HttpFoundation\StreamedResponse;
21
use Symfony\Component\Translation\TranslatorInterface;
22
use Twig_Environment;
23
24
25
/**
26
 * Default implementation of the ControllerInterface.
27
 */
28
class Controller implements ControllerInterface {
29
30
    /**
31
     * Holds the filesystme.
32
     * @var FilesystemInterface
33
     */
34
    protected $filesystem;
35
36
    /**
37
     * Holds the session.
38
     * @var SessionInterface
39
     */
40
    protected $session;
41
42
    /**
43
     * Holds the translator.
44
     * @var TranslatorInterface
45
     */
46
    protected $translator;
47
48
    /**
49
     * Holds the service.
50
     * @var Service
51
     */
52
    protected $service;
53
54
    /**
55
     * Holds the Twig instance.
56
     * @var Twig_Environment
57
     */
58
    protected $twig;
59
60
    /**
61
     * Postprocesses the entity after modification by handling the uploaded
62
     * files and setting the flash.
63
     *
64
     * @param Request $request
65
     * the current request
66
     * @param AbstractData $crudData
67
     * the data instance of the entity
68
     * @param Entity $instance
69
     * the entity
70
     * @param string $entity
71
     * the name of the entity
72
     * @param string $mode
73
     * whether to 'edit' or to 'create' the entity
74
     *
75
     * @return null|\Symfony\Component\HttpFoundation\RedirectResponse
76
     * the HTTP response of this modification
77
     */
78 4
    protected function modifyFilesAndSetFlashBag(Request $request, AbstractData $crudData, Entity $instance, $entity, $mode)
79
    {
80 4
        $id          = $instance->get('id');
81 4
        $fileHandler = new FileHandler($this->filesystem, $crudData->getDefinition());
82 4
        $result      = $mode == 'edit' ? $fileHandler->updateFiles($crudData, $request, $instance, $entity) : $fileHandler->createFiles($crudData, $request, $instance, $entity);
83 4
        if (!$result) {
84 2
            return null;
85
        }
86 4
        $this->session->getFlashBag()->add('success', $this->translator->trans('crudlex.'.$mode.'.success', [
87 4
            '%label%' => $crudData->getDefinition()->getLabel(),
88 4
            '%id%' => $id
89
        ]));
90 4
        return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
91
    }
92
93
    /**
94
     * Sets the flashes of a failed entity modification.
95
     *
96
     * @param boolean $optimisticLocking
97
     * whether the optimistic locking failed
98
     * @param string $mode
99
     * the modification mode, either 'create' or 'edit'
100
     */
101 2
    protected function setValidationFailedFlashes($optimisticLocking, $mode)
102
    {
103 2
        $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.'.$mode.'.error'));
104 2
        if ($optimisticLocking) {
105 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.edit.locked'));
106
        }
107 2
    }
108
109
    /**
110
     * Validates and saves the new or updated entity and returns the appropriate HTTP
111
     * response.
112
     *
113
     * @param Request $request
114
     * the current request
115
     * @param AbstractData $crudData
116
     * the data instance of the entity
117
     * @param Entity $instance
118
     * the entity
119
     * @param string $entity
120
     * the name of the entity
121
     * @param boolean $edit
122
     * whether to edit (true) or to create (false) the entity
123
     *
124
     * @return Response
125
     * the HTTP response of this modification
126
     */
127 4
    protected function modifyEntity(Request $request, AbstractData $crudData, Entity $instance, $entity, $edit)
128
    {
129 4
        $fieldErrors = [];
130 4
        $mode        = $edit ? 'edit' : 'create';
131 4
        if ($request->getMethod() == 'POST') {
132 4
            $instance->populateViaRequest($request);
133 4
            $validator  = new EntityValidator($instance);
134 4
            $validation = $validator->validate($crudData, intval($request->get('version')));
135
136 4
            $fieldErrors = $validation['errors'];
137 4
            if (!$validation['valid']) {
138 2
                $optimisticLocking = isset($fieldErrors['version']);
139 2
                $this->setValidationFailedFlashes($optimisticLocking, $mode);
140
            } else {
141 4
                $modified = $edit ? $crudData->update($instance) : $crudData->create($instance);
142 4
                $response = $modified ? $this->modifyFilesAndSetFlashBag($request, $crudData, $instance, $entity, $mode) : false;
143 4
                if ($response) {
144 4
                    return $response;
145
                }
146 2
                $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.'.$mode.'.failed'));
147
            }
148
        }
149
150 2
        return new Response($this->twig->render($this->service->getTemplate('template', 'form', $entity), [
151 2
            'crud' => $this->service,
152 2
            'crudEntity' => $entity,
153 2
            'crudData' => $crudData,
154 2
            'entity' => $instance,
155 2
            'mode' => $mode,
156 2
            'fieldErrors' => $fieldErrors,
157 2
            'layout' => $this->service->getTemplate('layout', $mode, $entity)
158
        ]));
159
    }
160
161
    /**
162
     * Gets the parameters for the redirection after deleting an entity.
163
     *
164
     * @param Request $request
165
     * the current request
166
     * @param string $entity
167
     * the entity name
168
     * @param string $redirectPage
169
     * reference, where the page to redirect to will be stored
170
     *
171
     * @return array<string,string>
172
     * the parameters of the redirection, entity and id
173
     */
174 1
    protected function getAfterDeleteRedirectParameters(Request $request, $entity, &$redirectPage)
175
    {
176 1
        $redirectPage       = 'crudList';
177 1
        $redirectParameters = ['entity' => $entity];
178 1
        $redirectEntity     = $request->get('redirectEntity');
179 1
        $redirectId         = $request->get('redirectId');
180 1
        if ($redirectEntity && $redirectId) {
181 1
            $redirectPage       = 'crudShow';
182
            $redirectParameters = [
183 1
                'entity' => $redirectEntity,
184 1
                'id' => $redirectId
185
            ];
186
        }
187 1
        return $redirectParameters;
188
    }
189
190
    /**
191
     * Builds up the parameters of the list page filters.
192
     *
193
     * @param Request $request
194
     * the current request
195
     * @param EntityDefinition $definition
196
     * the current entity definition
197
     * @param array &$filter
198
     * will hold a map of fields to request parameters for the filters
199
     * @param boolean $filterActive
200
     * reference, will be true if at least one filter is active
201
     * @param array $filterToUse
202
     * reference, will hold a map of fields to integers (0 or 1) which boolean filters are active
203
     * @param array $filterOperators
204
     * reference, will hold a map of fields to operators for AbstractData::listEntries()
205
     *
206
     * @return array
207
     * the raw filter query parameters
208
     */
209 2
    protected function buildUpListFilter(Request $request, EntityDefinition $definition, &$filter, &$filterActive, &$filterToUse, &$filterOperators)
210
    {
211 2
        $rawFilter = [];
212 2
        foreach ($definition->getFilter() as $filterField) {
213 2
            $type                    = $definition->getType($filterField);
214 2
            $filter[$filterField]    = $request->get('crudFilter'.$filterField);
215 2
            $rawFilter[$filterField] = $filter[$filterField];
216 2
            if ($filter[$filterField]) {
217 1
                $filterActive                  = true;
218 1
                $filterToUse[$filterField]     = $filter[$filterField];
219 1
                $filterOperators[$filterField] = '=';
220 1
                if ($type === 'boolean') {
221 1
                    $filterToUse[$filterField] = $filter[$filterField] == 'true' ? 1 : 0;
222 1
                } else if ($type === 'reference') {
223 1
                    $filter[$filterField] = ['id' => $filter[$filterField]];
224 1
                } else if ($type === 'many') {
225
                    $filter[$filterField] = array_map(function($value) {
226 1
                        return ['id' => $value];
227 1
                    }, $filter[$filterField]);
228 1
                    $filterToUse[$filterField] = $filter[$filterField];
229 1
                } else if (in_array($type, ['text', 'multiline', 'fixed'])) {
230 1
                    $filterToUse[$filterField]     = '%'.$filter[$filterField].'%';
231 1
                    $filterOperators[$filterField] = 'LIKE';
232
                }
233
            }
234
        }
235 2
        return $rawFilter;
236
    }
237
238
    /**
239
     * Generates the not found page.
240
     *
241
     * @param string $error
242
     * the cause of the not found error
243
     *
244
     * @return Response
245
     * the rendered not found page with the status code 404
246
     */
247 10
    protected function getNotFoundPage($error)
248
    {
249 10
        return new Response($this->twig->render('@crud/notFound.twig', [
250 10
            'crud' => $this->service,
251 10
            'error' => $error,
252 10
            'crudEntity' => '',
253 10
            'layout' => $this->service->getTemplate('layout', '', '')
254 10
        ]), 404);
255
    }
256
257
    /**
258
     * Controller constructor.
259
     *
260
     * @param Service $service
261
     * the CRUDlex service
262
     * @param FilesystemInterface $filesystem
263
     * the used filesystem
264
     * @param Twig_Environment $twig
265
     * the Twig environment
266
     * @param SessionInterface $session
267
     * the session service
268
     * @param TranslatorInterface $translator
269
     * the translation service
270
     */
271 10
    public function __construct(Service $service, FilesystemInterface $filesystem, Twig_Environment $twig, SessionInterface $session, TranslatorInterface $translator)
272
    {
273 10
        $this->service    = $service;
274 10
        $this->filesystem = $filesystem;
275 10
        $this->twig       = $twig;
276 10
        $this->session    = $session;
277 10
        $this->translator = $translator;
278 10
    }
279
280
    /**
281
     * {@inheritdoc}
282
     */
283 2
    public function setLocaleAndCheckEntity(Request $request)
284
    {
285 2
        $locale = $this->translator->getLocale();
286 2
        $this->service->setLocale($locale);
287 2
        if (!$this->service->getData($request->get('entity'))) {
288 2
            return $this->getNotFoundPage($this->translator->trans('crudlex.entityNotFound'));
289
        }
290 1
        return null;
291
    }
292
293
    /**
294
     * {@inheritdoc}
295
     */
296 3
    public function create(Request $request, $entity)
297
    {
298 3
        $crudData = $this->service->getData($entity);
299 3
        if (!$crudData) {
300 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
301
        }
302 3
        $instance = $crudData->createEmpty();
303 3
        $instance->populateViaRequest($request);
304 3
        return $this->modifyEntity($request, $crudData, $instance, $entity, false);
305
    }
306
307
    /**
308
     * {@inheritdoc}
309
     */
310 2
    public function showList(Request $request, $entity)
311
    {
312 2
        $crudData = $this->service->getData($entity);
313 2
        if (!$crudData) {
314 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
315
        }
316 2
        $definition = $crudData->getDefinition();
317
318 2
        $filter          = [];
319 2
        $filterActive    = false;
320 2
        $filterToUse     = [];
321 2
        $filterOperators = [];
322 2
        $rawFilter       = $this->buildUpListFilter($request, $definition, $filter, $filterActive, $filterToUse, $filterOperators);
323
324 2
        $pageSize = $definition->getPageSize();
325 2
        $total    = $crudData->countBy($definition->getTable(), $filterToUse, $filterOperators, true);
326 2
        $page     = abs(intval($request->get('crudPage', 0)));
327 2
        $maxPage  = intval($total / $pageSize);
328 2
        if ($total % $pageSize == 0) {
329 2
            $maxPage--;
330
        }
331 2
        if ($page > $maxPage) {
332 1
            $page = $maxPage;
333
        }
334 2
        $skip = $page * $pageSize;
335
336 2
        $sortField            = $request->get('crudSortField', $definition->getInitialSortField());
337 2
        $sortAscendingRequest = $request->get('crudSortAscending');
338 2
        $sortAscending        = $sortAscendingRequest !== null ? $sortAscendingRequest === 'true' : $definition->isInitialSortAscending();
339
340 2
        $entities = $crudData->listEntries($filterToUse, $filterOperators, $skip, $pageSize, $sortField, $sortAscending);
341
342 2
        return new Response($this->twig->render($this->service->getTemplate('template', 'list', $entity), [
343 2
            'crud' => $this->service,
344 2
            'crudEntity' => $entity,
345 2
            'crudData' => $crudData,
346 2
            'definition' => $definition,
347 2
            'entities' => $entities,
348 2
            'pageSize' => $pageSize,
349 2
            'maxPage' => $maxPage,
350 2
            'page' => $page,
351 2
            'total' => $total,
352 2
            'filter' => $filter,
353 2
            'rawFilter' => $rawFilter,
354 2
            'filterActive' => $filterActive,
355 2
            'sortField' => $sortField,
356 2
            'sortAscending' => $sortAscending,
357 2
            'layout' => $this->service->getTemplate('layout', 'list', $entity)
358
        ]));
359
    }
360
361
    /**
362
     * {@inheritdoc}
363
     */
364 1
    public function show($entity, $id)
365
    {
366 1
        $crudData = $this->service->getData($entity);
367 1
        if (!$crudData) {
368 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
369
        }
370 1
        $instance = $crudData->get($id);
371 1
        if (!$instance) {
372 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.instanceNotFound'));
373
        }
374 1
        $definition = $crudData->getDefinition();
375
376 1
        $childrenLabelFields = $definition->getChildrenLabelFields();
377 1
        $children            = [];
378 1
        if (count($childrenLabelFields) > 0) {
379 1
            foreach ($definition->getChildren() as $child) {
380 1
                $childField      = $child[1];
381 1
                $childEntity     = $child[2];
382 1
                $childLabelField = array_key_exists($childEntity, $childrenLabelFields) ? $childrenLabelFields[$childEntity] : 'id';
383 1
                $childCrud       = $this->service->getData($childEntity);
384 1
                $children[]      = [
385 1
                    $childCrud->getDefinition()->getLabel(),
386 1
                    $childEntity,
387 1
                    $childLabelField,
388 1
                    $childCrud->listEntries([$childField => $instance->get('id')]),
389 1
                    $childField
390
                ];
391
            }
392
        }
393
394 1
        return new Response($this->twig->render($this->service->getTemplate('template', 'show', $entity), [
395 1
            'crud' => $this->service,
396 1
            'crudEntity' => $entity,
397 1
            'entity' => $instance,
398 1
            'children' => $children,
399 1
            'layout' => $this->service->getTemplate('layout', 'show', $entity)
400
        ]));
401
    }
402
403
    /**
404
     * {@inheritdoc}
405
     */
406 1
    public function edit(Request $request, $entity, $id)
407
    {
408 1
        $crudData = $this->service->getData($entity);
409 1
        if (!$crudData) {
410 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
411
        }
412 1
        $instance = $crudData->get($id);
413 1
        if (!$instance) {
414 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.instanceNotFound'));
415
        }
416
417 1
        return $this->modifyEntity($request, $crudData, $instance, $entity, true);
418
    }
419
420
    /**
421
     * {@inheritdoc}
422
     */
423 1
    public function delete(Request $request, $entity, $id)
424
    {
425 1
        $crudData = $this->service->getData($entity);
426 1
        if (!$crudData) {
427 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
428
        }
429 1
        $instance = $crudData->get($id);
430 1
        if (!$instance) {
431 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.instanceNotFound'));
432
        }
433
434 1
        $fileHandler  = new FileHandler($this->filesystem, $crudData->getDefinition());
435 1
        $filesDeleted = $fileHandler->deleteFiles($crudData, $instance, $entity);
436 1
        $deleted      = $filesDeleted ? $crudData->delete($instance) : AbstractData::DELETION_FAILED_EVENT;
437
438 1
        if ($deleted === AbstractData::DELETION_FAILED_EVENT) {
439 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.delete.failed'));
440 1
            return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
441 1
        } elseif ($deleted === AbstractData::DELETION_FAILED_STILL_REFERENCED) {
442 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.delete.error', [
443 1
                '%label%' => $crudData->getDefinition()->getLabel()
444
            ]));
445 1
            return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
446
        }
447
448 1
        $redirectPage       = 'crudList';
449 1
        $redirectParameters = $this->getAfterDeleteRedirectParameters($request, $entity, $redirectPage);
450
451 1
        $this->session->getFlashBag()->add('success', $this->translator->trans('crudlex.delete.success', [
452 1
            '%label%' => $crudData->getDefinition()->getLabel()
453
        ]));
454 1
        return new RedirectResponse($this->service->generateURL($redirectPage, $redirectParameters));
455
    }
456
457
    /**
458
     * {@inheritdoc}
459
     */
460 1
    public function renderFile($entity, $id, $field)
461
    {
462 1
        $crudData = $this->service->getData($entity);
463 1
        if (!$crudData) {
464 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
465
        }
466 1
        $instance   = $crudData->get($id);
467 1
        $definition = $crudData->getDefinition();
468 1
        if (!$instance || $definition->getType($field) != 'file' || !$instance->get($field)) {
469 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.instanceNotFound'));
470
        }
471 1
        $fileHandler = new FileHandler($this->filesystem, $definition);
472 1
        return $fileHandler->renderFile($instance, $entity, $field);
473
    }
474
475
    /**
476
     * {@inheritdoc}
477
     */
478 1
    public function deleteFile($entity, $id, $field)
479
    {
480 1
        $crudData = $this->service->getData($entity);
481 1
        if (!$crudData) {
482 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
483
        }
484 1
        $instance = $crudData->get($id);
485 1
        if (!$instance) {
486 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.instanceNotFound'));
487
        }
488 1
        $fileHandler = new FileHandler($this->filesystem, $crudData->getDefinition());
489 1
        if (!$crudData->getDefinition()->getField($field, 'required', false) && $fileHandler->deleteFile($crudData, $instance, $entity, $field)) {
490 1
            $instance->set($field, '');
491 1
            $crudData->update($instance);
492 1
            $this->session->getFlashBag()->add('success', $this->translator->trans('crudlex.file.deleted'));
493
        } else {
494 1
            $this->session->getFlashBag()->add('danger', $this->translator->trans('crudlex.file.notDeleted'));
495
        }
496 1
        return new RedirectResponse($this->service->generateURL('crudShow', ['entity' => $entity, 'id' => $id]));
497
    }
498
499
    /**
500
     * {@inheritdoc}
501
     */
502 1
    public function staticFile(Request $request)
503
    {
504 1
        $fileParam = str_replace('..', '', $request->get('file'));
505 1
        $file      = __DIR__.'/../static/'.$fileParam;
506 1
        if (!$fileParam || !file_exists($file)) {
507 1
            return $this->getNotFoundPage($this->translator->trans('crudlex.resourceNotFound'));
508
        }
509
510 1
        $mimeType = MimeType::detectByFilename($file);
511 1
        $size     = filesize($file);
512
513 1
        $streamedFileResponse = new StreamedFileResponse();
514 1
        $response             = new StreamedResponse($streamedFileResponse->getStreamedFileFunction($file), 200, [
515 1
            'Content-Type' => $mimeType,
516 1
            'Content-Disposition' => 'attachment; filename="'.basename($file).'"',
517 1
            'Content-length' => $size
518
        ]);
519
520 1
        $response->setETag(filemtime($file))->setPublic()->isNotModified($request);
521 1
        $response->send();
522
523 1
        return $response;
524
    }
525
526
    /**
527
     * {@inheritdoc}
528
     */
529 1
    public function setLocale(Request $request, $locale)
530
    {
531
532 1
        if (!in_array($locale, $this->service->getLocales())) {
533 1
            return $this->getNotFoundPage('Locale '.$locale.' not found.');
534
        }
535
536 1
        $manageI18n = $this->service->isManageI18n();
537 1
        if ($manageI18n) {
538 1
            $this->session->set('locale', $locale);
539
        }
540 1
        $redirect = $request->get('redirect');
541 1
        return new RedirectResponse($redirect);
0 ignored issues
show
Security Cross-Site Scripting introduced by
$redirect can contain request data and is used in output context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: $this->parameters['HTTP_AUTHORIZATION'] seems to return tainted data, and $authorizationHeader is assigned in ServerBag.php on line 62
  1. $this->parameters['HTTP_AUTHORIZATION'] seems to return tainted data, and $authorizationHeader is assigned
    in vendor/ServerBag.php on line 62
  2. ParameterBag::$parameters is assigned
    in vendor/ServerBag.php on line 77
  3. Tainted property ParameterBag::$parameters is read
    in vendor/ParameterBag.php on line 84
  4. ParameterBag::get() returns tainted data, and $result is assigned
    in vendor/Request.php on line 687
  5. Request::get() returns tainted data, and $redirect is assigned
    in src/CRUDlex/Controller.php on line 540
  2. Path: Read from $_POST, and $_POST is passed to Request::createRequestFromFactory() in Request.php on line 281
  1. Read from $_POST, and $_POST is passed to Request::createRequestFromFactory()
    in vendor/Request.php on line 281
  2. $request is passed to Request::__construct()
    in vendor/Request.php on line 1950
  3. $request is passed to Request::initialize()
    in vendor/Request.php on line 235
  4. $request is passed to ParameterBag::__construct()
    in vendor/Request.php on line 253
  5. ParameterBag::$parameters is assigned
    in vendor/ParameterBag.php on line 31
  6. Tainted property ParameterBag::$parameters is read
    in vendor/ParameterBag.php on line 84
  7. ParameterBag::get() returns tainted data, and $result is assigned
    in vendor/Request.php on line 687
  8. Request::get() returns tainted data, and $redirect is assigned
    in src/CRUDlex/Controller.php on line 540

Used in output context

  1. RedirectResponse::__construct() uses RedirectResponse::setTargetUrl() ($url)
    in vendor/RedirectResponse.php on line 39
  2. RedirectResponse::setTargetUrl() uses Response::setContent() ($content)
    in vendor/RedirectResponse.php on line 92
  3. Response::setContent() uses property Response::$content for writing
    in vendor/Response.php on line 397
  4. Property Response::$content is used in echo
    in vendor/Response.php on line 356

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
542
    }
543
}
544