PluginProbe
Depicter — Popup & Slider Builder / 1.2.0
Depicter — Popup & Slider Builder v1.2.0
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / vendor / symfony / polyfill-mbstring / Mbstring.php

Mbstring.php in Depicter — Popup & Slider Builder 1.2.0, at vendor/symfony/polyfill-mbstring/Mbstring.php

874 lines 28.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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
12 namespace Symfony\Polyfill\Mbstring;
13
14 /**
15 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
16 *
17 * Implemented:
18 * - mb_chr - Returns a specific character from its Unicode code point
19 * - mb_convert_encoding - Convert character encoding
20 * - mb_convert_variables - Convert character code in variable(s)
21 * - mb_decode_mimeheader - Decode string in MIME header field
22 * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
23 * - mb_decode_numericentity - Decode HTML numeric string reference to character
24 * - mb_encode_numericentity - Encode character to HTML numeric string reference
25 * - mb_convert_case - Perform case folding on a string
26 * - mb_detect_encoding - Detect character encoding
27 * - mb_get_info - Get internal settings of mbstring
28 * - mb_http_input - Detect HTTP input character encoding
29 * - mb_http_output - Set/Get HTTP output character encoding
30 * - mb_internal_encoding - Set/Get internal character encoding
31 * - mb_list_encodings - Returns an array of all supported encodings
32 * - mb_ord - Returns the Unicode code point of a character
33 * - mb_output_handler - Callback function converts character encoding in output buffer
34 * - mb_scrub - Replaces ill-formed byte sequences with substitute characters
35 * - mb_strlen - Get string length
36 * - mb_strpos - Find position of first occurrence of string in a string
37 * - mb_strrpos - Find position of last occurrence of a string in a string
38 * - mb_str_split - Convert a string to an array
39 * - mb_strtolower - Make a string lowercase
40 * - mb_strtoupper - Make a string uppercase
41 * - mb_substitute_character - Set/Get substitution character
42 * - mb_substr - Get part of string
43 * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive
44 * - mb_stristr - Finds first occurrence of a string within another, case insensitive
45 * - mb_strrchr - Finds the last occurrence of a character in a string within another
46 * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive
47 * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive
48 * - mb_strstr - Finds first occurrence of a string within another
49 * - mb_strwidth - Return width of string
50 * - mb_substr_count - Count the number of substring occurrences
51 *
52 * Not implemented:
53 * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
54 * - mb_ereg_* - Regular expression with multibyte support
55 * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
56 * - mb_preferred_mime_name - Get MIME charset string
57 * - mb_regex_encoding - Returns current encoding for multibyte regex as string
58 * - mb_regex_set_options - Set/Get the default options for mbregex functions
59 * - mb_send_mail - Send encoded mail
60 * - mb_split - Split multibyte string using regular expression
61 * - mb_strcut - Get part of string
62 * - mb_strimwidth - Get truncated string with specified width
63 *
64 * @author Nicolas Grekas <p@tchwork.com>
65 *
66 * @internal
67 */
68 final class Mbstring
69 {
70 public const MB_CASE_FOLD = \PHP_INT_MAX;
71
72 private const CASE_FOLD = [
73 ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
74 ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'],
75 ];
76
77 private static $encodingList = ['ASCII', 'UTF-8'];
78 private static $language = 'neutral';
79 private static $internalEncoding = 'UTF-8';
80
81 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
82 {
83 if (\is_array($fromEncoding) || ($fromEncoding !== null && false !== strpos($fromEncoding, ','))) {
84 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
85 } else {
86 $fromEncoding = self::getEncoding($fromEncoding);
87 }
88
89 $toEncoding = self::getEncoding($toEncoding);
90
91 if ('BASE64' === $fromEncoding) {
92 $s = base64_decode($s);
93 $fromEncoding = $toEncoding;
94 }
95
96 if ('BASE64' === $toEncoding) {
97 return base64_encode($s);
98 }
99
100 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
101 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
102 $fromEncoding = 'Windows-1252';
103 }
104 if ('UTF-8' !== $fromEncoding) {
105 $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
106 }
107
108 return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
109 }
110
111 if ('HTML-ENTITIES' === $fromEncoding) {
112 $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
113 $fromEncoding = 'UTF-8';
114 }
115
116 return \iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
117 }
118
119 public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
120 {
121 $ok = true;
122 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
123 if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
124 $ok = false;
125 }
126 });
127
128 return $ok ? $fromEncoding : false;
129 }
130
131 public static function mb_decode_mimeheader($s)
132 {
133 return \iconv_mime_decode($s, 2, self::$internalEncoding);
134 }
135
136 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
137 {
138 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
139 }
140
141 public static function mb_decode_numericentity($s, $convmap, $encoding = null)
142 {
143 if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
144 trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
145
146 return null;
147 }
148
149 if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
150 return false;
151 }
152
153 if (null !== $encoding && !is_scalar($encoding)) {
154 trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
155
156 return ''; // Instead of null (cf. mb_encode_numericentity).
157 }
158
159 $s = (string) $s;
160 if ('' === $s) {
161 return '';
162 }
163
164 $encoding = self::getEncoding($encoding);
165
166 if ('UTF-8' === $encoding) {
167 $encoding = null;
168 if (!preg_match('//u', $s)) {
169 $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
170 }
171 } else {
172 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
173 }
174
175 $cnt = floor(\count($convmap) / 4) * 4;
176
177 for ($i = 0; $i < $cnt; $i += 4) {
178 // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
179 $convmap[$i] += $convmap[$i + 2];
180 $convmap[$i + 1] += $convmap[$i + 2];
181 }
182
183 $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) {
184 $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
185 for ($i = 0; $i < $cnt; $i += 4) {
186 if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
187 return self::mb_chr($c - $convmap[$i + 2]);
188 }
189 }
190
191 return $m[0];
192 }, $s);
193
194 if (null === $encoding) {
195 return $s;
196 }
197
198 return \iconv('UTF-8', $encoding.'//IGNORE', $s);
199 }
200
201 public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
202 {
203 if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
204 trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
205
206 return null;
207 }
208
209 if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
210 return false;
211 }
212
213 if (null !== $encoding && !is_scalar($encoding)) {
214 trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
215
216 return null; // Instead of '' (cf. mb_decode_numericentity).
217 }
218
219 if (null !== $is_hex && !is_scalar($is_hex)) {
220 trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING);
221
222 return null;
223 }
224
225 $s = (string) $s;
226 if ('' === $s) {
227 return '';
228 }
229
230 $encoding = self::getEncoding($encoding);
231
232 if ('UTF-8' === $encoding) {
233 $encoding = null;
234 if (!preg_match('//u', $s)) {
235 $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
236 }
237 } else {
238 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
239 }
240
241 static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
242
243 $cnt = floor(\count($convmap) / 4) * 4;
244 $i = 0;
245 $len = \strlen($s);
246 $result = '';
247
248 while ($i < $len) {
249 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
250 $uchr = substr($s, $i, $ulen);
251 $i += $ulen;
252 $c = self::mb_ord($uchr);
253
254 for ($j = 0; $j < $cnt; $j += 4) {
255 if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
256 $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
257 $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
258 continue 2;
259 }
260 }
261 $result .= $uchr;
262 }
263
264 if (null === $encoding) {
265 return $result;
266 }
267
268 return \iconv('UTF-8', $encoding.'//IGNORE', $result);
269 }
270
271 public static function mb_convert_case($s, $mode, $encoding = null)
272 {
273 $s = (string) $s;
274 if ('' === $s) {
275 return '';
276 }
277
278 $encoding = self::getEncoding($encoding);
279
280 if ('UTF-8' === $encoding) {
281 $encoding = null;
282 if (!preg_match('//u', $s)) {
283 $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
284 }
285 } else {
286 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
287 }
288
289 if (\MB_CASE_TITLE == $mode) {
290 static $titleRegexp = null;
291 if (null === $titleRegexp) {
292 $titleRegexp = self::getData('titleCaseRegexp');
293 }
294 $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
295 } else {
296 if (\MB_CASE_UPPER == $mode) {
297 static $upper = null;
298 if (null === $upper) {
299 $upper = self::getData('upperCase');
300 }
301 $map = $upper;
302 } else {
303 if (self::MB_CASE_FOLD === $mode) {
304 $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
305 }
306
307 static $lower = null;
308 if (null === $lower) {
309 $lower = self::getData('lowerCase');
310 }
311 $map = $lower;
312 }
313
314 static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
315
316 $i = 0;
317 $len = \strlen($s);
318
319 while ($i < $len) {
320 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
321 $uchr = substr($s, $i, $ulen);
322 $i += $ulen;
323
324 if (isset($map[$uchr])) {
325 $uchr = $map[$uchr];
326 $nlen = \strlen($uchr);
327
328 if ($nlen == $ulen) {
329 $nlen = $i;
330 do {
331 $s[--$nlen] = $uchr[--$ulen];
332 } while ($ulen);
333 } else {
334 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
335 $len += $nlen - $ulen;
336 $i += $nlen - $ulen;
337 }
338 }
339 }
340 }
341
342 if (null === $encoding) {
343 return $s;
344 }
345
346 return \iconv('UTF-8', $encoding.'//IGNORE', $s);
347 }
348
349 public static function mb_internal_encoding($encoding = null)
350 {
351 if (null === $encoding) {
352 return self::$internalEncoding;
353 }
354
355 $normalizedEncoding = self::getEncoding($encoding);
356
357 if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
358 self::$internalEncoding = $normalizedEncoding;
359
360 return true;
361 }
362
363 if (80000 > \PHP_VERSION_ID) {
364 return false;
365 }
366
367 throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
368 }
369
370 public static function mb_language($lang = null)
371 {
372 if (null === $lang) {
373 return self::$language;
374 }
375
376 switch ($normalizedLang = strtolower($lang)) {
377 case 'uni':
378 case 'neutral':
379 self::$language = $normalizedLang;
380
381 return true;
382 }
383
384 if (80000 > \PHP_VERSION_ID) {
385 return false;
386 }
387
388 throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
389 }
390
391 public static function mb_list_encodings()
392 {
393 return ['UTF-8'];
394 }
395
396 public static function mb_encoding_aliases($encoding)
397 {
398 switch (strtoupper($encoding)) {
399 case 'UTF8':
400 case 'UTF-8':
401 return ['utf8'];
402 }
403
404 return false;
405 }
406
407 public static function mb_check_encoding($var = null, $encoding = null)
408 {
409 if (null === $encoding) {
410 if (null === $var) {
411 return false;
412 }
413 $encoding = self::$internalEncoding;
414 }
415
416 return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var);
417 }
418
419 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
420 {
421 if (null === $encodingList) {
422 $encodingList = self::$encodingList;
423 } else {
424 if (!\is_array($encodingList)) {
425 $encodingList = array_map('trim', explode(',', $encodingList));
426 }
427 $encodingList = array_map('strtoupper', $encodingList);
428 }
429
430 foreach ($encodingList as $enc) {
431 switch ($enc) {
432 case 'ASCII':
433 if (!preg_match('/[\x80-\xFF]/', $str)) {
434 return $enc;
435 }
436 break;
437
438 case 'UTF8':
439 case 'UTF-8':
440 if (preg_match('//u', $str)) {
441 return 'UTF-8';
442 }
443 break;
444
445 default:
446 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
447 return $enc;
448 }
449 }
450 }
451
452 return false;
453 }
454
455 public static function mb_detect_order($encodingList = null)
456 {
457 if (null === $encodingList) {
458 return self::$encodingList;
459 }
460
461 if (!\is_array($encodingList)) {
462 $encodingList = array_map('trim', explode(',', $encodingList));
463 }
464 $encodingList = array_map('strtoupper', $encodingList);
465
466 foreach ($encodingList as $enc) {
467 switch ($enc) {
468 default:
469 if (strncmp($enc, 'ISO-8859-', 9)) {
470 return false;
471 }
472 // no break
473 case 'ASCII':
474 case 'UTF8':
475 case 'UTF-8':
476 }
477 }
478
479 self::$encodingList = $encodingList;
480
481 return true;
482 }
483
484 public static function mb_strlen($s, $encoding = null)
485 {
486 $encoding = self::getEncoding($encoding);
487 if ('CP850' === $encoding || 'ASCII' === $encoding) {
488 return \strlen($s);
489 }
490
491 return @\iconv_strlen($s, $encoding);
492 }
493
494 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
495 {
496 $encoding = self::getEncoding($encoding);
497 if ('CP850' === $encoding || 'ASCII' === $encoding) {
498 return strpos($haystack, $needle, $offset);
499 }
500
501 $needle = (string) $needle;
502 if ('' === $needle) {
503 if (80000 > \PHP_VERSION_ID) {
504 trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING);
505
506 return false;
507 }
508
509 return 0;
510 }
511
512 return \iconv_strpos($haystack, $needle, $offset, $encoding);
513 }
514
515 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
516 {
517 $encoding = self::getEncoding($encoding);
518 if ('CP850' === $encoding || 'ASCII' === $encoding) {
519 return strrpos($haystack, $needle, $offset);
520 }
521
522 if ($offset != (int) $offset) {
523 $offset = 0;
524 } elseif ($offset = (int) $offset) {
525 if ($offset < 0) {
526 if (0 > $offset += self::mb_strlen($needle)) {
527 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
528 }
529 $offset = 0;
530 } else {
531 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
532 }
533 }
534
535 $pos = '' !== $needle || 80000 > \PHP_VERSION_ID
536 ? \iconv_strrpos($haystack, $needle, $encoding)
537 : self::mb_strlen($haystack, $encoding);
538
539 return false !== $pos ? $offset + $pos : false;
540 }
541
542 public static function mb_str_split($string, $split_length = 1, $encoding = null)
543 {
544 if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
545 trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING);
546
547 return null;
548 }
549
550 if (1 > $split_length = (int) $split_length) {
551 if (80000 > \PHP_VERSION_ID) {
552 trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
553 return false;
554 }
555
556 throw new \ValueError('Argument #2 ($length) must be greater than 0');
557 }
558
559 if (null === $encoding) {
560 $encoding = mb_internal_encoding();
561 }
562
563 if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
564 $rx = '/(';
565 while (65535 < $split_length) {
566 $rx .= '.{65535}';
567 $split_length -= 65535;
568 }
569 $rx .= '.{'.$split_length.'})/us';
570
571 return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
572 }
573
574 $result = [];
575 $length = mb_strlen($string, $encoding);
576
577 for ($i = 0; $i < $length; $i += $split_length) {
578 $result[] = mb_substr($string, $i, $split_length, $encoding);
579 }
580
581 return $result;
582 }
583
584 public static function mb_strtolower($s, $encoding = null)
585 {
586 return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
587 }
588
589 public static function mb_strtoupper($s, $encoding = null)
590 {
591 return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
592 }
593
594 public static function mb_substitute_character($c = null)
595 {
596 if (null === $c) {
597 return 'none';
598 }
599 if (0 === strcasecmp($c, 'none')) {
600 return true;
601 }
602 if (80000 > \PHP_VERSION_ID) {
603 return false;
604 }
605 if (\is_int($c) || 'long' === $c || 'entity' === $c) {
606 return false;
607 }
608
609 throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
610 }
611
612 public static function mb_substr($s, $start, $length = null, $encoding = null)
613 {
614 $encoding = self::getEncoding($encoding);
615 if ('CP850' === $encoding || 'ASCII' === $encoding) {
616 return (string) substr($s, $start, null === $length ? 2147483647 : $length);
617 }
618
619 if ($start < 0) {
620 $start = \iconv_strlen($s, $encoding) + $start;
621 if ($start < 0) {
622 $start = 0;
623 }
624 }
625
626 if (null === $length) {
627 $length = 2147483647;
628 } elseif ($length < 0) {
629 $length = \iconv_strlen($s, $encoding) + $length - $start;
630 if ($length < 0) {
631 return '';
632 }
633 }
634
635 return (string) \iconv_substr($s, $start, $length, $encoding);
636 }
637
638 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
639 {
640 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
641 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
642
643 return self::mb_strpos($haystack, $needle, $offset, $encoding);
644 }
645
646 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
647 {
648 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
649
650 return self::getSubpart($pos, $part, $haystack, $encoding);
651 }
652
653 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
654 {
655 $encoding = self::getEncoding($encoding);
656 if ('CP850' === $encoding || 'ASCII' === $encoding) {
657 $pos = strrpos($haystack, $needle);
658 } else {
659 $needle = self::mb_substr($needle, 0, 1, $encoding);
660 $pos = \iconv_strrpos($haystack, $needle, $encoding);
661 }
662
663 return self::getSubpart($pos, $part, $haystack, $encoding);
664 }
665
666 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
667 {
668 $needle = self::mb_substr($needle, 0, 1, $encoding);
669 $pos = self::mb_strripos($haystack, $needle, $encoding);
670
671 return self::getSubpart($pos, $part, $haystack, $encoding);
672 }
673
674 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
675 {
676 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
677 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
678
679 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
680 }
681
682 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
683 {
684 $pos = strpos($haystack, $needle);
685 if (false === $pos) {
686 return false;
687 }
688 if ($part) {
689 return substr($haystack, 0, $pos);
690 }
691
692 return substr($haystack, $pos);
693 }
694
695 public static function mb_get_info($type = 'all')
696 {
697 $info = [
698 'internal_encoding' => self::$internalEncoding,
699 'http_output' => 'pass',
700 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
701 'func_overload' => 0,
702 'func_overload_list' => 'no overload',
703 'mail_charset' => 'UTF-8',
704 'mail_header_encoding' => 'BASE64',
705 'mail_body_encoding' => 'BASE64',
706 'illegal_chars' => 0,
707 'encoding_translation' => 'Off',
708 'language' => self::$language,
709 'detect_order' => self::$encodingList,
710 'substitute_character' => 'none',
711 'strict_detection' => 'Off',
712 ];
713
714 if ('all' === $type) {
715 return $info;
716 }
717 if (isset($info[$type])) {
718 return $info[$type];
719 }
720
721 return false;
722 }
723
724 public static function mb_http_input($type = '')
725 {
726 return false;
727 }
728
729 public static function mb_http_output($encoding = null)
730 {
731 return null !== $encoding ? 'pass' === $encoding : 'pass';
732 }
733
734 public static function mb_strwidth($s, $encoding = null)
735 {
736 $encoding = self::getEncoding($encoding);
737
738 if ('UTF-8' !== $encoding) {
739 $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
740 }
741
742 $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);
743
744 return ($wide << 1) + \iconv_strlen($s, 'UTF-8');
745 }
746
747 public static function mb_substr_count($haystack, $needle, $encoding = null)
748 {
749 return substr_count($haystack, $needle);
750 }
751
752 public static function mb_output_handler($contents, $status)
753 {
754 return $contents;
755 }
756
757 public static function mb_chr($code, $encoding = null)
758 {
759 if (0x80 > $code %= 0x200000) {
760 $s = \chr($code);
761 } elseif (0x800 > $code) {
762 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
763 } elseif (0x10000 > $code) {
764 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
765 } else {
766 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
767 }
768
769 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
770 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
771 }
772
773 return $s;
774 }
775
776 public static function mb_ord($s, $encoding = null)
777 {
778 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
779 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
780 }
781
782 if (1 === \strlen($s)) {
783 return \ord($s);
784 }
785
786 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
787 if (0xF0 <= $code) {
788 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
789 }
790 if (0xE0 <= $code) {
791 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
792 }
793 if (0xC0 <= $code) {
794 return (($code - 0xC0) << 6) + $s[2] - 0x80;
795 }
796
797 return $code;
798 }
799
800 private static function getSubpart($pos, $part, $haystack, $encoding)
801 {
802 if (false === $pos) {
803 return false;
804 }
805 if ($part) {
806 return self::mb_substr($haystack, 0, $pos, $encoding);
807 }
808
809 return self::mb_substr($haystack, $pos, null, $encoding);
810 }
811
812 private static function html_encoding_callback(array $m)
813 {
814 $i = 1;
815 $entities = '';
816 $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
817
818 while (isset($m[$i])) {
819 if (0x80 > $m[$i]) {
820 $entities .= \chr($m[$i++]);
821 continue;
822 }
823 if (0xF0 <= $m[$i]) {
824 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
825 } elseif (0xE0 <= $m[$i]) {
826 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
827 } else {
828 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
829 }
830
831 $entities .= '&#'.$c.';';
832 }
833
834 return $entities;
835 }
836
837 private static function title_case(array $s)
838 {
839 return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
840 }
841
842 private static function getData($file)
843 {
844 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
845 return require $file;
846 }
847
848 return false;
849 }
850
851 private static function getEncoding($encoding)
852 {
853 if (null === $encoding) {
854 return self::$internalEncoding;
855 }
856
857 if ('UTF-8' === $encoding) {
858 return 'UTF-8';
859 }
860
861 $encoding = strtoupper($encoding);
862
863 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
864 return 'CP850';
865 }
866
867 if ('UTF8' === $encoding) {
868 return 'UTF-8';
869 }
870
871 return $encoding;
872 }
873 }
874