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 namespace nyx\utils\str; |
||
2 | |||
3 | // External dependencies |
||
4 | use nyx\core; |
||
5 | use nyx\diagnostics; |
||
6 | |||
7 | // Internal dependencies |
||
8 | use nyx\utils; |
||
9 | |||
10 | /** |
||
11 | * Character |
||
12 | * |
||
13 | * @package Nyx\Utils\Strings |
||
14 | * @version 0.1.0 |
||
15 | * @author Michal Chojnacki <[email protected]> |
||
16 | * @copyright 2012-2016 Nyx Dev Team |
||
17 | * @link http://docs.muyo.io/nyx/utils/strings.html |
||
18 | */ |
||
19 | class Character |
||
20 | { |
||
21 | /** |
||
22 | * The traits of the Character class. |
||
23 | */ |
||
24 | use utils\traits\StaticallyExtendable; |
||
25 | |||
26 | /** |
||
27 | * Flags used to combine different characters into a set via self::buildCharacterSet() |
||
28 | */ |
||
29 | const CHARS_UPPER = 1; // Uppercase letters. |
||
30 | const CHARS_LOWER = 2; // Lowercase letters. |
||
31 | const CHARS_ALPHA = 3; // CHARS_UPPER and CHARS_LOWER. |
||
32 | const CHARS_NUMERIC = 4; // Digits. |
||
33 | const CHARS_ALNUM = 7; // CHARS_ALPHA and CHARS_NUMERIC (Base62) |
||
34 | const CHARS_HEX_UPPER = 12; // Uppercase hexadecimal symbols - CHARS_DIGITS and 8. |
||
35 | const CHARS_HEX_LOWER = 20; // Lowercase hexadecimal symbols - CHARS_DIGITS and 16. |
||
36 | const CHARS_BASE64 = 39; // CHARS_ALNUM and 32. |
||
37 | const CHARS_SYMBOLS = 64; // Additional symbols ($%& etc.) accessible on most if not all keyboards. |
||
38 | const CHARS_BRACKETS = 128; // Brackets. |
||
39 | const CHARS_PUNCTUATION = 256; // Punctuation marks. |
||
40 | |||
41 | /** |
||
42 | * @const Special character flag for alphanumeric characters excluding characters which tend |
||
43 | * to be hard to distinguish from each other. |
||
44 | */ |
||
45 | const CHARS_LEGIBLE = 512; |
||
46 | |||
47 | /** |
||
48 | * @var array A map of CHARS_* flags to their actual character lists. @todo Make writable, handle cache? |
||
49 | */ |
||
50 | protected static $setsMap = [ |
||
51 | self::CHARS_UPPER => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', |
||
52 | self::CHARS_LOWER => 'abcdefghijklmnopqrstuvwxyz', |
||
53 | self::CHARS_NUMERIC => '0123456789', |
||
54 | self::CHARS_HEX_UPPER => 'ABCDEF', |
||
55 | self::CHARS_HEX_LOWER => 'abcdef', |
||
56 | self::CHARS_BASE64 => '+/', |
||
57 | self::CHARS_SYMBOLS => '!"#$%&\'()* +,-./:;<=>?@[\]^_`{|}~', |
||
58 | self::CHARS_BRACKETS => '()[]{}<>', |
||
59 | self::CHARS_PUNCTUATION => ',.;:', |
||
60 | self::CHARS_LEGIBLE => 'DQO0B8|I1lS5Z2G6()[]{}:;,.' // Somewhat unintuitive as this is actually an |
||
61 | // exclusion map containing ambiguous characters. |
||
62 | ]; |
||
63 | |||
64 | /** |
||
65 | * @var array Cached character sets built via self::buildCharacterSet() in a $bitmask => $set format, |
||
66 | * where $bitmask are the flags used to build the $set character list. |
||
67 | */ |
||
68 | protected static $setsBuilt; |
||
69 | |||
70 | /** |
||
71 | * Returns the character at the specified $offset (0-indexed) in $haystack. |
||
72 | * |
||
73 | * @param string $haystack The string to search in. |
||
74 | * @param int $offset The requested index. If a negative index is given, this method will return |
||
75 | * the $offset-th character counting from the end of the string. |
||
76 | * @param string|null $encoding The encoding to use. |
||
77 | * @return string The character at the specified $index. |
||
78 | */ |
||
79 | public static function at(string $haystack, int $offset, string $encoding = null) : string |
||
80 | { |
||
81 | $encoding = $encoding ?: utils\Str::encoding($haystack); |
||
82 | |||
83 | // Check if the absolute starting index (to account for negative indexes) + 1 (since it's 0-indexed |
||
84 | // while length is > 1 at this point) is within the length of the string. |
||
85 | View Code Duplication | if (abs($offset) >= mb_strlen($haystack, $encoding)) { |
|
0 ignored issues
–
show
|
|||
86 | throw new \OutOfBoundsException('The given $offset ['.$offset.'] does not exist within the string ['.utils\Str::truncate($haystack, 20, '...', $encoding).'].'); |
||
0 ignored issues
–
show
$encoding is of type string , but the function expects a boolean .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
87 | } |
||
88 | |||
89 | return mb_substr($haystack, $offset, 1, $encoding); |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Creates a list of characters based on a set of flags (CHARS_* class constants) given. |
||
94 | * |
||
95 | * @param int|core\Mask $mask The combination of CHARS_* flags (see the class constants) to use. Can be |
||
96 | * passed in either as an integer or as an instance of nyx\core\Mask. |
||
97 | * @return string The resulting list of characters. |
||
98 | * @throws \InvalidArgumentException When an invalid $from mask was given or the supposed bitmask is <= 0. |
||
99 | */ |
||
100 | public static function buildSet($mask) : string |
||
101 | { |
||
102 | // Unpack the actual mask if we got a core\Mask (builder) instance. |
||
103 | if ($mask instanceof core\Mask) { |
||
104 | $mask = $mask->get(); |
||
105 | } else if (!is_int($mask)) { |
||
106 | throw new \InvalidArgumentException('Expected an integer or an instance of \nyx\core\Mask, got ['.diagnostics\Debug::getTypeName($mask).'] instead.'); |
||
107 | } |
||
108 | |||
109 | if ($mask <= 0) { |
||
110 | throw new \InvalidArgumentException("Expected a bitmask, got an integer with a value of [$mask] instead."); |
||
111 | } |
||
112 | |||
113 | // If all we get is the ambiguous exclusion flag, we need a base set of characters |
||
114 | // to work with (an exclude from). |
||
115 | if ($mask === self::CHARS_LEGIBLE) { |
||
116 | $mask |= self::CHARS_ALNUM; |
||
117 | } |
||
118 | |||
119 | // Return a cached set if we've got one. Can't do this before the check for CHARS_LEGIBLE |
||
120 | // above as the flag for alphanumeric chars gets applied to them first regardless of user given |
||
121 | // params. |
||
122 | if (isset(static::$setsBuilt[$mask])) { |
||
123 | return static::$setsBuilt[$mask]; |
||
124 | } |
||
125 | |||
126 | $result = ''; |
||
127 | |||
128 | // Iterate over all defined sets and build up the string for set flags. |
||
129 | foreach (static::$setsMap as $flag => $characters) { |
||
130 | // Ambiguous chars may get special exclusion treatment (see post loop). |
||
131 | if ($flag === self::CHARS_LEGIBLE) { |
||
132 | continue; |
||
133 | } |
||
134 | |||
135 | if (($mask & $flag) === $flag) { |
||
136 | $result .= $characters; |
||
137 | } |
||
138 | } |
||
139 | |||
140 | // Remove all known ambiguous characters from the set, if CHARS_LEGIBLE is set. |
||
141 | if ($mask & self::CHARS_LEGIBLE) { |
||
142 | $result = str_replace(str_split(static::$setsMap[self::CHARS_LEGIBLE]), '', $result); |
||
143 | } |
||
144 | |||
145 | // In mode 3 count_chars() returns only unique characters. Cache the result for the |
||
146 | // flag set given so we can avoid the loops later on for the exact same mask. |
||
147 | return static::$setsBuilt[$mask] = count_chars($result, 3); |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Runs the given callable over each character in the given string and returns the resulting string. |
||
152 | * |
||
153 | * The callable should accept two arguments (in this order): |
||
154 | * - the character (multibyte string) |
||
155 | * - the character's index (int). |
||
156 | * |
||
157 | * Additional arguments may also be added and will be appended to the callable in the order given. |
||
158 | * The callable must return either a string or a value castable to a string. |
||
159 | * |
||
160 | * @param string $str The string over which to run the callable. |
||
161 | * @param callable $callable The callable to apply. |
||
162 | * @param string|null $encoding The encoding to use. |
||
163 | * @param mixed ...$args Additional arguments to pass to the callable. |
||
164 | * @return string The string after applying the callable to each of its characters. |
||
165 | */ |
||
166 | public static function each(string $str, callable $callable, string $encoding = null, ...$args) : string |
||
167 | { |
||
168 | if ($str === '') { |
||
169 | return $str; |
||
170 | } |
||
171 | |||
172 | $result = ''; |
||
173 | $encoding = $encoding ?: utils\Str::encoding($str); |
||
174 | $length = mb_strlen($str, $encoding); |
||
175 | |||
176 | for ($idx = 0; $idx < $length; $idx++) { |
||
177 | $result .= (string) call_user_func($callable, mb_substr($str, $idx, 1, $encoding), $idx, ...$args); |
||
178 | } |
||
179 | |||
180 | return $result; |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * Returns the binary string representation of the given character. Multi-byte safe. |
||
185 | * |
||
186 | * @param string $character The character to represent. |
||
187 | * @return string |
||
188 | */ |
||
189 | public static function toBinaryString(string $character) : string |
||
190 | { |
||
191 | $result = null; |
||
192 | $length = strlen($character); // Note: We want the raw length, not the mb length. |
||
193 | |||
194 | for ($i = 0; $i < $length; ++$i) { |
||
195 | $result .= sprintf('%08b', ord($character[$i])); |
||
196 | } |
||
197 | |||
198 | return $result; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Returns the decimal code representation of the given character. Multi-byte safe. |
||
203 | * |
||
204 | * @param string $character The character to represent. |
||
205 | * @return int |
||
206 | */ |
||
207 | public static function toDecimalCode(string $character) : int |
||
208 | { |
||
209 | $code = ord($character[0]); |
||
210 | |||
211 | // Single byte / 0xxxxxxx |
||
212 | if (!($code & 0x80)) { |
||
213 | return $code; |
||
214 | } |
||
215 | |||
216 | $bytes = 1; |
||
217 | |||
218 | // 2 bytes / 110xxxxx |
||
219 | if (0xc0 === ($code & 0xe0)) { |
||
220 | $code = $code & ~0xc0; |
||
221 | $bytes = 2; |
||
222 | // 3 bytes / 1110xxxx |
||
223 | } elseif (0xe0 === ($code & 0xf0)) { |
||
224 | $code = $code & ~0xe0; |
||
225 | $bytes = 3; |
||
226 | // 4 bytes / 11110xxx |
||
227 | } elseif (0xf0 === ($code & 0xf8)) { |
||
228 | $code = $code & ~0xf0; |
||
229 | $bytes = 4; |
||
230 | } |
||
231 | |||
232 | for ($i = 2; $i <= $bytes; $i++) { |
||
233 | $code = ($code << 6) + (ord($character[$i - 1]) & ~0x80); |
||
234 | } |
||
235 | |||
236 | return $code; |
||
237 | } |
||
238 | } |
||
239 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.