1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | /* |
||
6 | * This file is part of the humbug/php-scoper package. |
||
7 | * |
||
8 | * Copyright (c) 2017 Théo FIDRY <[email protected]>, |
||
9 | * Pádraic Brady <[email protected]> |
||
10 | * |
||
11 | * For the full copyright and license information, please view the LICENSE |
||
12 | * file that was distributed with this source code. |
||
13 | */ |
||
14 | |||
15 | namespace Humbug\PhpScoper\Configuration; |
||
16 | |||
17 | use function array_pop; |
||
18 | use function count; |
||
19 | use function explode; |
||
20 | use function in_array; |
||
21 | use function preg_last_error; |
||
22 | use function preg_last_error_msg; |
||
23 | use function preg_match as native_preg_match; |
||
24 | use function Safe\sprintf; |
||
25 | use function str_split; |
||
26 | use function strlen; |
||
27 | |||
28 | final class RegexChecker |
||
29 | { |
||
30 | // Some characters are best to not be allowed as regex delimiters in order |
||
31 | // to not result in some fancy regexes |
||
32 | // See https://github.com/humbug/php-scoper/issues/597 |
||
33 | private const INVALID_REGEX_DELIMITERS = [ |
||
34 | '\\', |
||
35 | '_', |
||
36 | ]; |
||
37 | |||
38 | // https://www.php.net/manual/en/reference.pcre.pattern.modifiers.php |
||
39 | private const PATTERN_MODIFIERS = [ |
||
40 | 'i', |
||
41 | 'm', |
||
42 | 's', |
||
43 | 'x', |
||
44 | 'A', |
||
45 | 'D', |
||
46 | 'S', |
||
47 | 'U', |
||
48 | 'X', |
||
49 | 'J', |
||
50 | 'u', |
||
51 | ]; |
||
52 | |||
53 | public function isRegexLike(string $value): bool |
||
54 | { |
||
55 | $valueLength = strlen($value); |
||
56 | |||
57 | if ($valueLength < 2) { |
||
58 | return false; |
||
59 | } |
||
60 | |||
61 | /** @var non-empty-string $firstCharacter */ |
||
62 | $firstCharacter = $value[0]; |
||
63 | |||
64 | if (!self::isValidDelimiter($firstCharacter)) { |
||
65 | return false; |
||
66 | } |
||
67 | |||
68 | $parts = explode($firstCharacter, $value); |
||
69 | |||
70 | if (count($parts) !== 3) { |
||
71 | return false; |
||
72 | } |
||
73 | |||
74 | $lastPart = array_pop($parts); |
||
75 | |||
76 | if (!self::isValidRegexFlags($lastPart)) { |
||
77 | return false; |
||
78 | } |
||
79 | |||
80 | return true; |
||
81 | } |
||
82 | |||
83 | public function validateRegex(string $regex): ?string |
||
84 | { |
||
85 | if (@native_preg_match($regex, '') !== false) { |
||
86 | return null; |
||
87 | } |
||
88 | |||
89 | return sprintf( |
||
0 ignored issues
–
show
|
|||
90 | 'Invalid regex: %s (code %s)', |
||
91 | preg_last_error_msg(), |
||
92 | preg_last_error(), |
||
93 | ); |
||
94 | } |
||
95 | |||
96 | private static function isValidDelimiter(string $delimiter): bool |
||
97 | { |
||
98 | return !in_array($delimiter, self::INVALID_REGEX_DELIMITERS, true) |
||
99 | && native_preg_match('/^\p{L}$/u', $delimiter) === 0; |
||
100 | } |
||
101 | |||
102 | private static function isValidRegexFlags(string $value): bool |
||
103 | { |
||
104 | if ('' === $value) { |
||
105 | return true; |
||
106 | } |
||
107 | |||
108 | $characters = str_split($value); |
||
109 | |||
110 | foreach ($characters as $character) { |
||
111 | if (!in_array($character, self::PATTERN_MODIFIERS, true)) { |
||
112 | return false; |
||
113 | } |
||
114 | } |
||
115 | |||
116 | return true; |
||
117 | } |
||
118 | } |
||
119 |
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.