PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.11.1
Independent Analytics – WordPress Analytics Plugin v2.11.1
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / symfony / polyfill-mbstring / Mbstring.php
independent-analytics / vendor / symfony / polyfill-mbstring Last commit date
Resources 2 years ago Mbstring.php 2 years ago bootstrap.php 2 years ago bootstrap80.php 2 years ago
Mbstring.php
795 lines
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.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 namespace Symfony\Polyfill\Mbstring;
12
13 /**
14 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
15 *
16 * Implemented:
17 * - mb_chr - Returns a specific character from its Unicode code point
18 * - mb_convert_encoding - Convert character encoding
19 * - mb_convert_variables - Convert character code in variable(s)
20 * - mb_decode_mimeheader - Decode string in MIME header field
21 * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
22 * - mb_decode_numericentity - Decode HTML numeric string reference to character
23 * - mb_encode_numericentity - Encode character to HTML numeric string reference
24 * - mb_convert_case - Perform case folding on a string
25 * - mb_detect_encoding - Detect character encoding
26 * - mb_get_info - Get internal settings of mbstring
27 * - mb_http_input - Detect HTTP input character encoding
28 * - mb_http_output - Set/Get HTTP output character encoding
29 * - mb_internal_encoding - Set/Get internal character encoding
30 * - mb_list_encodings - Returns an array of all supported encodings
31 * - mb_ord - Returns the Unicode code point of a character
32 * - mb_output_handler - Callback function converts character encoding in output buffer
33 * - mb_scrub - Replaces ill-formed byte sequences with substitute characters
34 * - mb_strlen - Get string length
35 * - mb_strpos - Find position of first occurrence of string in a string
36 * - mb_strrpos - Find position of last occurrence of a string in a string
37 * - mb_str_split - Convert a string to an array
38 * - mb_strtolower - Make a string lowercase
39 * - mb_strtoupper - Make a string uppercase
40 * - mb_substitute_character - Set/Get substitution character
41 * - mb_substr - Get part of string
42 * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive
43 * - mb_stristr - Finds first occurrence of a string within another, case insensitive
44 * - mb_strrchr - Finds the last occurrence of a character in a string within another
45 * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive
46 * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive
47 * - mb_strstr - Finds first occurrence of a string within another
48 * - mb_strwidth - Return width of string
49 * - mb_substr_count - Count the number of substring occurrences
50 * - mb_ucfirst - Make a string's first character uppercase
51 * - mb_lcfirst - Make a string's first character lowercase
52 *
53 * Not implemented:
54 * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
55 * - mb_ereg_* - Regular expression with multibyte support
56 * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
57 * - mb_preferred_mime_name - Get MIME charset string
58 * - mb_regex_encoding - Returns current encoding for multibyte regex as string
59 * - mb_regex_set_options - Set/Get the default options for mbregex functions
60 * - mb_send_mail - Send encoded mail
61 * - mb_split - Split multibyte string using regular expression
62 * - mb_strcut - Get part of string
63 * - mb_strimwidth - Get truncated string with specified width
64 *
65 * @author Nicolas Grekas <p@tchwork.com>
66 *
67 * @internal
68 */
69 final class Mbstring
70 {
71 public const MB_CASE_FOLD = \PHP_INT_MAX;
72 private const SIMPLE_CASE_FOLD = [['µ', 'ſ', "�
73 ", 'ς', "ϐ", "ϑ", "ϕ", "ϖ", "ϰ", "ϱ", "ϵ", "", ""], ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "", 'ι']];
74 private static $encodingList = ['ASCII', 'UTF-8'];
75 private static $language = 'neutral';
76 private static $internalEncoding = 'UTF-8';
77 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
78 {
79 if (\is_array($s)) {
80 if (\PHP_VERSION_ID < 70200) {
81 \trigger_error('mb_convert_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING);
82 return null;
83 }
84 $r = [];
85 foreach ($s as $str) {
86 $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding);
87 }
88 return $r;
89 }
90 if (\is_array($fromEncoding) || null !== $fromEncoding && \false !== \strpos($fromEncoding, ',')) {
91 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
92 } else {
93 $fromEncoding = self::getEncoding($fromEncoding);
94 }
95 $toEncoding = self::getEncoding($toEncoding);
96 if ('BASE64' === $fromEncoding) {
97 $s = \base64_decode($s);
98 $fromEncoding = $toEncoding;
99 }
100 if ('BASE64' === $toEncoding) {
101 return \base64_encode($s);
102 }
103 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
104 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
105 $fromEncoding = 'Windows-1252';
106 }
107 if ('UTF-8' !== $fromEncoding) {
108 $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
109 }
110 return \preg_replace_callback('/[\\x80-\\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
111 }
112 if ('HTML-ENTITIES' === $fromEncoding) {
113 $s = \html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
114 $fromEncoding = 'UTF-8';
115 }
116 return \iconv($fromEncoding, $toEncoding . '//IGNORE', $s);
117 }
118 public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
119 {
120 $ok = \true;
121 \array_walk_recursive($vars, function (&$v) use(&$ok, $toEncoding, $fromEncoding) {
122 if (\false === ($v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding))) {
123 $ok = \false;
124 }
125 });
126 return $ok ? $fromEncoding : \false;
127 }
128 public static function mb_decode_mimeheader($s)
129 {
130 return \iconv_mime_decode($s, 2, self::$internalEncoding);
131 }
132 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
133 {
134 \trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
135 }
136 public static function mb_decode_numericentity($s, $convmap, $encoding = null)
137 {
138 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
139 \trigger_error('mb_decode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
140 return null;
141 }
142 if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
143 return \false;
144 }
145 if (null !== $encoding && !\is_scalar($encoding)) {
146 \trigger_error('mb_decode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
147 return '';
148 // Instead of null (cf. mb_encode_numericentity).
149 }
150 $s = (string) $s;
151 if ('' === $s) {
152 return '';
153 }
154 $encoding = self::getEncoding($encoding);
155 if ('UTF-8' === $encoding) {
156 $encoding = null;
157 if (!\preg_match('//u', $s)) {
158 $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
159 }
160 } else {
161 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
162 }
163 $cnt = \floor(\count($convmap) / 4) * 4;
164 for ($i = 0; $i < $cnt; $i += 4) {
165 // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
166 $convmap[$i] += $convmap[$i + 2];
167 $convmap[$i + 1] += $convmap[$i + 2];
168 }
169 $s = \preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use($cnt, $convmap) {
170 $c = isset($m[2]) ? (int) \hexdec($m[2]) : $m[1];
171 for ($i = 0; $i < $cnt; $i += 4) {
172 if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
173 return self::mb_chr($c - $convmap[$i + 2]);
174 }
175 }
176 return $m[0];
177 }, $s);
178 if (null === $encoding) {
179 return $s;
180 }
181 return \iconv('UTF-8', $encoding . '//IGNORE', $s);
182 }
183 public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = \false)
184 {
185 if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) {
186 \trigger_error('mb_encode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
187 return null;
188 }
189 if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
190 return \false;
191 }
192 if (null !== $encoding && !\is_scalar($encoding)) {
193 \trigger_error('mb_encode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
194 return null;
195 // Instead of '' (cf. mb_decode_numericentity).
196 }
197 if (null !== $is_hex && !\is_scalar($is_hex)) {
198 \trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, ' . \gettype($s) . ' given', \E_USER_WARNING);
199 return null;
200 }
201 $s = (string) $s;
202 if ('' === $s) {
203 return '';
204 }
205 $encoding = self::getEncoding($encoding);
206 if ('UTF-8' === $encoding) {
207 $encoding = null;
208 if (!\preg_match('//u', $s)) {
209 $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
210 }
211 } else {
212 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
213 }
214 static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
215 $cnt = \floor(\count($convmap) / 4) * 4;
216 $i = 0;
217 $len = \strlen($s);
218 $result = '';
219 while ($i < $len) {
220 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
221 $uchr = \substr($s, $i, $ulen);
222 $i += $ulen;
223 $c = self::mb_ord($uchr);
224 for ($j = 0; $j < $cnt; $j += 4) {
225 if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
226 $cOffset = $c + $convmap[$j + 2] & $convmap[$j + 3];
227 $result .= $is_hex ? \sprintf('&#x%X;', $cOffset) : '&#' . $cOffset . ';';
228 continue 2;
229 }
230 }
231 $result .= $uchr;
232 }
233 if (null === $encoding) {
234 return $result;
235 }
236 return \iconv('UTF-8', $encoding . '//IGNORE', $result);
237 }
238 public static function mb_convert_case($s, $mode, $encoding = null)
239 {
240 $s = (string) $s;
241 if ('' === $s) {
242 return '';
243 }
244 $encoding = self::getEncoding($encoding);
245 if ('UTF-8' === $encoding) {
246 $encoding = null;
247 if (!\preg_match('//u', $s)) {
248 $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
249 }
250 } else {
251 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
252 }
253 if (\MB_CASE_TITLE == $mode) {
254 static $titleRegexp = null;
255 if (null === $titleRegexp) {
256 $titleRegexp = self::getData('titleCaseRegexp');
257 }
258 $s = \preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
259 } else {
260 if (\MB_CASE_UPPER == $mode) {
261 static $upper = null;
262 if (null === $upper) {
263 $upper = self::getData('upperCase');
264 }
265 $map = $upper;
266 } else {
267 if (self::MB_CASE_FOLD === $mode) {
268 static $caseFolding = null;
269 if (null === $caseFolding) {
270 $caseFolding = self::getData('caseFolding');
271 }
272 $s = \strtr($s, $caseFolding);
273 }
274 static $lower = null;
275 if (null === $lower) {
276 $lower = self::getData('lowerCase');
277 }
278 $map = $lower;
279 }
280 static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
281 $i = 0;
282 $len = \strlen($s);
283 while ($i < $len) {
284 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
285 $uchr = \substr($s, $i, $ulen);
286 $i += $ulen;
287 if (isset($map[$uchr])) {
288 $uchr = $map[$uchr];
289 $nlen = \strlen($uchr);
290 if ($nlen == $ulen) {
291 $nlen = $i;
292 do {
293 $s[--$nlen] = $uchr[--$ulen];
294 } while ($ulen);
295 } else {
296 $s = \substr_replace($s, $uchr, $i - $ulen, $ulen);
297 $len += $nlen - $ulen;
298 $i += $nlen - $ulen;
299 }
300 }
301 }
302 }
303 if (null === $encoding) {
304 return $s;
305 }
306 return \iconv('UTF-8', $encoding . '//IGNORE', $s);
307 }
308 public static function mb_internal_encoding($encoding = null)
309 {
310 if (null === $encoding) {
311 return self::$internalEncoding;
312 }
313 $normalizedEncoding = self::getEncoding($encoding);
314 if ('UTF-8' === $normalizedEncoding || \false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
315 self::$internalEncoding = $normalizedEncoding;
316 return \true;
317 }
318 if (80000 > \PHP_VERSION_ID) {
319 return \false;
320 }
321 throw new \ValueError(\sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
322 }
323 public static function mb_language($lang = null)
324 {
325 if (null === $lang) {
326 return self::$language;
327 }
328 switch ($normalizedLang = \strtolower($lang)) {
329 case 'uni':
330 case 'neutral':
331 self::$language = $normalizedLang;
332 return \true;
333 }
334 if (80000 > \PHP_VERSION_ID) {
335 return \false;
336 }
337 throw new \ValueError(\sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
338 }
339 public static function mb_list_encodings()
340 {
341 return ['UTF-8'];
342 }
343 public static function mb_encoding_aliases($encoding)
344 {
345 switch (\strtoupper($encoding)) {
346 case 'UTF8':
347 case 'UTF-8':
348 return ['utf8'];
349 }
350 return \false;
351 }
352 public static function mb_check_encoding($var = null, $encoding = null)
353 {
354 if (\PHP_VERSION_ID < 70200 && \is_array($var)) {
355 \trigger_error('mb_check_encoding() expects parameter 1 to be string, array given', \E_USER_WARNING);
356 return null;
357 }
358 if (null === $encoding) {
359 if (null === $var) {
360 return \false;
361 }
362 $encoding = self::$internalEncoding;
363 }
364 if (!\is_array($var)) {
365 return self::mb_detect_encoding($var, [$encoding]) || \false !== @\iconv($encoding, $encoding, $var);
366 }
367 foreach ($var as $key => $value) {
368 if (!self::mb_check_encoding($key, $encoding)) {
369 return \false;
370 }
371 if (!self::mb_check_encoding($value, $encoding)) {
372 return \false;
373 }
374 }
375 return \true;
376 }
377 public static function mb_detect_encoding($str, $encodingList = null, $strict = \false)
378 {
379 if (null === $encodingList) {
380 $encodingList = self::$encodingList;
381 } else {
382 if (!\is_array($encodingList)) {
383 $encodingList = \array_map('trim', \explode(',', $encodingList));
384 }
385 $encodingList = \array_map('strtoupper', $encodingList);
386 }
387 foreach ($encodingList as $enc) {
388 switch ($enc) {
389 case 'ASCII':
390 if (!\preg_match('/[\\x80-\\xFF]/', $str)) {
391 return $enc;
392 }
393 break;
394 case 'UTF8':
395 case 'UTF-8':
396 if (\preg_match('//u', $str)) {
397 return 'UTF-8';
398 }
399 break;
400 default:
401 if (0 === \strncmp($enc, 'ISO-8859-', 9)) {
402 return $enc;
403 }
404 }
405 }
406 return \false;
407 }
408 public static function mb_detect_order($encodingList = null)
409 {
410 if (null === $encodingList) {
411 return self::$encodingList;
412 }
413 if (!\is_array($encodingList)) {
414 $encodingList = \array_map('trim', \explode(',', $encodingList));
415 }
416 $encodingList = \array_map('strtoupper', $encodingList);
417 foreach ($encodingList as $enc) {
418 switch ($enc) {
419 default:
420 if (\strncmp($enc, 'ISO-8859-', 9)) {
421 return \false;
422 }
423 // no break
424 case 'ASCII':
425 case 'UTF8':
426 case 'UTF-8':
427 }
428 }
429 self::$encodingList = $encodingList;
430 return \true;
431 }
432 public static function mb_strlen($s, $encoding = null)
433 {
434 $encoding = self::getEncoding($encoding);
435 if ('CP850' === $encoding || 'ASCII' === $encoding) {
436 return \strlen($s);
437 }
438 return @\iconv_strlen($s, $encoding);
439 }
440 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
441 {
442 $encoding = self::getEncoding($encoding);
443 if ('CP850' === $encoding || 'ASCII' === $encoding) {
444 return \strpos($haystack, $needle, $offset);
445 }
446 $needle = (string) $needle;
447 if ('' === $needle) {
448 if (80000 > \PHP_VERSION_ID) {
449 \trigger_error(__METHOD__ . ': Empty delimiter', \E_USER_WARNING);
450 return \false;
451 }
452 return 0;
453 }
454 return \iconv_strpos($haystack, $needle, $offset, $encoding);
455 }
456 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
457 {
458 $encoding = self::getEncoding($encoding);
459 if ('CP850' === $encoding || 'ASCII' === $encoding) {
460 return \strrpos($haystack, $needle, $offset);
461 }
462 if ($offset != (int) $offset) {
463 $offset = 0;
464 } elseif ($offset = (int) $offset) {
465 if ($offset < 0) {
466 if (0 > ($offset += self::mb_strlen($needle))) {
467 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
468 }
469 $offset = 0;
470 } else {
471 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
472 }
473 }
474 $pos = '' !== $needle || 80000 > \PHP_VERSION_ID ? \iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding);
475 return \false !== $pos ? $offset + $pos : \false;
476 }
477 public static function mb_str_split($string, $split_length = 1, $encoding = null)
478 {
479 if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) {
480 \trigger_error('mb_str_split() expects parameter 1 to be string, ' . \gettype($string) . ' given', \E_USER_WARNING);
481 return null;
482 }
483 if (1 > ($split_length = (int) $split_length)) {
484 if (80000 > \PHP_VERSION_ID) {
485 \trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
486 return \false;
487 }
488 throw new \ValueError('Argument #2 ($length) must be greater than 0');
489 }
490 if (null === $encoding) {
491 $encoding = \mb_internal_encoding();
492 }
493 if ('UTF-8' === ($encoding = self::getEncoding($encoding))) {
494 $rx = '/(';
495 while (65535 < $split_length) {
496 $rx .= '.{65535}';
497 $split_length -= 65535;
498 }
499 $rx .= '.{' . $split_length . '})/us';
500 return \preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
501 }
502 $result = [];
503 $length = \mb_strlen($string, $encoding);
504 for ($i = 0; $i < $length; $i += $split_length) {
505 $result[] = \mb_substr($string, $i, $split_length, $encoding);
506 }
507 return $result;
508 }
509 public static function mb_strtolower($s, $encoding = null)
510 {
511 return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
512 }
513 public static function mb_strtoupper($s, $encoding = null)
514 {
515 return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
516 }
517 public static function mb_substitute_character($c = null)
518 {
519 if (null === $c) {
520 return 'none';
521 }
522 if (0 === \strcasecmp($c, 'none')) {
523 return \true;
524 }
525 if (80000 > \PHP_VERSION_ID) {
526 return \false;
527 }
528 if (\is_int($c) || 'long' === $c || 'entity' === $c) {
529 return \false;
530 }
531 throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
532 }
533 public static function mb_substr($s, $start, $length = null, $encoding = null)
534 {
535 $encoding = self::getEncoding($encoding);
536 if ('CP850' === $encoding || 'ASCII' === $encoding) {
537 return (string) \substr($s, $start, null === $length ? 2147483647 : $length);
538 }
539 if ($start < 0) {
540 $start = \iconv_strlen($s, $encoding) + $start;
541 if ($start < 0) {
542 $start = 0;
543 }
544 }
545 if (null === $length) {
546 $length = 2147483647;
547 } elseif ($length < 0) {
548 $length = \iconv_strlen($s, $encoding) + $length - $start;
549 if ($length < 0) {
550 return '';
551 }
552 }
553 return (string) \iconv_substr($s, $start, $length, $encoding);
554 }
555 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
556 {
557 [$haystack, $needle] = \str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding), self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding)]);
558 return self::mb_strpos($haystack, $needle, $offset, $encoding);
559 }
560 public static function mb_stristr($haystack, $needle, $part = \false, $encoding = null)
561 {
562 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
563 return self::getSubpart($pos, $part, $haystack, $encoding);
564 }
565 public static function mb_strrchr($haystack, $needle, $part = \false, $encoding = null)
566 {
567 $encoding = self::getEncoding($encoding);
568 if ('CP850' === $encoding || 'ASCII' === $encoding) {
569 $pos = \strrpos($haystack, $needle);
570 } else {
571 $needle = self::mb_substr($needle, 0, 1, $encoding);
572 $pos = \iconv_strrpos($haystack, $needle, $encoding);
573 }
574 return self::getSubpart($pos, $part, $haystack, $encoding);
575 }
576 public static function mb_strrichr($haystack, $needle, $part = \false, $encoding = null)
577 {
578 $needle = self::mb_substr($needle, 0, 1, $encoding);
579 $pos = self::mb_strripos($haystack, $needle, $encoding);
580 return self::getSubpart($pos, $part, $haystack, $encoding);
581 }
582 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
583 {
584 $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding);
585 $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding);
586 $haystack = \str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack);
587 $needle = \str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle);
588 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
589 }
590 public static function mb_strstr($haystack, $needle, $part = \false, $encoding = null)
591 {
592 $pos = \strpos($haystack, $needle);
593 if (\false === $pos) {
594 return \false;
595 }
596 if ($part) {
597 return \substr($haystack, 0, $pos);
598 }
599 return \substr($haystack, $pos);
600 }
601 public static function mb_get_info($type = 'all')
602 {
603 $info = ['internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\\+xml)', 'func_overload' => 0, 'func_overload_list' => 'no overload', 'mail_charset' => 'UTF-8', 'mail_header_encoding' => 'BASE64', 'mail_body_encoding' => 'BASE64', 'illegal_chars' => 0, 'encoding_translation' => 'Off', 'language' => self::$language, 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off'];
604 if ('all' === $type) {
605 return $info;
606 }
607 if (isset($info[$type])) {
608 return $info[$type];
609 }
610 return \false;
611 }
612 public static function mb_http_input($type = '')
613 {
614 return \false;
615 }
616 public static function mb_http_output($encoding = null)
617 {
618 return null !== $encoding ? 'pass' === $encoding : 'pass';
619 }
620 public static function mb_strwidth($s, $encoding = null)
621 {
622 $encoding = self::getEncoding($encoding);
623 if ('UTF-8' !== $encoding) {
624 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
625 }
626 $s = \preg_replace('/[\\x{1100}-\\x{115F}\\x{2329}\\x{232A}\\x{2E80}-\\x{303E}\\x{3040}-\\x{A4CF}\\x{AC00}-\\x{D7A3}\\x{F900}-\\x{FAFF}\\x{FE10}-\\x{FE19}\\x{FE30}-\\x{FE6F}\\x{FF00}-\\x{FF60}\\x{FFE0}-\\x{FFE6}\\x{20000}-\\x{2FFFD}\\x{30000}-\\x{3FFFD}]/u', '', $s, -1, $wide);
627 return ($wide << 1) + \iconv_strlen($s, 'UTF-8');
628 }
629 public static function mb_substr_count($haystack, $needle, $encoding = null)
630 {
631 return \substr_count($haystack, $needle);
632 }
633 public static function mb_output_handler($contents, $status)
634 {
635 return $contents;
636 }
637 public static function mb_chr($code, $encoding = null)
638 {
639 if (0x80 > ($code %= 0x200000)) {
640 $s = \chr($code);
641 } elseif (0x800 > $code) {
642 $s = \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
643 } elseif (0x10000 > $code) {
644 $s = \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
645 } else {
646 $s = \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
647 }
648 if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
649 $s = \mb_convert_encoding($s, $encoding, 'UTF-8');
650 }
651 return $s;
652 }
653 public static function mb_ord($s, $encoding = null)
654 {
655 if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
656 $s = \mb_convert_encoding($s, 'UTF-8', $encoding);
657 }
658 if (1 === \strlen($s)) {
659 return \ord($s);
660 }
661 $code = ($s = \unpack('C*', \substr($s, 0, 4))) ? $s[1] : 0;
662 if (0xf0 <= $code) {
663 return ($code - 0xf0 << 18) + ($s[2] - 0x80 << 12) + ($s[3] - 0x80 << 6) + $s[4] - 0x80;
664 }
665 if (0xe0 <= $code) {
666 return ($code - 0xe0 << 12) + ($s[2] - 0x80 << 6) + $s[3] - 0x80;
667 }
668 if (0xc0 <= $code) {
669 return ($code - 0xc0 << 6) + $s[2] - 0x80;
670 }
671 return $code;
672 }
673 public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null) : string
674 {
675 if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], \true)) {
676 throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
677 }
678 if (null === $encoding) {
679 $encoding = self::mb_internal_encoding();
680 } else {
681 self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given');
682 }
683 if (self::mb_strlen($pad_string, $encoding) <= 0) {
684 throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string');
685 }
686 $paddingRequired = $length - self::mb_strlen($string, $encoding);
687 if ($paddingRequired < 1) {
688 return $string;
689 }
690 switch ($pad_type) {
691 case \STR_PAD_LEFT:
692 return self::mb_substr(\str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding) . $string;
693 case \STR_PAD_RIGHT:
694 return $string . self::mb_substr(\str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
695 default:
696 $leftPaddingLength = \floor($paddingRequired / 2);
697 $rightPaddingLength = $paddingRequired - $leftPaddingLength;
698 return self::mb_substr(\str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding) . $string . self::mb_substr(\str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
699 }
700 }
701 public static function mb_ucfirst(string $string, ?string $encoding = null) : string
702 {
703 if (null === $encoding) {
704 $encoding = self::mb_internal_encoding();
705 } else {
706 self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given');
707 }
708 $firstChar = \mb_substr($string, 0, 1, $encoding);
709 $firstChar = \mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
710 return $firstChar . \mb_substr($string, 1, null, $encoding);
711 }
712 public static function mb_lcfirst(string $string, ?string $encoding = null) : string
713 {
714 if (null === $encoding) {
715 $encoding = self::mb_internal_encoding();
716 } else {
717 self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given');
718 }
719 $firstChar = \mb_substr($string, 0, 1, $encoding);
720 $firstChar = \mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
721 return $firstChar . \mb_substr($string, 1, null, $encoding);
722 }
723 private static function getSubpart($pos, $part, $haystack, $encoding)
724 {
725 if (\false === $pos) {
726 return \false;
727 }
728 if ($part) {
729 return self::mb_substr($haystack, 0, $pos, $encoding);
730 }
731 return self::mb_substr($haystack, $pos, null, $encoding);
732 }
733 private static function html_encoding_callback(array $m)
734 {
735 $i = 1;
736 $entities = '';
737 $m = \unpack('C*', \htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
738 while (isset($m[$i])) {
739 if (0x80 > $m[$i]) {
740 $entities .= \chr($m[$i++]);
741 continue;
742 }
743 if (0xf0 <= $m[$i]) {
744 $c = ($m[$i++] - 0xf0 << 18) + ($m[$i++] - 0x80 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
745 } elseif (0xe0 <= $m[$i]) {
746 $c = ($m[$i++] - 0xe0 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
747 } else {
748 $c = ($m[$i++] - 0xc0 << 6) + $m[$i++] - 0x80;
749 }
750 $entities .= '&#' . $c . ';';
751 }
752 return $entities;
753 }
754 private static function title_case(array $s)
755 {
756 return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8') . self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
757 }
758 private static function getData($file)
759 {
760 if (\file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) {
761 return require $file;
762 }
763 return \false;
764 }
765 private static function getEncoding($encoding)
766 {
767 if (null === $encoding) {
768 return self::$internalEncoding;
769 }
770 if ('UTF-8' === $encoding) {
771 return 'UTF-8';
772 }
773 $encoding = \strtoupper($encoding);
774 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
775 return 'CP850';
776 }
777 if ('UTF8' === $encoding) {
778 return 'UTF-8';
779 }
780 return $encoding;
781 }
782 private static function assertEncoding(string $encoding, string $errorFormat) : void
783 {
784 try {
785 $validEncoding = @self::mb_check_encoding('', $encoding);
786 } catch (\ValueError $e) {
787 throw new \ValueError(\sprintf($errorFormat, $encoding));
788 }
789 // BC for PHP 7.3 and lower
790 if (!$validEncoding) {
791 throw new \ValueError(\sprintf($errorFormat, $encoding));
792 }
793 }
794 }
795