PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.20.0
GiveWP – Donation Plugin and Fundraising Platform v2.20.0
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 4 years ago LICENSE 4 years ago Mbstring.php 4 years ago bootstrap.php 4 years ago
Mbstring.php
849 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 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(
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", 'ι'),
78 );
79
80 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
81 {
82 if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
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
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
272 public static function mb_convert_case($s, $mode, $encoding = null)
273 {
274 $s = (string) $s;
275 if ('' === $s) {
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) {
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);
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;
318 $len = \strlen($s);
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];
327 $nlen = \strlen($uchr);
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;
337 $i += $nlen - $ulen;
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 {
417 if (!\is_array($encodingList)) {
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
454 if (!\is_array($encodingList)) {
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 }
465 // no break
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) {
481 return \strlen($s);
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
494 $needle = (string) $needle;
495 if ('' === $needle) {
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) {
515 if (0 > $offset += self::mb_strlen($needle)) {
516 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
517 }
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
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
537 if (1 > $split_length = (int) $split_length) {
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
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
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
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) {
591 return (string) substr($s, $start, null === $length ? 2147483647 : $length);
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
610 return (string) iconv_substr($s, $start, $length, $encoding);
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 $pos = strrpos($haystack, $needle);
633 } else {
634 $needle = self::mb_substr($needle, 0, 1, $encoding);
635 $pos = iconv_strrpos($haystack, $needle, $encoding);
636 }
637
638 return self::getSubpart($pos, $part, $haystack, $encoding);
639 }
640
641 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
642 {
643 $needle = self::mb_substr($needle, 0, 1, $encoding);
644 $pos = self::mb_strripos($haystack, $needle, $encoding);
645
646 return self::getSubpart($pos, $part, $haystack, $encoding);
647 }
648
649 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
650 {
651 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
652 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
653
654 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
655 }
656
657 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
658 {
659 $pos = strpos($haystack, $needle);
660 if (false === $pos) {
661 return false;
662 }
663 if ($part) {
664 return substr($haystack, 0, $pos);
665 }
666
667 return substr($haystack, $pos);
668 }
669
670 public static function mb_get_info($type = 'all')
671 {
672 $info = array(
673 'internal_encoding' => self::$internalEncoding,
674 'http_output' => 'pass',
675 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
676 'func_overload' => 0,
677 'func_overload_list' => 'no overload',
678 'mail_charset' => 'UTF-8',
679 'mail_header_encoding' => 'BASE64',
680 'mail_body_encoding' => 'BASE64',
681 'illegal_chars' => 0,
682 'encoding_translation' => 'Off',
683 'language' => self::$language,
684 'detect_order' => self::$encodingList,
685 'substitute_character' => 'none',
686 'strict_detection' => 'Off',
687 );
688
689 if ('all' === $type) {
690 return $info;
691 }
692 if (isset($info[$type])) {
693 return $info[$type];
694 }
695
696 return false;
697 }
698
699 public static function mb_http_input($type = '')
700 {
701 return false;
702 }
703
704 public static function mb_http_output($encoding = null)
705 {
706 return null !== $encoding ? 'pass' === $encoding : 'pass';
707 }
708
709 public static function mb_strwidth($s, $encoding = null)
710 {
711 $encoding = self::getEncoding($encoding);
712
713 if ('UTF-8' !== $encoding) {
714 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
715 }
716
717 $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);
718
719 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
720 }
721
722 public static function mb_substr_count($haystack, $needle, $encoding = null)
723 {
724 return substr_count($haystack, $needle);
725 }
726
727 public static function mb_output_handler($contents, $status)
728 {
729 return $contents;
730 }
731
732 public static function mb_chr($code, $encoding = null)
733 {
734 if (0x80 > $code %= 0x200000) {
735 $s = \chr($code);
736 } elseif (0x800 > $code) {
737 $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
738 } elseif (0x10000 > $code) {
739 $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
740 } else {
741 $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
742 }
743
744 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
745 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
746 }
747
748 return $s;
749 }
750
751 public static function mb_ord($s, $encoding = null)
752 {
753 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
754 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
755 }
756
757 if (1 === \strlen($s)) {
758 return \ord($s);
759 }
760
761 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
762 if (0xF0 <= $code) {
763 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
764 }
765 if (0xE0 <= $code) {
766 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
767 }
768 if (0xC0 <= $code) {
769 return (($code - 0xC0) << 6) + $s[2] - 0x80;
770 }
771
772 return $code;
773 }
774
775 private static function getSubpart($pos, $part, $haystack, $encoding)
776 {
777 if (false === $pos) {
778 return false;
779 }
780 if ($part) {
781 return self::mb_substr($haystack, 0, $pos, $encoding);
782 }
783
784 return self::mb_substr($haystack, $pos, null, $encoding);
785 }
786
787 private static function html_encoding_callback(array $m)
788 {
789 $i = 1;
790 $entities = '';
791 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
792
793 while (isset($m[$i])) {
794 if (0x80 > $m[$i]) {
795 $entities .= \chr($m[$i++]);
796 continue;
797 }
798 if (0xF0 <= $m[$i]) {
799 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
800 } elseif (0xE0 <= $m[$i]) {
801 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
802 } else {
803 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
804 }
805
806 $entities .= '&#'.$c.';';
807 }
808
809 return $entities;
810 }
811
812 private static function title_case(array $s)
813 {
814 return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8');
815 }
816
817 private static function getData($file)
818 {
819 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
820 return require $file;
821 }
822
823 return false;
824 }
825
826 private static function getEncoding($encoding)
827 {
828 if (null === $encoding) {
829 return self::$internalEncoding;
830 }
831
832 if ('UTF-8' === $encoding) {
833 return 'UTF-8';
834 }
835
836 $encoding = strtoupper($encoding);
837
838 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
839 return 'CP850';
840 }
841
842 if ('UTF8' === $encoding) {
843 return 'UTF-8';
844 }
845
846 return $encoding;
847 }
848 }
849