Completed
Push — master ( 711a8e...e3d0d1 )
by
unknown
15:18
created

FileNameValidator   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 63
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
dl 0
loc 63
rs 10
c 1
b 0
f 0
wmc 8

4 Methods

Rating   Name   Duplication   Size   Complexity  
A missingImportantPatterns() 0 6 1
A customFileDenyPatternConfigured() 0 3 1
A isValid() 0 7 3
A __construct() 0 8 3
1
<?php
2
declare(strict_types = 1);
3
namespace TYPO3\CMS\Core\Resource\Security;
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
/**
19
 * Ensures that any filename that an editor chooses for naming (or uses for uploading a file) is valid, meaning
20
 * that no invalid characters (null-bytes) are added, or that the file does not contain an invalid file extension.
21
 */
22
class FileNameValidator
23
{
24
    /**
25
     * Previously this was used within SystemEnvironmentBuilder
26
     */
27
    public const DEFAULT_FILE_DENY_PATTERN = '\\.(php[3-8]?|phpsh|phtml|pht|phar|shtml|cgi)(\\..*)?$|\\.pl$|^\\.htaccess$';
28
29
    /**
30
     * @var string
31
     */
32
    protected $fileDenyPattern;
33
34
    public function __construct(string $fileDenyPattern = null)
35
    {
36
        if ($fileDenyPattern !== null) {
37
            $this->fileDenyPattern = $fileDenyPattern;
38
        } elseif (isset($GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'])) {
39
            $this->fileDenyPattern = (string)$GLOBALS['TYPO3_CONF_VARS']['BE']['fileDenyPattern'];
40
        } else {
41
            $this->fileDenyPattern = static::DEFAULT_FILE_DENY_PATTERN;
42
        }
43
    }
44
45
    /**
46
     * Verifies the input filename against the 'fileDenyPattern'
47
     *
48
     * Filenames are not allowed to contain control characters. Therefore we
49
     * always filter on [[:cntrl:]].
50
     *
51
     * @param string $fileName File path to evaluate
52
     * @return bool Returns TRUE if the file name is OK.
53
     */
54
    public function isValid(string $fileName): bool
55
    {
56
        $pattern = '/[[:cntrl:]]/';
57
        if ($fileName !== '' && $this->fileDenyPattern !== '') {
58
            $pattern = '/(?:[[:cntrl:]]|' . $this->fileDenyPattern . ')/iu';
59
        }
60
        return preg_match($pattern, $fileName) === 0;
61
    }
62
63
    /**
64
     * Find out if there is a custom file deny pattern configured.
65
     *
66
     * @return bool
67
     */
68
    public function customFileDenyPatternConfigured(): bool
69
    {
70
        return $this->fileDenyPattern !== self::DEFAULT_FILE_DENY_PATTERN;
71
    }
72
73
    /**
74
     * Checks if the given file deny pattern does not have parts that the default pattern should
75
     * recommend. Used in status overview.
76
     *
77
     * @return bool
78
     */
79
    public function missingImportantPatterns(): bool
80
    {
81
        $defaultParts = explode('|', self::DEFAULT_FILE_DENY_PATTERN);
82
        $givenParts = explode('|', $this->fileDenyPattern);
83
        $missingParts = array_diff($defaultParts, $givenParts);
84
        return !empty($missingParts);
85
    }
86
}
87