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