create-berna-stencil 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/.eleventy.js +38 -19
  2. package/README.md +1 -1
  3. package/bin/create.js +1 -1
  4. package/docs/Components.md +12 -0
  5. package/docs/Creating pages.md +1 -2
  6. package/package.json +63 -61
  7. package/src/backend/_core/vendor/composer/autoload_static.php +10 -10
  8. package/src/backend/_core/vendor/composer/installed.json +6 -6
  9. package/src/backend/_core/vendor/composer/installed.php +2 -2
  10. package/src/backend/_core/vendor/graham-campbell/result-type/LICENSE +21 -21
  11. package/src/backend/_core/vendor/graham-campbell/result-type/composer.json +33 -33
  12. package/src/backend/_core/vendor/graham-campbell/result-type/src/Error.php +121 -121
  13. package/src/backend/_core/vendor/graham-campbell/result-type/src/Result.php +69 -69
  14. package/src/backend/_core/vendor/graham-campbell/result-type/src/Success.php +120 -120
  15. package/src/backend/_core/vendor/phpoption/phpoption/LICENSE +200 -200
  16. package/src/backend/_core/vendor/phpoption/phpoption/composer.json +50 -50
  17. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/LazyOption.php +175 -175
  18. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/None.php +136 -136
  19. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/Option.php +434 -434
  20. package/src/backend/_core/vendor/phpoption/phpoption/src/PhpOption/Some.php +169 -169
  21. package/src/backend/_core/vendor/symfony/polyfill-ctype/Ctype.php +232 -232
  22. package/src/backend/_core/vendor/symfony/polyfill-ctype/LICENSE +19 -19
  23. package/src/backend/_core/vendor/symfony/polyfill-ctype/README.md +12 -12
  24. package/src/backend/_core/vendor/symfony/polyfill-ctype/bootstrap.php +50 -50
  25. package/src/backend/_core/vendor/symfony/polyfill-ctype/bootstrap80.php +46 -46
  26. package/src/backend/_core/vendor/symfony/polyfill-ctype/composer.json +38 -38
  27. package/src/backend/_core/vendor/symfony/polyfill-mbstring/LICENSE +19 -19
  28. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Mbstring.php +1077 -1077
  29. package/src/backend/_core/vendor/symfony/polyfill-mbstring/README.md +13 -13
  30. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/caseFolding.php +119 -119
  31. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +1397 -1397
  32. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php +5 -5
  33. package/src/backend/_core/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php +1489 -1489
  34. package/src/backend/_core/vendor/symfony/polyfill-mbstring/bootstrap.php +171 -171
  35. package/src/backend/_core/vendor/symfony/polyfill-mbstring/bootstrap80.php +167 -167
  36. package/src/backend/_core/vendor/symfony/polyfill-mbstring/composer.json +39 -39
  37. package/src/backend/_core/vendor/symfony/polyfill-php80/LICENSE +19 -19
  38. package/src/backend/_core/vendor/symfony/polyfill-php80/Php80.php +115 -115
  39. package/src/backend/_core/vendor/symfony/polyfill-php80/PhpToken.php +106 -106
  40. package/src/backend/_core/vendor/symfony/polyfill-php80/README.md +25 -25
  41. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php +31 -31
  42. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php +16 -16
  43. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php +20 -20
  44. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php +16 -16
  45. package/src/backend/_core/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php +16 -16
  46. package/src/backend/_core/vendor/symfony/polyfill-php80/bootstrap.php +42 -42
  47. package/src/backend/_core/vendor/symfony/polyfill-php80/composer.json +37 -37
  48. package/src/backend/_core/vendor/vlucas/phpdotenv/LICENSE +30 -30
  49. package/src/backend/_core/vendor/vlucas/phpdotenv/composer.json +60 -60
  50. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Dotenv.php +267 -267
  51. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/ExceptionInterface.php +12 -12
  52. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/InvalidEncodingException.php +12 -12
  53. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/InvalidFileException.php +12 -12
  54. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/InvalidPathException.php +12 -12
  55. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Exception/ValidationException.php +12 -12
  56. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Loader/Loader.php +48 -48
  57. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Loader/LoaderInterface.php +20 -20
  58. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Loader/Resolver.php +65 -65
  59. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Entry.php +59 -59
  60. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/EntryParser.php +299 -299
  61. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Lexer.php +58 -58
  62. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Lines.php +127 -127
  63. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Parser.php +53 -53
  64. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/ParserInterface.php +19 -19
  65. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Parser/Value.php +88 -88
  66. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/AdapterInterface.php +15 -15
  67. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ApacheAdapter.php +89 -89
  68. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ArrayAdapter.php +80 -80
  69. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/EnvConstAdapter.php +88 -88
  70. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/GuardedWriter.php +85 -85
  71. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ImmutableWriter.php +110 -110
  72. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiReader.php +48 -48
  73. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/MultiWriter.php +64 -64
  74. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/PutenvAdapter.php +91 -91
  75. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReaderInterface.php +17 -17
  76. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ReplacingWriter.php +104 -104
  77. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/ServerConstAdapter.php +88 -88
  78. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/Adapter/WriterInterface.php +27 -27
  79. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/AdapterRepository.php +107 -107
  80. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/RepositoryBuilder.php +272 -272
  81. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Repository/RepositoryInterface.php +51 -51
  82. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/File/Paths.php +44 -44
  83. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/File/Reader.php +81 -81
  84. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/FileStore.php +72 -72
  85. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/StoreBuilder.php +141 -141
  86. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/StoreInterface.php +17 -17
  87. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Store/StringStore.php +37 -37
  88. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Util/Regex.php +112 -112
  89. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Util/Str.php +108 -108
  90. package/src/backend/_core/vendor/vlucas/phpdotenv/src/Validator.php +207 -207
  91. package/src/frontend/components/layouts/base.njk +47 -34
  92. package/src/frontend/components/welcome.njk +32 -668
  93. package/src/frontend/data/site.json +43 -43
  94. package/src/frontend/scss/modules/_global.scss +0 -1
  95. package/src/backend/_core/vendor/graham-campbell/result-type/.gitattributes +0 -9
  96. package/src/backend/_core/vendor/graham-campbell/result-type/.github/CODE_OF_CONDUCT.md +0 -132
  97. package/src/backend/_core/vendor/graham-campbell/result-type/.github/CONTRIBUTING.md +0 -31
  98. package/src/backend/_core/vendor/graham-campbell/result-type/.github/FUNDING.yml +0 -2
  99. package/src/backend/_core/vendor/graham-campbell/result-type/.github/SECURITY.md +0 -14
  100. package/src/backend/_core/vendor/graham-campbell/result-type/.github/workflows/stale.yml +0 -11
  101. package/src/backend/_core/vendor/graham-campbell/result-type/.github/workflows/tests.yml +0 -40
  102. package/src/backend/_core/vendor/graham-campbell/result-type/CHANGELOG.md +0 -53
  103. package/src/backend/_core/vendor/graham-campbell/result-type/README.md +0 -42
  104. package/src/backend/_core/vendor/graham-campbell/result-type/phpunit.xml.dist +0 -13
  105. package/src/backend/_core/vendor/graham-campbell/result-type/tests/ResultTest.php +0 -95
  106. package/src/backend/_core/vendor/phpoption/phpoption/.gitattributes +0 -13
  107. package/src/backend/_core/vendor/phpoption/phpoption/.github/CODE_OF_CONDUCT.md +0 -132
  108. package/src/backend/_core/vendor/phpoption/phpoption/.github/CONTRIBUTING.md +0 -30
  109. package/src/backend/_core/vendor/phpoption/phpoption/.github/FUNDING.yml +0 -2
  110. package/src/backend/_core/vendor/phpoption/phpoption/.github/SECURITY.md +0 -14
  111. package/src/backend/_core/vendor/phpoption/phpoption/.github/workflows/static.yml +0 -40
  112. package/src/backend/_core/vendor/phpoption/phpoption/.github/workflows/tests.yml +0 -40
  113. package/src/backend/_core/vendor/phpoption/phpoption/Makefile +0 -17
  114. package/src/backend/_core/vendor/phpoption/phpoption/README.md +0 -201
  115. package/src/backend/_core/vendor/phpoption/phpoption/phpstan-baseline.neon +0 -44
  116. package/src/backend/_core/vendor/phpoption/phpoption/phpstan.neon.dist +0 -7
  117. package/src/backend/_core/vendor/phpoption/phpoption/phpunit.xml.dist +0 -13
  118. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/EnsureTest.php +0 -72
  119. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/LazyOptionTest.php +0 -357
  120. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/NoneTest.php +0 -153
  121. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/OptionTest.php +0 -166
  122. package/src/backend/_core/vendor/phpoption/phpoption/tests/PhpOption/Tests/SomeTest.php +0 -194
  123. package/src/backend/_core/vendor/phpoption/phpoption/tests/bootstrap.php +0 -8
  124. package/src/backend/_core/vendor/phpoption/phpoption/vendor-bin/phpstan/composer.json +0 -8
  125. package/src/backend/_core/vendor/vlucas/phpdotenv/.editorconfig +0 -15
  126. package/src/backend/_core/vendor/vlucas/phpdotenv/.gitattributes +0 -15
  127. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/CODE_OF_CONDUCT.md +0 -132
  128. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/CONTRIBUTING.md +0 -30
  129. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/FUNDING.yml +0 -2
  130. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/SECURITY.md +0 -14
  131. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/workflows/static.yml +0 -40
  132. package/src/backend/_core/vendor/vlucas/phpdotenv/.github/workflows/tests.yml +0 -70
  133. package/src/backend/_core/vendor/vlucas/phpdotenv/Makefile +0 -17
  134. package/src/backend/_core/vendor/vlucas/phpdotenv/README.md +0 -370
  135. package/src/backend/_core/vendor/vlucas/phpdotenv/UPGRADING.md +0 -196
  136. package/src/backend/_core/vendor/vlucas/phpdotenv/phpstan-baseline.neon +0 -157
  137. package/src/backend/_core/vendor/vlucas/phpdotenv/phpstan.neon.dist +0 -7
  138. package/src/backend/_core/vendor/vlucas/phpdotenv/phpunit.xml.dist +0 -13
  139. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/DotenvTest.php +0 -387
  140. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Loader/LoaderTest.php +0 -86
  141. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/EntryParserTest.php +0 -234
  142. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/LexerTest.php +0 -40
  143. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/LinesTest.php +0 -53
  144. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Parser/ParserTest.php +0 -98
  145. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/ArrayAdapterTest.php +0 -57
  146. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/EnvConstAdapterTest.php +0 -75
  147. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/PutenvAdapterTest.php +0 -52
  148. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/Adapter/ServerConstAdapterTest.php +0 -75
  149. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Repository/RepositoryTest.php +0 -305
  150. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/Store/StoreTest.php +0 -141
  151. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/Dotenv/ValidatorTest.php +0 -479
  152. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/.env +0 -5
  153. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/assertions.env +0 -18
  154. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/booleans.env +0 -33
  155. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/commented.env +0 -15
  156. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/empty.env +0 -1
  157. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/example.env +0 -1
  158. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/exported.env +0 -7
  159. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/immutable.env +0 -1
  160. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/integers.env +0 -17
  161. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/large.env +0 -2
  162. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/multibyte.env +0 -3
  163. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/multiline.env +0 -14
  164. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/multiple.env +0 -4
  165. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/mutable.env +0 -1
  166. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/nested.env +0 -15
  167. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/quoted.env +0 -11
  168. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/specialchars.env +0 -8
  169. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/unicodevarnames.env +0 -2
  170. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/utf8-with-bom-encoding.env +0 -3
  171. package/src/backend/_core/vendor/vlucas/phpdotenv/tests/fixtures/env/windows.env +0 -1
  172. package/src/backend/_core/vendor/vlucas/phpdotenv/vendor-bin/phpstan/composer.json +0 -15
  173. package/src/backend/config.php +0 -19
@@ -1,1077 +1,1077 @@
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
- * - mb_ucfirst - Make a string's first character uppercase
52
- * - mb_lcfirst - Make a string's first character lowercase
53
- * - mb_trim - Strip whitespace (or other characters) from the beginning and end of a string
54
- * - mb_ltrim - Strip whitespace (or other characters) from the beginning of a string
55
- * - mb_rtrim - Strip whitespace (or other characters) from the end of a string
56
- *
57
- * Not implemented:
58
- * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
59
- * - mb_ereg_* - Regular expression with multibyte support
60
- * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
61
- * - mb_preferred_mime_name - Get MIME charset string
62
- * - mb_regex_encoding - Returns current encoding for multibyte regex as string
63
- * - mb_regex_set_options - Set/Get the default options for mbregex functions
64
- * - mb_send_mail - Send encoded mail
65
- * - mb_split - Split multibyte string using regular expression
66
- * - mb_strcut - Get part of string
67
- * - mb_strimwidth - Get truncated string with specified width
68
- *
69
- * @author Nicolas Grekas <p@tchwork.com>
70
- *
71
- * @internal
72
- */
73
- final class Mbstring
74
- {
75
- public const MB_CASE_FOLD = \PHP_INT_MAX;
76
-
77
- private const SIMPLE_CASE_FOLD = [
78
- ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
79
- ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'],
80
- ];
81
-
82
- private static $encodingList = ['ASCII', 'UTF-8'];
83
- private static $language = 'neutral';
84
- private static $internalEncoding = 'UTF-8';
85
-
86
- public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
87
- {
88
- if (\is_array($s)) {
89
- $r = [];
90
- foreach ($s as $str) {
91
- $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding);
92
- }
93
-
94
- return $r;
95
- }
96
-
97
- if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) {
98
- $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
99
- } else {
100
- $fromEncoding = self::getEncoding($fromEncoding);
101
- }
102
-
103
- $toEncoding = self::getEncoding($toEncoding);
104
-
105
- if ('BASE64' === $fromEncoding) {
106
- $s = base64_decode($s);
107
- $fromEncoding = $toEncoding;
108
- }
109
-
110
- if ('BASE64' === $toEncoding) {
111
- return base64_encode($s);
112
- }
113
-
114
- if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
115
- if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
116
- $fromEncoding = 'Windows-1252';
117
- }
118
- if ('UTF-8' !== $fromEncoding) {
119
- $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
120
- }
121
-
122
- return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
123
- }
124
-
125
- if ('HTML-ENTITIES' === $fromEncoding) {
126
- $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
127
- $fromEncoding = 'UTF-8';
128
- }
129
-
130
- return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
131
- }
132
-
133
- public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
134
- {
135
- $ok = true;
136
- array_walk_recursive($vars, static function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
137
- if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
138
- $ok = false;
139
- }
140
- });
141
-
142
- return $ok ? $fromEncoding : false;
143
- }
144
-
145
- public static function mb_decode_mimeheader($s)
146
- {
147
- return iconv_mime_decode($s, 2, self::$internalEncoding);
148
- }
149
-
150
- public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
151
- {
152
- trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
153
- }
154
-
155
- public static function mb_decode_numericentity($s, $convmap, $encoding = null)
156
- {
157
- if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
158
- trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
159
-
160
- return null;
161
- }
162
-
163
- if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
164
- return false;
165
- }
166
-
167
- if (null !== $encoding && !\is_scalar($encoding)) {
168
- trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
169
-
170
- return ''; // Instead of null (cf. mb_encode_numericentity).
171
- }
172
-
173
- $s = (string) $s;
174
- if ('' === $s) {
175
- return '';
176
- }
177
-
178
- $encoding = self::getEncoding($encoding);
179
-
180
- if ('UTF-8' === $encoding) {
181
- $encoding = null;
182
- if (!preg_match('//u', $s)) {
183
- $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
184
- }
185
- } else {
186
- $s = iconv($encoding, 'UTF-8//IGNORE', $s);
187
- }
188
-
189
- $cnt = floor(\count($convmap) / 4) * 4;
190
-
191
- for ($i = 0; $i < $cnt; $i += 4) {
192
- // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
193
- $convmap[$i] += $convmap[$i + 2];
194
- $convmap[$i + 1] += $convmap[$i + 2];
195
- }
196
-
197
- $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))'.(\PHP_VERSION_ID >= 80200 ? '' : '(?!&)').';?/', static function (array $m) use ($cnt, $convmap) {
198
- $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
199
- for ($i = 0; $i < $cnt; $i += 4) {
200
- if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
201
- return self::mb_chr($c - $convmap[$i + 2]);
202
- }
203
- }
204
-
205
- return $m[0];
206
- }, $s);
207
-
208
- if (null === $encoding) {
209
- return $s;
210
- }
211
-
212
- return iconv('UTF-8', $encoding.'//IGNORE', $s);
213
- }
214
-
215
- public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
216
- {
217
- if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
218
- trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
219
-
220
- return null;
221
- }
222
-
223
- if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
224
- return false;
225
- }
226
-
227
- if (null !== $encoding && !\is_scalar($encoding)) {
228
- trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
229
-
230
- return null; // Instead of '' (cf. mb_decode_numericentity).
231
- }
232
-
233
- if (null !== $is_hex && !\is_scalar($is_hex)) {
234
- trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING);
235
-
236
- return null;
237
- }
238
-
239
- $s = (string) $s;
240
- if ('' === $s) {
241
- return '';
242
- }
243
-
244
- $encoding = self::getEncoding($encoding);
245
-
246
- if ('UTF-8' === $encoding) {
247
- $encoding = null;
248
- if (!preg_match('//u', $s)) {
249
- $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
250
- }
251
- } else {
252
- $s = iconv($encoding, 'UTF-8//IGNORE', $s);
253
- }
254
-
255
- static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
256
-
257
- $cnt = floor(\count($convmap) / 4) * 4;
258
- $i = 0;
259
- $len = \strlen($s);
260
- $result = '';
261
-
262
- while ($i < $len) {
263
- $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
264
- $uchr = substr($s, $i, $ulen);
265
- $i += $ulen;
266
- $c = self::mb_ord($uchr);
267
-
268
- for ($j = 0; $j < $cnt; $j += 4) {
269
- if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
270
- $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
271
- $result .= $is_hex ? \sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
272
- continue 2;
273
- }
274
- }
275
- $result .= $uchr;
276
- }
277
-
278
- if (null === $encoding) {
279
- return $result;
280
- }
281
-
282
- return iconv('UTF-8', $encoding.'//IGNORE', $result);
283
- }
284
-
285
- public static function mb_convert_case($s, $mode, $encoding = null)
286
- {
287
- $s = (string) $s;
288
- if ('' === $s) {
289
- return '';
290
- }
291
-
292
- $encoding = self::getEncoding($encoding);
293
-
294
- if ('UTF-8' === $encoding) {
295
- $encoding = null;
296
- if (!preg_match('//u', $s)) {
297
- $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
298
- }
299
- } else {
300
- $s = iconv($encoding, 'UTF-8//IGNORE', $s);
301
- }
302
-
303
- if (\MB_CASE_TITLE == $mode) {
304
- static $titleRegexp = null;
305
- if (null === $titleRegexp) {
306
- $titleRegexp = self::getData('titleCaseRegexp');
307
- }
308
- $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
309
- } else {
310
- if (\MB_CASE_UPPER == $mode) {
311
- static $upper = null;
312
- if (null === $upper) {
313
- $upper = self::getData('upperCase');
314
- }
315
- $map = $upper;
316
- } else {
317
- if (self::MB_CASE_FOLD === $mode) {
318
- static $caseFolding = null;
319
- if (null === $caseFolding) {
320
- $caseFolding = self::getData('caseFolding');
321
- }
322
- $s = strtr($s, $caseFolding);
323
- }
324
-
325
- static $lower = null;
326
- if (null === $lower) {
327
- $lower = self::getData('lowerCase');
328
- }
329
- $map = $lower;
330
- }
331
-
332
- static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
333
-
334
- $i = 0;
335
- $len = \strlen($s);
336
-
337
- while ($i < $len) {
338
- $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
339
- $uchr = substr($s, $i, $ulen);
340
- $i += $ulen;
341
-
342
- if (isset($map[$uchr])) {
343
- $uchr = $map[$uchr];
344
- $nlen = \strlen($uchr);
345
-
346
- if ($nlen == $ulen) {
347
- $nlen = $i;
348
- do {
349
- $s[--$nlen] = $uchr[--$ulen];
350
- } while ($ulen);
351
- } else {
352
- $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
353
- $len += $nlen - $ulen;
354
- $i += $nlen - $ulen;
355
- }
356
- }
357
- }
358
- }
359
-
360
- if (null === $encoding) {
361
- return $s;
362
- }
363
-
364
- return iconv('UTF-8', $encoding.'//IGNORE', $s);
365
- }
366
-
367
- public static function mb_internal_encoding($encoding = null)
368
- {
369
- if (null === $encoding) {
370
- return self::$internalEncoding;
371
- }
372
-
373
- $normalizedEncoding = self::getEncoding($encoding);
374
-
375
- if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
376
- self::$internalEncoding = $normalizedEncoding;
377
-
378
- return true;
379
- }
380
-
381
- if (80000 > \PHP_VERSION_ID) {
382
- return false;
383
- }
384
-
385
- throw new \ValueError(\sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
386
- }
387
-
388
- public static function mb_language($lang = null)
389
- {
390
- if (null === $lang) {
391
- return self::$language;
392
- }
393
-
394
- switch ($normalizedLang = strtolower($lang)) {
395
- case 'uni':
396
- case 'neutral':
397
- self::$language = $normalizedLang;
398
-
399
- return true;
400
- }
401
-
402
- if (80000 > \PHP_VERSION_ID) {
403
- return false;
404
- }
405
-
406
- throw new \ValueError(\sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
407
- }
408
-
409
- public static function mb_list_encodings()
410
- {
411
- return ['UTF-8'];
412
- }
413
-
414
- public static function mb_encoding_aliases($encoding)
415
- {
416
- switch (strtoupper($encoding)) {
417
- case 'UTF8':
418
- case 'UTF-8':
419
- return ['utf8'];
420
- }
421
-
422
- return false;
423
- }
424
-
425
- public static function mb_check_encoding($var = null, $encoding = null)
426
- {
427
- if (null === $encoding) {
428
- if (null === $var) {
429
- return false;
430
- }
431
- $encoding = self::$internalEncoding;
432
- }
433
-
434
- if (!\is_array($var)) {
435
- return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var);
436
- }
437
-
438
- foreach ($var as $key => $value) {
439
- if (!self::mb_check_encoding($key, $encoding)) {
440
- return false;
441
- }
442
- if (!self::mb_check_encoding($value, $encoding)) {
443
- return false;
444
- }
445
- }
446
-
447
- return true;
448
- }
449
-
450
- public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
451
- {
452
- if (null === $encodingList) {
453
- $encodingList = self::$encodingList;
454
- } else {
455
- if (!\is_array($encodingList)) {
456
- $encodingList = array_map('trim', explode(',', $encodingList));
457
- }
458
- $encodingList = array_map('strtoupper', $encodingList);
459
- }
460
-
461
- foreach ($encodingList as $enc) {
462
- switch ($enc) {
463
- case 'ASCII':
464
- if (!preg_match('/[\x80-\xFF]/', $str)) {
465
- return $enc;
466
- }
467
- break;
468
-
469
- case 'UTF8':
470
- case 'UTF-8':
471
- if (preg_match('//u', $str)) {
472
- return 'UTF-8';
473
- }
474
- break;
475
-
476
- default:
477
- if (0 === strncmp($enc, 'ISO-8859-', 9)) {
478
- return $enc;
479
- }
480
- }
481
- }
482
-
483
- return false;
484
- }
485
-
486
- public static function mb_detect_order($encodingList = null)
487
- {
488
- if (null === $encodingList) {
489
- return self::$encodingList;
490
- }
491
-
492
- if (!\is_array($encodingList)) {
493
- $encodingList = array_map('trim', explode(',', $encodingList));
494
- }
495
- $encodingList = array_map('strtoupper', $encodingList);
496
-
497
- foreach ($encodingList as $enc) {
498
- switch ($enc) {
499
- default:
500
- if (strncmp($enc, 'ISO-8859-', 9)) {
501
- return false;
502
- }
503
- // no break
504
- case 'ASCII':
505
- case 'UTF8':
506
- case 'UTF-8':
507
- }
508
- }
509
-
510
- self::$encodingList = $encodingList;
511
-
512
- return true;
513
- }
514
-
515
- public static function mb_strlen($s, $encoding = null)
516
- {
517
- $encoding = self::getEncoding($encoding);
518
- if ('CP850' === $encoding || 'ASCII' === $encoding) {
519
- return \strlen($s);
520
- }
521
-
522
- return @iconv_strlen($s, $encoding);
523
- }
524
-
525
- public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
526
- {
527
- $encoding = self::getEncoding($encoding);
528
- if ('CP850' === $encoding || 'ASCII' === $encoding) {
529
- return strpos($haystack, $needle, $offset);
530
- }
531
-
532
- $needle = (string) $needle;
533
- if ('' === $needle) {
534
- if (80000 > \PHP_VERSION_ID) {
535
- trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING);
536
-
537
- return false;
538
- }
539
-
540
- return 0;
541
- }
542
-
543
- return iconv_strpos($haystack, $needle, $offset, $encoding);
544
- }
545
-
546
- public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
547
- {
548
- $encoding = self::getEncoding($encoding);
549
- if ('CP850' === $encoding || 'ASCII' === $encoding) {
550
- return strrpos($haystack, $needle, $offset);
551
- }
552
-
553
- if ($offset != (int) $offset) {
554
- $offset = 0;
555
- } elseif ($offset = (int) $offset) {
556
- if ($offset < 0) {
557
- if (0 > $offset += self::mb_strlen($needle)) {
558
- $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
559
- }
560
- $offset = 0;
561
- } else {
562
- $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
563
- }
564
- }
565
-
566
- $pos = '' !== $needle || 80000 > \PHP_VERSION_ID
567
- ? iconv_strrpos($haystack, $needle, $encoding)
568
- : self::mb_strlen($haystack, $encoding);
569
-
570
- return false !== $pos ? $offset + $pos : false;
571
- }
572
-
573
- public static function mb_str_split($string, $split_length = 1, $encoding = null)
574
- {
575
- if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
576
- trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING);
577
-
578
- return null;
579
- }
580
-
581
- if (1 > $split_length = (int) $split_length) {
582
- if (80000 > \PHP_VERSION_ID) {
583
- trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
584
-
585
- return false;
586
- }
587
-
588
- throw new \ValueError('Argument #2 ($length) must be greater than 0');
589
- }
590
-
591
- if (null === $encoding) {
592
- $encoding = mb_internal_encoding();
593
- }
594
-
595
- if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
596
- $rx = '/(';
597
- while (65535 < $split_length) {
598
- $rx .= '.{65535}';
599
- $split_length -= 65535;
600
- }
601
- $rx .= '.{'.$split_length.'})/us';
602
-
603
- return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
604
- }
605
-
606
- $result = [];
607
- $length = mb_strlen($string, $encoding);
608
-
609
- for ($i = 0; $i < $length; $i += $split_length) {
610
- $result[] = mb_substr($string, $i, $split_length, $encoding);
611
- }
612
-
613
- return $result;
614
- }
615
-
616
- public static function mb_strtolower($s, $encoding = null)
617
- {
618
- return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
619
- }
620
-
621
- public static function mb_strtoupper($s, $encoding = null)
622
- {
623
- return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
624
- }
625
-
626
- public static function mb_substitute_character($c = null)
627
- {
628
- if (null === $c) {
629
- return 'none';
630
- }
631
- if (0 === strcasecmp($c, 'none')) {
632
- return true;
633
- }
634
- if (80000 > \PHP_VERSION_ID) {
635
- return false;
636
- }
637
- if (\is_int($c) || 'long' === $c || 'entity' === $c) {
638
- return false;
639
- }
640
-
641
- throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
642
- }
643
-
644
- public static function mb_substr($s, $start, $length = null, $encoding = null)
645
- {
646
- $encoding = self::getEncoding($encoding);
647
- if ('CP850' === $encoding || 'ASCII' === $encoding) {
648
- return (string) substr($s, $start, null === $length ? 2147483647 : $length);
649
- }
650
-
651
- if ($start < 0) {
652
- $start = iconv_strlen($s, $encoding) + $start;
653
- if ($start < 0) {
654
- $start = 0;
655
- }
656
- }
657
-
658
- if (null === $length) {
659
- $length = 2147483647;
660
- } elseif ($length < 0) {
661
- $length = iconv_strlen($s, $encoding) + $length - $start;
662
- if ($length < 0) {
663
- return '';
664
- }
665
- }
666
-
667
- return (string) iconv_substr($s, $start, $length, $encoding);
668
- }
669
-
670
- public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
671
- {
672
- [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [
673
- self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding),
674
- self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding),
675
- ]);
676
-
677
- return self::mb_strpos($haystack, $needle, $offset, $encoding);
678
- }
679
-
680
- public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
681
- {
682
- $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
683
-
684
- return self::getSubpart($pos, $part, $haystack, $encoding);
685
- }
686
-
687
- public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
688
- {
689
- $encoding = self::getEncoding($encoding);
690
- if ('CP850' === $encoding || 'ASCII' === $encoding) {
691
- $pos = strrpos($haystack, $needle);
692
- } else {
693
- $needle = self::mb_substr($needle, 0, 1, $encoding);
694
- $pos = iconv_strrpos($haystack, $needle, $encoding);
695
- }
696
-
697
- return self::getSubpart($pos, $part, $haystack, $encoding);
698
- }
699
-
700
- public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
701
- {
702
- $needle = self::mb_substr($needle, 0, 1, $encoding);
703
- $pos = self::mb_strripos($haystack, $needle, $encoding);
704
-
705
- return self::getSubpart($pos, $part, $haystack, $encoding);
706
- }
707
-
708
- public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
709
- {
710
- $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding);
711
- $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding);
712
-
713
- $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack);
714
- $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle);
715
-
716
- return self::mb_strrpos($haystack, $needle, $offset, $encoding);
717
- }
718
-
719
- public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
720
- {
721
- $pos = strpos($haystack, $needle);
722
- if (false === $pos) {
723
- return false;
724
- }
725
- if ($part) {
726
- return substr($haystack, 0, $pos);
727
- }
728
-
729
- return substr($haystack, $pos);
730
- }
731
-
732
- public static function mb_get_info($type = 'all')
733
- {
734
- $info = [
735
- 'internal_encoding' => self::$internalEncoding,
736
- 'http_output' => 'pass',
737
- 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
738
- 'func_overload' => 0,
739
- 'func_overload_list' => 'no overload',
740
- 'mail_charset' => 'UTF-8',
741
- 'mail_header_encoding' => 'BASE64',
742
- 'mail_body_encoding' => 'BASE64',
743
- 'illegal_chars' => 0,
744
- 'encoding_translation' => 'Off',
745
- 'language' => self::$language,
746
- 'detect_order' => self::$encodingList,
747
- 'substitute_character' => 'none',
748
- 'strict_detection' => 'Off',
749
- ];
750
-
751
- if ('all' === $type) {
752
- return $info;
753
- }
754
- if (isset($info[$type])) {
755
- return $info[$type];
756
- }
757
-
758
- return false;
759
- }
760
-
761
- public static function mb_http_input($type = '')
762
- {
763
- return false;
764
- }
765
-
766
- public static function mb_http_output($encoding = null)
767
- {
768
- return null !== $encoding ? 'pass' === $encoding : 'pass';
769
- }
770
-
771
- public static function mb_strwidth($s, $encoding = null)
772
- {
773
- $encoding = self::getEncoding($encoding);
774
-
775
- if ('UTF-8' !== $encoding) {
776
- $s = iconv($encoding, 'UTF-8//IGNORE', $s);
777
- }
778
-
779
- $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);
780
-
781
- return ($wide << 1) + iconv_strlen($s, 'UTF-8');
782
- }
783
-
784
- public static function mb_substr_count($haystack, $needle, $encoding = null)
785
- {
786
- return substr_count($haystack, $needle);
787
- }
788
-
789
- public static function mb_output_handler($contents, $status)
790
- {
791
- return $contents;
792
- }
793
-
794
- public static function mb_chr($code, $encoding = null)
795
- {
796
- if (0x80 > $code %= 0x200000) {
797
- $s = \chr($code);
798
- } elseif (0x800 > $code) {
799
- $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
800
- } elseif (0x10000 > $code) {
801
- $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
802
- } else {
803
- $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
804
- }
805
-
806
- if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
807
- $s = mb_convert_encoding($s, $encoding, 'UTF-8');
808
- }
809
-
810
- return $s;
811
- }
812
-
813
- public static function mb_ord($s, $encoding = null)
814
- {
815
- if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
816
- $s = mb_convert_encoding($s, 'UTF-8', $encoding);
817
- }
818
-
819
- if (1 === \strlen($s)) {
820
- return \ord($s);
821
- }
822
-
823
- $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
824
- if (0xF0 <= $code) {
825
- return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
826
- }
827
- if (0xE0 <= $code) {
828
- return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
829
- }
830
- if (0xC0 <= $code) {
831
- return (($code - 0xC0) << 6) + $s[2] - 0x80;
832
- }
833
-
834
- return $code;
835
- }
836
-
837
- /** @return string|false */
838
- public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null)
839
- {
840
- if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) {
841
- if (\PHP_VERSION_ID < 80000) {
842
- trigger_error('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH', \E_USER_WARNING);
843
-
844
- return false;
845
- }
846
-
847
- throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
848
- }
849
-
850
- if (null === $encoding) {
851
- $encoding = self::mb_internal_encoding();
852
- } elseif (!self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given')) {
853
- return false;
854
- }
855
-
856
- if (self::mb_strlen($pad_string, $encoding) <= 0) {
857
- if (\PHP_VERSION_ID < 80000) {
858
- trigger_error('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string', \E_USER_WARNING);
859
-
860
- return false;
861
- }
862
-
863
- throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string');
864
- }
865
-
866
- $paddingRequired = $length - self::mb_strlen($string, $encoding);
867
-
868
- if ($paddingRequired < 1) {
869
- return $string;
870
- }
871
-
872
- switch ($pad_type) {
873
- case \STR_PAD_LEFT:
874
- return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string;
875
- case \STR_PAD_RIGHT:
876
- return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
877
- default:
878
- $leftPaddingLength = floor($paddingRequired / 2);
879
- $rightPaddingLength = $paddingRequired - $leftPaddingLength;
880
-
881
- return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
882
- }
883
- }
884
-
885
- /** @return string|false */
886
- public static function mb_ucfirst(string $string, ?string $encoding = null)
887
- {
888
- if (null === $encoding) {
889
- $encoding = self::mb_internal_encoding();
890
- } elseif (!self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
891
- return false;
892
- }
893
-
894
- $firstChar = mb_substr($string, 0, 1, $encoding);
895
- $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
896
-
897
- return $firstChar.mb_substr($string, 1, null, $encoding);
898
- }
899
-
900
- /** @return string|false */
901
- public static function mb_lcfirst(string $string, ?string $encoding = null)
902
- {
903
- if (null === $encoding) {
904
- $encoding = self::mb_internal_encoding();
905
- } elseif (!self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
906
- return false;
907
- }
908
-
909
- $firstChar = mb_substr($string, 0, 1, $encoding);
910
- $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
911
-
912
- return $firstChar.mb_substr($string, 1, null, $encoding);
913
- }
914
-
915
- private static function getSubpart($pos, $part, $haystack, $encoding)
916
- {
917
- if (false === $pos) {
918
- return false;
919
- }
920
- if ($part) {
921
- return self::mb_substr($haystack, 0, $pos, $encoding);
922
- }
923
-
924
- return self::mb_substr($haystack, $pos, null, $encoding);
925
- }
926
-
927
- private static function html_encoding_callback(array $m)
928
- {
929
- $i = 1;
930
- $entities = '';
931
- $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
932
-
933
- while (isset($m[$i])) {
934
- if (0x80 > $m[$i]) {
935
- $entities .= \chr($m[$i++]);
936
- continue;
937
- }
938
- if (0xF0 <= $m[$i]) {
939
- $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
940
- } elseif (0xE0 <= $m[$i]) {
941
- $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
942
- } else {
943
- $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
944
- }
945
-
946
- $entities .= '&#'.$c.';';
947
- }
948
-
949
- return $entities;
950
- }
951
-
952
- private static function title_case(array $s)
953
- {
954
- return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
955
- }
956
-
957
- private static function getData($file)
958
- {
959
- if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
960
- return require $file;
961
- }
962
-
963
- return false;
964
- }
965
-
966
- private static function getEncoding($encoding)
967
- {
968
- if (null === $encoding) {
969
- return self::$internalEncoding;
970
- }
971
-
972
- if ('UTF-8' === $encoding) {
973
- return 'UTF-8';
974
- }
975
-
976
- $encoding = strtoupper($encoding);
977
-
978
- if ('8BIT' === $encoding || 'BINARY' === $encoding) {
979
- return 'CP850';
980
- }
981
-
982
- if ('UTF8' === $encoding) {
983
- return 'UTF-8';
984
- }
985
-
986
- if ('UTF-32' === $encoding) {
987
- return 'UTF-32BE';
988
- }
989
-
990
- if ('UTF-16' === $encoding) {
991
- return 'UTF-16BE';
992
- }
993
-
994
- return $encoding;
995
- }
996
-
997
- /** @return string|false */
998
- public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null)
999
- {
1000
- return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
1001
- }
1002
-
1003
- /** @return string|false */
1004
- public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null)
1005
- {
1006
- return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
1007
- }
1008
-
1009
- /** @return string|false */
1010
- public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null)
1011
- {
1012
- return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
1013
- }
1014
-
1015
- /** @return string|false */
1016
- private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function)
1017
- {
1018
- if (null === $encoding) {
1019
- $encoding = self::mb_internal_encoding();
1020
- } elseif (!self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given')) {
1021
- return false;
1022
- }
1023
-
1024
- if ('' === $characters) {
1025
- return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding);
1026
- }
1027
-
1028
- if ('UTF-8' === $encoding) {
1029
- $encoding = null;
1030
- if (!preg_match('//u', $string)) {
1031
- $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string);
1032
- }
1033
- if (null !== $characters && !preg_match('//u', $characters)) {
1034
- $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters);
1035
- }
1036
- } else {
1037
- $string = iconv($encoding, 'UTF-8//IGNORE', $string);
1038
-
1039
- if (null !== $characters) {
1040
- $characters = iconv($encoding, 'UTF-8//IGNORE', $characters);
1041
- }
1042
- }
1043
-
1044
- if (null === $characters) {
1045
- $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}";
1046
- } else {
1047
- $characters = preg_quote($characters);
1048
- }
1049
-
1050
- $string = preg_replace(\sprintf($regex, $characters), '', $string);
1051
-
1052
- if (null === $encoding) {
1053
- return $string;
1054
- }
1055
-
1056
- return iconv('UTF-8', $encoding.'//IGNORE', $string);
1057
- }
1058
-
1059
- private static function assertEncoding(string $encoding, string $errorFormat): bool
1060
- {
1061
- try {
1062
- $validEncoding = @self::mb_check_encoding('', $encoding);
1063
- } catch (\ValueError $e) {
1064
- throw new \ValueError(\sprintf($errorFormat, $encoding));
1065
- }
1066
-
1067
- if (!$validEncoding) {
1068
- if (80000 > \PHP_VERSION_ID) {
1069
- trigger_error(\sprintf($errorFormat, $encoding), \E_USER_WARNING);
1070
- } else {
1071
- throw new \ValueError(\sprintf($errorFormat, $encoding));
1072
- }
1073
- }
1074
-
1075
- return $validEncoding;
1076
- }
1077
- }
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
+ * - mb_ucfirst - Make a string's first character uppercase
52
+ * - mb_lcfirst - Make a string's first character lowercase
53
+ * - mb_trim - Strip whitespace (or other characters) from the beginning and end of a string
54
+ * - mb_ltrim - Strip whitespace (or other characters) from the beginning of a string
55
+ * - mb_rtrim - Strip whitespace (or other characters) from the end of a string
56
+ *
57
+ * Not implemented:
58
+ * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
59
+ * - mb_ereg_* - Regular expression with multibyte support
60
+ * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable
61
+ * - mb_preferred_mime_name - Get MIME charset string
62
+ * - mb_regex_encoding - Returns current encoding for multibyte regex as string
63
+ * - mb_regex_set_options - Set/Get the default options for mbregex functions
64
+ * - mb_send_mail - Send encoded mail
65
+ * - mb_split - Split multibyte string using regular expression
66
+ * - mb_strcut - Get part of string
67
+ * - mb_strimwidth - Get truncated string with specified width
68
+ *
69
+ * @author Nicolas Grekas <p@tchwork.com>
70
+ *
71
+ * @internal
72
+ */
73
+ final class Mbstring
74
+ {
75
+ public const MB_CASE_FOLD = \PHP_INT_MAX;
76
+
77
+ private const SIMPLE_CASE_FOLD = [
78
+ ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
79
+ ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'],
80
+ ];
81
+
82
+ private static $encodingList = ['ASCII', 'UTF-8'];
83
+ private static $language = 'neutral';
84
+ private static $internalEncoding = 'UTF-8';
85
+
86
+ public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
87
+ {
88
+ if (\is_array($s)) {
89
+ $r = [];
90
+ foreach ($s as $str) {
91
+ $r[] = self::mb_convert_encoding($str, $toEncoding, $fromEncoding);
92
+ }
93
+
94
+ return $r;
95
+ }
96
+
97
+ if (\is_array($fromEncoding) || (null !== $fromEncoding && false !== strpos($fromEncoding, ','))) {
98
+ $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
99
+ } else {
100
+ $fromEncoding = self::getEncoding($fromEncoding);
101
+ }
102
+
103
+ $toEncoding = self::getEncoding($toEncoding);
104
+
105
+ if ('BASE64' === $fromEncoding) {
106
+ $s = base64_decode($s);
107
+ $fromEncoding = $toEncoding;
108
+ }
109
+
110
+ if ('BASE64' === $toEncoding) {
111
+ return base64_encode($s);
112
+ }
113
+
114
+ if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
115
+ if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
116
+ $fromEncoding = 'Windows-1252';
117
+ }
118
+ if ('UTF-8' !== $fromEncoding) {
119
+ $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
120
+ }
121
+
122
+ return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
123
+ }
124
+
125
+ if ('HTML-ENTITIES' === $fromEncoding) {
126
+ $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
127
+ $fromEncoding = 'UTF-8';
128
+ }
129
+
130
+ return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
131
+ }
132
+
133
+ public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
134
+ {
135
+ $ok = true;
136
+ array_walk_recursive($vars, static function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
137
+ if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
138
+ $ok = false;
139
+ }
140
+ });
141
+
142
+ return $ok ? $fromEncoding : false;
143
+ }
144
+
145
+ public static function mb_decode_mimeheader($s)
146
+ {
147
+ return iconv_mime_decode($s, 2, self::$internalEncoding);
148
+ }
149
+
150
+ public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
151
+ {
152
+ trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
153
+ }
154
+
155
+ public static function mb_decode_numericentity($s, $convmap, $encoding = null)
156
+ {
157
+ if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
158
+ trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
159
+
160
+ return null;
161
+ }
162
+
163
+ if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
164
+ return false;
165
+ }
166
+
167
+ if (null !== $encoding && !\is_scalar($encoding)) {
168
+ trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
169
+
170
+ return ''; // Instead of null (cf. mb_encode_numericentity).
171
+ }
172
+
173
+ $s = (string) $s;
174
+ if ('' === $s) {
175
+ return '';
176
+ }
177
+
178
+ $encoding = self::getEncoding($encoding);
179
+
180
+ if ('UTF-8' === $encoding) {
181
+ $encoding = null;
182
+ if (!preg_match('//u', $s)) {
183
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
184
+ }
185
+ } else {
186
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
187
+ }
188
+
189
+ $cnt = floor(\count($convmap) / 4) * 4;
190
+
191
+ for ($i = 0; $i < $cnt; $i += 4) {
192
+ // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
193
+ $convmap[$i] += $convmap[$i + 2];
194
+ $convmap[$i + 1] += $convmap[$i + 2];
195
+ }
196
+
197
+ $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))'.(\PHP_VERSION_ID >= 80200 ? '' : '(?!&)').';?/', static function (array $m) use ($cnt, $convmap) {
198
+ $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
199
+ for ($i = 0; $i < $cnt; $i += 4) {
200
+ if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
201
+ return self::mb_chr($c - $convmap[$i + 2]);
202
+ }
203
+ }
204
+
205
+ return $m[0];
206
+ }, $s);
207
+
208
+ if (null === $encoding) {
209
+ return $s;
210
+ }
211
+
212
+ return iconv('UTF-8', $encoding.'//IGNORE', $s);
213
+ }
214
+
215
+ public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
216
+ {
217
+ if (null !== $s && !\is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
218
+ trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING);
219
+
220
+ return null;
221
+ }
222
+
223
+ if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) {
224
+ return false;
225
+ }
226
+
227
+ if (null !== $encoding && !\is_scalar($encoding)) {
228
+ trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING);
229
+
230
+ return null; // Instead of '' (cf. mb_decode_numericentity).
231
+ }
232
+
233
+ if (null !== $is_hex && !\is_scalar($is_hex)) {
234
+ trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING);
235
+
236
+ return null;
237
+ }
238
+
239
+ $s = (string) $s;
240
+ if ('' === $s) {
241
+ return '';
242
+ }
243
+
244
+ $encoding = self::getEncoding($encoding);
245
+
246
+ if ('UTF-8' === $encoding) {
247
+ $encoding = null;
248
+ if (!preg_match('//u', $s)) {
249
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
250
+ }
251
+ } else {
252
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
253
+ }
254
+
255
+ static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
256
+
257
+ $cnt = floor(\count($convmap) / 4) * 4;
258
+ $i = 0;
259
+ $len = \strlen($s);
260
+ $result = '';
261
+
262
+ while ($i < $len) {
263
+ $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
264
+ $uchr = substr($s, $i, $ulen);
265
+ $i += $ulen;
266
+ $c = self::mb_ord($uchr);
267
+
268
+ for ($j = 0; $j < $cnt; $j += 4) {
269
+ if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
270
+ $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3];
271
+ $result .= $is_hex ? \sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';';
272
+ continue 2;
273
+ }
274
+ }
275
+ $result .= $uchr;
276
+ }
277
+
278
+ if (null === $encoding) {
279
+ return $result;
280
+ }
281
+
282
+ return iconv('UTF-8', $encoding.'//IGNORE', $result);
283
+ }
284
+
285
+ public static function mb_convert_case($s, $mode, $encoding = null)
286
+ {
287
+ $s = (string) $s;
288
+ if ('' === $s) {
289
+ return '';
290
+ }
291
+
292
+ $encoding = self::getEncoding($encoding);
293
+
294
+ if ('UTF-8' === $encoding) {
295
+ $encoding = null;
296
+ if (!preg_match('//u', $s)) {
297
+ $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
298
+ }
299
+ } else {
300
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
301
+ }
302
+
303
+ if (\MB_CASE_TITLE == $mode) {
304
+ static $titleRegexp = null;
305
+ if (null === $titleRegexp) {
306
+ $titleRegexp = self::getData('titleCaseRegexp');
307
+ }
308
+ $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
309
+ } else {
310
+ if (\MB_CASE_UPPER == $mode) {
311
+ static $upper = null;
312
+ if (null === $upper) {
313
+ $upper = self::getData('upperCase');
314
+ }
315
+ $map = $upper;
316
+ } else {
317
+ if (self::MB_CASE_FOLD === $mode) {
318
+ static $caseFolding = null;
319
+ if (null === $caseFolding) {
320
+ $caseFolding = self::getData('caseFolding');
321
+ }
322
+ $s = strtr($s, $caseFolding);
323
+ }
324
+
325
+ static $lower = null;
326
+ if (null === $lower) {
327
+ $lower = self::getData('lowerCase');
328
+ }
329
+ $map = $lower;
330
+ }
331
+
332
+ static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4];
333
+
334
+ $i = 0;
335
+ $len = \strlen($s);
336
+
337
+ while ($i < $len) {
338
+ $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
339
+ $uchr = substr($s, $i, $ulen);
340
+ $i += $ulen;
341
+
342
+ if (isset($map[$uchr])) {
343
+ $uchr = $map[$uchr];
344
+ $nlen = \strlen($uchr);
345
+
346
+ if ($nlen == $ulen) {
347
+ $nlen = $i;
348
+ do {
349
+ $s[--$nlen] = $uchr[--$ulen];
350
+ } while ($ulen);
351
+ } else {
352
+ $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
353
+ $len += $nlen - $ulen;
354
+ $i += $nlen - $ulen;
355
+ }
356
+ }
357
+ }
358
+ }
359
+
360
+ if (null === $encoding) {
361
+ return $s;
362
+ }
363
+
364
+ return iconv('UTF-8', $encoding.'//IGNORE', $s);
365
+ }
366
+
367
+ public static function mb_internal_encoding($encoding = null)
368
+ {
369
+ if (null === $encoding) {
370
+ return self::$internalEncoding;
371
+ }
372
+
373
+ $normalizedEncoding = self::getEncoding($encoding);
374
+
375
+ if ('UTF-8' === $normalizedEncoding || false !== @iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
376
+ self::$internalEncoding = $normalizedEncoding;
377
+
378
+ return true;
379
+ }
380
+
381
+ if (80000 > \PHP_VERSION_ID) {
382
+ return false;
383
+ }
384
+
385
+ throw new \ValueError(\sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
386
+ }
387
+
388
+ public static function mb_language($lang = null)
389
+ {
390
+ if (null === $lang) {
391
+ return self::$language;
392
+ }
393
+
394
+ switch ($normalizedLang = strtolower($lang)) {
395
+ case 'uni':
396
+ case 'neutral':
397
+ self::$language = $normalizedLang;
398
+
399
+ return true;
400
+ }
401
+
402
+ if (80000 > \PHP_VERSION_ID) {
403
+ return false;
404
+ }
405
+
406
+ throw new \ValueError(\sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
407
+ }
408
+
409
+ public static function mb_list_encodings()
410
+ {
411
+ return ['UTF-8'];
412
+ }
413
+
414
+ public static function mb_encoding_aliases($encoding)
415
+ {
416
+ switch (strtoupper($encoding)) {
417
+ case 'UTF8':
418
+ case 'UTF-8':
419
+ return ['utf8'];
420
+ }
421
+
422
+ return false;
423
+ }
424
+
425
+ public static function mb_check_encoding($var = null, $encoding = null)
426
+ {
427
+ if (null === $encoding) {
428
+ if (null === $var) {
429
+ return false;
430
+ }
431
+ $encoding = self::$internalEncoding;
432
+ }
433
+
434
+ if (!\is_array($var)) {
435
+ return self::mb_detect_encoding($var, [$encoding]) || false !== @iconv($encoding, $encoding, $var);
436
+ }
437
+
438
+ foreach ($var as $key => $value) {
439
+ if (!self::mb_check_encoding($key, $encoding)) {
440
+ return false;
441
+ }
442
+ if (!self::mb_check_encoding($value, $encoding)) {
443
+ return false;
444
+ }
445
+ }
446
+
447
+ return true;
448
+ }
449
+
450
+ public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
451
+ {
452
+ if (null === $encodingList) {
453
+ $encodingList = self::$encodingList;
454
+ } else {
455
+ if (!\is_array($encodingList)) {
456
+ $encodingList = array_map('trim', explode(',', $encodingList));
457
+ }
458
+ $encodingList = array_map('strtoupper', $encodingList);
459
+ }
460
+
461
+ foreach ($encodingList as $enc) {
462
+ switch ($enc) {
463
+ case 'ASCII':
464
+ if (!preg_match('/[\x80-\xFF]/', $str)) {
465
+ return $enc;
466
+ }
467
+ break;
468
+
469
+ case 'UTF8':
470
+ case 'UTF-8':
471
+ if (preg_match('//u', $str)) {
472
+ return 'UTF-8';
473
+ }
474
+ break;
475
+
476
+ default:
477
+ if (0 === strncmp($enc, 'ISO-8859-', 9)) {
478
+ return $enc;
479
+ }
480
+ }
481
+ }
482
+
483
+ return false;
484
+ }
485
+
486
+ public static function mb_detect_order($encodingList = null)
487
+ {
488
+ if (null === $encodingList) {
489
+ return self::$encodingList;
490
+ }
491
+
492
+ if (!\is_array($encodingList)) {
493
+ $encodingList = array_map('trim', explode(',', $encodingList));
494
+ }
495
+ $encodingList = array_map('strtoupper', $encodingList);
496
+
497
+ foreach ($encodingList as $enc) {
498
+ switch ($enc) {
499
+ default:
500
+ if (strncmp($enc, 'ISO-8859-', 9)) {
501
+ return false;
502
+ }
503
+ // no break
504
+ case 'ASCII':
505
+ case 'UTF8':
506
+ case 'UTF-8':
507
+ }
508
+ }
509
+
510
+ self::$encodingList = $encodingList;
511
+
512
+ return true;
513
+ }
514
+
515
+ public static function mb_strlen($s, $encoding = null)
516
+ {
517
+ $encoding = self::getEncoding($encoding);
518
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
519
+ return \strlen($s);
520
+ }
521
+
522
+ return @iconv_strlen($s, $encoding);
523
+ }
524
+
525
+ public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
526
+ {
527
+ $encoding = self::getEncoding($encoding);
528
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
529
+ return strpos($haystack, $needle, $offset);
530
+ }
531
+
532
+ $needle = (string) $needle;
533
+ if ('' === $needle) {
534
+ if (80000 > \PHP_VERSION_ID) {
535
+ trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING);
536
+
537
+ return false;
538
+ }
539
+
540
+ return 0;
541
+ }
542
+
543
+ return iconv_strpos($haystack, $needle, $offset, $encoding);
544
+ }
545
+
546
+ public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
547
+ {
548
+ $encoding = self::getEncoding($encoding);
549
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
550
+ return strrpos($haystack, $needle, $offset);
551
+ }
552
+
553
+ if ($offset != (int) $offset) {
554
+ $offset = 0;
555
+ } elseif ($offset = (int) $offset) {
556
+ if ($offset < 0) {
557
+ if (0 > $offset += self::mb_strlen($needle)) {
558
+ $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
559
+ }
560
+ $offset = 0;
561
+ } else {
562
+ $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
563
+ }
564
+ }
565
+
566
+ $pos = '' !== $needle || 80000 > \PHP_VERSION_ID
567
+ ? iconv_strrpos($haystack, $needle, $encoding)
568
+ : self::mb_strlen($haystack, $encoding);
569
+
570
+ return false !== $pos ? $offset + $pos : false;
571
+ }
572
+
573
+ public static function mb_str_split($string, $split_length = 1, $encoding = null)
574
+ {
575
+ if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
576
+ trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING);
577
+
578
+ return null;
579
+ }
580
+
581
+ if (1 > $split_length = (int) $split_length) {
582
+ if (80000 > \PHP_VERSION_ID) {
583
+ trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
584
+
585
+ return false;
586
+ }
587
+
588
+ throw new \ValueError('Argument #2 ($length) must be greater than 0');
589
+ }
590
+
591
+ if (null === $encoding) {
592
+ $encoding = mb_internal_encoding();
593
+ }
594
+
595
+ if ('UTF-8' === $encoding = self::getEncoding($encoding)) {
596
+ $rx = '/(';
597
+ while (65535 < $split_length) {
598
+ $rx .= '.{65535}';
599
+ $split_length -= 65535;
600
+ }
601
+ $rx .= '.{'.$split_length.'})/us';
602
+
603
+ return preg_split($rx, $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
604
+ }
605
+
606
+ $result = [];
607
+ $length = mb_strlen($string, $encoding);
608
+
609
+ for ($i = 0; $i < $length; $i += $split_length) {
610
+ $result[] = mb_substr($string, $i, $split_length, $encoding);
611
+ }
612
+
613
+ return $result;
614
+ }
615
+
616
+ public static function mb_strtolower($s, $encoding = null)
617
+ {
618
+ return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
619
+ }
620
+
621
+ public static function mb_strtoupper($s, $encoding = null)
622
+ {
623
+ return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
624
+ }
625
+
626
+ public static function mb_substitute_character($c = null)
627
+ {
628
+ if (null === $c) {
629
+ return 'none';
630
+ }
631
+ if (0 === strcasecmp($c, 'none')) {
632
+ return true;
633
+ }
634
+ if (80000 > \PHP_VERSION_ID) {
635
+ return false;
636
+ }
637
+ if (\is_int($c) || 'long' === $c || 'entity' === $c) {
638
+ return false;
639
+ }
640
+
641
+ throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
642
+ }
643
+
644
+ public static function mb_substr($s, $start, $length = null, $encoding = null)
645
+ {
646
+ $encoding = self::getEncoding($encoding);
647
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
648
+ return (string) substr($s, $start, null === $length ? 2147483647 : $length);
649
+ }
650
+
651
+ if ($start < 0) {
652
+ $start = iconv_strlen($s, $encoding) + $start;
653
+ if ($start < 0) {
654
+ $start = 0;
655
+ }
656
+ }
657
+
658
+ if (null === $length) {
659
+ $length = 2147483647;
660
+ } elseif ($length < 0) {
661
+ $length = iconv_strlen($s, $encoding) + $length - $start;
662
+ if ($length < 0) {
663
+ return '';
664
+ }
665
+ }
666
+
667
+ return (string) iconv_substr($s, $start, $length, $encoding);
668
+ }
669
+
670
+ public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
671
+ {
672
+ [$haystack, $needle] = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], [
673
+ self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding),
674
+ self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding),
675
+ ]);
676
+
677
+ return self::mb_strpos($haystack, $needle, $offset, $encoding);
678
+ }
679
+
680
+ public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
681
+ {
682
+ $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
683
+
684
+ return self::getSubpart($pos, $part, $haystack, $encoding);
685
+ }
686
+
687
+ public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
688
+ {
689
+ $encoding = self::getEncoding($encoding);
690
+ if ('CP850' === $encoding || 'ASCII' === $encoding) {
691
+ $pos = strrpos($haystack, $needle);
692
+ } else {
693
+ $needle = self::mb_substr($needle, 0, 1, $encoding);
694
+ $pos = iconv_strrpos($haystack, $needle, $encoding);
695
+ }
696
+
697
+ return self::getSubpart($pos, $part, $haystack, $encoding);
698
+ }
699
+
700
+ public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
701
+ {
702
+ $needle = self::mb_substr($needle, 0, 1, $encoding);
703
+ $pos = self::mb_strripos($haystack, $needle, $encoding);
704
+
705
+ return self::getSubpart($pos, $part, $haystack, $encoding);
706
+ }
707
+
708
+ public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
709
+ {
710
+ $haystack = self::mb_convert_case($haystack, \MB_CASE_LOWER, $encoding);
711
+ $needle = self::mb_convert_case($needle, \MB_CASE_LOWER, $encoding);
712
+
713
+ $haystack = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $haystack);
714
+ $needle = str_replace(self::SIMPLE_CASE_FOLD[0], self::SIMPLE_CASE_FOLD[1], $needle);
715
+
716
+ return self::mb_strrpos($haystack, $needle, $offset, $encoding);
717
+ }
718
+
719
+ public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
720
+ {
721
+ $pos = strpos($haystack, $needle);
722
+ if (false === $pos) {
723
+ return false;
724
+ }
725
+ if ($part) {
726
+ return substr($haystack, 0, $pos);
727
+ }
728
+
729
+ return substr($haystack, $pos);
730
+ }
731
+
732
+ public static function mb_get_info($type = 'all')
733
+ {
734
+ $info = [
735
+ 'internal_encoding' => self::$internalEncoding,
736
+ 'http_output' => 'pass',
737
+ 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
738
+ 'func_overload' => 0,
739
+ 'func_overload_list' => 'no overload',
740
+ 'mail_charset' => 'UTF-8',
741
+ 'mail_header_encoding' => 'BASE64',
742
+ 'mail_body_encoding' => 'BASE64',
743
+ 'illegal_chars' => 0,
744
+ 'encoding_translation' => 'Off',
745
+ 'language' => self::$language,
746
+ 'detect_order' => self::$encodingList,
747
+ 'substitute_character' => 'none',
748
+ 'strict_detection' => 'Off',
749
+ ];
750
+
751
+ if ('all' === $type) {
752
+ return $info;
753
+ }
754
+ if (isset($info[$type])) {
755
+ return $info[$type];
756
+ }
757
+
758
+ return false;
759
+ }
760
+
761
+ public static function mb_http_input($type = '')
762
+ {
763
+ return false;
764
+ }
765
+
766
+ public static function mb_http_output($encoding = null)
767
+ {
768
+ return null !== $encoding ? 'pass' === $encoding : 'pass';
769
+ }
770
+
771
+ public static function mb_strwidth($s, $encoding = null)
772
+ {
773
+ $encoding = self::getEncoding($encoding);
774
+
775
+ if ('UTF-8' !== $encoding) {
776
+ $s = iconv($encoding, 'UTF-8//IGNORE', $s);
777
+ }
778
+
779
+ $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);
780
+
781
+ return ($wide << 1) + iconv_strlen($s, 'UTF-8');
782
+ }
783
+
784
+ public static function mb_substr_count($haystack, $needle, $encoding = null)
785
+ {
786
+ return substr_count($haystack, $needle);
787
+ }
788
+
789
+ public static function mb_output_handler($contents, $status)
790
+ {
791
+ return $contents;
792
+ }
793
+
794
+ public static function mb_chr($code, $encoding = null)
795
+ {
796
+ if (0x80 > $code %= 0x200000) {
797
+ $s = \chr($code);
798
+ } elseif (0x800 > $code) {
799
+ $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F);
800
+ } elseif (0x10000 > $code) {
801
+ $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
802
+ } else {
803
+ $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F);
804
+ }
805
+
806
+ if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
807
+ $s = mb_convert_encoding($s, $encoding, 'UTF-8');
808
+ }
809
+
810
+ return $s;
811
+ }
812
+
813
+ public static function mb_ord($s, $encoding = null)
814
+ {
815
+ if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
816
+ $s = mb_convert_encoding($s, 'UTF-8', $encoding);
817
+ }
818
+
819
+ if (1 === \strlen($s)) {
820
+ return \ord($s);
821
+ }
822
+
823
+ $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
824
+ if (0xF0 <= $code) {
825
+ return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
826
+ }
827
+ if (0xE0 <= $code) {
828
+ return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
829
+ }
830
+ if (0xC0 <= $code) {
831
+ return (($code - 0xC0) << 6) + $s[2] - 0x80;
832
+ }
833
+
834
+ return $code;
835
+ }
836
+
837
+ /** @return string|false */
838
+ public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null)
839
+ {
840
+ if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) {
841
+ if (\PHP_VERSION_ID < 80000) {
842
+ trigger_error('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH', \E_USER_WARNING);
843
+
844
+ return false;
845
+ }
846
+
847
+ throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH');
848
+ }
849
+
850
+ if (null === $encoding) {
851
+ $encoding = self::mb_internal_encoding();
852
+ } elseif (!self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given')) {
853
+ return false;
854
+ }
855
+
856
+ if (self::mb_strlen($pad_string, $encoding) <= 0) {
857
+ if (\PHP_VERSION_ID < 80000) {
858
+ trigger_error('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string', \E_USER_WARNING);
859
+
860
+ return false;
861
+ }
862
+
863
+ throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string');
864
+ }
865
+
866
+ $paddingRequired = $length - self::mb_strlen($string, $encoding);
867
+
868
+ if ($paddingRequired < 1) {
869
+ return $string;
870
+ }
871
+
872
+ switch ($pad_type) {
873
+ case \STR_PAD_LEFT:
874
+ return self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding).$string;
875
+ case \STR_PAD_RIGHT:
876
+ return $string.self::mb_substr(str_repeat($pad_string, $paddingRequired), 0, $paddingRequired, $encoding);
877
+ default:
878
+ $leftPaddingLength = floor($paddingRequired / 2);
879
+ $rightPaddingLength = $paddingRequired - $leftPaddingLength;
880
+
881
+ return self::mb_substr(str_repeat($pad_string, $leftPaddingLength), 0, $leftPaddingLength, $encoding).$string.self::mb_substr(str_repeat($pad_string, $rightPaddingLength), 0, $rightPaddingLength, $encoding);
882
+ }
883
+ }
884
+
885
+ /** @return string|false */
886
+ public static function mb_ucfirst(string $string, ?string $encoding = null)
887
+ {
888
+ if (null === $encoding) {
889
+ $encoding = self::mb_internal_encoding();
890
+ } elseif (!self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
891
+ return false;
892
+ }
893
+
894
+ $firstChar = mb_substr($string, 0, 1, $encoding);
895
+ $firstChar = mb_convert_case($firstChar, \MB_CASE_TITLE, $encoding);
896
+
897
+ return $firstChar.mb_substr($string, 1, null, $encoding);
898
+ }
899
+
900
+ /** @return string|false */
901
+ public static function mb_lcfirst(string $string, ?string $encoding = null)
902
+ {
903
+ if (null === $encoding) {
904
+ $encoding = self::mb_internal_encoding();
905
+ } elseif (!self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) {
906
+ return false;
907
+ }
908
+
909
+ $firstChar = mb_substr($string, 0, 1, $encoding);
910
+ $firstChar = mb_convert_case($firstChar, \MB_CASE_LOWER, $encoding);
911
+
912
+ return $firstChar.mb_substr($string, 1, null, $encoding);
913
+ }
914
+
915
+ private static function getSubpart($pos, $part, $haystack, $encoding)
916
+ {
917
+ if (false === $pos) {
918
+ return false;
919
+ }
920
+ if ($part) {
921
+ return self::mb_substr($haystack, 0, $pos, $encoding);
922
+ }
923
+
924
+ return self::mb_substr($haystack, $pos, null, $encoding);
925
+ }
926
+
927
+ private static function html_encoding_callback(array $m)
928
+ {
929
+ $i = 1;
930
+ $entities = '';
931
+ $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
932
+
933
+ while (isset($m[$i])) {
934
+ if (0x80 > $m[$i]) {
935
+ $entities .= \chr($m[$i++]);
936
+ continue;
937
+ }
938
+ if (0xF0 <= $m[$i]) {
939
+ $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
940
+ } elseif (0xE0 <= $m[$i]) {
941
+ $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
942
+ } else {
943
+ $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
944
+ }
945
+
946
+ $entities .= '&#'.$c.';';
947
+ }
948
+
949
+ return $entities;
950
+ }
951
+
952
+ private static function title_case(array $s)
953
+ {
954
+ return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
955
+ }
956
+
957
+ private static function getData($file)
958
+ {
959
+ if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
960
+ return require $file;
961
+ }
962
+
963
+ return false;
964
+ }
965
+
966
+ private static function getEncoding($encoding)
967
+ {
968
+ if (null === $encoding) {
969
+ return self::$internalEncoding;
970
+ }
971
+
972
+ if ('UTF-8' === $encoding) {
973
+ return 'UTF-8';
974
+ }
975
+
976
+ $encoding = strtoupper($encoding);
977
+
978
+ if ('8BIT' === $encoding || 'BINARY' === $encoding) {
979
+ return 'CP850';
980
+ }
981
+
982
+ if ('UTF8' === $encoding) {
983
+ return 'UTF-8';
984
+ }
985
+
986
+ if ('UTF-32' === $encoding) {
987
+ return 'UTF-32BE';
988
+ }
989
+
990
+ if ('UTF-16' === $encoding) {
991
+ return 'UTF-16BE';
992
+ }
993
+
994
+ return $encoding;
995
+ }
996
+
997
+ /** @return string|false */
998
+ public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null)
999
+ {
1000
+ return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
1001
+ }
1002
+
1003
+ /** @return string|false */
1004
+ public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null)
1005
+ {
1006
+ return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__);
1007
+ }
1008
+
1009
+ /** @return string|false */
1010
+ public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null)
1011
+ {
1012
+ return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
1013
+ }
1014
+
1015
+ /** @return string|false */
1016
+ private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function)
1017
+ {
1018
+ if (null === $encoding) {
1019
+ $encoding = self::mb_internal_encoding();
1020
+ } elseif (!self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given')) {
1021
+ return false;
1022
+ }
1023
+
1024
+ if ('' === $characters) {
1025
+ return null === $encoding ? $string : self::mb_convert_encoding($string, $encoding);
1026
+ }
1027
+
1028
+ if ('UTF-8' === $encoding) {
1029
+ $encoding = null;
1030
+ if (!preg_match('//u', $string)) {
1031
+ $string = @iconv('UTF-8', 'UTF-8//IGNORE', $string);
1032
+ }
1033
+ if (null !== $characters && !preg_match('//u', $characters)) {
1034
+ $characters = @iconv('UTF-8', 'UTF-8//IGNORE', $characters);
1035
+ }
1036
+ } else {
1037
+ $string = iconv($encoding, 'UTF-8//IGNORE', $string);
1038
+
1039
+ if (null !== $characters) {
1040
+ $characters = iconv($encoding, 'UTF-8//IGNORE', $characters);
1041
+ }
1042
+ }
1043
+
1044
+ if (null === $characters) {
1045
+ $characters = "\\0 \f\n\r\t\v\u{00A0}\u{1680}\u{2000}\u{2001}\u{2002}\u{2003}\u{2004}\u{2005}\u{2006}\u{2007}\u{2008}\u{2009}\u{200A}\u{2028}\u{2029}\u{202F}\u{205F}\u{3000}\u{0085}\u{180E}";
1046
+ } else {
1047
+ $characters = preg_quote($characters);
1048
+ }
1049
+
1050
+ $string = preg_replace(\sprintf($regex, $characters), '', $string);
1051
+
1052
+ if (null === $encoding) {
1053
+ return $string;
1054
+ }
1055
+
1056
+ return iconv('UTF-8', $encoding.'//IGNORE', $string);
1057
+ }
1058
+
1059
+ private static function assertEncoding(string $encoding, string $errorFormat): bool
1060
+ {
1061
+ try {
1062
+ $validEncoding = @self::mb_check_encoding('', $encoding);
1063
+ } catch (\ValueError $e) {
1064
+ throw new \ValueError(\sprintf($errorFormat, $encoding));
1065
+ }
1066
+
1067
+ if (!$validEncoding) {
1068
+ if (80000 > \PHP_VERSION_ID) {
1069
+ trigger_error(\sprintf($errorFormat, $encoding), \E_USER_WARNING);
1070
+ } else {
1071
+ throw new \ValueError(\sprintf($errorFormat, $encoding));
1072
+ }
1073
+ }
1074
+
1075
+ return $validEncoding;
1076
+ }
1077
+ }