PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 3.0.4
GiveWP – Donation Plugin and Fundraising Platform v3.0.4
4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / vendor / symfony / polyfill-mbstring / Mbstring.php
give / vendor / symfony / polyfill-mbstring Last commit date
Resources 2 years ago LICENSE 4 years ago Mbstring.php 2 years ago bootstrap.php 2 years ago bootstrap80.php 2 years ago
Mbstring.php
875 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
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) || (null !== $fromEncoding && 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
554 return false;
555 }
556
557 throw new \ValueError('Argument #2 ($length) must be greater than 0');
558 }
559
560 if (null === $encoding) {
561 $encoding = mb_internal_encoding();
562 }
563
564 if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
565 $rx = '/(';
566 while (65535 < $split_length) {
567 $rx .= '.{65535}';
568 $split_length -= 65535;
569 }
570 $rx .= '.{'.$split_length.'})/us';
571
572 return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
573 }
574
575 $result = [];
576 $length = mb_strlen($string, $encoding);
577
578 for ($i = 0; $i < $length; $i += $split_length) {
579 $result[] = mb_substr($string, $i, $split_length, $encoding);
580 }
581
582 return $result;
583 }
584
585 public static function mb_strtolower($s, $encoding = null)
586 {
587 return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
588 }
589
590 public static function mb_strtoupper($s, $encoding = null)
591 {
592 return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
593 }
594
595 public static function mb_substitute_character($c = null)
596 {
597 if (null === $c) {
598 return 'none';
599 }
600 if (0 === strcasecmp($c, 'none')) {
601 return true;
602 }
603 if (80000 > \PHP_VERSION_ID) {
604 return false;
605 }
606 if (\is_int($c) || 'long' === $c || 'entity' === $c) {
607 return false;
608 }
609
610 throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
611 }
612
613 public static function mb_substr($s, $start, $length = null, $encoding = null)
614 {
615 $encoding = self::getEncoding($encoding);
616 if ('CP850' === $encoding || 'ASCII' === $encoding) {
617 return (string) substr($s, $start, null === $length ? 2147483647 : $length);
618 }
619
620 if ($start < 0) {
621 $start = iconv_strlen($s, $encoding) + $start;
622 if ($start < 0) {
623 $start = 0;
624 }
625 }
626
627 if (null === $length) {
628 $length = 2147483647;
629 } elseif ($length < 0) {
630 $length = iconv_strlen($s, $encoding) + $length - $start;
631 if ($length < 0) {
632 return '';
633 }
634 }
635
636 return (string) iconv_substr($s, $start, $length, $encoding);
637 }
638
639 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
640 {
641 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
642 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
643
644 return self::mb_strpos($haystack, $needle, $offset, $encoding);
645 }
646
647 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
648 {
649 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
650
651 return self::getSubpart($pos, $part, $haystack, $encoding);
652 }
653
654 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
655 {
656 $encoding = self::getEncoding($encoding);
657 if ('CP850' === $encoding || 'ASCII' === $encoding) {
658 $pos = strrpos($haystack, $needle);
659 } else {
660 $needle = self::mb_substr($needle, 0, 1, $encoding);
661 $pos = iconv_strrpos($haystack, $needle, $encoding);
662 }
663
664 return self::getSubpart($pos, $part, $haystack, $encoding);
665 }
666
667 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
668 {
669 $needle = self::mb_substr($needle, 0, 1, $encoding);
670 $pos = self::mb_strripos($haystack, $needle, $encoding);
671
672 return self::getSubpart($pos, $part, $haystack, $encoding);
673 }
674
675 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
676 {
677 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
678 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
679
680 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
681 }
682
683 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
684 {
685 $pos = strpos($haystack, $needle);
686 if (false === $pos) {
687 return false;
688 }
689 if ($part) {
690 return substr($haystack, 0, $pos);
691 }
692
693 return substr($haystack, $pos);
694 }
695
696 public static function mb_get_info($type = 'all')
697 {
698 $info = [
699 'internal_encoding' => self::$internalEncoding,
700 'http_output' => 'pass',
701 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
702 'func_overload' => 0,
703 'func_overload_list' => 'no overload',
704 'mail_charset' => 'UTF-8',
705 'mail_header_encoding' => 'BASE64',
706 'mail_body_encoding' => 'BASE64',
707 'illegal_chars' => 0,
708 'encoding_translation' => 'Off',
709 'language' => self::$language,
710 'detect_order' => self::$encodingList,
711 'substitute_character' => 'none',
712 'strict_detection' => 'Off',
713 ];
714
715 if ('all' === $type) {
716 return $info;
717 }
718 if (isset($info[$type])) {
719 return $info[$type];
720 }
721
722 return false;
723 }
724
725 public static function mb_http_input($type = '')
726 {
727 return false;
728 }
729
730 public static function mb_http_output($encoding = null)
731 {
732 return null !== $encoding ? 'pass' === $encoding : 'pass';
733 }
734
735 public static function mb_strwidth($s, $encoding = null)
736 {
737 $encoding = self::getEncoding($encoding);
738
739 if ('UTF-8' !== $encoding) {
740 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
741 }
742
743 $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);
744
745 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
746 }
747
748 public static function mb_substr_count($haystack, $needle, $encoding = null)
749 {
750 return substr_count($haystack, $needle);
751 }
752
753 public static function mb_output_handler($contents, $status)
754 {
755 return $contents;
756 }
757
758 public static function mb_chr($code, $encoding = null)
759 {
760 if (0x80 > $code %= 0x200000) {
761 $s = \chr($code);
762 } elseif (0x800 > $code) {
763 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
764 } elseif (0x10000 > $code) {
765 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
766 } else {
767 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
768 }
769
770 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
771 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
772 }
773
774 return $s;
775 }
776
777 public static function mb_ord($s, $encoding = null)
778 {
779 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
780 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
781 }
782
783 if (1 === \strlen($s)) {
784 return \ord($s);
785 }
786
787 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
788 if (0xF0 <= $code) {
789 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
790 }
791 if (0xE0 <= $code) {
792 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
793 }
794 if (0xC0 <= $code) {
795 return (($code - 0xC0) << 6) + $s[2] - 0x80;
796 }
797
798 return $code;
799 }
800
801 private static function getSubpart($pos, $part, $haystack, $encoding)
802 {
803 if (false === $pos) {
804 return false;
805 }
806 if ($part) {
807 return self::mb_substr($haystack, 0, $pos, $encoding);
808 }
809
810 return self::mb_substr($haystack, $pos, null, $encoding);
811 }
812
813 private static function html_encoding_callback(array $m)
814 {
815 $i = 1;
816 $entities = '';
817 $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
818
819 while (isset($m[$i])) {
820 if (0x80 > $m[$i]) {
821 $entities .= \chr($m[$i++]);
822 continue;
823 }
824 if (0xF0 <= $m[$i]) {
825 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
826 } elseif (0xE0 <= $m[$i]) {
827 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
828 } else {
829 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
830 }
831
832 $entities .= '&#'.$c.';';
833 }
834
835 return $entities;
836 }
837
838 private static function title_case(array $s)
839 {
840 return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
841 }
842
843 private static function getData($file)
844 {
845 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
846 return require $file;
847 }
848
849 return false;
850 }
851
852 private static function getEncoding($encoding)
853 {
854 if (null === $encoding) {
855 return self::$internalEncoding;
856 }
857
858 if ('UTF-8' === $encoding) {
859 return 'UTF-8';
860 }
861
862 $encoding = strtoupper($encoding);
863
864 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
865 return 'CP850';
866 }
867
868 if ('UTF8' === $encoding) {
869 return 'UTF-8';
870 }
871
872 return $encoding;
873 }
874 }
875