8889841cpolyfill-intl-idn/Resources/unidata/Regex.php000064400000304012150432043200015265 0ustar00 true, 1 => true, 2 => true, 3 => true, 4 => true, 5 => true, 6 => true, 7 => true, 8 => true, 9 => true, 10 => true, 11 => true, 12 => true, 13 => true, 14 => true, 15 => true, 16 => true, 17 => true, 18 => true, 19 => true, 20 => true, 21 => true, 22 => true, 23 => true, 24 => true, 25 => true, 26 => true, 27 => true, 28 => true, 29 => true, 30 => true, 31 => true, 32 => true, 33 => true, 34 => true, 35 => true, 36 => true, 37 => true, 38 => true, 39 => true, 40 => true, 41 => true, 42 => true, 43 => true, 44 => true, 47 => true, 58 => true, 59 => true, 60 => true, 61 => true, 62 => true, 63 => true, 64 => true, 91 => true, 92 => true, 93 => true, 94 => true, 95 => true, 96 => true, 123 => true, 124 => true, 125 => true, 126 => true, 127 => true, 8800 => true, 8814 => true, 8815 => true, ); polyfill-intl-idn/Resources/unidata/mapped.php000064400000311513150432043200015465 0ustar00 'a', 66 => 'b', 67 => 'c', 68 => 'd', 69 => 'e', 70 => 'f', 71 => 'g', 72 => 'h', 73 => 'i', 74 => 'j', 75 => 'k', 76 => 'l', 77 => 'm', 78 => 'n', 79 => 'o', 80 => 'p', 81 => 'q', 82 => 'r', 83 => 's', 84 => 't', 85 => 'u', 86 => 'v', 87 => 'w', 88 => 'x', 89 => 'y', 90 => 'z', 170 => 'a', 178 => '2', 179 => '3', 181 => 'μ', 185 => '1', 186 => 'o', 188 => '1⁄4', 189 => '1⁄2', 190 => '3⁄4', 192 => 'à', 193 => 'á', 194 => 'â', 195 => 'ã', 196 => 'ä', 197 => 'å', 198 => 'æ', 199 => 'ç', 200 => 'è', 201 => 'é', 202 => 'ê', 203 => 'ë', 204 => 'ì', 205 => 'í', 206 => 'î', 207 => 'ï', 208 => 'ð', 209 => 'ñ', 210 => 'ò', 211 => 'ó', 212 => 'ô', 213 => 'õ', 214 => 'ö', 216 => 'ø', 217 => 'ù', 218 => 'ú', 219 => 'û', 220 => 'ü', 221 => 'ý', 222 => 'þ', 256 => 'ā', 258 => 'ă', 260 => 'ą', 262 => 'ć', 264 => 'ĉ', 266 => 'ċ', 268 => 'č', 270 => 'ď', 272 => 'đ', 274 => 'ē', 276 => 'ĕ', 278 => 'ė', 280 => 'ę', 282 => 'ě', 284 => 'ĝ', 286 => 'ğ', 288 => 'ġ', 290 => 'ģ', 292 => 'ĥ', 294 => 'ħ', 296 => 'ĩ', 298 => 'ī', 300 => 'ĭ', 302 => 'į', 304 => 'i̇', 306 => 'ij', 307 => 'ij', 308 => 'ĵ', 310 => 'ķ', 313 => 'ĺ', 315 => 'ļ', 317 => 'ľ', 319 => 'l·', 320 => 'l·', 321 => 'ł', 323 => 'ń', 325 => 'ņ', 327 => 'ň', 329 => 'ʼn', 330 => 'ŋ', 332 => 'ō', 334 => 'ŏ', 336 => 'ő', 338 => 'œ', 340 => 'ŕ', 342 => 'ŗ', 344 => 'ř', 346 => 'ś', 348 => 'ŝ', 350 => 'ş', 352 => 'š', 354 => 'ţ', 356 => 'ť', 358 => 'ŧ', 360 => 'ũ', 362 => 'ū', 364 => 'ŭ', 366 => 'ů', 368 => 'ű', 370 => 'ų', 372 => 'ŵ', 374 => 'ŷ', 376 => 'ÿ', 377 => 'ź', 379 => 'ż', 381 => 'ž', 383 => 's', 385 => 'ɓ', 386 => 'ƃ', 388 => 'ƅ', 390 => 'ɔ', 391 => 'ƈ', 393 => 'ɖ', 394 => 'ɗ', 395 => 'ƌ', 398 => 'ǝ', 399 => 'ə', 400 => 'ɛ', 401 => 'ƒ', 403 => 'ɠ', 404 => 'ɣ', 406 => 'ɩ', 407 => 'ɨ', 408 => 'ƙ', 412 => 'ɯ', 413 => 'ɲ', 415 => 'ɵ', 416 => 'ơ', 418 => 'ƣ', 420 => 'ƥ', 422 => 'ʀ', 423 => 'ƨ', 425 => 'ʃ', 428 => 'ƭ', 430 => 'ʈ', 431 => 'ư', 433 => 'ʊ', 434 => 'ʋ', 435 => 'ƴ', 437 => 'ƶ', 439 => 'ʒ', 440 => 'ƹ', 444 => 'ƽ', 452 => 'dž', 453 => 'dž', 454 => 'dž', 455 => 'lj', 456 => 'lj', 457 => 'lj', 458 => 'nj', 459 => 'nj', 460 => 'nj', 461 => 'ǎ', 463 => 'ǐ', 465 => 'ǒ', 467 => 'ǔ', 469 => 'ǖ', 471 => 'ǘ', 473 => 'ǚ', 475 => 'ǜ', 478 => 'ǟ', 480 => 'ǡ', 482 => 'ǣ', 484 => 'ǥ', 486 => 'ǧ', 488 => 'ǩ', 490 => 'ǫ', 492 => 'ǭ', 494 => 'ǯ', 497 => 'dz', 498 => 'dz', 499 => 'dz', 500 => 'ǵ', 502 => 'ƕ', 503 => 'ƿ', 504 => 'ǹ', 506 => 'ǻ', 508 => 'ǽ', 510 => 'ǿ', 512 => 'ȁ', 514 => 'ȃ', 516 => 'ȅ', 518 => 'ȇ', 520 => 'ȉ', 522 => 'ȋ', 524 => 'ȍ', 526 => 'ȏ', 528 => 'ȑ', 530 => 'ȓ', 532 => 'ȕ', 534 => 'ȗ', 536 => 'ș', 538 => 'ț', 540 => 'ȝ', 542 => 'ȟ', 544 => 'ƞ', 546 => 'ȣ', 548 => 'ȥ', 550 => 'ȧ', 552 => 'ȩ', 554 => 'ȫ', 556 => 'ȭ', 558 => 'ȯ', 560 => 'ȱ', 562 => 'ȳ', 570 => 'ⱥ', 571 => 'ȼ', 573 => 'ƚ', 574 => 'ⱦ', 577 => 'ɂ', 579 => 'ƀ', 580 => 'ʉ', 581 => 'ʌ', 582 => 'ɇ', 584 => 'ɉ', 586 => 'ɋ', 588 => 'ɍ', 590 => 'ɏ', 688 => 'h', 689 => 'ɦ', 690 => 'j', 691 => 'r', 692 => 'ɹ', 693 => 'ɻ', 694 => 'ʁ', 695 => 'w', 696 => 'y', 736 => 'ɣ', 737 => 'l', 738 => 's', 739 => 'x', 740 => 'ʕ', 832 => '̀', 833 => '́', 835 => '̓', 836 => '̈́', 837 => 'ι', 880 => 'ͱ', 882 => 'ͳ', 884 => 'ʹ', 886 => 'ͷ', 895 => 'ϳ', 902 => 'ά', 903 => '·', 904 => 'έ', 905 => 'ή', 906 => 'ί', 908 => 'ό', 910 => 'ύ', 911 => 'ώ', 913 => 'α', 914 => 'β', 915 => 'γ', 916 => 'δ', 917 => 'ε', 918 => 'ζ', 919 => 'η', 920 => 'θ', 921 => 'ι', 922 => 'κ', 923 => 'λ', 924 => 'μ', 925 => 'ν', 926 => 'ξ', 927 => 'ο', 928 => 'π', 929 => 'ρ', 931 => 'σ', 932 => 'τ', 933 => 'υ', 934 => 'φ', 935 => 'χ', 936 => 'ψ', 937 => 'ω', 938 => 'ϊ', 939 => 'ϋ', 975 => 'ϗ', 976 => 'β', 977 => 'θ', 978 => 'υ', 979 => 'ύ', 980 => 'ϋ', 981 => 'φ', 982 => 'π', 984 => 'ϙ', 986 => 'ϛ', 988 => 'ϝ', 990 => 'ϟ', 992 => 'ϡ', 994 => 'ϣ', 996 => 'ϥ', 998 => 'ϧ', 1000 => 'ϩ', 1002 => 'ϫ', 1004 => 'ϭ', 1006 => 'ϯ', 1008 => 'κ', 1009 => 'ρ', 1010 => 'σ', 1012 => 'θ', 1013 => 'ε', 1015 => 'ϸ', 1017 => 'σ', 1018 => 'ϻ', 1021 => 'ͻ', 1022 => 'ͼ', 1023 => 'ͽ', 1024 => 'ѐ', 1025 => 'ё', 1026 => 'ђ', 1027 => 'ѓ', 1028 => 'є', 1029 => 'ѕ', 1030 => 'і', 1031 => 'ї', 1032 => 'ј', 1033 => 'љ', 1034 => 'њ', 1035 => 'ћ', 1036 => 'ќ', 1037 => 'ѝ', 1038 => 'ў', 1039 => 'џ', 1040 => 'а', 1041 => 'б', 1042 => 'в', 1043 => 'г', 1044 => 'д', 1045 => 'е', 1046 => 'ж', 1047 => 'з', 1048 => 'и', 1049 => 'й', 1050 => 'к', 1051 => 'л', 1052 => 'м', 1053 => 'н', 1054 => 'о', 1055 => 'п', 1056 => 'р', 1057 => 'с', 1058 => 'т', 1059 => 'у', 1060 => 'ф', 1061 => 'х', 1062 => 'ц', 1063 => 'ч', 1064 => 'ш', 1065 => 'щ', 1066 => 'ъ', 1067 => 'ы', 1068 => 'ь', 1069 => 'э', 1070 => 'ю', 1071 => 'я', 1120 => 'ѡ', 1122 => 'ѣ', 1124 => 'ѥ', 1126 => 'ѧ', 1128 => 'ѩ', 1130 => 'ѫ', 1132 => 'ѭ', 1134 => 'ѯ', 1136 => 'ѱ', 1138 => 'ѳ', 1140 => 'ѵ', 1142 => 'ѷ', 1144 => 'ѹ', 1146 => 'ѻ', 1148 => 'ѽ', 1150 => 'ѿ', 1152 => 'ҁ', 1162 => 'ҋ', 1164 => 'ҍ', 1166 => 'ҏ', 1168 => 'ґ', 1170 => 'ғ', 1172 => 'ҕ', 1174 => 'җ', 1176 => 'ҙ', 1178 => 'қ', 1180 => 'ҝ', 1182 => 'ҟ', 1184 => 'ҡ', 1186 => 'ң', 1188 => 'ҥ', 1190 => 'ҧ', 1192 => 'ҩ', 1194 => 'ҫ', 1196 => 'ҭ', 1198 => 'ү', 1200 => 'ұ', 1202 => 'ҳ', 1204 => 'ҵ', 1206 => 'ҷ', 1208 => 'ҹ', 1210 => 'һ', 1212 => 'ҽ', 1214 => 'ҿ', 1217 => 'ӂ', 1219 => 'ӄ', 1221 => 'ӆ', 1223 => 'ӈ', 1225 => 'ӊ', 1227 => 'ӌ', 1229 => 'ӎ', 1232 => 'ӑ', 1234 => 'ӓ', 1236 => 'ӕ', 1238 => 'ӗ', 1240 => 'ә', 1242 => 'ӛ', 1244 => 'ӝ', 1246 => 'ӟ', 1248 => 'ӡ', 1250 => 'ӣ', 1252 => 'ӥ', 1254 => 'ӧ', 1256 => 'ө', 1258 => 'ӫ', 1260 => 'ӭ', 1262 => 'ӯ', 1264 => 'ӱ', 1266 => 'ӳ', 1268 => 'ӵ', 1270 => 'ӷ', 1272 => 'ӹ', 1274 => 'ӻ', 1276 => 'ӽ', 1278 => 'ӿ', 1280 => 'ԁ', 1282 => 'ԃ', 1284 => 'ԅ', 1286 => 'ԇ', 1288 => 'ԉ', 1290 => 'ԋ', 1292 => 'ԍ', 1294 => 'ԏ', 1296 => 'ԑ', 1298 => 'ԓ', 1300 => 'ԕ', 1302 => 'ԗ', 1304 => 'ԙ', 1306 => 'ԛ', 1308 => 'ԝ', 1310 => 'ԟ', 1312 => 'ԡ', 1314 => 'ԣ', 1316 => 'ԥ', 1318 => 'ԧ', 1320 => 'ԩ', 1322 => 'ԫ', 1324 => 'ԭ', 1326 => 'ԯ', 1329 => 'ա', 1330 => 'բ', 1331 => 'գ', 1332 => 'դ', 1333 => 'ե', 1334 => 'զ', 1335 => 'է', 1336 => 'ը', 1337 => 'թ', 1338 => 'ժ', 1339 => 'ի', 1340 => 'լ', 1341 => 'խ', 1342 => 'ծ', 1343 => 'կ', 1344 => 'հ', 1345 => 'ձ', 1346 => 'ղ', 1347 => 'ճ', 1348 => 'մ', 1349 => 'յ', 1350 => 'ն', 1351 => 'շ', 1352 => 'ո', 1353 => 'չ', 1354 => 'պ', 1355 => 'ջ', 1356 => 'ռ', 1357 => 'ս', 1358 => 'վ', 1359 => 'տ', 1360 => 'ր', 1361 => 'ց', 1362 => 'ւ', 1363 => 'փ', 1364 => 'ք', 1365 => 'օ', 1366 => 'ֆ', 1415 => 'եւ', 1653 => 'اٴ', 1654 => 'وٴ', 1655 => 'ۇٴ', 1656 => 'يٴ', 2392 => 'क़', 2393 => 'ख़', 2394 => 'ग़', 2395 => 'ज़', 2396 => 'ड़', 2397 => 'ढ़', 2398 => 'फ़', 2399 => 'य़', 2524 => 'ড়', 2525 => 'ঢ়', 2527 => 'য়', 2611 => 'ਲ਼', 2614 => 'ਸ਼', 2649 => 'ਖ਼', 2650 => 'ਗ਼', 2651 => 'ਜ਼', 2654 => 'ਫ਼', 2908 => 'ଡ଼', 2909 => 'ଢ଼', 3635 => 'ํา', 3763 => 'ໍາ', 3804 => 'ຫນ', 3805 => 'ຫມ', 3852 => '་', 3907 => 'གྷ', 3917 => 'ཌྷ', 3922 => 'དྷ', 3927 => 'བྷ', 3932 => 'ཛྷ', 3945 => 'ཀྵ', 3955 => 'ཱི', 3957 => 'ཱུ', 3958 => 'ྲྀ', 3959 => 'ྲཱྀ', 3960 => 'ླྀ', 3961 => 'ླཱྀ', 3969 => 'ཱྀ', 3987 => 'ྒྷ', 3997 => 'ྜྷ', 4002 => 'ྡྷ', 4007 => 'ྦྷ', 4012 => 'ྫྷ', 4025 => 'ྐྵ', 4295 => 'ⴧ', 4301 => 'ⴭ', 4348 => 'ნ', 5112 => 'Ᏸ', 5113 => 'Ᏹ', 5114 => 'Ᏺ', 5115 => 'Ᏻ', 5116 => 'Ᏼ', 5117 => 'Ᏽ', 7296 => 'в', 7297 => 'д', 7298 => 'о', 7299 => 'с', 7300 => 'т', 7301 => 'т', 7302 => 'ъ', 7303 => 'ѣ', 7304 => 'ꙋ', 7312 => 'ა', 7313 => 'ბ', 7314 => 'გ', 7315 => 'დ', 7316 => 'ე', 7317 => 'ვ', 7318 => 'ზ', 7319 => 'თ', 7320 => 'ი', 7321 => 'კ', 7322 => 'ლ', 7323 => 'მ', 7324 => 'ნ', 7325 => 'ო', 7326 => 'პ', 7327 => 'ჟ', 7328 => 'რ', 7329 => 'ს', 7330 => 'ტ', 7331 => 'უ', 7332 => 'ფ', 7333 => 'ქ', 7334 => 'ღ', 7335 => 'ყ', 7336 => 'შ', 7337 => 'ჩ', 7338 => 'ც', 7339 => 'ძ', 7340 => 'წ', 7341 => 'ჭ', 7342 => 'ხ', 7343 => 'ჯ', 7344 => 'ჰ', 7345 => 'ჱ', 7346 => 'ჲ', 7347 => 'ჳ', 7348 => 'ჴ', 7349 => 'ჵ', 7350 => 'ჶ', 7351 => 'ჷ', 7352 => 'ჸ', 7353 => 'ჹ', 7354 => 'ჺ', 7357 => 'ჽ', 7358 => 'ჾ', 7359 => 'ჿ', 7468 => 'a', 7469 => 'æ', 7470 => 'b', 7472 => 'd', 7473 => 'e', 7474 => 'ǝ', 7475 => 'g', 7476 => 'h', 7477 => 'i', 7478 => 'j', 7479 => 'k', 7480 => 'l', 7481 => 'm', 7482 => 'n', 7484 => 'o', 7485 => 'ȣ', 7486 => 'p', 7487 => 'r', 7488 => 't', 7489 => 'u', 7490 => 'w', 7491 => 'a', 7492 => 'ɐ', 7493 => 'ɑ', 7494 => 'ᴂ', 7495 => 'b', 7496 => 'd', 7497 => 'e', 7498 => 'ə', 7499 => 'ɛ', 7500 => 'ɜ', 7501 => 'g', 7503 => 'k', 7504 => 'm', 7505 => 'ŋ', 7506 => 'o', 7507 => 'ɔ', 7508 => 'ᴖ', 7509 => 'ᴗ', 7510 => 'p', 7511 => 't', 7512 => 'u', 7513 => 'ᴝ', 7514 => 'ɯ', 7515 => 'v', 7516 => 'ᴥ', 7517 => 'β', 7518 => 'γ', 7519 => 'δ', 7520 => 'φ', 7521 => 'χ', 7522 => 'i', 7523 => 'r', 7524 => 'u', 7525 => 'v', 7526 => 'β', 7527 => 'γ', 7528 => 'ρ', 7529 => 'φ', 7530 => 'χ', 7544 => 'н', 7579 => 'ɒ', 7580 => 'c', 7581 => 'ɕ', 7582 => 'ð', 7583 => 'ɜ', 7584 => 'f', 7585 => 'ɟ', 7586 => 'ɡ', 7587 => 'ɥ', 7588 => 'ɨ', 7589 => 'ɩ', 7590 => 'ɪ', 7591 => 'ᵻ', 7592 => 'ʝ', 7593 => 'ɭ', 7594 => 'ᶅ', 7595 => 'ʟ', 7596 => 'ɱ', 7597 => 'ɰ', 7598 => 'ɲ', 7599 => 'ɳ', 7600 => 'ɴ', 7601 => 'ɵ', 7602 => 'ɸ', 7603 => 'ʂ', 7604 => 'ʃ', 7605 => 'ƫ', 7606 => 'ʉ', 7607 => 'ʊ', 7608 => 'ᴜ', 7609 => 'ʋ', 7610 => 'ʌ', 7611 => 'z', 7612 => 'ʐ', 7613 => 'ʑ', 7614 => 'ʒ', 7615 => 'θ', 7680 => 'ḁ', 7682 => 'ḃ', 7684 => 'ḅ', 7686 => 'ḇ', 7688 => 'ḉ', 7690 => 'ḋ', 7692 => 'ḍ', 7694 => 'ḏ', 7696 => 'ḑ', 7698 => 'ḓ', 7700 => 'ḕ', 7702 => 'ḗ', 7704 => 'ḙ', 7706 => 'ḛ', 7708 => 'ḝ', 7710 => 'ḟ', 7712 => 'ḡ', 7714 => 'ḣ', 7716 => 'ḥ', 7718 => 'ḧ', 7720 => 'ḩ', 7722 => 'ḫ', 7724 => 'ḭ', 7726 => 'ḯ', 7728 => 'ḱ', 7730 => 'ḳ', 7732 => 'ḵ', 7734 => 'ḷ', 7736 => 'ḹ', 7738 => 'ḻ', 7740 => 'ḽ', 7742 => 'ḿ', 7744 => 'ṁ', 7746 => 'ṃ', 7748 => 'ṅ', 7750 => 'ṇ', 7752 => 'ṉ', 7754 => 'ṋ', 7756 => 'ṍ', 7758 => 'ṏ', 7760 => 'ṑ', 7762 => 'ṓ', 7764 => 'ṕ', 7766 => 'ṗ', 7768 => 'ṙ', 7770 => 'ṛ', 7772 => 'ṝ', 7774 => 'ṟ', 7776 => 'ṡ', 7778 => 'ṣ', 7780 => 'ṥ', 7782 => 'ṧ', 7784 => 'ṩ', 7786 => 'ṫ', 7788 => 'ṭ', 7790 => 'ṯ', 7792 => 'ṱ', 7794 => 'ṳ', 7796 => 'ṵ', 7798 => 'ṷ', 7800 => 'ṹ', 7802 => 'ṻ', 7804 => 'ṽ', 7806 => 'ṿ', 7808 => 'ẁ', 7810 => 'ẃ', 7812 => 'ẅ', 7814 => 'ẇ', 7816 => 'ẉ', 7818 => 'ẋ', 7820 => 'ẍ', 7822 => 'ẏ', 7824 => 'ẑ', 7826 => 'ẓ', 7828 => 'ẕ', 7834 => 'aʾ', 7835 => 'ṡ', 7838 => 'ss', 7840 => 'ạ', 7842 => 'ả', 7844 => 'ấ', 7846 => 'ầ', 7848 => 'ẩ', 7850 => 'ẫ', 7852 => 'ậ', 7854 => 'ắ', 7856 => 'ằ', 7858 => 'ẳ', 7860 => 'ẵ', 7862 => 'ặ', 7864 => 'ẹ', 7866 => 'ẻ', 7868 => 'ẽ', 7870 => 'ế', 7872 => 'ề', 7874 => 'ể', 7876 => 'ễ', 7878 => 'ệ', 7880 => 'ỉ', 7882 => 'ị', 7884 => 'ọ', 7886 => 'ỏ', 7888 => 'ố', 7890 => 'ồ', 7892 => 'ổ', 7894 => 'ỗ', 7896 => 'ộ', 7898 => 'ớ', 7900 => 'ờ', 7902 => 'ở', 7904 => 'ỡ', 7906 => 'ợ', 7908 => 'ụ', 7910 => 'ủ', 7912 => 'ứ', 7914 => 'ừ', 7916 => 'ử', 7918 => 'ữ', 7920 => 'ự', 7922 => 'ỳ', 7924 => 'ỵ', 7926 => 'ỷ', 7928 => 'ỹ', 7930 => 'ỻ', 7932 => 'ỽ', 7934 => 'ỿ', 7944 => 'ἀ', 7945 => 'ἁ', 7946 => 'ἂ', 7947 => 'ἃ', 7948 => 'ἄ', 7949 => 'ἅ', 7950 => 'ἆ', 7951 => 'ἇ', 7960 => 'ἐ', 7961 => 'ἑ', 7962 => 'ἒ', 7963 => 'ἓ', 7964 => 'ἔ', 7965 => 'ἕ', 7976 => 'ἠ', 7977 => 'ἡ', 7978 => 'ἢ', 7979 => 'ἣ', 7980 => 'ἤ', 7981 => 'ἥ', 7982 => 'ἦ', 7983 => 'ἧ', 7992 => 'ἰ', 7993 => 'ἱ', 7994 => 'ἲ', 7995 => 'ἳ', 7996 => 'ἴ', 7997 => 'ἵ', 7998 => 'ἶ', 7999 => 'ἷ', 8008 => 'ὀ', 8009 => 'ὁ', 8010 => 'ὂ', 8011 => 'ὃ', 8012 => 'ὄ', 8013 => 'ὅ', 8025 => 'ὑ', 8027 => 'ὓ', 8029 => 'ὕ', 8031 => 'ὗ', 8040 => 'ὠ', 8041 => 'ὡ', 8042 => 'ὢ', 8043 => 'ὣ', 8044 => 'ὤ', 8045 => 'ὥ', 8046 => 'ὦ', 8047 => 'ὧ', 8049 => 'ά', 8051 => 'έ', 8053 => 'ή', 8055 => 'ί', 8057 => 'ό', 8059 => 'ύ', 8061 => 'ώ', 8064 => 'ἀι', 8065 => 'ἁι', 8066 => 'ἂι', 8067 => 'ἃι', 8068 => 'ἄι', 8069 => 'ἅι', 8070 => 'ἆι', 8071 => 'ἇι', 8072 => 'ἀι', 8073 => 'ἁι', 8074 => 'ἂι', 8075 => 'ἃι', 8076 => 'ἄι', 8077 => 'ἅι', 8078 => 'ἆι', 8079 => 'ἇι', 8080 => 'ἠι', 8081 => 'ἡι', 8082 => 'ἢι', 8083 => 'ἣι', 8084 => 'ἤι', 8085 => 'ἥι', 8086 => 'ἦι', 8087 => 'ἧι', 8088 => 'ἠι', 8089 => 'ἡι', 8090 => 'ἢι', 8091 => 'ἣι', 8092 => 'ἤι', 8093 => 'ἥι', 8094 => 'ἦι', 8095 => 'ἧι', 8096 => 'ὠι', 8097 => 'ὡι', 8098 => 'ὢι', 8099 => 'ὣι', 8100 => 'ὤι', 8101 => 'ὥι', 8102 => 'ὦι', 8103 => 'ὧι', 8104 => 'ὠι', 8105 => 'ὡι', 8106 => 'ὢι', 8107 => 'ὣι', 8108 => 'ὤι', 8109 => 'ὥι', 8110 => 'ὦι', 8111 => 'ὧι', 8114 => 'ὰι', 8115 => 'αι', 8116 => 'άι', 8119 => 'ᾶι', 8120 => 'ᾰ', 8121 => 'ᾱ', 8122 => 'ὰ', 8123 => 'ά', 8124 => 'αι', 8126 => 'ι', 8130 => 'ὴι', 8131 => 'ηι', 8132 => 'ήι', 8135 => 'ῆι', 8136 => 'ὲ', 8137 => 'έ', 8138 => 'ὴ', 8139 => 'ή', 8140 => 'ηι', 8147 => 'ΐ', 8152 => 'ῐ', 8153 => 'ῑ', 8154 => 'ὶ', 8155 => 'ί', 8163 => 'ΰ', 8168 => 'ῠ', 8169 => 'ῡ', 8170 => 'ὺ', 8171 => 'ύ', 8172 => 'ῥ', 8178 => 'ὼι', 8179 => 'ωι', 8180 => 'ώι', 8183 => 'ῶι', 8184 => 'ὸ', 8185 => 'ό', 8186 => 'ὼ', 8187 => 'ώ', 8188 => 'ωι', 8209 => '‐', 8243 => '′′', 8244 => '′′′', 8246 => '‵‵', 8247 => '‵‵‵', 8279 => '′′′′', 8304 => '0', 8305 => 'i', 8308 => '4', 8309 => '5', 8310 => '6', 8311 => '7', 8312 => '8', 8313 => '9', 8315 => '−', 8319 => 'n', 8320 => '0', 8321 => '1', 8322 => '2', 8323 => '3', 8324 => '4', 8325 => '5', 8326 => '6', 8327 => '7', 8328 => '8', 8329 => '9', 8331 => '−', 8336 => 'a', 8337 => 'e', 8338 => 'o', 8339 => 'x', 8340 => 'ə', 8341 => 'h', 8342 => 'k', 8343 => 'l', 8344 => 'm', 8345 => 'n', 8346 => 'p', 8347 => 's', 8348 => 't', 8360 => 'rs', 8450 => 'c', 8451 => '°c', 8455 => 'ɛ', 8457 => '°f', 8458 => 'g', 8459 => 'h', 8460 => 'h', 8461 => 'h', 8462 => 'h', 8463 => 'ħ', 8464 => 'i', 8465 => 'i', 8466 => 'l', 8467 => 'l', 8469 => 'n', 8470 => 'no', 8473 => 'p', 8474 => 'q', 8475 => 'r', 8476 => 'r', 8477 => 'r', 8480 => 'sm', 8481 => 'tel', 8482 => 'tm', 8484 => 'z', 8486 => 'ω', 8488 => 'z', 8490 => 'k', 8491 => 'å', 8492 => 'b', 8493 => 'c', 8495 => 'e', 8496 => 'e', 8497 => 'f', 8499 => 'm', 8500 => 'o', 8501 => 'א', 8502 => 'ב', 8503 => 'ג', 8504 => 'ד', 8505 => 'i', 8507 => 'fax', 8508 => 'π', 8509 => 'γ', 8510 => 'γ', 8511 => 'π', 8512 => '∑', 8517 => 'd', 8518 => 'd', 8519 => 'e', 8520 => 'i', 8521 => 'j', 8528 => '1⁄7', 8529 => '1⁄9', 8530 => '1⁄10', 8531 => '1⁄3', 8532 => '2⁄3', 8533 => '1⁄5', 8534 => '2⁄5', 8535 => '3⁄5', 8536 => '4⁄5', 8537 => '1⁄6', 8538 => '5⁄6', 8539 => '1⁄8', 8540 => '3⁄8', 8541 => '5⁄8', 8542 => '7⁄8', 8543 => '1⁄', 8544 => 'i', 8545 => 'ii', 8546 => 'iii', 8547 => 'iv', 8548 => 'v', 8549 => 'vi', 8550 => 'vii', 8551 => 'viii', 8552 => 'ix', 8553 => 'x', 8554 => 'xi', 8555 => 'xii', 8556 => 'l', 8557 => 'c', 8558 => 'd', 8559 => 'm', 8560 => 'i', 8561 => 'ii', 8562 => 'iii', 8563 => 'iv', 8564 => 'v', 8565 => 'vi', 8566 => 'vii', 8567 => 'viii', 8568 => 'ix', 8569 => 'x', 8570 => 'xi', 8571 => 'xii', 8572 => 'l', 8573 => 'c', 8574 => 'd', 8575 => 'm', 8585 => '0⁄3', 8748 => '∫∫', 8749 => '∫∫∫', 8751 => '∮∮', 8752 => '∮∮∮', 9001 => '〈', 9002 => '〉', 9312 => '1', 9313 => '2', 9314 => '3', 9315 => '4', 9316 => '5', 9317 => '6', 9318 => '7', 9319 => '8', 9320 => '9', 9321 => '10', 9322 => '11', 9323 => '12', 9324 => '13', 9325 => '14', 9326 => '15', 9327 => '16', 9328 => '17', 9329 => '18', 9330 => '19', 9331 => '20', 9398 => 'a', 9399 => 'b', 9400 => 'c', 9401 => 'd', 9402 => 'e', 9403 => 'f', 9404 => 'g', 9405 => 'h', 9406 => 'i', 9407 => 'j', 9408 => 'k', 9409 => 'l', 9410 => 'm', 9411 => 'n', 9412 => 'o', 9413 => 'p', 9414 => 'q', 9415 => 'r', 9416 => 's', 9417 => 't', 9418 => 'u', 9419 => 'v', 9420 => 'w', 9421 => 'x', 9422 => 'y', 9423 => 'z', 9424 => 'a', 9425 => 'b', 9426 => 'c', 9427 => 'd', 9428 => 'e', 9429 => 'f', 9430 => 'g', 9431 => 'h', 9432 => 'i', 9433 => 'j', 9434 => 'k', 9435 => 'l', 9436 => 'm', 9437 => 'n', 9438 => 'o', 9439 => 'p', 9440 => 'q', 9441 => 'r', 9442 => 's', 9443 => 't', 9444 => 'u', 9445 => 'v', 9446 => 'w', 9447 => 'x', 9448 => 'y', 9449 => 'z', 9450 => '0', 10764 => '∫∫∫∫', 10972 => '⫝̸', 11264 => 'ⰰ', 11265 => 'ⰱ', 11266 => 'ⰲ', 11267 => 'ⰳ', 11268 => 'ⰴ', 11269 => 'ⰵ', 11270 => 'ⰶ', 11271 => 'ⰷ', 11272 => 'ⰸ', 11273 => 'ⰹ', 11274 => 'ⰺ', 11275 => 'ⰻ', 11276 => 'ⰼ', 11277 => 'ⰽ', 11278 => 'ⰾ', 11279 => 'ⰿ', 11280 => 'ⱀ', 11281 => 'ⱁ', 11282 => 'ⱂ', 11283 => 'ⱃ', 11284 => 'ⱄ', 11285 => 'ⱅ', 11286 => 'ⱆ', 11287 => 'ⱇ', 11288 => 'ⱈ', 11289 => 'ⱉ', 11290 => 'ⱊ', 11291 => 'ⱋ', 11292 => 'ⱌ', 11293 => 'ⱍ', 11294 => 'ⱎ', 11295 => 'ⱏ', 11296 => 'ⱐ', 11297 => 'ⱑ', 11298 => 'ⱒ', 11299 => 'ⱓ', 11300 => 'ⱔ', 11301 => 'ⱕ', 11302 => 'ⱖ', 11303 => 'ⱗ', 11304 => 'ⱘ', 11305 => 'ⱙ', 11306 => 'ⱚ', 11307 => 'ⱛ', 11308 => 'ⱜ', 11309 => 'ⱝ', 11310 => 'ⱞ', 11360 => 'ⱡ', 11362 => 'ɫ', 11363 => 'ᵽ', 11364 => 'ɽ', 11367 => 'ⱨ', 11369 => 'ⱪ', 11371 => 'ⱬ', 11373 => 'ɑ', 11374 => 'ɱ', 11375 => 'ɐ', 11376 => 'ɒ', 11378 => 'ⱳ', 11381 => 'ⱶ', 11388 => 'j', 11389 => 'v', 11390 => 'ȿ', 11391 => 'ɀ', 11392 => 'ⲁ', 11394 => 'ⲃ', 11396 => 'ⲅ', 11398 => 'ⲇ', 11400 => 'ⲉ', 11402 => 'ⲋ', 11404 => 'ⲍ', 11406 => 'ⲏ', 11408 => 'ⲑ', 11410 => 'ⲓ', 11412 => 'ⲕ', 11414 => 'ⲗ', 11416 => 'ⲙ', 11418 => 'ⲛ', 11420 => 'ⲝ', 11422 => 'ⲟ', 11424 => 'ⲡ', 11426 => 'ⲣ', 11428 => 'ⲥ', 11430 => 'ⲧ', 11432 => 'ⲩ', 11434 => 'ⲫ', 11436 => 'ⲭ', 11438 => 'ⲯ', 11440 => 'ⲱ', 11442 => 'ⲳ', 11444 => 'ⲵ', 11446 => 'ⲷ', 11448 => 'ⲹ', 11450 => 'ⲻ', 11452 => 'ⲽ', 11454 => 'ⲿ', 11456 => 'ⳁ', 11458 => 'ⳃ', 11460 => 'ⳅ', 11462 => 'ⳇ', 11464 => 'ⳉ', 11466 => 'ⳋ', 11468 => 'ⳍ', 11470 => 'ⳏ', 11472 => 'ⳑ', 11474 => 'ⳓ', 11476 => 'ⳕ', 11478 => 'ⳗ', 11480 => 'ⳙ', 11482 => 'ⳛ', 11484 => 'ⳝ', 11486 => 'ⳟ', 11488 => 'ⳡ', 11490 => 'ⳣ', 11499 => 'ⳬ', 11501 => 'ⳮ', 11506 => 'ⳳ', 11631 => 'ⵡ', 11935 => '母', 12019 => '龟', 12032 => '一', 12033 => '丨', 12034 => '丶', 12035 => '丿', 12036 => '乙', 12037 => '亅', 12038 => '二', 12039 => '亠', 12040 => '人', 12041 => '儿', 12042 => '入', 12043 => '八', 12044 => '冂', 12045 => '冖', 12046 => '冫', 12047 => '几', 12048 => '凵', 12049 => '刀', 12050 => '力', 12051 => '勹', 12052 => '匕', 12053 => '匚', 12054 => '匸', 12055 => '十', 12056 => '卜', 12057 => '卩', 12058 => '厂', 12059 => '厶', 12060 => '又', 12061 => '口', 12062 => '囗', 12063 => '土', 12064 => '士', 12065 => '夂', 12066 => '夊', 12067 => '夕', 12068 => '大', 12069 => '女', 12070 => '子', 12071 => '宀', 12072 => '寸', 12073 => '小', 12074 => '尢', 12075 => '尸', 12076 => '屮', 12077 => '山', 12078 => '巛', 12079 => '工', 12080 => '己', 12081 => '巾', 12082 => '干', 12083 => '幺', 12084 => '广', 12085 => '廴', 12086 => '廾', 12087 => '弋', 12088 => '弓', 12089 => '彐', 12090 => '彡', 12091 => '彳', 12092 => '心', 12093 => '戈', 12094 => '戶', 12095 => '手', 12096 => '支', 12097 => '攴', 12098 => '文', 12099 => '斗', 12100 => '斤', 12101 => '方', 12102 => '无', 12103 => '日', 12104 => '曰', 12105 => '月', 12106 => '木', 12107 => '欠', 12108 => '止', 12109 => '歹', 12110 => '殳', 12111 => '毋', 12112 => '比', 12113 => '毛', 12114 => '氏', 12115 => '气', 12116 => '水', 12117 => '火', 12118 => '爪', 12119 => '父', 12120 => '爻', 12121 => '爿', 12122 => '片', 12123 => '牙', 12124 => '牛', 12125 => '犬', 12126 => '玄', 12127 => '玉', 12128 => '瓜', 12129 => '瓦', 12130 => '甘', 12131 => '生', 12132 => '用', 12133 => '田', 12134 => '疋', 12135 => '疒', 12136 => '癶', 12137 => '白', 12138 => '皮', 12139 => '皿', 12140 => '目', 12141 => '矛', 12142 => '矢', 12143 => '石', 12144 => '示', 12145 => '禸', 12146 => '禾', 12147 => '穴', 12148 => '立', 12149 => '竹', 12150 => '米', 12151 => '糸', 12152 => '缶', 12153 => '网', 12154 => '羊', 12155 => '羽', 12156 => '老', 12157 => '而', 12158 => '耒', 12159 => '耳', 12160 => '聿', 12161 => '肉', 12162 => '臣', 12163 => '自', 12164 => '至', 12165 => '臼', 12166 => '舌', 12167 => '舛', 12168 => '舟', 12169 => '艮', 12170 => '色', 12171 => '艸', 12172 => '虍', 12173 => '虫', 12174 => '血', 12175 => '行', 12176 => '衣', 12177 => '襾', 12178 => '見', 12179 => '角', 12180 => '言', 12181 => '谷', 12182 => '豆', 12183 => '豕', 12184 => '豸', 12185 => '貝', 12186 => '赤', 12187 => '走', 12188 => '足', 12189 => '身', 12190 => '車', 12191 => '辛', 12192 => '辰', 12193 => '辵', 12194 => '邑', 12195 => '酉', 12196 => '釆', 12197 => '里', 12198 => '金', 12199 => '長', 12200 => '門', 12201 => '阜', 12202 => '隶', 12203 => '隹', 12204 => '雨', 12205 => '靑', 12206 => '非', 12207 => '面', 12208 => '革', 12209 => '韋', 12210 => '韭', 12211 => '音', 12212 => '頁', 12213 => '風', 12214 => '飛', 12215 => '食', 12216 => '首', 12217 => '香', 12218 => '馬', 12219 => '骨', 12220 => '高', 12221 => '髟', 12222 => '鬥', 12223 => '鬯', 12224 => '鬲', 12225 => '鬼', 12226 => '魚', 12227 => '鳥', 12228 => '鹵', 12229 => '鹿', 12230 => '麥', 12231 => '麻', 12232 => '黃', 12233 => '黍', 12234 => '黑', 12235 => '黹', 12236 => '黽', 12237 => '鼎', 12238 => '鼓', 12239 => '鼠', 12240 => '鼻', 12241 => '齊', 12242 => '齒', 12243 => '龍', 12244 => '龜', 12245 => '龠', 12290 => '.', 12342 => '〒', 12344 => '十', 12345 => '卄', 12346 => '卅', 12447 => 'より', 12543 => 'コト', 12593 => 'ᄀ', 12594 => 'ᄁ', 12595 => 'ᆪ', 12596 => 'ᄂ', 12597 => 'ᆬ', 12598 => 'ᆭ', 12599 => 'ᄃ', 12600 => 'ᄄ', 12601 => 'ᄅ', 12602 => 'ᆰ', 12603 => 'ᆱ', 12604 => 'ᆲ', 12605 => 'ᆳ', 12606 => 'ᆴ', 12607 => 'ᆵ', 12608 => 'ᄚ', 12609 => 'ᄆ', 12610 => 'ᄇ', 12611 => 'ᄈ', 12612 => 'ᄡ', 12613 => 'ᄉ', 12614 => 'ᄊ', 12615 => 'ᄋ', 12616 => 'ᄌ', 12617 => 'ᄍ', 12618 => 'ᄎ', 12619 => 'ᄏ', 12620 => 'ᄐ', 12621 => 'ᄑ', 12622 => 'ᄒ', 12623 => 'ᅡ', 12624 => 'ᅢ', 12625 => 'ᅣ', 12626 => 'ᅤ', 12627 => 'ᅥ', 12628 => 'ᅦ', 12629 => 'ᅧ', 12630 => 'ᅨ', 12631 => 'ᅩ', 12632 => 'ᅪ', 12633 => 'ᅫ', 12634 => 'ᅬ', 12635 => 'ᅭ', 12636 => 'ᅮ', 12637 => 'ᅯ', 12638 => 'ᅰ', 12639 => 'ᅱ', 12640 => 'ᅲ', 12641 => 'ᅳ', 12642 => 'ᅴ', 12643 => 'ᅵ', 12645 => 'ᄔ', 12646 => 'ᄕ', 12647 => 'ᇇ', 12648 => 'ᇈ', 12649 => 'ᇌ', 12650 => 'ᇎ', 12651 => 'ᇓ', 12652 => 'ᇗ', 12653 => 'ᇙ', 12654 => 'ᄜ', 12655 => 'ᇝ', 12656 => 'ᇟ', 12657 => 'ᄝ', 12658 => 'ᄞ', 12659 => 'ᄠ', 12660 => 'ᄢ', 12661 => 'ᄣ', 12662 => 'ᄧ', 12663 => 'ᄩ', 12664 => 'ᄫ', 12665 => 'ᄬ', 12666 => 'ᄭ', 12667 => 'ᄮ', 12668 => 'ᄯ', 12669 => 'ᄲ', 12670 => 'ᄶ', 12671 => 'ᅀ', 12672 => 'ᅇ', 12673 => 'ᅌ', 12674 => 'ᇱ', 12675 => 'ᇲ', 12676 => 'ᅗ', 12677 => 'ᅘ', 12678 => 'ᅙ', 12679 => 'ᆄ', 12680 => 'ᆅ', 12681 => 'ᆈ', 12682 => 'ᆑ', 12683 => 'ᆒ', 12684 => 'ᆔ', 12685 => 'ᆞ', 12686 => 'ᆡ', 12690 => '一', 12691 => '二', 12692 => '三', 12693 => '四', 12694 => '上', 12695 => '中', 12696 => '下', 12697 => '甲', 12698 => '乙', 12699 => '丙', 12700 => '丁', 12701 => '天', 12702 => '地', 12703 => '人', 12868 => '問', 12869 => '幼', 12870 => '文', 12871 => '箏', 12880 => 'pte', 12881 => '21', 12882 => '22', 12883 => '23', 12884 => '24', 12885 => '25', 12886 => '26', 12887 => '27', 12888 => '28', 12889 => '29', 12890 => '30', 12891 => '31', 12892 => '32', 12893 => '33', 12894 => '34', 12895 => '35', 12896 => 'ᄀ', 12897 => 'ᄂ', 12898 => 'ᄃ', 12899 => 'ᄅ', 12900 => 'ᄆ', 12901 => 'ᄇ', 12902 => 'ᄉ', 12903 => 'ᄋ', 12904 => 'ᄌ', 12905 => 'ᄎ', 12906 => 'ᄏ', 12907 => 'ᄐ', 12908 => 'ᄑ', 12909 => 'ᄒ', 12910 => '가', 12911 => '나', 12912 => '다', 12913 => '라', 12914 => '마', 12915 => '바', 12916 => '사', 12917 => '아', 12918 => '자', 12919 => '차', 12920 => '카', 12921 => '타', 12922 => '파', 12923 => '하', 12924 => '참고', 12925 => '주의', 12926 => '우', 12928 => '一', 12929 => '二', 12930 => '三', 12931 => '四', 12932 => '五', 12933 => '六', 12934 => '七', 12935 => '八', 12936 => '九', 12937 => '十', 12938 => '月', 12939 => '火', 12940 => '水', 12941 => '木', 12942 => '金', 12943 => '土', 12944 => '日', 12945 => '株', 12946 => '有', 12947 => '社', 12948 => '名', 12949 => '特', 12950 => '財', 12951 => '祝', 12952 => '労', 12953 => '秘', 12954 => '男', 12955 => '女', 12956 => '適', 12957 => '優', 12958 => '印', 12959 => '注', 12960 => '項', 12961 => '休', 12962 => '写', 12963 => '正', 12964 => '上', 12965 => '中', 12966 => '下', 12967 => '左', 12968 => '右', 12969 => '医', 12970 => '宗', 12971 => '学', 12972 => '監', 12973 => '企', 12974 => '資', 12975 => '協', 12976 => '夜', 12977 => '36', 12978 => '37', 12979 => '38', 12980 => '39', 12981 => '40', 12982 => '41', 12983 => '42', 12984 => '43', 12985 => '44', 12986 => '45', 12987 => '46', 12988 => '47', 12989 => '48', 12990 => '49', 12991 => '50', 12992 => '1月', 12993 => '2月', 12994 => '3月', 12995 => '4月', 12996 => '5月', 12997 => '6月', 12998 => '7月', 12999 => '8月', 13000 => '9月', 13001 => '10月', 13002 => '11月', 13003 => '12月', 13004 => 'hg', 13005 => 'erg', 13006 => 'ev', 13007 => 'ltd', 13008 => 'ア', 13009 => 'イ', 13010 => 'ウ', 13011 => 'エ', 13012 => 'オ', 13013 => 'カ', 13014 => 'キ', 13015 => 'ク', 13016 => 'ケ', 13017 => 'コ', 13018 => 'サ', 13019 => 'シ', 13020 => 'ス', 13021 => 'セ', 13022 => 'ソ', 13023 => 'タ', 13024 => 'チ', 13025 => 'ツ', 13026 => 'テ', 13027 => 'ト', 13028 => 'ナ', 13029 => 'ニ', 13030 => 'ヌ', 13031 => 'ネ', 13032 => 'ノ', 13033 => 'ハ', 13034 => 'ヒ', 13035 => 'フ', 13036 => 'ヘ', 13037 => 'ホ', 13038 => 'マ', 13039 => 'ミ', 13040 => 'ム', 13041 => 'メ', 13042 => 'モ', 13043 => 'ヤ', 13044 => 'ユ', 13045 => 'ヨ', 13046 => 'ラ', 13047 => 'リ', 13048 => 'ル', 13049 => 'レ', 13050 => 'ロ', 13051 => 'ワ', 13052 => 'ヰ', 13053 => 'ヱ', 13054 => 'ヲ', 13055 => '令和', 13056 => 'アパート', 13057 => 'アルファ', 13058 => 'アンペア', 13059 => 'アール', 13060 => 'イニング', 13061 => 'インチ', 13062 => 'ウォン', 13063 => 'エスクード', 13064 => 'エーカー', 13065 => 'オンス', 13066 => 'オーム', 13067 => 'カイリ', 13068 => 'カラット', 13069 => 'カロリー', 13070 => 'ガロン', 13071 => 'ガンマ', 13072 => 'ギガ', 13073 => 'ギニー', 13074 => 'キュリー', 13075 => 'ギルダー', 13076 => 'キロ', 13077 => 'キログラム', 13078 => 'キロメートル', 13079 => 'キロワット', 13080 => 'グラム', 13081 => 'グラムトン', 13082 => 'クルゼイロ', 13083 => 'クローネ', 13084 => 'ケース', 13085 => 'コルナ', 13086 => 'コーポ', 13087 => 'サイクル', 13088 => 'サンチーム', 13089 => 'シリング', 13090 => 'センチ', 13091 => 'セント', 13092 => 'ダース', 13093 => 'デシ', 13094 => 'ドル', 13095 => 'トン', 13096 => 'ナノ', 13097 => 'ノット', 13098 => 'ハイツ', 13099 => 'パーセント', 13100 => 'パーツ', 13101 => 'バーレル', 13102 => 'ピアストル', 13103 => 'ピクル', 13104 => 'ピコ', 13105 => 'ビル', 13106 => 'ファラッド', 13107 => 'フィート', 13108 => 'ブッシェル', 13109 => 'フラン', 13110 => 'ヘクタール', 13111 => 'ペソ', 13112 => 'ペニヒ', 13113 => 'ヘルツ', 13114 => 'ペンス', 13115 => 'ページ', 13116 => 'ベータ', 13117 => 'ポイント', 13118 => 'ボルト', 13119 => 'ホン', 13120 => 'ポンド', 13121 => 'ホール', 13122 => 'ホーン', 13123 => 'マイクロ', 13124 => 'マイル', 13125 => 'マッハ', 13126 => 'マルク', 13127 => 'マンション', 13128 => 'ミクロン', 13129 => 'ミリ', 13130 => 'ミリバール', 13131 => 'メガ', 13132 => 'メガトン', 13133 => 'メートル', 13134 => 'ヤード', 13135 => 'ヤール', 13136 => 'ユアン', 13137 => 'リットル', 13138 => 'リラ', 13139 => 'ルピー', 13140 => 'ルーブル', 13141 => 'レム', 13142 => 'レントゲン', 13143 => 'ワット', 13144 => '0点', 13145 => '1点', 13146 => '2点', 13147 => '3点', 13148 => '4点', 13149 => '5点', 13150 => '6点', 13151 => '7点', 13152 => '8点', 13153 => '9点', 13154 => '10点', 13155 => '11点', 13156 => '12点', 13157 => '13点', 13158 => '14点', 13159 => '15点', 13160 => '16点', 13161 => '17点', 13162 => '18点', 13163 => '19点', 13164 => '20点', 13165 => '21点', 13166 => '22点', 13167 => '23点', 13168 => '24点', 13169 => 'hpa', 13170 => 'da', 13171 => 'au', 13172 => 'bar', 13173 => 'ov', 13174 => 'pc', 13175 => 'dm', 13176 => 'dm2', 13177 => 'dm3', 13178 => 'iu', 13179 => '平成', 13180 => '昭和', 13181 => '大正', 13182 => '明治', 13183 => '株式会社', 13184 => 'pa', 13185 => 'na', 13186 => 'μa', 13187 => 'ma', 13188 => 'ka', 13189 => 'kb', 13190 => 'mb', 13191 => 'gb', 13192 => 'cal', 13193 => 'kcal', 13194 => 'pf', 13195 => 'nf', 13196 => 'μf', 13197 => 'μg', 13198 => 'mg', 13199 => 'kg', 13200 => 'hz', 13201 => 'khz', 13202 => 'mhz', 13203 => 'ghz', 13204 => 'thz', 13205 => 'μl', 13206 => 'ml', 13207 => 'dl', 13208 => 'kl', 13209 => 'fm', 13210 => 'nm', 13211 => 'μm', 13212 => 'mm', 13213 => 'cm', 13214 => 'km', 13215 => 'mm2', 13216 => 'cm2', 13217 => 'm2', 13218 => 'km2', 13219 => 'mm3', 13220 => 'cm3', 13221 => 'm3', 13222 => 'km3', 13223 => 'm∕s', 13224 => 'm∕s2', 13225 => 'pa', 13226 => 'kpa', 13227 => 'mpa', 13228 => 'gpa', 13229 => 'rad', 13230 => 'rad∕s', 13231 => 'rad∕s2', 13232 => 'ps', 13233 => 'ns', 13234 => 'μs', 13235 => 'ms', 13236 => 'pv', 13237 => 'nv', 13238 => 'μv', 13239 => 'mv', 13240 => 'kv', 13241 => 'mv', 13242 => 'pw', 13243 => 'nw', 13244 => 'μw', 13245 => 'mw', 13246 => 'kw', 13247 => 'mw', 13248 => 'kω', 13249 => 'mω', 13251 => 'bq', 13252 => 'cc', 13253 => 'cd', 13254 => 'c∕kg', 13256 => 'db', 13257 => 'gy', 13258 => 'ha', 13259 => 'hp', 13260 => 'in', 13261 => 'kk', 13262 => 'km', 13263 => 'kt', 13264 => 'lm', 13265 => 'ln', 13266 => 'log', 13267 => 'lx', 13268 => 'mb', 13269 => 'mil', 13270 => 'mol', 13271 => 'ph', 13273 => 'ppm', 13274 => 'pr', 13275 => 'sr', 13276 => 'sv', 13277 => 'wb', 13278 => 'v∕m', 13279 => 'a∕m', 13280 => '1日', 13281 => '2日', 13282 => '3日', 13283 => '4日', 13284 => '5日', 13285 => '6日', 13286 => '7日', 13287 => '8日', 13288 => '9日', 13289 => '10日', 13290 => '11日', 13291 => '12日', 13292 => '13日', 13293 => '14日', 13294 => '15日', 13295 => '16日', 13296 => '17日', 13297 => '18日', 13298 => '19日', 13299 => '20日', 13300 => '21日', 13301 => '22日', 13302 => '23日', 13303 => '24日', 13304 => '25日', 13305 => '26日', 13306 => '27日', 13307 => '28日', 13308 => '29日', 13309 => '30日', 13310 => '31日', 13311 => 'gal', 42560 => 'ꙁ', 42562 => 'ꙃ', 42564 => 'ꙅ', 42566 => 'ꙇ', 42568 => 'ꙉ', 42570 => 'ꙋ', 42572 => 'ꙍ', 42574 => 'ꙏ', 42576 => 'ꙑ', 42578 => 'ꙓ', 42580 => 'ꙕ', 42582 => 'ꙗ', 42584 => 'ꙙ', 42586 => 'ꙛ', 42588 => 'ꙝ', 42590 => 'ꙟ', 42592 => 'ꙡ', 42594 => 'ꙣ', 42596 => 'ꙥ', 42598 => 'ꙧ', 42600 => 'ꙩ', 42602 => 'ꙫ', 42604 => 'ꙭ', 42624 => 'ꚁ', 42626 => 'ꚃ', 42628 => 'ꚅ', 42630 => 'ꚇ', 42632 => 'ꚉ', 42634 => 'ꚋ', 42636 => 'ꚍ', 42638 => 'ꚏ', 42640 => 'ꚑ', 42642 => 'ꚓ', 42644 => 'ꚕ', 42646 => 'ꚗ', 42648 => 'ꚙ', 42650 => 'ꚛ', 42652 => 'ъ', 42653 => 'ь', 42786 => 'ꜣ', 42788 => 'ꜥ', 42790 => 'ꜧ', 42792 => 'ꜩ', 42794 => 'ꜫ', 42796 => 'ꜭ', 42798 => 'ꜯ', 42802 => 'ꜳ', 42804 => 'ꜵ', 42806 => 'ꜷ', 42808 => 'ꜹ', 42810 => 'ꜻ', 42812 => 'ꜽ', 42814 => 'ꜿ', 42816 => 'ꝁ', 42818 => 'ꝃ', 42820 => 'ꝅ', 42822 => 'ꝇ', 42824 => 'ꝉ', 42826 => 'ꝋ', 42828 => 'ꝍ', 42830 => 'ꝏ', 42832 => 'ꝑ', 42834 => 'ꝓ', 42836 => 'ꝕ', 42838 => 'ꝗ', 42840 => 'ꝙ', 42842 => 'ꝛ', 42844 => 'ꝝ', 42846 => 'ꝟ', 42848 => 'ꝡ', 42850 => 'ꝣ', 42852 => 'ꝥ', 42854 => 'ꝧ', 42856 => 'ꝩ', 42858 => 'ꝫ', 42860 => 'ꝭ', 42862 => 'ꝯ', 42864 => 'ꝯ', 42873 => 'ꝺ', 42875 => 'ꝼ', 42877 => 'ᵹ', 42878 => 'ꝿ', 42880 => 'ꞁ', 42882 => 'ꞃ', 42884 => 'ꞅ', 42886 => 'ꞇ', 42891 => 'ꞌ', 42893 => 'ɥ', 42896 => 'ꞑ', 42898 => 'ꞓ', 42902 => 'ꞗ', 42904 => 'ꞙ', 42906 => 'ꞛ', 42908 => 'ꞝ', 42910 => 'ꞟ', 42912 => 'ꞡ', 42914 => 'ꞣ', 42916 => 'ꞥ', 42918 => 'ꞧ', 42920 => 'ꞩ', 42922 => 'ɦ', 42923 => 'ɜ', 42924 => 'ɡ', 42925 => 'ɬ', 42926 => 'ɪ', 42928 => 'ʞ', 42929 => 'ʇ', 42930 => 'ʝ', 42931 => 'ꭓ', 42932 => 'ꞵ', 42934 => 'ꞷ', 42936 => 'ꞹ', 42938 => 'ꞻ', 42940 => 'ꞽ', 42942 => 'ꞿ', 42946 => 'ꟃ', 42948 => 'ꞔ', 42949 => 'ʂ', 42950 => 'ᶎ', 42951 => 'ꟈ', 42953 => 'ꟊ', 42997 => 'ꟶ', 43000 => 'ħ', 43001 => 'œ', 43868 => 'ꜧ', 43869 => 'ꬷ', 43870 => 'ɫ', 43871 => 'ꭒ', 43881 => 'ʍ', 43888 => 'Ꭰ', 43889 => 'Ꭱ', 43890 => 'Ꭲ', 43891 => 'Ꭳ', 43892 => 'Ꭴ', 43893 => 'Ꭵ', 43894 => 'Ꭶ', 43895 => 'Ꭷ', 43896 => 'Ꭸ', 43897 => 'Ꭹ', 43898 => 'Ꭺ', 43899 => 'Ꭻ', 43900 => 'Ꭼ', 43901 => 'Ꭽ', 43902 => 'Ꭾ', 43903 => 'Ꭿ', 43904 => 'Ꮀ', 43905 => 'Ꮁ', 43906 => 'Ꮂ', 43907 => 'Ꮃ', 43908 => 'Ꮄ', 43909 => 'Ꮅ', 43910 => 'Ꮆ', 43911 => 'Ꮇ', 43912 => 'Ꮈ', 43913 => 'Ꮉ', 43914 => 'Ꮊ', 43915 => 'Ꮋ', 43916 => 'Ꮌ', 43917 => 'Ꮍ', 43918 => 'Ꮎ', 43919 => 'Ꮏ', 43920 => 'Ꮐ', 43921 => 'Ꮑ', 43922 => 'Ꮒ', 43923 => 'Ꮓ', 43924 => 'Ꮔ', 43925 => 'Ꮕ', 43926 => 'Ꮖ', 43927 => 'Ꮗ', 43928 => 'Ꮘ', 43929 => 'Ꮙ', 43930 => 'Ꮚ', 43931 => 'Ꮛ', 43932 => 'Ꮜ', 43933 => 'Ꮝ', 43934 => 'Ꮞ', 43935 => 'Ꮟ', 43936 => 'Ꮠ', 43937 => 'Ꮡ', 43938 => 'Ꮢ', 43939 => 'Ꮣ', 43940 => 'Ꮤ', 43941 => 'Ꮥ', 43942 => 'Ꮦ', 43943 => 'Ꮧ', 43944 => 'Ꮨ', 43945 => 'Ꮩ', 43946 => 'Ꮪ', 43947 => 'Ꮫ', 43948 => 'Ꮬ', 43949 => 'Ꮭ', 43950 => 'Ꮮ', 43951 => 'Ꮯ', 43952 => 'Ꮰ', 43953 => 'Ꮱ', 43954 => 'Ꮲ', 43955 => 'Ꮳ', 43956 => 'Ꮴ', 43957 => 'Ꮵ', 43958 => 'Ꮶ', 43959 => 'Ꮷ', 43960 => 'Ꮸ', 43961 => 'Ꮹ', 43962 => 'Ꮺ', 43963 => 'Ꮻ', 43964 => 'Ꮼ', 43965 => 'Ꮽ', 43966 => 'Ꮾ', 43967 => 'Ꮿ', 63744 => '豈', 63745 => '更', 63746 => '車', 63747 => '賈', 63748 => '滑', 63749 => '串', 63750 => '句', 63751 => '龜', 63752 => '龜', 63753 => '契', 63754 => '金', 63755 => '喇', 63756 => '奈', 63757 => '懶', 63758 => '癩', 63759 => '羅', 63760 => '蘿', 63761 => '螺', 63762 => '裸', 63763 => '邏', 63764 => '樂', 63765 => '洛', 63766 => '烙', 63767 => '珞', 63768 => '落', 63769 => '酪', 63770 => '駱', 63771 => '亂', 63772 => '卵', 63773 => '欄', 63774 => '爛', 63775 => '蘭', 63776 => '鸞', 63777 => '嵐', 63778 => '濫', 63779 => '藍', 63780 => '襤', 63781 => '拉', 63782 => '臘', 63783 => '蠟', 63784 => '廊', 63785 => '朗', 63786 => '浪', 63787 => '狼', 63788 => '郎', 63789 => '來', 63790 => '冷', 63791 => '勞', 63792 => '擄', 63793 => '櫓', 63794 => '爐', 63795 => '盧', 63796 => '老', 63797 => '蘆', 63798 => '虜', 63799 => '路', 63800 => '露', 63801 => '魯', 63802 => '鷺', 63803 => '碌', 63804 => '祿', 63805 => '綠', 63806 => '菉', 63807 => '錄', 63808 => '鹿', 63809 => '論', 63810 => '壟', 63811 => '弄', 63812 => '籠', 63813 => '聾', 63814 => '牢', 63815 => '磊', 63816 => '賂', 63817 => '雷', 63818 => '壘', 63819 => '屢', 63820 => '樓', 63821 => '淚', 63822 => '漏', 63823 => '累', 63824 => '縷', 63825 => '陋', 63826 => '勒', 63827 => '肋', 63828 => '凜', 63829 => '凌', 63830 => '稜', 63831 => '綾', 63832 => '菱', 63833 => '陵', 63834 => '讀', 63835 => '拏', 63836 => '樂', 63837 => '諾', 63838 => '丹', 63839 => '寧', 63840 => '怒', 63841 => '率', 63842 => '異', 63843 => '北', 63844 => '磻', 63845 => '便', 63846 => '復', 63847 => '不', 63848 => '泌', 63849 => '數', 63850 => '索', 63851 => '參', 63852 => '塞', 63853 => '省', 63854 => '葉', 63855 => '說', 63856 => '殺', 63857 => '辰', 63858 => '沈', 63859 => '拾', 63860 => '若', 63861 => '掠', 63862 => '略', 63863 => '亮', 63864 => '兩', 63865 => '凉', 63866 => '梁', 63867 => '糧', 63868 => '良', 63869 => '諒', 63870 => '量', 63871 => '勵', 63872 => '呂', 63873 => '女', 63874 => '廬', 63875 => '旅', 63876 => '濾', 63877 => '礪', 63878 => '閭', 63879 => '驪', 63880 => '麗', 63881 => '黎', 63882 => '力', 63883 => '曆', 63884 => '歷', 63885 => '轢', 63886 => '年', 63887 => '憐', 63888 => '戀', 63889 => '撚', 63890 => '漣', 63891 => '煉', 63892 => '璉', 63893 => '秊', 63894 => '練', 63895 => '聯', 63896 => '輦', 63897 => '蓮', 63898 => '連', 63899 => '鍊', 63900 => '列', 63901 => '劣', 63902 => '咽', 63903 => '烈', 63904 => '裂', 63905 => '說', 63906 => '廉', 63907 => '念', 63908 => '捻', 63909 => '殮', 63910 => '簾', 63911 => '獵', 63912 => '令', 63913 => '囹', 63914 => '寧', 63915 => '嶺', 63916 => '怜', 63917 => '玲', 63918 => '瑩', 63919 => '羚', 63920 => '聆', 63921 => '鈴', 63922 => '零', 63923 => '靈', 63924 => '領', 63925 => '例', 63926 => '禮', 63927 => '醴', 63928 => '隸', 63929 => '惡', 63930 => '了', 63931 => '僚', 63932 => '寮', 63933 => '尿', 63934 => '料', 63935 => '樂', 63936 => '燎', 63937 => '療', 63938 => '蓼', 63939 => '遼', 63940 => '龍', 63941 => '暈', 63942 => '阮', 63943 => '劉', 63944 => '杻', 63945 => '柳', 63946 => '流', 63947 => '溜', 63948 => '琉', 63949 => '留', 63950 => '硫', 63951 => '紐', 63952 => '類', 63953 => '六', 63954 => '戮', 63955 => '陸', 63956 => '倫', 63957 => '崙', 63958 => '淪', 63959 => '輪', 63960 => '律', 63961 => '慄', 63962 => '栗', 63963 => '率', 63964 => '隆', 63965 => '利', 63966 => '吏', 63967 => '履', 63968 => '易', 63969 => '李', 63970 => '梨', 63971 => '泥', 63972 => '理', 63973 => '痢', 63974 => '罹', 63975 => '裏', 63976 => '裡', 63977 => '里', 63978 => '離', 63979 => '匿', 63980 => '溺', 63981 => '吝', 63982 => '燐', 63983 => '璘', 63984 => '藺', 63985 => '隣', 63986 => '鱗', 63987 => '麟', 63988 => '林', 63989 => '淋', 63990 => '臨', 63991 => '立', 63992 => '笠', 63993 => '粒', 63994 => '狀', 63995 => '炙', 63996 => '識', 63997 => '什', 63998 => '茶', 63999 => '刺', 64000 => '切', 64001 => '度', 64002 => '拓', 64003 => '糖', 64004 => '宅', 64005 => '洞', 64006 => '暴', 64007 => '輻', 64008 => '行', 64009 => '降', 64010 => '見', 64011 => '廓', 64012 => '兀', 64013 => '嗀', 64016 => '塚', 64018 => '晴', 64021 => '凞', 64022 => '猪', 64023 => '益', 64024 => '礼', 64025 => '神', 64026 => '祥', 64027 => '福', 64028 => '靖', 64029 => '精', 64030 => '羽', 64032 => '蘒', 64034 => '諸', 64037 => '逸', 64038 => '都', 64042 => '飯', 64043 => '飼', 64044 => '館', 64045 => '鶴', 64046 => '郞', 64047 => '隷', 64048 => '侮', 64049 => '僧', 64050 => '免', 64051 => '勉', 64052 => '勤', 64053 => '卑', 64054 => '喝', 64055 => '嘆', 64056 => '器', 64057 => '塀', 64058 => '墨', 64059 => '層', 64060 => '屮', 64061 => '悔', 64062 => '慨', 64063 => '憎', 64064 => '懲', 64065 => '敏', 64066 => '既', 64067 => '暑', 64068 => '梅', 64069 => '海', 64070 => '渚', 64071 => '漢', 64072 => '煮', 64073 => '爫', 64074 => '琢', 64075 => '碑', 64076 => '社', 64077 => '祉', 64078 => '祈', 64079 => '祐', 64080 => '祖', 64081 => '祝', 64082 => '禍', 64083 => '禎', 64084 => '穀', 64085 => '突', 64086 => '節', 64087 => '練', 64088 => '縉', 64089 => '繁', 64090 => '署', 64091 => '者', 64092 => '臭', 64093 => '艹', 64094 => '艹', 64095 => '著', 64096 => '褐', 64097 => '視', 64098 => '謁', 64099 => '謹', 64100 => '賓', 64101 => '贈', 64102 => '辶', 64103 => '逸', 64104 => '難', 64105 => '響', 64106 => '頻', 64107 => '恵', 64108 => '𤋮', 64109 => '舘', 64112 => '並', 64113 => '况', 64114 => '全', 64115 => '侀', 64116 => '充', 64117 => '冀', 64118 => '勇', 64119 => '勺', 64120 => '喝', 64121 => '啕', 64122 => '喙', 64123 => '嗢', 64124 => '塚', 64125 => '墳', 64126 => '奄', 64127 => '奔', 64128 => '婢', 64129 => '嬨', 64130 => '廒', 64131 => '廙', 64132 => '彩', 64133 => '徭', 64134 => '惘', 64135 => '慎', 64136 => '愈', 64137 => '憎', 64138 => '慠', 64139 => '懲', 64140 => '戴', 64141 => '揄', 64142 => '搜', 64143 => '摒', 64144 => '敖', 64145 => '晴', 64146 => '朗', 64147 => '望', 64148 => '杖', 64149 => '歹', 64150 => '殺', 64151 => '流', 64152 => '滛', 64153 => '滋', 64154 => '漢', 64155 => '瀞', 64156 => '煮', 64157 => '瞧', 64158 => '爵', 64159 => '犯', 64160 => '猪', 64161 => '瑱', 64162 => '甆', 64163 => '画', 64164 => '瘝', 64165 => '瘟', 64166 => '益', 64167 => '盛', 64168 => '直', 64169 => '睊', 64170 => '着', 64171 => '磌', 64172 => '窱', 64173 => '節', 64174 => '类', 64175 => '絛', 64176 => '練', 64177 => '缾', 64178 => '者', 64179 => '荒', 64180 => '華', 64181 => '蝹', 64182 => '襁', 64183 => '覆', 64184 => '視', 64185 => '調', 64186 => '諸', 64187 => '請', 64188 => '謁', 64189 => '諾', 64190 => '諭', 64191 => '謹', 64192 => '變', 64193 => '贈', 64194 => '輸', 64195 => '遲', 64196 => '醙', 64197 => '鉶', 64198 => '陼', 64199 => '難', 64200 => '靖', 64201 => '韛', 64202 => '響', 64203 => '頋', 64204 => '頻', 64205 => '鬒', 64206 => '龜', 64207 => '𢡊', 64208 => '𢡄', 64209 => '𣏕', 64210 => '㮝', 64211 => '䀘', 64212 => '䀹', 64213 => '𥉉', 64214 => '𥳐', 64215 => '𧻓', 64216 => '齃', 64217 => '龎', 64256 => 'ff', 64257 => 'fi', 64258 => 'fl', 64259 => 'ffi', 64260 => 'ffl', 64261 => 'st', 64262 => 'st', 64275 => 'մն', 64276 => 'մե', 64277 => 'մի', 64278 => 'վն', 64279 => 'մխ', 64285 => 'יִ', 64287 => 'ײַ', 64288 => 'ע', 64289 => 'א', 64290 => 'ד', 64291 => 'ה', 64292 => 'כ', 64293 => 'ל', 64294 => 'ם', 64295 => 'ר', 64296 => 'ת', 64298 => 'שׁ', 64299 => 'שׂ', 64300 => 'שּׁ', 64301 => 'שּׂ', 64302 => 'אַ', 64303 => 'אָ', 64304 => 'אּ', 64305 => 'בּ', 64306 => 'גּ', 64307 => 'דּ', 64308 => 'הּ', 64309 => 'וּ', 64310 => 'זּ', 64312 => 'טּ', 64313 => 'יּ', 64314 => 'ךּ', 64315 => 'כּ', 64316 => 'לּ', 64318 => 'מּ', 64320 => 'נּ', 64321 => 'סּ', 64323 => 'ףּ', 64324 => 'פּ', 64326 => 'צּ', 64327 => 'קּ', 64328 => 'רּ', 64329 => 'שּ', 64330 => 'תּ', 64331 => 'וֹ', 64332 => 'בֿ', 64333 => 'כֿ', 64334 => 'פֿ', 64335 => 'אל', 64336 => 'ٱ', 64337 => 'ٱ', 64338 => 'ٻ', 64339 => 'ٻ', 64340 => 'ٻ', 64341 => 'ٻ', 64342 => 'پ', 64343 => 'پ', 64344 => 'پ', 64345 => 'پ', 64346 => 'ڀ', 64347 => 'ڀ', 64348 => 'ڀ', 64349 => 'ڀ', 64350 => 'ٺ', 64351 => 'ٺ', 64352 => 'ٺ', 64353 => 'ٺ', 64354 => 'ٿ', 64355 => 'ٿ', 64356 => 'ٿ', 64357 => 'ٿ', 64358 => 'ٹ', 64359 => 'ٹ', 64360 => 'ٹ', 64361 => 'ٹ', 64362 => 'ڤ', 64363 => 'ڤ', 64364 => 'ڤ', 64365 => 'ڤ', 64366 => 'ڦ', 64367 => 'ڦ', 64368 => 'ڦ', 64369 => 'ڦ', 64370 => 'ڄ', 64371 => 'ڄ', 64372 => 'ڄ', 64373 => 'ڄ', 64374 => 'ڃ', 64375 => 'ڃ', 64376 => 'ڃ', 64377 => 'ڃ', 64378 => 'چ', 64379 => 'چ', 64380 => 'چ', 64381 => 'چ', 64382 => 'ڇ', 64383 => 'ڇ', 64384 => 'ڇ', 64385 => 'ڇ', 64386 => 'ڍ', 64387 => 'ڍ', 64388 => 'ڌ', 64389 => 'ڌ', 64390 => 'ڎ', 64391 => 'ڎ', 64392 => 'ڈ', 64393 => 'ڈ', 64394 => 'ژ', 64395 => 'ژ', 64396 => 'ڑ', 64397 => 'ڑ', 64398 => 'ک', 64399 => 'ک', 64400 => 'ک', 64401 => 'ک', 64402 => 'گ', 64403 => 'گ', 64404 => 'گ', 64405 => 'گ', 64406 => 'ڳ', 64407 => 'ڳ', 64408 => 'ڳ', 64409 => 'ڳ', 64410 => 'ڱ', 64411 => 'ڱ', 64412 => 'ڱ', 64413 => 'ڱ', 64414 => 'ں', 64415 => 'ں', 64416 => 'ڻ', 64417 => 'ڻ', 64418 => 'ڻ', 64419 => 'ڻ', 64420 => 'ۀ', 64421 => 'ۀ', 64422 => 'ہ', 64423 => 'ہ', 64424 => 'ہ', 64425 => 'ہ', 64426 => 'ھ', 64427 => 'ھ', 64428 => 'ھ', 64429 => 'ھ', 64430 => 'ے', 64431 => 'ے', 64432 => 'ۓ', 64433 => 'ۓ', 64467 => 'ڭ', 64468 => 'ڭ', 64469 => 'ڭ', 64470 => 'ڭ', 64471 => 'ۇ', 64472 => 'ۇ', 64473 => 'ۆ', 64474 => 'ۆ', 64475 => 'ۈ', 64476 => 'ۈ', 64477 => 'ۇٴ', 64478 => 'ۋ', 64479 => 'ۋ', 64480 => 'ۅ', 64481 => 'ۅ', 64482 => 'ۉ', 64483 => 'ۉ', 64484 => 'ې', 64485 => 'ې', 64486 => 'ې', 64487 => 'ې', 64488 => 'ى', 64489 => 'ى', 64490 => 'ئا', 64491 => 'ئا', 64492 => 'ئە', 64493 => 'ئە', 64494 => 'ئو', 64495 => 'ئو', 64496 => 'ئۇ', 64497 => 'ئۇ', 64498 => 'ئۆ', 64499 => 'ئۆ', 64500 => 'ئۈ', 64501 => 'ئۈ', 64502 => 'ئې', 64503 => 'ئې', 64504 => 'ئې', 64505 => 'ئى', 64506 => 'ئى', 64507 => 'ئى', 64508 => 'ی', 64509 => 'ی', 64510 => 'ی', 64511 => 'ی', 64512 => 'ئج', 64513 => 'ئح', 64514 => 'ئم', 64515 => 'ئى', 64516 => 'ئي', 64517 => 'بج', 64518 => 'بح', 64519 => 'بخ', 64520 => 'بم', 64521 => 'بى', 64522 => 'بي', 64523 => 'تج', 64524 => 'تح', 64525 => 'تخ', 64526 => 'تم', 64527 => 'تى', 64528 => 'تي', 64529 => 'ثج', 64530 => 'ثم', 64531 => 'ثى', 64532 => 'ثي', 64533 => 'جح', 64534 => 'جم', 64535 => 'حج', 64536 => 'حم', 64537 => 'خج', 64538 => 'خح', 64539 => 'خم', 64540 => 'سج', 64541 => 'سح', 64542 => 'سخ', 64543 => 'سم', 64544 => 'صح', 64545 => 'صم', 64546 => 'ضج', 64547 => 'ضح', 64548 => 'ضخ', 64549 => 'ضم', 64550 => 'طح', 64551 => 'طم', 64552 => 'ظم', 64553 => 'عج', 64554 => 'عم', 64555 => 'غج', 64556 => 'غم', 64557 => 'فج', 64558 => 'فح', 64559 => 'فخ', 64560 => 'فم', 64561 => 'فى', 64562 => 'في', 64563 => 'قح', 64564 => 'قم', 64565 => 'قى', 64566 => 'قي', 64567 => 'كا', 64568 => 'كج', 64569 => 'كح', 64570 => 'كخ', 64571 => 'كل', 64572 => 'كم', 64573 => 'كى', 64574 => 'كي', 64575 => 'لج', 64576 => 'لح', 64577 => 'لخ', 64578 => 'لم', 64579 => 'لى', 64580 => 'لي', 64581 => 'مج', 64582 => 'مح', 64583 => 'مخ', 64584 => 'مم', 64585 => 'مى', 64586 => 'مي', 64587 => 'نج', 64588 => 'نح', 64589 => 'نخ', 64590 => 'نم', 64591 => 'نى', 64592 => 'ني', 64593 => 'هج', 64594 => 'هم', 64595 => 'هى', 64596 => 'هي', 64597 => 'يج', 64598 => 'يح', 64599 => 'يخ', 64600 => 'يم', 64601 => 'يى', 64602 => 'يي', 64603 => 'ذٰ', 64604 => 'رٰ', 64605 => 'ىٰ', 64612 => 'ئر', 64613 => 'ئز', 64614 => 'ئم', 64615 => 'ئن', 64616 => 'ئى', 64617 => 'ئي', 64618 => 'بر', 64619 => 'بز', 64620 => 'بم', 64621 => 'بن', 64622 => 'بى', 64623 => 'بي', 64624 => 'تر', 64625 => 'تز', 64626 => 'تم', 64627 => 'تن', 64628 => 'تى', 64629 => 'تي', 64630 => 'ثر', 64631 => 'ثز', 64632 => 'ثم', 64633 => 'ثن', 64634 => 'ثى', 64635 => 'ثي', 64636 => 'فى', 64637 => 'في', 64638 => 'قى', 64639 => 'قي', 64640 => 'كا', 64641 => 'كل', 64642 => 'كم', 64643 => 'كى', 64644 => 'كي', 64645 => 'لم', 64646 => 'لى', 64647 => 'لي', 64648 => 'ما', 64649 => 'مم', 64650 => 'نر', 64651 => 'نز', 64652 => 'نم', 64653 => 'نن', 64654 => 'نى', 64655 => 'ني', 64656 => 'ىٰ', 64657 => 'ير', 64658 => 'يز', 64659 => 'يم', 64660 => 'ين', 64661 => 'يى', 64662 => 'يي', 64663 => 'ئج', 64664 => 'ئح', 64665 => 'ئخ', 64666 => 'ئم', 64667 => 'ئه', 64668 => 'بج', 64669 => 'بح', 64670 => 'بخ', 64671 => 'بم', 64672 => 'به', 64673 => 'تج', 64674 => 'تح', 64675 => 'تخ', 64676 => 'تم', 64677 => 'ته', 64678 => 'ثم', 64679 => 'جح', 64680 => 'جم', 64681 => 'حج', 64682 => 'حم', 64683 => 'خج', 64684 => 'خم', 64685 => 'سج', 64686 => 'سح', 64687 => 'سخ', 64688 => 'سم', 64689 => 'صح', 64690 => 'صخ', 64691 => 'صم', 64692 => 'ضج', 64693 => 'ضح', 64694 => 'ضخ', 64695 => 'ضم', 64696 => 'طح', 64697 => 'ظم', 64698 => 'عج', 64699 => 'عم', 64700 => 'غج', 64701 => 'غم', 64702 => 'فج', 64703 => 'فح', 64704 => 'فخ', 64705 => 'فم', 64706 => 'قح', 64707 => 'قم', 64708 => 'كج', 64709 => 'كح', 64710 => 'كخ', 64711 => 'كل', 64712 => 'كم', 64713 => 'لج', 64714 => 'لح', 64715 => 'لخ', 64716 => 'لم', 64717 => 'له', 64718 => 'مج', 64719 => 'مح', 64720 => 'مخ', 64721 => 'مم', 64722 => 'نج', 64723 => 'نح', 64724 => 'نخ', 64725 => 'نم', 64726 => 'نه', 64727 => 'هج', 64728 => 'هم', 64729 => 'هٰ', 64730 => 'يج', 64731 => 'يح', 64732 => 'يخ', 64733 => 'يم', 64734 => 'يه', 64735 => 'ئم', 64736 => 'ئه', 64737 => 'بم', 64738 => 'به', 64739 => 'تم', 64740 => 'ته', 64741 => 'ثم', 64742 => 'ثه', 64743 => 'سم', 64744 => 'سه', 64745 => 'شم', 64746 => 'شه', 64747 => 'كل', 64748 => 'كم', 64749 => 'لم', 64750 => 'نم', 64751 => 'نه', 64752 => 'يم', 64753 => 'يه', 64754 => 'ـَّ', 64755 => 'ـُّ', 64756 => 'ـِّ', 64757 => 'طى', 64758 => 'طي', 64759 => 'عى', 64760 => 'عي', 64761 => 'غى', 64762 => 'غي', 64763 => 'سى', 64764 => 'سي', 64765 => 'شى', 64766 => 'شي', 64767 => 'حى', 64768 => 'حي', 64769 => 'جى', 64770 => 'جي', 64771 => 'خى', 64772 => 'خي', 64773 => 'صى', 64774 => 'صي', 64775 => 'ضى', 64776 => 'ضي', 64777 => 'شج', 64778 => 'شح', 64779 => 'شخ', 64780 => 'شم', 64781 => 'شر', 64782 => 'سر', 64783 => 'صر', 64784 => 'ضر', 64785 => 'طى', 64786 => 'طي', 64787 => 'عى', 64788 => 'عي', 64789 => 'غى', 64790 => 'غي', 64791 => 'سى', 64792 => 'سي', 64793 => 'شى', 64794 => 'شي', 64795 => 'حى', 64796 => 'حي', 64797 => 'جى', 64798 => 'جي', 64799 => 'خى', 64800 => 'خي', 64801 => 'صى', 64802 => 'صي', 64803 => 'ضى', 64804 => 'ضي', 64805 => 'شج', 64806 => 'شح', 64807 => 'شخ', 64808 => 'شم', 64809 => 'شر', 64810 => 'سر', 64811 => 'صر', 64812 => 'ضر', 64813 => 'شج', 64814 => 'شح', 64815 => 'شخ', 64816 => 'شم', 64817 => 'سه', 64818 => 'شه', 64819 => 'طم', 64820 => 'سج', 64821 => 'سح', 64822 => 'سخ', 64823 => 'شج', 64824 => 'شح', 64825 => 'شخ', 64826 => 'طم', 64827 => 'ظم', 64828 => 'اً', 64829 => 'اً', 64848 => 'تجم', 64849 => 'تحج', 64850 => 'تحج', 64851 => 'تحم', 64852 => 'تخم', 64853 => 'تمج', 64854 => 'تمح', 64855 => 'تمخ', 64856 => 'جمح', 64857 => 'جمح', 64858 => 'حمي', 64859 => 'حمى', 64860 => 'سحج', 64861 => 'سجح', 64862 => 'سجى', 64863 => 'سمح', 64864 => 'سمح', 64865 => 'سمج', 64866 => 'سمم', 64867 => 'سمم', 64868 => 'صحح', 64869 => 'صحح', 64870 => 'صمم', 64871 => 'شحم', 64872 => 'شحم', 64873 => 'شجي', 64874 => 'شمخ', 64875 => 'شمخ', 64876 => 'شمم', 64877 => 'شمم', 64878 => 'ضحى', 64879 => 'ضخم', 64880 => 'ضخم', 64881 => 'طمح', 64882 => 'طمح', 64883 => 'طمم', 64884 => 'طمي', 64885 => 'عجم', 64886 => 'عمم', 64887 => 'عمم', 64888 => 'عمى', 64889 => 'غمم', 64890 => 'غمي', 64891 => 'غمى', 64892 => 'فخم', 64893 => 'فخم', 64894 => 'قمح', 64895 => 'قمم', 64896 => 'لحم', 64897 => 'لحي', 64898 => 'لحى', 64899 => 'لجج', 64900 => 'لجج', 64901 => 'لخم', 64902 => 'لخم', 64903 => 'لمح', 64904 => 'لمح', 64905 => 'محج', 64906 => 'محم', 64907 => 'محي', 64908 => 'مجح', 64909 => 'مجم', 64910 => 'مخج', 64911 => 'مخم', 64914 => 'مجخ', 64915 => 'همج', 64916 => 'همم', 64917 => 'نحم', 64918 => 'نحى', 64919 => 'نجم', 64920 => 'نجم', 64921 => 'نجى', 64922 => 'نمي', 64923 => 'نمى', 64924 => 'يمم', 64925 => 'يمم', 64926 => 'بخي', 64927 => 'تجي', 64928 => 'تجى', 64929 => 'تخي', 64930 => 'تخى', 64931 => 'تمي', 64932 => 'تمى', 64933 => 'جمي', 64934 => 'جحى', 64935 => 'جمى', 64936 => 'سخى', 64937 => 'صحي', 64938 => 'شحي', 64939 => 'ضحي', 64940 => 'لجي', 64941 => 'لمي', 64942 => 'يحي', 64943 => 'يجي', 64944 => 'يمي', 64945 => 'ممي', 64946 => 'قمي', 64947 => 'نحي', 64948 => 'قمح', 64949 => 'لحم', 64950 => 'عمي', 64951 => 'كمي', 64952 => 'نجح', 64953 => 'مخي', 64954 => 'لجم', 64955 => 'كمم', 64956 => 'لجم', 64957 => 'نجح', 64958 => 'جحي', 64959 => 'حجي', 64960 => 'مجي', 64961 => 'فمي', 64962 => 'بحي', 64963 => 'كمم', 64964 => 'عجم', 64965 => 'صمم', 64966 => 'سخي', 64967 => 'نجي', 65008 => 'صلے', 65009 => 'قلے', 65010 => 'الله', 65011 => 'اكبر', 65012 => 'محمد', 65013 => 'صلعم', 65014 => 'رسول', 65015 => 'عليه', 65016 => 'وسلم', 65017 => 'صلى', 65020 => 'ریال', 65041 => '、', 65047 => '〖', 65048 => '〗', 65073 => '—', 65074 => '–', 65081 => '〔', 65082 => '〕', 65083 => '【', 65084 => '】', 65085 => '《', 65086 => '》', 65087 => '〈', 65088 => '〉', 65089 => '「', 65090 => '」', 65091 => '『', 65092 => '』', 65105 => '、', 65112 => '—', 65117 => '〔', 65118 => '〕', 65123 => '-', 65137 => 'ـً', 65143 => 'ـَ', 65145 => 'ـُ', 65147 => 'ـِ', 65149 => 'ـّ', 65151 => 'ـْ', 65152 => 'ء', 65153 => 'آ', 65154 => 'آ', 65155 => 'أ', 65156 => 'أ', 65157 => 'ؤ', 65158 => 'ؤ', 65159 => 'إ', 65160 => 'إ', 65161 => 'ئ', 65162 => 'ئ', 65163 => 'ئ', 65164 => 'ئ', 65165 => 'ا', 65166 => 'ا', 65167 => 'ب', 65168 => 'ب', 65169 => 'ب', 65170 => 'ب', 65171 => 'ة', 65172 => 'ة', 65173 => 'ت', 65174 => 'ت', 65175 => 'ت', 65176 => 'ت', 65177 => 'ث', 65178 => 'ث', 65179 => 'ث', 65180 => 'ث', 65181 => 'ج', 65182 => 'ج', 65183 => 'ج', 65184 => 'ج', 65185 => 'ح', 65186 => 'ح', 65187 => 'ح', 65188 => 'ح', 65189 => 'خ', 65190 => 'خ', 65191 => 'خ', 65192 => 'خ', 65193 => 'د', 65194 => 'د', 65195 => 'ذ', 65196 => 'ذ', 65197 => 'ر', 65198 => 'ر', 65199 => 'ز', 65200 => 'ز', 65201 => 'س', 65202 => 'س', 65203 => 'س', 65204 => 'س', 65205 => 'ش', 65206 => 'ش', 65207 => 'ش', 65208 => 'ش', 65209 => 'ص', 65210 => 'ص', 65211 => 'ص', 65212 => 'ص', 65213 => 'ض', 65214 => 'ض', 65215 => 'ض', 65216 => 'ض', 65217 => 'ط', 65218 => 'ط', 65219 => 'ط', 65220 => 'ط', 65221 => 'ظ', 65222 => 'ظ', 65223 => 'ظ', 65224 => 'ظ', 65225 => 'ع', 65226 => 'ع', 65227 => 'ع', 65228 => 'ع', 65229 => 'غ', 65230 => 'غ', 65231 => 'غ', 65232 => 'غ', 65233 => 'ف', 65234 => 'ف', 65235 => 'ف', 65236 => 'ف', 65237 => 'ق', 65238 => 'ق', 65239 => 'ق', 65240 => 'ق', 65241 => 'ك', 65242 => 'ك', 65243 => 'ك', 65244 => 'ك', 65245 => 'ل', 65246 => 'ل', 65247 => 'ل', 65248 => 'ل', 65249 => 'م', 65250 => 'م', 65251 => 'م', 65252 => 'م', 65253 => 'ن', 65254 => 'ن', 65255 => 'ن', 65256 => 'ن', 65257 => 'ه', 65258 => 'ه', 65259 => 'ه', 65260 => 'ه', 65261 => 'و', 65262 => 'و', 65263 => 'ى', 65264 => 'ى', 65265 => 'ي', 65266 => 'ي', 65267 => 'ي', 65268 => 'ي', 65269 => 'لآ', 65270 => 'لآ', 65271 => 'لأ', 65272 => 'لأ', 65273 => 'لإ', 65274 => 'لإ', 65275 => 'لا', 65276 => 'لا', 65293 => '-', 65294 => '.', 65296 => '0', 65297 => '1', 65298 => '2', 65299 => '3', 65300 => '4', 65301 => '5', 65302 => '6', 65303 => '7', 65304 => '8', 65305 => '9', 65313 => 'a', 65314 => 'b', 65315 => 'c', 65316 => 'd', 65317 => 'e', 65318 => 'f', 65319 => 'g', 65320 => 'h', 65321 => 'i', 65322 => 'j', 65323 => 'k', 65324 => 'l', 65325 => 'm', 65326 => 'n', 65327 => 'o', 65328 => 'p', 65329 => 'q', 65330 => 'r', 65331 => 's', 65332 => 't', 65333 => 'u', 65334 => 'v', 65335 => 'w', 65336 => 'x', 65337 => 'y', 65338 => 'z', 65345 => 'a', 65346 => 'b', 65347 => 'c', 65348 => 'd', 65349 => 'e', 65350 => 'f', 65351 => 'g', 65352 => 'h', 65353 => 'i', 65354 => 'j', 65355 => 'k', 65356 => 'l', 65357 => 'm', 65358 => 'n', 65359 => 'o', 65360 => 'p', 65361 => 'q', 65362 => 'r', 65363 => 's', 65364 => 't', 65365 => 'u', 65366 => 'v', 65367 => 'w', 65368 => 'x', 65369 => 'y', 65370 => 'z', 65375 => '⦅', 65376 => '⦆', 65377 => '.', 65378 => '「', 65379 => '」', 65380 => '、', 65381 => '・', 65382 => 'ヲ', 65383 => 'ァ', 65384 => 'ィ', 65385 => 'ゥ', 65386 => 'ェ', 65387 => 'ォ', 65388 => 'ャ', 65389 => 'ュ', 65390 => 'ョ', 65391 => 'ッ', 65392 => 'ー', 65393 => 'ア', 65394 => 'イ', 65395 => 'ウ', 65396 => 'エ', 65397 => 'オ', 65398 => 'カ', 65399 => 'キ', 65400 => 'ク', 65401 => 'ケ', 65402 => 'コ', 65403 => 'サ', 65404 => 'シ', 65405 => 'ス', 65406 => 'セ', 65407 => 'ソ', 65408 => 'タ', 65409 => 'チ', 65410 => 'ツ', 65411 => 'テ', 65412 => 'ト', 65413 => 'ナ', 65414 => 'ニ', 65415 => 'ヌ', 65416 => 'ネ', 65417 => 'ノ', 65418 => 'ハ', 65419 => 'ヒ', 65420 => 'フ', 65421 => 'ヘ', 65422 => 'ホ', 65423 => 'マ', 65424 => 'ミ', 65425 => 'ム', 65426 => 'メ', 65427 => 'モ', 65428 => 'ヤ', 65429 => 'ユ', 65430 => 'ヨ', 65431 => 'ラ', 65432 => 'リ', 65433 => 'ル', 65434 => 'レ', 65435 => 'ロ', 65436 => 'ワ', 65437 => 'ン', 65438 => '゙', 65439 => '゚', 65441 => 'ᄀ', 65442 => 'ᄁ', 65443 => 'ᆪ', 65444 => 'ᄂ', 65445 => 'ᆬ', 65446 => 'ᆭ', 65447 => 'ᄃ', 65448 => 'ᄄ', 65449 => 'ᄅ', 65450 => 'ᆰ', 65451 => 'ᆱ', 65452 => 'ᆲ', 65453 => 'ᆳ', 65454 => 'ᆴ', 65455 => 'ᆵ', 65456 => 'ᄚ', 65457 => 'ᄆ', 65458 => 'ᄇ', 65459 => 'ᄈ', 65460 => 'ᄡ', 65461 => 'ᄉ', 65462 => 'ᄊ', 65463 => 'ᄋ', 65464 => 'ᄌ', 65465 => 'ᄍ', 65466 => 'ᄎ', 65467 => 'ᄏ', 65468 => 'ᄐ', 65469 => 'ᄑ', 65470 => 'ᄒ', 65474 => 'ᅡ', 65475 => 'ᅢ', 65476 => 'ᅣ', 65477 => 'ᅤ', 65478 => 'ᅥ', 65479 => 'ᅦ', 65482 => 'ᅧ', 65483 => 'ᅨ', 65484 => 'ᅩ', 65485 => 'ᅪ', 65486 => 'ᅫ', 65487 => 'ᅬ', 65490 => 'ᅭ', 65491 => 'ᅮ', 65492 => 'ᅯ', 65493 => 'ᅰ', 65494 => 'ᅱ', 65495 => 'ᅲ', 65498 => 'ᅳ', 65499 => 'ᅴ', 65500 => 'ᅵ', 65504 => '¢', 65505 => '£', 65506 => '¬', 65508 => '¦', 65509 => '¥', 65510 => '₩', 65512 => '│', 65513 => '←', 65514 => '↑', 65515 => '→', 65516 => '↓', 65517 => '■', 65518 => '○', 66560 => '𐐨', 66561 => '𐐩', 66562 => '𐐪', 66563 => '𐐫', 66564 => '𐐬', 66565 => '𐐭', 66566 => '𐐮', 66567 => '𐐯', 66568 => '𐐰', 66569 => '𐐱', 66570 => '𐐲', 66571 => '𐐳', 66572 => '𐐴', 66573 => '𐐵', 66574 => '𐐶', 66575 => '𐐷', 66576 => '𐐸', 66577 => '𐐹', 66578 => '𐐺', 66579 => '𐐻', 66580 => '𐐼', 66581 => '𐐽', 66582 => '𐐾', 66583 => '𐐿', 66584 => '𐑀', 66585 => '𐑁', 66586 => '𐑂', 66587 => '𐑃', 66588 => '𐑄', 66589 => '𐑅', 66590 => '𐑆', 66591 => '𐑇', 66592 => '𐑈', 66593 => '𐑉', 66594 => '𐑊', 66595 => '𐑋', 66596 => '𐑌', 66597 => '𐑍', 66598 => '𐑎', 66599 => '𐑏', 66736 => '𐓘', 66737 => '𐓙', 66738 => '𐓚', 66739 => '𐓛', 66740 => '𐓜', 66741 => '𐓝', 66742 => '𐓞', 66743 => '𐓟', 66744 => '𐓠', 66745 => '𐓡', 66746 => '𐓢', 66747 => '𐓣', 66748 => '𐓤', 66749 => '𐓥', 66750 => '𐓦', 66751 => '𐓧', 66752 => '𐓨', 66753 => '𐓩', 66754 => '𐓪', 66755 => '𐓫', 66756 => '𐓬', 66757 => '𐓭', 66758 => '𐓮', 66759 => '𐓯', 66760 => '𐓰', 66761 => '𐓱', 66762 => '𐓲', 66763 => '𐓳', 66764 => '𐓴', 66765 => '𐓵', 66766 => '𐓶', 66767 => '𐓷', 66768 => '𐓸', 66769 => '𐓹', 66770 => '𐓺', 66771 => '𐓻', 68736 => '𐳀', 68737 => '𐳁', 68738 => '𐳂', 68739 => '𐳃', 68740 => '𐳄', 68741 => '𐳅', 68742 => '𐳆', 68743 => '𐳇', 68744 => '𐳈', 68745 => '𐳉', 68746 => '𐳊', 68747 => '𐳋', 68748 => '𐳌', 68749 => '𐳍', 68750 => '𐳎', 68751 => '𐳏', 68752 => '𐳐', 68753 => '𐳑', 68754 => '𐳒', 68755 => '𐳓', 68756 => '𐳔', 68757 => '𐳕', 68758 => '𐳖', 68759 => '𐳗', 68760 => '𐳘', 68761 => '𐳙', 68762 => '𐳚', 68763 => '𐳛', 68764 => '𐳜', 68765 => '𐳝', 68766 => '𐳞', 68767 => '𐳟', 68768 => '𐳠', 68769 => '𐳡', 68770 => '𐳢', 68771 => '𐳣', 68772 => '𐳤', 68773 => '𐳥', 68774 => '𐳦', 68775 => '𐳧', 68776 => '𐳨', 68777 => '𐳩', 68778 => '𐳪', 68779 => '𐳫', 68780 => '𐳬', 68781 => '𐳭', 68782 => '𐳮', 68783 => '𐳯', 68784 => '𐳰', 68785 => '𐳱', 68786 => '𐳲', 71840 => '𑣀', 71841 => '𑣁', 71842 => '𑣂', 71843 => '𑣃', 71844 => '𑣄', 71845 => '𑣅', 71846 => '𑣆', 71847 => '𑣇', 71848 => '𑣈', 71849 => '𑣉', 71850 => '𑣊', 71851 => '𑣋', 71852 => '𑣌', 71853 => '𑣍', 71854 => '𑣎', 71855 => '𑣏', 71856 => '𑣐', 71857 => '𑣑', 71858 => '𑣒', 71859 => '𑣓', 71860 => '𑣔', 71861 => '𑣕', 71862 => '𑣖', 71863 => '𑣗', 71864 => '𑣘', 71865 => '𑣙', 71866 => '𑣚', 71867 => '𑣛', 71868 => '𑣜', 71869 => '𑣝', 71870 => '𑣞', 71871 => '𑣟', 93760 => '𖹠', 93761 => '𖹡', 93762 => '𖹢', 93763 => '𖹣', 93764 => '𖹤', 93765 => '𖹥', 93766 => '𖹦', 93767 => '𖹧', 93768 => '𖹨', 93769 => '𖹩', 93770 => '𖹪', 93771 => '𖹫', 93772 => '𖹬', 93773 => '𖹭', 93774 => '𖹮', 93775 => '𖹯', 93776 => '𖹰', 93777 => '𖹱', 93778 => '𖹲', 93779 => '𖹳', 93780 => '𖹴', 93781 => '𖹵', 93782 => '𖹶', 93783 => '𖹷', 93784 => '𖹸', 93785 => '𖹹', 93786 => '𖹺', 93787 => '𖹻', 93788 => '𖹼', 93789 => '𖹽', 93790 => '𖹾', 93791 => '𖹿', 119134 => '𝅗𝅥', 119135 => '𝅘𝅥', 119136 => '𝅘𝅥𝅮', 119137 => '𝅘𝅥𝅯', 119138 => '𝅘𝅥𝅰', 119139 => '𝅘𝅥𝅱', 119140 => '𝅘𝅥𝅲', 119227 => '𝆹𝅥', 119228 => '𝆺𝅥', 119229 => '𝆹𝅥𝅮', 119230 => '𝆺𝅥𝅮', 119231 => '𝆹𝅥𝅯', 119232 => '𝆺𝅥𝅯', 119808 => 'a', 119809 => 'b', 119810 => 'c', 119811 => 'd', 119812 => 'e', 119813 => 'f', 119814 => 'g', 119815 => 'h', 119816 => 'i', 119817 => 'j', 119818 => 'k', 119819 => 'l', 119820 => 'm', 119821 => 'n', 119822 => 'o', 119823 => 'p', 119824 => 'q', 119825 => 'r', 119826 => 's', 119827 => 't', 119828 => 'u', 119829 => 'v', 119830 => 'w', 119831 => 'x', 119832 => 'y', 119833 => 'z', 119834 => 'a', 119835 => 'b', 119836 => 'c', 119837 => 'd', 119838 => 'e', 119839 => 'f', 119840 => 'g', 119841 => 'h', 119842 => 'i', 119843 => 'j', 119844 => 'k', 119845 => 'l', 119846 => 'm', 119847 => 'n', 119848 => 'o', 119849 => 'p', 119850 => 'q', 119851 => 'r', 119852 => 's', 119853 => 't', 119854 => 'u', 119855 => 'v', 119856 => 'w', 119857 => 'x', 119858 => 'y', 119859 => 'z', 119860 => 'a', 119861 => 'b', 119862 => 'c', 119863 => 'd', 119864 => 'e', 119865 => 'f', 119866 => 'g', 119867 => 'h', 119868 => 'i', 119869 => 'j', 119870 => 'k', 119871 => 'l', 119872 => 'm', 119873 => 'n', 119874 => 'o', 119875 => 'p', 119876 => 'q', 119877 => 'r', 119878 => 's', 119879 => 't', 119880 => 'u', 119881 => 'v', 119882 => 'w', 119883 => 'x', 119884 => 'y', 119885 => 'z', 119886 => 'a', 119887 => 'b', 119888 => 'c', 119889 => 'd', 119890 => 'e', 119891 => 'f', 119892 => 'g', 119894 => 'i', 119895 => 'j', 119896 => 'k', 119897 => 'l', 119898 => 'm', 119899 => 'n', 119900 => 'o', 119901 => 'p', 119902 => 'q', 119903 => 'r', 119904 => 's', 119905 => 't', 119906 => 'u', 119907 => 'v', 119908 => 'w', 119909 => 'x', 119910 => 'y', 119911 => 'z', 119912 => 'a', 119913 => 'b', 119914 => 'c', 119915 => 'd', 119916 => 'e', 119917 => 'f', 119918 => 'g', 119919 => 'h', 119920 => 'i', 119921 => 'j', 119922 => 'k', 119923 => 'l', 119924 => 'm', 119925 => 'n', 119926 => 'o', 119927 => 'p', 119928 => 'q', 119929 => 'r', 119930 => 's', 119931 => 't', 119932 => 'u', 119933 => 'v', 119934 => 'w', 119935 => 'x', 119936 => 'y', 119937 => 'z', 119938 => 'a', 119939 => 'b', 119940 => 'c', 119941 => 'd', 119942 => 'e', 119943 => 'f', 119944 => 'g', 119945 => 'h', 119946 => 'i', 119947 => 'j', 119948 => 'k', 119949 => 'l', 119950 => 'm', 119951 => 'n', 119952 => 'o', 119953 => 'p', 119954 => 'q', 119955 => 'r', 119956 => 's', 119957 => 't', 119958 => 'u', 119959 => 'v', 119960 => 'w', 119961 => 'x', 119962 => 'y', 119963 => 'z', 119964 => 'a', 119966 => 'c', 119967 => 'd', 119970 => 'g', 119973 => 'j', 119974 => 'k', 119977 => 'n', 119978 => 'o', 119979 => 'p', 119980 => 'q', 119982 => 's', 119983 => 't', 119984 => 'u', 119985 => 'v', 119986 => 'w', 119987 => 'x', 119988 => 'y', 119989 => 'z', 119990 => 'a', 119991 => 'b', 119992 => 'c', 119993 => 'd', 119995 => 'f', 119997 => 'h', 119998 => 'i', 119999 => 'j', 120000 => 'k', 120001 => 'l', 120002 => 'm', 120003 => 'n', 120005 => 'p', 120006 => 'q', 120007 => 'r', 120008 => 's', 120009 => 't', 120010 => 'u', 120011 => 'v', 120012 => 'w', 120013 => 'x', 120014 => 'y', 120015 => 'z', 120016 => 'a', 120017 => 'b', 120018 => 'c', 120019 => 'd', 120020 => 'e', 120021 => 'f', 120022 => 'g', 120023 => 'h', 120024 => 'i', 120025 => 'j', 120026 => 'k', 120027 => 'l', 120028 => 'm', 120029 => 'n', 120030 => 'o', 120031 => 'p', 120032 => 'q', 120033 => 'r', 120034 => 's', 120035 => 't', 120036 => 'u', 120037 => 'v', 120038 => 'w', 120039 => 'x', 120040 => 'y', 120041 => 'z', 120042 => 'a', 120043 => 'b', 120044 => 'c', 120045 => 'd', 120046 => 'e', 120047 => 'f', 120048 => 'g', 120049 => 'h', 120050 => 'i', 120051 => 'j', 120052 => 'k', 120053 => 'l', 120054 => 'm', 120055 => 'n', 120056 => 'o', 120057 => 'p', 120058 => 'q', 120059 => 'r', 120060 => 's', 120061 => 't', 120062 => 'u', 120063 => 'v', 120064 => 'w', 120065 => 'x', 120066 => 'y', 120067 => 'z', 120068 => 'a', 120069 => 'b', 120071 => 'd', 120072 => 'e', 120073 => 'f', 120074 => 'g', 120077 => 'j', 120078 => 'k', 120079 => 'l', 120080 => 'm', 120081 => 'n', 120082 => 'o', 120083 => 'p', 120084 => 'q', 120086 => 's', 120087 => 't', 120088 => 'u', 120089 => 'v', 120090 => 'w', 120091 => 'x', 120092 => 'y', 120094 => 'a', 120095 => 'b', 120096 => 'c', 120097 => 'd', 120098 => 'e', 120099 => 'f', 120100 => 'g', 120101 => 'h', 120102 => 'i', 120103 => 'j', 120104 => 'k', 120105 => 'l', 120106 => 'm', 120107 => 'n', 120108 => 'o', 120109 => 'p', 120110 => 'q', 120111 => 'r', 120112 => 's', 120113 => 't', 120114 => 'u', 120115 => 'v', 120116 => 'w', 120117 => 'x', 120118 => 'y', 120119 => 'z', 120120 => 'a', 120121 => 'b', 120123 => 'd', 120124 => 'e', 120125 => 'f', 120126 => 'g', 120128 => 'i', 120129 => 'j', 120130 => 'k', 120131 => 'l', 120132 => 'm', 120134 => 'o', 120138 => 's', 120139 => 't', 120140 => 'u', 120141 => 'v', 120142 => 'w', 120143 => 'x', 120144 => 'y', 120146 => 'a', 120147 => 'b', 120148 => 'c', 120149 => 'd', 120150 => 'e', 120151 => 'f', 120152 => 'g', 120153 => 'h', 120154 => 'i', 120155 => 'j', 120156 => 'k', 120157 => 'l', 120158 => 'm', 120159 => 'n', 120160 => 'o', 120161 => 'p', 120162 => 'q', 120163 => 'r', 120164 => 's', 120165 => 't', 120166 => 'u', 120167 => 'v', 120168 => 'w', 120169 => 'x', 120170 => 'y', 120171 => 'z', 120172 => 'a', 120173 => 'b', 120174 => 'c', 120175 => 'd', 120176 => 'e', 120177 => 'f', 120178 => 'g', 120179 => 'h', 120180 => 'i', 120181 => 'j', 120182 => 'k', 120183 => 'l', 120184 => 'm', 120185 => 'n', 120186 => 'o', 120187 => 'p', 120188 => 'q', 120189 => 'r', 120190 => 's', 120191 => 't', 120192 => 'u', 120193 => 'v', 120194 => 'w', 120195 => 'x', 120196 => 'y', 120197 => 'z', 120198 => 'a', 120199 => 'b', 120200 => 'c', 120201 => 'd', 120202 => 'e', 120203 => 'f', 120204 => 'g', 120205 => 'h', 120206 => 'i', 120207 => 'j', 120208 => 'k', 120209 => 'l', 120210 => 'm', 120211 => 'n', 120212 => 'o', 120213 => 'p', 120214 => 'q', 120215 => 'r', 120216 => 's', 120217 => 't', 120218 => 'u', 120219 => 'v', 120220 => 'w', 120221 => 'x', 120222 => 'y', 120223 => 'z', 120224 => 'a', 120225 => 'b', 120226 => 'c', 120227 => 'd', 120228 => 'e', 120229 => 'f', 120230 => 'g', 120231 => 'h', 120232 => 'i', 120233 => 'j', 120234 => 'k', 120235 => 'l', 120236 => 'm', 120237 => 'n', 120238 => 'o', 120239 => 'p', 120240 => 'q', 120241 => 'r', 120242 => 's', 120243 => 't', 120244 => 'u', 120245 => 'v', 120246 => 'w', 120247 => 'x', 120248 => 'y', 120249 => 'z', 120250 => 'a', 120251 => 'b', 120252 => 'c', 120253 => 'd', 120254 => 'e', 120255 => 'f', 120256 => 'g', 120257 => 'h', 120258 => 'i', 120259 => 'j', 120260 => 'k', 120261 => 'l', 120262 => 'm', 120263 => 'n', 120264 => 'o', 120265 => 'p', 120266 => 'q', 120267 => 'r', 120268 => 's', 120269 => 't', 120270 => 'u', 120271 => 'v', 120272 => 'w', 120273 => 'x', 120274 => 'y', 120275 => 'z', 120276 => 'a', 120277 => 'b', 120278 => 'c', 120279 => 'd', 120280 => 'e', 120281 => 'f', 120282 => 'g', 120283 => 'h', 120284 => 'i', 120285 => 'j', 120286 => 'k', 120287 => 'l', 120288 => 'm', 120289 => 'n', 120290 => 'o', 120291 => 'p', 120292 => 'q', 120293 => 'r', 120294 => 's', 120295 => 't', 120296 => 'u', 120297 => 'v', 120298 => 'w', 120299 => 'x', 120300 => 'y', 120301 => 'z', 120302 => 'a', 120303 => 'b', 120304 => 'c', 120305 => 'd', 120306 => 'e', 120307 => 'f', 120308 => 'g', 120309 => 'h', 120310 => 'i', 120311 => 'j', 120312 => 'k', 120313 => 'l', 120314 => 'm', 120315 => 'n', 120316 => 'o', 120317 => 'p', 120318 => 'q', 120319 => 'r', 120320 => 's', 120321 => 't', 120322 => 'u', 120323 => 'v', 120324 => 'w', 120325 => 'x', 120326 => 'y', 120327 => 'z', 120328 => 'a', 120329 => 'b', 120330 => 'c', 120331 => 'd', 120332 => 'e', 120333 => 'f', 120334 => 'g', 120335 => 'h', 120336 => 'i', 120337 => 'j', 120338 => 'k', 120339 => 'l', 120340 => 'm', 120341 => 'n', 120342 => 'o', 120343 => 'p', 120344 => 'q', 120345 => 'r', 120346 => 's', 120347 => 't', 120348 => 'u', 120349 => 'v', 120350 => 'w', 120351 => 'x', 120352 => 'y', 120353 => 'z', 120354 => 'a', 120355 => 'b', 120356 => 'c', 120357 => 'd', 120358 => 'e', 120359 => 'f', 120360 => 'g', 120361 => 'h', 120362 => 'i', 120363 => 'j', 120364 => 'k', 120365 => 'l', 120366 => 'm', 120367 => 'n', 120368 => 'o', 120369 => 'p', 120370 => 'q', 120371 => 'r', 120372 => 's', 120373 => 't', 120374 => 'u', 120375 => 'v', 120376 => 'w', 120377 => 'x', 120378 => 'y', 120379 => 'z', 120380 => 'a', 120381 => 'b', 120382 => 'c', 120383 => 'd', 120384 => 'e', 120385 => 'f', 120386 => 'g', 120387 => 'h', 120388 => 'i', 120389 => 'j', 120390 => 'k', 120391 => 'l', 120392 => 'm', 120393 => 'n', 120394 => 'o', 120395 => 'p', 120396 => 'q', 120397 => 'r', 120398 => 's', 120399 => 't', 120400 => 'u', 120401 => 'v', 120402 => 'w', 120403 => 'x', 120404 => 'y', 120405 => 'z', 120406 => 'a', 120407 => 'b', 120408 => 'c', 120409 => 'd', 120410 => 'e', 120411 => 'f', 120412 => 'g', 120413 => 'h', 120414 => 'i', 120415 => 'j', 120416 => 'k', 120417 => 'l', 120418 => 'm', 120419 => 'n', 120420 => 'o', 120421 => 'p', 120422 => 'q', 120423 => 'r', 120424 => 's', 120425 => 't', 120426 => 'u', 120427 => 'v', 120428 => 'w', 120429 => 'x', 120430 => 'y', 120431 => 'z', 120432 => 'a', 120433 => 'b', 120434 => 'c', 120435 => 'd', 120436 => 'e', 120437 => 'f', 120438 => 'g', 120439 => 'h', 120440 => 'i', 120441 => 'j', 120442 => 'k', 120443 => 'l', 120444 => 'm', 120445 => 'n', 120446 => 'o', 120447 => 'p', 120448 => 'q', 120449 => 'r', 120450 => 's', 120451 => 't', 120452 => 'u', 120453 => 'v', 120454 => 'w', 120455 => 'x', 120456 => 'y', 120457 => 'z', 120458 => 'a', 120459 => 'b', 120460 => 'c', 120461 => 'd', 120462 => 'e', 120463 => 'f', 120464 => 'g', 120465 => 'h', 120466 => 'i', 120467 => 'j', 120468 => 'k', 120469 => 'l', 120470 => 'm', 120471 => 'n', 120472 => 'o', 120473 => 'p', 120474 => 'q', 120475 => 'r', 120476 => 's', 120477 => 't', 120478 => 'u', 120479 => 'v', 120480 => 'w', 120481 => 'x', 120482 => 'y', 120483 => 'z', 120484 => 'ı', 120485 => 'ȷ', 120488 => 'α', 120489 => 'β', 120490 => 'γ', 120491 => 'δ', 120492 => 'ε', 120493 => 'ζ', 120494 => 'η', 120495 => 'θ', 120496 => 'ι', 120497 => 'κ', 120498 => 'λ', 120499 => 'μ', 120500 => 'ν', 120501 => 'ξ', 120502 => 'ο', 120503 => 'π', 120504 => 'ρ', 120505 => 'θ', 120506 => 'σ', 120507 => 'τ', 120508 => 'υ', 120509 => 'φ', 120510 => 'χ', 120511 => 'ψ', 120512 => 'ω', 120513 => '∇', 120514 => 'α', 120515 => 'β', 120516 => 'γ', 120517 => 'δ', 120518 => 'ε', 120519 => 'ζ', 120520 => 'η', 120521 => 'θ', 120522 => 'ι', 120523 => 'κ', 120524 => 'λ', 120525 => 'μ', 120526 => 'ν', 120527 => 'ξ', 120528 => 'ο', 120529 => 'π', 120530 => 'ρ', 120531 => 'σ', 120532 => 'σ', 120533 => 'τ', 120534 => 'υ', 120535 => 'φ', 120536 => 'χ', 120537 => 'ψ', 120538 => 'ω', 120539 => '∂', 120540 => 'ε', 120541 => 'θ', 120542 => 'κ', 120543 => 'φ', 120544 => 'ρ', 120545 => 'π', 120546 => 'α', 120547 => 'β', 120548 => 'γ', 120549 => 'δ', 120550 => 'ε', 120551 => 'ζ', 120552 => 'η', 120553 => 'θ', 120554 => 'ι', 120555 => 'κ', 120556 => 'λ', 120557 => 'μ', 120558 => 'ν', 120559 => 'ξ', 120560 => 'ο', 120561 => 'π', 120562 => 'ρ', 120563 => 'θ', 120564 => 'σ', 120565 => 'τ', 120566 => 'υ', 120567 => 'φ', 120568 => 'χ', 120569 => 'ψ', 120570 => 'ω', 120571 => '∇', 120572 => 'α', 120573 => 'β', 120574 => 'γ', 120575 => 'δ', 120576 => 'ε', 120577 => 'ζ', 120578 => 'η', 120579 => 'θ', 120580 => 'ι', 120581 => 'κ', 120582 => 'λ', 120583 => 'μ', 120584 => 'ν', 120585 => 'ξ', 120586 => 'ο', 120587 => 'π', 120588 => 'ρ', 120589 => 'σ', 120590 => 'σ', 120591 => 'τ', 120592 => 'υ', 120593 => 'φ', 120594 => 'χ', 120595 => 'ψ', 120596 => 'ω', 120597 => '∂', 120598 => 'ε', 120599 => 'θ', 120600 => 'κ', 120601 => 'φ', 120602 => 'ρ', 120603 => 'π', 120604 => 'α', 120605 => 'β', 120606 => 'γ', 120607 => 'δ', 120608 => 'ε', 120609 => 'ζ', 120610 => 'η', 120611 => 'θ', 120612 => 'ι', 120613 => 'κ', 120614 => 'λ', 120615 => 'μ', 120616 => 'ν', 120617 => 'ξ', 120618 => 'ο', 120619 => 'π', 120620 => 'ρ', 120621 => 'θ', 120622 => 'σ', 120623 => 'τ', 120624 => 'υ', 120625 => 'φ', 120626 => 'χ', 120627 => 'ψ', 120628 => 'ω', 120629 => '∇', 120630 => 'α', 120631 => 'β', 120632 => 'γ', 120633 => 'δ', 120634 => 'ε', 120635 => 'ζ', 120636 => 'η', 120637 => 'θ', 120638 => 'ι', 120639 => 'κ', 120640 => 'λ', 120641 => 'μ', 120642 => 'ν', 120643 => 'ξ', 120644 => 'ο', 120645 => 'π', 120646 => 'ρ', 120647 => 'σ', 120648 => 'σ', 120649 => 'τ', 120650 => 'υ', 120651 => 'φ', 120652 => 'χ', 120653 => 'ψ', 120654 => 'ω', 120655 => '∂', 120656 => 'ε', 120657 => 'θ', 120658 => 'κ', 120659 => 'φ', 120660 => 'ρ', 120661 => 'π', 120662 => 'α', 120663 => 'β', 120664 => 'γ', 120665 => 'δ', 120666 => 'ε', 120667 => 'ζ', 120668 => 'η', 120669 => 'θ', 120670 => 'ι', 120671 => 'κ', 120672 => 'λ', 120673 => 'μ', 120674 => 'ν', 120675 => 'ξ', 120676 => 'ο', 120677 => 'π', 120678 => 'ρ', 120679 => 'θ', 120680 => 'σ', 120681 => 'τ', 120682 => 'υ', 120683 => 'φ', 120684 => 'χ', 120685 => 'ψ', 120686 => 'ω', 120687 => '∇', 120688 => 'α', 120689 => 'β', 120690 => 'γ', 120691 => 'δ', 120692 => 'ε', 120693 => 'ζ', 120694 => 'η', 120695 => 'θ', 120696 => 'ι', 120697 => 'κ', 120698 => 'λ', 120699 => 'μ', 120700 => 'ν', 120701 => 'ξ', 120702 => 'ο', 120703 => 'π', 120704 => 'ρ', 120705 => 'σ', 120706 => 'σ', 120707 => 'τ', 120708 => 'υ', 120709 => 'φ', 120710 => 'χ', 120711 => 'ψ', 120712 => 'ω', 120713 => '∂', 120714 => 'ε', 120715 => 'θ', 120716 => 'κ', 120717 => 'φ', 120718 => 'ρ', 120719 => 'π', 120720 => 'α', 120721 => 'β', 120722 => 'γ', 120723 => 'δ', 120724 => 'ε', 120725 => 'ζ', 120726 => 'η', 120727 => 'θ', 120728 => 'ι', 120729 => 'κ', 120730 => 'λ', 120731 => 'μ', 120732 => 'ν', 120733 => 'ξ', 120734 => 'ο', 120735 => 'π', 120736 => 'ρ', 120737 => 'θ', 120738 => 'σ', 120739 => 'τ', 120740 => 'υ', 120741 => 'φ', 120742 => 'χ', 120743 => 'ψ', 120744 => 'ω', 120745 => '∇', 120746 => 'α', 120747 => 'β', 120748 => 'γ', 120749 => 'δ', 120750 => 'ε', 120751 => 'ζ', 120752 => 'η', 120753 => 'θ', 120754 => 'ι', 120755 => 'κ', 120756 => 'λ', 120757 => 'μ', 120758 => 'ν', 120759 => 'ξ', 120760 => 'ο', 120761 => 'π', 120762 => 'ρ', 120763 => 'σ', 120764 => 'σ', 120765 => 'τ', 120766 => 'υ', 120767 => 'φ', 120768 => 'χ', 120769 => 'ψ', 120770 => 'ω', 120771 => '∂', 120772 => 'ε', 120773 => 'θ', 120774 => 'κ', 120775 => 'φ', 120776 => 'ρ', 120777 => 'π', 120778 => 'ϝ', 120779 => 'ϝ', 120782 => '0', 120783 => '1', 120784 => '2', 120785 => '3', 120786 => '4', 120787 => '5', 120788 => '6', 120789 => '7', 120790 => '8', 120791 => '9', 120792 => '0', 120793 => '1', 120794 => '2', 120795 => '3', 120796 => '4', 120797 => '5', 120798 => '6', 120799 => '7', 120800 => '8', 120801 => '9', 120802 => '0', 120803 => '1', 120804 => '2', 120805 => '3', 120806 => '4', 120807 => '5', 120808 => '6', 120809 => '7', 120810 => '8', 120811 => '9', 120812 => '0', 120813 => '1', 120814 => '2', 120815 => '3', 120816 => '4', 120817 => '5', 120818 => '6', 120819 => '7', 120820 => '8', 120821 => '9', 120822 => '0', 120823 => '1', 120824 => '2', 120825 => '3', 120826 => '4', 120827 => '5', 120828 => '6', 120829 => '7', 120830 => '8', 120831 => '9', 125184 => '𞤢', 125185 => '𞤣', 125186 => '𞤤', 125187 => '𞤥', 125188 => '𞤦', 125189 => '𞤧', 125190 => '𞤨', 125191 => '𞤩', 125192 => '𞤪', 125193 => '𞤫', 125194 => '𞤬', 125195 => '𞤭', 125196 => '𞤮', 125197 => '𞤯', 125198 => '𞤰', 125199 => '𞤱', 125200 => '𞤲', 125201 => '𞤳', 125202 => '𞤴', 125203 => '𞤵', 125204 => '𞤶', 125205 => '𞤷', 125206 => '𞤸', 125207 => '𞤹', 125208 => '𞤺', 125209 => '𞤻', 125210 => '𞤼', 125211 => '𞤽', 125212 => '𞤾', 125213 => '𞤿', 125214 => '𞥀', 125215 => '𞥁', 125216 => '𞥂', 125217 => '𞥃', 126464 => 'ا', 126465 => 'ب', 126466 => 'ج', 126467 => 'د', 126469 => 'و', 126470 => 'ز', 126471 => 'ح', 126472 => 'ط', 126473 => 'ي', 126474 => 'ك', 126475 => 'ل', 126476 => 'م', 126477 => 'ن', 126478 => 'س', 126479 => 'ع', 126480 => 'ف', 126481 => 'ص', 126482 => 'ق', 126483 => 'ر', 126484 => 'ش', 126485 => 'ت', 126486 => 'ث', 126487 => 'خ', 126488 => 'ذ', 126489 => 'ض', 126490 => 'ظ', 126491 => 'غ', 126492 => 'ٮ', 126493 => 'ں', 126494 => 'ڡ', 126495 => 'ٯ', 126497 => 'ب', 126498 => 'ج', 126500 => 'ه', 126503 => 'ح', 126505 => 'ي', 126506 => 'ك', 126507 => 'ل', 126508 => 'م', 126509 => 'ن', 126510 => 'س', 126511 => 'ع', 126512 => 'ف', 126513 => 'ص', 126514 => 'ق', 126516 => 'ش', 126517 => 'ت', 126518 => 'ث', 126519 => 'خ', 126521 => 'ض', 126523 => 'غ', 126530 => 'ج', 126535 => 'ح', 126537 => 'ي', 126539 => 'ل', 126541 => 'ن', 126542 => 'س', 126543 => 'ع', 126545 => 'ص', 126546 => 'ق', 126548 => 'ش', 126551 => 'خ', 126553 => 'ض', 126555 => 'غ', 126557 => 'ں', 126559 => 'ٯ', 126561 => 'ب', 126562 => 'ج', 126564 => 'ه', 126567 => 'ح', 126568 => 'ط', 126569 => 'ي', 126570 => 'ك', 126572 => 'م', 126573 => 'ن', 126574 => 'س', 126575 => 'ع', 126576 => 'ف', 126577 => 'ص', 126578 => 'ق', 126580 => 'ش', 126581 => 'ت', 126582 => 'ث', 126583 => 'خ', 126585 => 'ض', 126586 => 'ظ', 126587 => 'غ', 126588 => 'ٮ', 126590 => 'ڡ', 126592 => 'ا', 126593 => 'ب', 126594 => 'ج', 126595 => 'د', 126596 => 'ه', 126597 => 'و', 126598 => 'ز', 126599 => 'ح', 126600 => 'ط', 126601 => 'ي', 126603 => 'ل', 126604 => 'م', 126605 => 'ن', 126606 => 'س', 126607 => 'ع', 126608 => 'ف', 126609 => 'ص', 126610 => 'ق', 126611 => 'ر', 126612 => 'ش', 126613 => 'ت', 126614 => 'ث', 126615 => 'خ', 126616 => 'ذ', 126617 => 'ض', 126618 => 'ظ', 126619 => 'غ', 126625 => 'ب', 126626 => 'ج', 126627 => 'د', 126629 => 'و', 126630 => 'ز', 126631 => 'ح', 126632 => 'ط', 126633 => 'ي', 126635 => 'ل', 126636 => 'م', 126637 => 'ن', 126638 => 'س', 126639 => 'ع', 126640 => 'ف', 126641 => 'ص', 126642 => 'ق', 126643 => 'ر', 126644 => 'ش', 126645 => 'ت', 126646 => 'ث', 126647 => 'خ', 126648 => 'ذ', 126649 => 'ض', 126650 => 'ظ', 126651 => 'غ', 127274 => '〔s〕', 127275 => 'c', 127276 => 'r', 127277 => 'cd', 127278 => 'wz', 127280 => 'a', 127281 => 'b', 127282 => 'c', 127283 => 'd', 127284 => 'e', 127285 => 'f', 127286 => 'g', 127287 => 'h', 127288 => 'i', 127289 => 'j', 127290 => 'k', 127291 => 'l', 127292 => 'm', 127293 => 'n', 127294 => 'o', 127295 => 'p', 127296 => 'q', 127297 => 'r', 127298 => 's', 127299 => 't', 127300 => 'u', 127301 => 'v', 127302 => 'w', 127303 => 'x', 127304 => 'y', 127305 => 'z', 127306 => 'hv', 127307 => 'mv', 127308 => 'sd', 127309 => 'ss', 127310 => 'ppv', 127311 => 'wc', 127338 => 'mc', 127339 => 'md', 127340 => 'mr', 127376 => 'dj', 127488 => 'ほか', 127489 => 'ココ', 127490 => 'サ', 127504 => '手', 127505 => '字', 127506 => '双', 127507 => 'デ', 127508 => '二', 127509 => '多', 127510 => '解', 127511 => '天', 127512 => '交', 127513 => '映', 127514 => '無', 127515 => '料', 127516 => '前', 127517 => '後', 127518 => '再', 127519 => '新', 127520 => '初', 127521 => '終', 127522 => '生', 127523 => '販', 127524 => '声', 127525 => '吹', 127526 => '演', 127527 => '投', 127528 => '捕', 127529 => '一', 127530 => '三', 127531 => '遊', 127532 => '左', 127533 => '中', 127534 => '右', 127535 => '指', 127536 => '走', 127537 => '打', 127538 => '禁', 127539 => '空', 127540 => '合', 127541 => '満', 127542 => '有', 127543 => '月', 127544 => '申', 127545 => '割', 127546 => '営', 127547 => '配', 127552 => '〔本〕', 127553 => '〔三〕', 127554 => '〔二〕', 127555 => '〔安〕', 127556 => '〔点〕', 127557 => '〔打〕', 127558 => '〔盗〕', 127559 => '〔勝〕', 127560 => '〔敗〕', 127568 => '得', 127569 => '可', 130032 => '0', 130033 => '1', 130034 => '2', 130035 => '3', 130036 => '4', 130037 => '5', 130038 => '6', 130039 => '7', 130040 => '8', 130041 => '9', 194560 => '丽', 194561 => '丸', 194562 => '乁', 194563 => '𠄢', 194564 => '你', 194565 => '侮', 194566 => '侻', 194567 => '倂', 194568 => '偺', 194569 => '備', 194570 => '僧', 194571 => '像', 194572 => '㒞', 194573 => '𠘺', 194574 => '免', 194575 => '兔', 194576 => '兤', 194577 => '具', 194578 => '𠔜', 194579 => '㒹', 194580 => '內', 194581 => '再', 194582 => '𠕋', 194583 => '冗', 194584 => '冤', 194585 => '仌', 194586 => '冬', 194587 => '况', 194588 => '𩇟', 194589 => '凵', 194590 => '刃', 194591 => '㓟', 194592 => '刻', 194593 => '剆', 194594 => '割', 194595 => '剷', 194596 => '㔕', 194597 => '勇', 194598 => '勉', 194599 => '勤', 194600 => '勺', 194601 => '包', 194602 => '匆', 194603 => '北', 194604 => '卉', 194605 => '卑', 194606 => '博', 194607 => '即', 194608 => '卽', 194609 => '卿', 194610 => '卿', 194611 => '卿', 194612 => '𠨬', 194613 => '灰', 194614 => '及', 194615 => '叟', 194616 => '𠭣', 194617 => '叫', 194618 => '叱', 194619 => '吆', 194620 => '咞', 194621 => '吸', 194622 => '呈', 194623 => '周', 194624 => '咢', 194625 => '哶', 194626 => '唐', 194627 => '啓', 194628 => '啣', 194629 => '善', 194630 => '善', 194631 => '喙', 194632 => '喫', 194633 => '喳', 194634 => '嗂', 194635 => '圖', 194636 => '嘆', 194637 => '圗', 194638 => '噑', 194639 => '噴', 194640 => '切', 194641 => '壮', 194642 => '城', 194643 => '埴', 194644 => '堍', 194645 => '型', 194646 => '堲', 194647 => '報', 194648 => '墬', 194649 => '𡓤', 194650 => '売', 194651 => '壷', 194652 => '夆', 194653 => '多', 194654 => '夢', 194655 => '奢', 194656 => '𡚨', 194657 => '𡛪', 194658 => '姬', 194659 => '娛', 194660 => '娧', 194661 => '姘', 194662 => '婦', 194663 => '㛮', 194665 => '嬈', 194666 => '嬾', 194667 => '嬾', 194668 => '𡧈', 194669 => '寃', 194670 => '寘', 194671 => '寧', 194672 => '寳', 194673 => '𡬘', 194674 => '寿', 194675 => '将', 194677 => '尢', 194678 => '㞁', 194679 => '屠', 194680 => '屮', 194681 => '峀', 194682 => '岍', 194683 => '𡷤', 194684 => '嵃', 194685 => '𡷦', 194686 => '嵮', 194687 => '嵫', 194688 => '嵼', 194689 => '巡', 194690 => '巢', 194691 => '㠯', 194692 => '巽', 194693 => '帨', 194694 => '帽', 194695 => '幩', 194696 => '㡢', 194697 => '𢆃', 194698 => '㡼', 194699 => '庰', 194700 => '庳', 194701 => '庶', 194702 => '廊', 194703 => '𪎒', 194704 => '廾', 194705 => '𢌱', 194706 => '𢌱', 194707 => '舁', 194708 => '弢', 194709 => '弢', 194710 => '㣇', 194711 => '𣊸', 194712 => '𦇚', 194713 => '形', 194714 => '彫', 194715 => '㣣', 194716 => '徚', 194717 => '忍', 194718 => '志', 194719 => '忹', 194720 => '悁', 194721 => '㤺', 194722 => '㤜', 194723 => '悔', 194724 => '𢛔', 194725 => '惇', 194726 => '慈', 194727 => '慌', 194728 => '慎', 194729 => '慌', 194730 => '慺', 194731 => '憎', 194732 => '憲', 194733 => '憤', 194734 => '憯', 194735 => '懞', 194736 => '懲', 194737 => '懶', 194738 => '成', 194739 => '戛', 194740 => '扝', 194741 => '抱', 194742 => '拔', 194743 => '捐', 194744 => '𢬌', 194745 => '挽', 194746 => '拼', 194747 => '捨', 194748 => '掃', 194749 => '揤', 194750 => '𢯱', 194751 => '搢', 194752 => '揅', 194753 => '掩', 194754 => '㨮', 194755 => '摩', 194756 => '摾', 194757 => '撝', 194758 => '摷', 194759 => '㩬', 194760 => '敏', 194761 => '敬', 194762 => '𣀊', 194763 => '旣', 194764 => '書', 194765 => '晉', 194766 => '㬙', 194767 => '暑', 194768 => '㬈', 194769 => '㫤', 194770 => '冒', 194771 => '冕', 194772 => '最', 194773 => '暜', 194774 => '肭', 194775 => '䏙', 194776 => '朗', 194777 => '望', 194778 => '朡', 194779 => '杞', 194780 => '杓', 194781 => '𣏃', 194782 => '㭉', 194783 => '柺', 194784 => '枅', 194785 => '桒', 194786 => '梅', 194787 => '𣑭', 194788 => '梎', 194789 => '栟', 194790 => '椔', 194791 => '㮝', 194792 => '楂', 194793 => '榣', 194794 => '槪', 194795 => '檨', 194796 => '𣚣', 194797 => '櫛', 194798 => '㰘', 194799 => '次', 194800 => '𣢧', 194801 => '歔', 194802 => '㱎', 194803 => '歲', 194804 => '殟', 194805 => '殺', 194806 => '殻', 194807 => '𣪍', 194808 => '𡴋', 194809 => '𣫺', 194810 => '汎', 194811 => '𣲼', 194812 => '沿', 194813 => '泍', 194814 => '汧', 194815 => '洖', 194816 => '派', 194817 => '海', 194818 => '流', 194819 => '浩', 194820 => '浸', 194821 => '涅', 194822 => '𣴞', 194823 => '洴', 194824 => '港', 194825 => '湮', 194826 => '㴳', 194827 => '滋', 194828 => '滇', 194829 => '𣻑', 194830 => '淹', 194831 => '潮', 194832 => '𣽞', 194833 => '𣾎', 194834 => '濆', 194835 => '瀹', 194836 => '瀞', 194837 => '瀛', 194838 => '㶖', 194839 => '灊', 194840 => '災', 194841 => '灷', 194842 => '炭', 194843 => '𠔥', 194844 => '煅', 194845 => '𤉣', 194846 => '熜', 194848 => '爨', 194849 => '爵', 194850 => '牐', 194851 => '𤘈', 194852 => '犀', 194853 => '犕', 194854 => '𤜵', 194855 => '𤠔', 194856 => '獺', 194857 => '王', 194858 => '㺬', 194859 => '玥', 194860 => '㺸', 194861 => '㺸', 194862 => '瑇', 194863 => '瑜', 194864 => '瑱', 194865 => '璅', 194866 => '瓊', 194867 => '㼛', 194868 => '甤', 194869 => '𤰶', 194870 => '甾', 194871 => '𤲒', 194872 => '異', 194873 => '𢆟', 194874 => '瘐', 194875 => '𤾡', 194876 => '𤾸', 194877 => '𥁄', 194878 => '㿼', 194879 => '䀈', 194880 => '直', 194881 => '𥃳', 194882 => '𥃲', 194883 => '𥄙', 194884 => '𥄳', 194885 => '眞', 194886 => '真', 194887 => '真', 194888 => '睊', 194889 => '䀹', 194890 => '瞋', 194891 => '䁆', 194892 => '䂖', 194893 => '𥐝', 194894 => '硎', 194895 => '碌', 194896 => '磌', 194897 => '䃣', 194898 => '𥘦', 194899 => '祖', 194900 => '𥚚', 194901 => '𥛅', 194902 => '福', 194903 => '秫', 194904 => '䄯', 194905 => '穀', 194906 => '穊', 194907 => '穏', 194908 => '𥥼', 194909 => '𥪧', 194910 => '𥪧', 194912 => '䈂', 194913 => '𥮫', 194914 => '篆', 194915 => '築', 194916 => '䈧', 194917 => '𥲀', 194918 => '糒', 194919 => '䊠', 194920 => '糨', 194921 => '糣', 194922 => '紀', 194923 => '𥾆', 194924 => '絣', 194925 => '䌁', 194926 => '緇', 194927 => '縂', 194928 => '繅', 194929 => '䌴', 194930 => '𦈨', 194931 => '𦉇', 194932 => '䍙', 194933 => '𦋙', 194934 => '罺', 194935 => '𦌾', 194936 => '羕', 194937 => '翺', 194938 => '者', 194939 => '𦓚', 194940 => '𦔣', 194941 => '聠', 194942 => '𦖨', 194943 => '聰', 194944 => '𣍟', 194945 => '䏕', 194946 => '育', 194947 => '脃', 194948 => '䐋', 194949 => '脾', 194950 => '媵', 194951 => '𦞧', 194952 => '𦞵', 194953 => '𣎓', 194954 => '𣎜', 194955 => '舁', 194956 => '舄', 194957 => '辞', 194958 => '䑫', 194959 => '芑', 194960 => '芋', 194961 => '芝', 194962 => '劳', 194963 => '花', 194964 => '芳', 194965 => '芽', 194966 => '苦', 194967 => '𦬼', 194968 => '若', 194969 => '茝', 194970 => '荣', 194971 => '莭', 194972 => '茣', 194973 => '莽', 194974 => '菧', 194975 => '著', 194976 => '荓', 194977 => '菊', 194978 => '菌', 194979 => '菜', 194980 => '𦰶', 194981 => '𦵫', 194982 => '𦳕', 194983 => '䔫', 194984 => '蓱', 194985 => '蓳', 194986 => '蔖', 194987 => '𧏊', 194988 => '蕤', 194989 => '𦼬', 194990 => '䕝', 194991 => '䕡', 194992 => '𦾱', 194993 => '𧃒', 194994 => '䕫', 194995 => '虐', 194996 => '虜', 194997 => '虧', 194998 => '虩', 194999 => '蚩', 195000 => '蚈', 195001 => '蜎', 195002 => '蛢', 195003 => '蝹', 195004 => '蜨', 195005 => '蝫', 195006 => '螆', 195008 => '蟡', 195009 => '蠁', 195010 => '䗹', 195011 => '衠', 195012 => '衣', 195013 => '𧙧', 195014 => '裗', 195015 => '裞', 195016 => '䘵', 195017 => '裺', 195018 => '㒻', 195019 => '𧢮', 195020 => '𧥦', 195021 => '䚾', 195022 => '䛇', 195023 => '誠', 195024 => '諭', 195025 => '變', 195026 => '豕', 195027 => '𧲨', 195028 => '貫', 195029 => '賁', 195030 => '贛', 195031 => '起', 195032 => '𧼯', 195033 => '𠠄', 195034 => '跋', 195035 => '趼', 195036 => '跰', 195037 => '𠣞', 195038 => '軔', 195039 => '輸', 195040 => '𨗒', 195041 => '𨗭', 195042 => '邔', 195043 => '郱', 195044 => '鄑', 195045 => '𨜮', 195046 => '鄛', 195047 => '鈸', 195048 => '鋗', 195049 => '鋘', 195050 => '鉼', 195051 => '鏹', 195052 => '鐕', 195053 => '𨯺', 195054 => '開', 195055 => '䦕', 195056 => '閷', 195057 => '𨵷', 195058 => '䧦', 195059 => '雃', 195060 => '嶲', 195061 => '霣', 195062 => '𩅅', 195063 => '𩈚', 195064 => '䩮', 195065 => '䩶', 195066 => '韠', 195067 => '𩐊', 195068 => '䪲', 195069 => '𩒖', 195070 => '頋', 195071 => '頋', 195072 => '頩', 195073 => '𩖶', 195074 => '飢', 195075 => '䬳', 195076 => '餩', 195077 => '馧', 195078 => '駂', 195079 => '駾', 195080 => '䯎', 195081 => '𩬰', 195082 => '鬒', 195083 => '鱀', 195084 => '鳽', 195085 => '䳎', 195086 => '䳭', 195087 => '鵧', 195088 => '𪃎', 195089 => '䳸', 195090 => '𪄅', 195091 => '𪈎', 195092 => '𪊑', 195093 => '麻', 195094 => '䵖', 195095 => '黹', 195096 => '黾', 195097 => '鼅', 195098 => '鼏', 195099 => '鼖', 195100 => '鼻', 195101 => '𪘀', ); polyfill-intl-idn/Resources/unidata/DisallowedRanges.php000064400000021003150432043200017436 0ustar00= 128 && $codePoint <= 159) { return true; } if ($codePoint >= 2155 && $codePoint <= 2207) { return true; } if ($codePoint >= 3676 && $codePoint <= 3712) { return true; } if ($codePoint >= 3808 && $codePoint <= 3839) { return true; } if ($codePoint >= 4059 && $codePoint <= 4095) { return true; } if ($codePoint >= 4256 && $codePoint <= 4293) { return true; } if ($codePoint >= 6849 && $codePoint <= 6911) { return true; } if ($codePoint >= 11859 && $codePoint <= 11903) { return true; } if ($codePoint >= 42955 && $codePoint <= 42996) { return true; } if ($codePoint >= 55296 && $codePoint <= 57343) { return true; } if ($codePoint >= 57344 && $codePoint <= 63743) { return true; } if ($codePoint >= 64218 && $codePoint <= 64255) { return true; } if ($codePoint >= 64976 && $codePoint <= 65007) { return true; } if ($codePoint >= 65630 && $codePoint <= 65663) { return true; } if ($codePoint >= 65953 && $codePoint <= 65999) { return true; } if ($codePoint >= 66046 && $codePoint <= 66175) { return true; } if ($codePoint >= 66518 && $codePoint <= 66559) { return true; } if ($codePoint >= 66928 && $codePoint <= 67071) { return true; } if ($codePoint >= 67432 && $codePoint <= 67583) { return true; } if ($codePoint >= 67760 && $codePoint <= 67807) { return true; } if ($codePoint >= 67904 && $codePoint <= 67967) { return true; } if ($codePoint >= 68256 && $codePoint <= 68287) { return true; } if ($codePoint >= 68528 && $codePoint <= 68607) { return true; } if ($codePoint >= 68681 && $codePoint <= 68735) { return true; } if ($codePoint >= 68922 && $codePoint <= 69215) { return true; } if ($codePoint >= 69298 && $codePoint <= 69375) { return true; } if ($codePoint >= 69466 && $codePoint <= 69551) { return true; } if ($codePoint >= 70207 && $codePoint <= 70271) { return true; } if ($codePoint >= 70517 && $codePoint <= 70655) { return true; } if ($codePoint >= 70874 && $codePoint <= 71039) { return true; } if ($codePoint >= 71134 && $codePoint <= 71167) { return true; } if ($codePoint >= 71370 && $codePoint <= 71423) { return true; } if ($codePoint >= 71488 && $codePoint <= 71679) { return true; } if ($codePoint >= 71740 && $codePoint <= 71839) { return true; } if ($codePoint >= 72026 && $codePoint <= 72095) { return true; } if ($codePoint >= 72441 && $codePoint <= 72703) { return true; } if ($codePoint >= 72887 && $codePoint <= 72959) { return true; } if ($codePoint >= 73130 && $codePoint <= 73439) { return true; } if ($codePoint >= 73465 && $codePoint <= 73647) { return true; } if ($codePoint >= 74650 && $codePoint <= 74751) { return true; } if ($codePoint >= 75076 && $codePoint <= 77823) { return true; } if ($codePoint >= 78905 && $codePoint <= 82943) { return true; } if ($codePoint >= 83527 && $codePoint <= 92159) { return true; } if ($codePoint >= 92784 && $codePoint <= 92879) { return true; } if ($codePoint >= 93072 && $codePoint <= 93759) { return true; } if ($codePoint >= 93851 && $codePoint <= 93951) { return true; } if ($codePoint >= 94112 && $codePoint <= 94175) { return true; } if ($codePoint >= 101590 && $codePoint <= 101631) { return true; } if ($codePoint >= 101641 && $codePoint <= 110591) { return true; } if ($codePoint >= 110879 && $codePoint <= 110927) { return true; } if ($codePoint >= 111356 && $codePoint <= 113663) { return true; } if ($codePoint >= 113828 && $codePoint <= 118783) { return true; } if ($codePoint >= 119366 && $codePoint <= 119519) { return true; } if ($codePoint >= 119673 && $codePoint <= 119807) { return true; } if ($codePoint >= 121520 && $codePoint <= 122879) { return true; } if ($codePoint >= 122923 && $codePoint <= 123135) { return true; } if ($codePoint >= 123216 && $codePoint <= 123583) { return true; } if ($codePoint >= 123648 && $codePoint <= 124927) { return true; } if ($codePoint >= 125143 && $codePoint <= 125183) { return true; } if ($codePoint >= 125280 && $codePoint <= 126064) { return true; } if ($codePoint >= 126133 && $codePoint <= 126208) { return true; } if ($codePoint >= 126270 && $codePoint <= 126463) { return true; } if ($codePoint >= 126652 && $codePoint <= 126703) { return true; } if ($codePoint >= 126706 && $codePoint <= 126975) { return true; } if ($codePoint >= 127406 && $codePoint <= 127461) { return true; } if ($codePoint >= 127590 && $codePoint <= 127743) { return true; } if ($codePoint >= 129202 && $codePoint <= 129279) { return true; } if ($codePoint >= 129751 && $codePoint <= 129791) { return true; } if ($codePoint >= 129995 && $codePoint <= 130031) { return true; } if ($codePoint >= 130042 && $codePoint <= 131069) { return true; } if ($codePoint >= 173790 && $codePoint <= 173823) { return true; } if ($codePoint >= 191457 && $codePoint <= 194559) { return true; } if ($codePoint >= 195102 && $codePoint <= 196605) { return true; } if ($codePoint >= 201547 && $codePoint <= 262141) { return true; } if ($codePoint >= 262144 && $codePoint <= 327677) { return true; } if ($codePoint >= 327680 && $codePoint <= 393213) { return true; } if ($codePoint >= 393216 && $codePoint <= 458749) { return true; } if ($codePoint >= 458752 && $codePoint <= 524285) { return true; } if ($codePoint >= 524288 && $codePoint <= 589821) { return true; } if ($codePoint >= 589824 && $codePoint <= 655357) { return true; } if ($codePoint >= 655360 && $codePoint <= 720893) { return true; } if ($codePoint >= 720896 && $codePoint <= 786429) { return true; } if ($codePoint >= 786432 && $codePoint <= 851965) { return true; } if ($codePoint >= 851968 && $codePoint <= 917501) { return true; } if ($codePoint >= 917536 && $codePoint <= 917631) { return true; } if ($codePoint >= 917632 && $codePoint <= 917759) { return true; } if ($codePoint >= 918000 && $codePoint <= 983037) { return true; } if ($codePoint >= 983040 && $codePoint <= 1048573) { return true; } if ($codePoint >= 1048576 && $codePoint <= 1114109) { return true; } return false; } } polyfill-intl-idn/Resources/unidata/disallowed.php000064400000126714150432043200016355 0ustar00 true, 889 => true, 896 => true, 897 => true, 898 => true, 899 => true, 907 => true, 909 => true, 930 => true, 1216 => true, 1328 => true, 1367 => true, 1368 => true, 1419 => true, 1420 => true, 1424 => true, 1480 => true, 1481 => true, 1482 => true, 1483 => true, 1484 => true, 1485 => true, 1486 => true, 1487 => true, 1515 => true, 1516 => true, 1517 => true, 1518 => true, 1525 => true, 1526 => true, 1527 => true, 1528 => true, 1529 => true, 1530 => true, 1531 => true, 1532 => true, 1533 => true, 1534 => true, 1535 => true, 1536 => true, 1537 => true, 1538 => true, 1539 => true, 1540 => true, 1541 => true, 1564 => true, 1565 => true, 1757 => true, 1806 => true, 1807 => true, 1867 => true, 1868 => true, 1970 => true, 1971 => true, 1972 => true, 1973 => true, 1974 => true, 1975 => true, 1976 => true, 1977 => true, 1978 => true, 1979 => true, 1980 => true, 1981 => true, 1982 => true, 1983 => true, 2043 => true, 2044 => true, 2094 => true, 2095 => true, 2111 => true, 2140 => true, 2141 => true, 2143 => true, 2229 => true, 2248 => true, 2249 => true, 2250 => true, 2251 => true, 2252 => true, 2253 => true, 2254 => true, 2255 => true, 2256 => true, 2257 => true, 2258 => true, 2274 => true, 2436 => true, 2445 => true, 2446 => true, 2449 => true, 2450 => true, 2473 => true, 2481 => true, 2483 => true, 2484 => true, 2485 => true, 2490 => true, 2491 => true, 2501 => true, 2502 => true, 2505 => true, 2506 => true, 2511 => true, 2512 => true, 2513 => true, 2514 => true, 2515 => true, 2516 => true, 2517 => true, 2518 => true, 2520 => true, 2521 => true, 2522 => true, 2523 => true, 2526 => true, 2532 => true, 2533 => true, 2559 => true, 2560 => true, 2564 => true, 2571 => true, 2572 => true, 2573 => true, 2574 => true, 2577 => true, 2578 => true, 2601 => true, 2609 => true, 2612 => true, 2615 => true, 2618 => true, 2619 => true, 2621 => true, 2627 => true, 2628 => true, 2629 => true, 2630 => true, 2633 => true, 2634 => true, 2638 => true, 2639 => true, 2640 => true, 2642 => true, 2643 => true, 2644 => true, 2645 => true, 2646 => true, 2647 => true, 2648 => true, 2653 => true, 2655 => true, 2656 => true, 2657 => true, 2658 => true, 2659 => true, 2660 => true, 2661 => true, 2679 => true, 2680 => true, 2681 => true, 2682 => true, 2683 => true, 2684 => true, 2685 => true, 2686 => true, 2687 => true, 2688 => true, 2692 => true, 2702 => true, 2706 => true, 2729 => true, 2737 => true, 2740 => true, 2746 => true, 2747 => true, 2758 => true, 2762 => true, 2766 => true, 2767 => true, 2769 => true, 2770 => true, 2771 => true, 2772 => true, 2773 => true, 2774 => true, 2775 => true, 2776 => true, 2777 => true, 2778 => true, 2779 => true, 2780 => true, 2781 => true, 2782 => true, 2783 => true, 2788 => true, 2789 => true, 2802 => true, 2803 => true, 2804 => true, 2805 => true, 2806 => true, 2807 => true, 2808 => true, 2816 => true, 2820 => true, 2829 => true, 2830 => true, 2833 => true, 2834 => true, 2857 => true, 2865 => true, 2868 => true, 2874 => true, 2875 => true, 2885 => true, 2886 => true, 2889 => true, 2890 => true, 2894 => true, 2895 => true, 2896 => true, 2897 => true, 2898 => true, 2899 => true, 2900 => true, 2904 => true, 2905 => true, 2906 => true, 2907 => true, 2910 => true, 2916 => true, 2917 => true, 2936 => true, 2937 => true, 2938 => true, 2939 => true, 2940 => true, 2941 => true, 2942 => true, 2943 => true, 2944 => true, 2945 => true, 2948 => true, 2955 => true, 2956 => true, 2957 => true, 2961 => true, 2966 => true, 2967 => true, 2968 => true, 2971 => true, 2973 => true, 2976 => true, 2977 => true, 2978 => true, 2981 => true, 2982 => true, 2983 => true, 2987 => true, 2988 => true, 2989 => true, 3002 => true, 3003 => true, 3004 => true, 3005 => true, 3011 => true, 3012 => true, 3013 => true, 3017 => true, 3022 => true, 3023 => true, 3025 => true, 3026 => true, 3027 => true, 3028 => true, 3029 => true, 3030 => true, 3032 => true, 3033 => true, 3034 => true, 3035 => true, 3036 => true, 3037 => true, 3038 => true, 3039 => true, 3040 => true, 3041 => true, 3042 => true, 3043 => true, 3044 => true, 3045 => true, 3067 => true, 3068 => true, 3069 => true, 3070 => true, 3071 => true, 3085 => true, 3089 => true, 3113 => true, 3130 => true, 3131 => true, 3132 => true, 3141 => true, 3145 => true, 3150 => true, 3151 => true, 3152 => true, 3153 => true, 3154 => true, 3155 => true, 3156 => true, 3159 => true, 3163 => true, 3164 => true, 3165 => true, 3166 => true, 3167 => true, 3172 => true, 3173 => true, 3184 => true, 3185 => true, 3186 => true, 3187 => true, 3188 => true, 3189 => true, 3190 => true, 3213 => true, 3217 => true, 3241 => true, 3252 => true, 3258 => true, 3259 => true, 3269 => true, 3273 => true, 3278 => true, 3279 => true, 3280 => true, 3281 => true, 3282 => true, 3283 => true, 3284 => true, 3287 => true, 3288 => true, 3289 => true, 3290 => true, 3291 => true, 3292 => true, 3293 => true, 3295 => true, 3300 => true, 3301 => true, 3312 => true, 3315 => true, 3316 => true, 3317 => true, 3318 => true, 3319 => true, 3320 => true, 3321 => true, 3322 => true, 3323 => true, 3324 => true, 3325 => true, 3326 => true, 3327 => true, 3341 => true, 3345 => true, 3397 => true, 3401 => true, 3408 => true, 3409 => true, 3410 => true, 3411 => true, 3428 => true, 3429 => true, 3456 => true, 3460 => true, 3479 => true, 3480 => true, 3481 => true, 3506 => true, 3516 => true, 3518 => true, 3519 => true, 3527 => true, 3528 => true, 3529 => true, 3531 => true, 3532 => true, 3533 => true, 3534 => true, 3541 => true, 3543 => true, 3552 => true, 3553 => true, 3554 => true, 3555 => true, 3556 => true, 3557 => true, 3568 => true, 3569 => true, 3573 => true, 3574 => true, 3575 => true, 3576 => true, 3577 => true, 3578 => true, 3579 => true, 3580 => true, 3581 => true, 3582 => true, 3583 => true, 3584 => true, 3643 => true, 3644 => true, 3645 => true, 3646 => true, 3715 => true, 3717 => true, 3723 => true, 3748 => true, 3750 => true, 3774 => true, 3775 => true, 3781 => true, 3783 => true, 3790 => true, 3791 => true, 3802 => true, 3803 => true, 3912 => true, 3949 => true, 3950 => true, 3951 => true, 3952 => true, 3992 => true, 4029 => true, 4045 => true, 4294 => true, 4296 => true, 4297 => true, 4298 => true, 4299 => true, 4300 => true, 4302 => true, 4303 => true, 4447 => true, 4448 => true, 4681 => true, 4686 => true, 4687 => true, 4695 => true, 4697 => true, 4702 => true, 4703 => true, 4745 => true, 4750 => true, 4751 => true, 4785 => true, 4790 => true, 4791 => true, 4799 => true, 4801 => true, 4806 => true, 4807 => true, 4823 => true, 4881 => true, 4886 => true, 4887 => true, 4955 => true, 4956 => true, 4989 => true, 4990 => true, 4991 => true, 5018 => true, 5019 => true, 5020 => true, 5021 => true, 5022 => true, 5023 => true, 5110 => true, 5111 => true, 5118 => true, 5119 => true, 5760 => true, 5789 => true, 5790 => true, 5791 => true, 5881 => true, 5882 => true, 5883 => true, 5884 => true, 5885 => true, 5886 => true, 5887 => true, 5901 => true, 5909 => true, 5910 => true, 5911 => true, 5912 => true, 5913 => true, 5914 => true, 5915 => true, 5916 => true, 5917 => true, 5918 => true, 5919 => true, 5943 => true, 5944 => true, 5945 => true, 5946 => true, 5947 => true, 5948 => true, 5949 => true, 5950 => true, 5951 => true, 5972 => true, 5973 => true, 5974 => true, 5975 => true, 5976 => true, 5977 => true, 5978 => true, 5979 => true, 5980 => true, 5981 => true, 5982 => true, 5983 => true, 5997 => true, 6001 => true, 6004 => true, 6005 => true, 6006 => true, 6007 => true, 6008 => true, 6009 => true, 6010 => true, 6011 => true, 6012 => true, 6013 => true, 6014 => true, 6015 => true, 6068 => true, 6069 => true, 6110 => true, 6111 => true, 6122 => true, 6123 => true, 6124 => true, 6125 => true, 6126 => true, 6127 => true, 6138 => true, 6139 => true, 6140 => true, 6141 => true, 6142 => true, 6143 => true, 6150 => true, 6158 => true, 6159 => true, 6170 => true, 6171 => true, 6172 => true, 6173 => true, 6174 => true, 6175 => true, 6265 => true, 6266 => true, 6267 => true, 6268 => true, 6269 => true, 6270 => true, 6271 => true, 6315 => true, 6316 => true, 6317 => true, 6318 => true, 6319 => true, 6390 => true, 6391 => true, 6392 => true, 6393 => true, 6394 => true, 6395 => true, 6396 => true, 6397 => true, 6398 => true, 6399 => true, 6431 => true, 6444 => true, 6445 => true, 6446 => true, 6447 => true, 6460 => true, 6461 => true, 6462 => true, 6463 => true, 6465 => true, 6466 => true, 6467 => true, 6510 => true, 6511 => true, 6517 => true, 6518 => true, 6519 => true, 6520 => true, 6521 => true, 6522 => true, 6523 => true, 6524 => true, 6525 => true, 6526 => true, 6527 => true, 6572 => true, 6573 => true, 6574 => true, 6575 => true, 6602 => true, 6603 => true, 6604 => true, 6605 => true, 6606 => true, 6607 => true, 6619 => true, 6620 => true, 6621 => true, 6684 => true, 6685 => true, 6751 => true, 6781 => true, 6782 => true, 6794 => true, 6795 => true, 6796 => true, 6797 => true, 6798 => true, 6799 => true, 6810 => true, 6811 => true, 6812 => true, 6813 => true, 6814 => true, 6815 => true, 6830 => true, 6831 => true, 6988 => true, 6989 => true, 6990 => true, 6991 => true, 7037 => true, 7038 => true, 7039 => true, 7156 => true, 7157 => true, 7158 => true, 7159 => true, 7160 => true, 7161 => true, 7162 => true, 7163 => true, 7224 => true, 7225 => true, 7226 => true, 7242 => true, 7243 => true, 7244 => true, 7305 => true, 7306 => true, 7307 => true, 7308 => true, 7309 => true, 7310 => true, 7311 => true, 7355 => true, 7356 => true, 7368 => true, 7369 => true, 7370 => true, 7371 => true, 7372 => true, 7373 => true, 7374 => true, 7375 => true, 7419 => true, 7420 => true, 7421 => true, 7422 => true, 7423 => true, 7674 => true, 7958 => true, 7959 => true, 7966 => true, 7967 => true, 8006 => true, 8007 => true, 8014 => true, 8015 => true, 8024 => true, 8026 => true, 8028 => true, 8030 => true, 8062 => true, 8063 => true, 8117 => true, 8133 => true, 8148 => true, 8149 => true, 8156 => true, 8176 => true, 8177 => true, 8181 => true, 8191 => true, 8206 => true, 8207 => true, 8228 => true, 8229 => true, 8230 => true, 8232 => true, 8233 => true, 8234 => true, 8235 => true, 8236 => true, 8237 => true, 8238 => true, 8289 => true, 8290 => true, 8291 => true, 8293 => true, 8294 => true, 8295 => true, 8296 => true, 8297 => true, 8298 => true, 8299 => true, 8300 => true, 8301 => true, 8302 => true, 8303 => true, 8306 => true, 8307 => true, 8335 => true, 8349 => true, 8350 => true, 8351 => true, 8384 => true, 8385 => true, 8386 => true, 8387 => true, 8388 => true, 8389 => true, 8390 => true, 8391 => true, 8392 => true, 8393 => true, 8394 => true, 8395 => true, 8396 => true, 8397 => true, 8398 => true, 8399 => true, 8433 => true, 8434 => true, 8435 => true, 8436 => true, 8437 => true, 8438 => true, 8439 => true, 8440 => true, 8441 => true, 8442 => true, 8443 => true, 8444 => true, 8445 => true, 8446 => true, 8447 => true, 8498 => true, 8579 => true, 8588 => true, 8589 => true, 8590 => true, 8591 => true, 9255 => true, 9256 => true, 9257 => true, 9258 => true, 9259 => true, 9260 => true, 9261 => true, 9262 => true, 9263 => true, 9264 => true, 9265 => true, 9266 => true, 9267 => true, 9268 => true, 9269 => true, 9270 => true, 9271 => true, 9272 => true, 9273 => true, 9274 => true, 9275 => true, 9276 => true, 9277 => true, 9278 => true, 9279 => true, 9291 => true, 9292 => true, 9293 => true, 9294 => true, 9295 => true, 9296 => true, 9297 => true, 9298 => true, 9299 => true, 9300 => true, 9301 => true, 9302 => true, 9303 => true, 9304 => true, 9305 => true, 9306 => true, 9307 => true, 9308 => true, 9309 => true, 9310 => true, 9311 => true, 9352 => true, 9353 => true, 9354 => true, 9355 => true, 9356 => true, 9357 => true, 9358 => true, 9359 => true, 9360 => true, 9361 => true, 9362 => true, 9363 => true, 9364 => true, 9365 => true, 9366 => true, 9367 => true, 9368 => true, 9369 => true, 9370 => true, 9371 => true, 11124 => true, 11125 => true, 11158 => true, 11311 => true, 11359 => true, 11508 => true, 11509 => true, 11510 => true, 11511 => true, 11512 => true, 11558 => true, 11560 => true, 11561 => true, 11562 => true, 11563 => true, 11564 => true, 11566 => true, 11567 => true, 11624 => true, 11625 => true, 11626 => true, 11627 => true, 11628 => true, 11629 => true, 11630 => true, 11633 => true, 11634 => true, 11635 => true, 11636 => true, 11637 => true, 11638 => true, 11639 => true, 11640 => true, 11641 => true, 11642 => true, 11643 => true, 11644 => true, 11645 => true, 11646 => true, 11671 => true, 11672 => true, 11673 => true, 11674 => true, 11675 => true, 11676 => true, 11677 => true, 11678 => true, 11679 => true, 11687 => true, 11695 => true, 11703 => true, 11711 => true, 11719 => true, 11727 => true, 11735 => true, 11743 => true, 11930 => true, 12020 => true, 12021 => true, 12022 => true, 12023 => true, 12024 => true, 12025 => true, 12026 => true, 12027 => true, 12028 => true, 12029 => true, 12030 => true, 12031 => true, 12246 => true, 12247 => true, 12248 => true, 12249 => true, 12250 => true, 12251 => true, 12252 => true, 12253 => true, 12254 => true, 12255 => true, 12256 => true, 12257 => true, 12258 => true, 12259 => true, 12260 => true, 12261 => true, 12262 => true, 12263 => true, 12264 => true, 12265 => true, 12266 => true, 12267 => true, 12268 => true, 12269 => true, 12270 => true, 12271 => true, 12272 => true, 12273 => true, 12274 => true, 12275 => true, 12276 => true, 12277 => true, 12278 => true, 12279 => true, 12280 => true, 12281 => true, 12282 => true, 12283 => true, 12284 => true, 12285 => true, 12286 => true, 12287 => true, 12352 => true, 12439 => true, 12440 => true, 12544 => true, 12545 => true, 12546 => true, 12547 => true, 12548 => true, 12592 => true, 12644 => true, 12687 => true, 12772 => true, 12773 => true, 12774 => true, 12775 => true, 12776 => true, 12777 => true, 12778 => true, 12779 => true, 12780 => true, 12781 => true, 12782 => true, 12783 => true, 12831 => true, 13250 => true, 13255 => true, 13272 => true, 40957 => true, 40958 => true, 40959 => true, 42125 => true, 42126 => true, 42127 => true, 42183 => true, 42184 => true, 42185 => true, 42186 => true, 42187 => true, 42188 => true, 42189 => true, 42190 => true, 42191 => true, 42540 => true, 42541 => true, 42542 => true, 42543 => true, 42544 => true, 42545 => true, 42546 => true, 42547 => true, 42548 => true, 42549 => true, 42550 => true, 42551 => true, 42552 => true, 42553 => true, 42554 => true, 42555 => true, 42556 => true, 42557 => true, 42558 => true, 42559 => true, 42744 => true, 42745 => true, 42746 => true, 42747 => true, 42748 => true, 42749 => true, 42750 => true, 42751 => true, 42944 => true, 42945 => true, 43053 => true, 43054 => true, 43055 => true, 43066 => true, 43067 => true, 43068 => true, 43069 => true, 43070 => true, 43071 => true, 43128 => true, 43129 => true, 43130 => true, 43131 => true, 43132 => true, 43133 => true, 43134 => true, 43135 => true, 43206 => true, 43207 => true, 43208 => true, 43209 => true, 43210 => true, 43211 => true, 43212 => true, 43213 => true, 43226 => true, 43227 => true, 43228 => true, 43229 => true, 43230 => true, 43231 => true, 43348 => true, 43349 => true, 43350 => true, 43351 => true, 43352 => true, 43353 => true, 43354 => true, 43355 => true, 43356 => true, 43357 => true, 43358 => true, 43389 => true, 43390 => true, 43391 => true, 43470 => true, 43482 => true, 43483 => true, 43484 => true, 43485 => true, 43519 => true, 43575 => true, 43576 => true, 43577 => true, 43578 => true, 43579 => true, 43580 => true, 43581 => true, 43582 => true, 43583 => true, 43598 => true, 43599 => true, 43610 => true, 43611 => true, 43715 => true, 43716 => true, 43717 => true, 43718 => true, 43719 => true, 43720 => true, 43721 => true, 43722 => true, 43723 => true, 43724 => true, 43725 => true, 43726 => true, 43727 => true, 43728 => true, 43729 => true, 43730 => true, 43731 => true, 43732 => true, 43733 => true, 43734 => true, 43735 => true, 43736 => true, 43737 => true, 43738 => true, 43767 => true, 43768 => true, 43769 => true, 43770 => true, 43771 => true, 43772 => true, 43773 => true, 43774 => true, 43775 => true, 43776 => true, 43783 => true, 43784 => true, 43791 => true, 43792 => true, 43799 => true, 43800 => true, 43801 => true, 43802 => true, 43803 => true, 43804 => true, 43805 => true, 43806 => true, 43807 => true, 43815 => true, 43823 => true, 43884 => true, 43885 => true, 43886 => true, 43887 => true, 44014 => true, 44015 => true, 44026 => true, 44027 => true, 44028 => true, 44029 => true, 44030 => true, 44031 => true, 55204 => true, 55205 => true, 55206 => true, 55207 => true, 55208 => true, 55209 => true, 55210 => true, 55211 => true, 55212 => true, 55213 => true, 55214 => true, 55215 => true, 55239 => true, 55240 => true, 55241 => true, 55242 => true, 55292 => true, 55293 => true, 55294 => true, 55295 => true, 64110 => true, 64111 => true, 64263 => true, 64264 => true, 64265 => true, 64266 => true, 64267 => true, 64268 => true, 64269 => true, 64270 => true, 64271 => true, 64272 => true, 64273 => true, 64274 => true, 64280 => true, 64281 => true, 64282 => true, 64283 => true, 64284 => true, 64311 => true, 64317 => true, 64319 => true, 64322 => true, 64325 => true, 64450 => true, 64451 => true, 64452 => true, 64453 => true, 64454 => true, 64455 => true, 64456 => true, 64457 => true, 64458 => true, 64459 => true, 64460 => true, 64461 => true, 64462 => true, 64463 => true, 64464 => true, 64465 => true, 64466 => true, 64832 => true, 64833 => true, 64834 => true, 64835 => true, 64836 => true, 64837 => true, 64838 => true, 64839 => true, 64840 => true, 64841 => true, 64842 => true, 64843 => true, 64844 => true, 64845 => true, 64846 => true, 64847 => true, 64912 => true, 64913 => true, 64968 => true, 64969 => true, 64970 => true, 64971 => true, 64972 => true, 64973 => true, 64974 => true, 64975 => true, 65022 => true, 65023 => true, 65042 => true, 65049 => true, 65050 => true, 65051 => true, 65052 => true, 65053 => true, 65054 => true, 65055 => true, 65072 => true, 65106 => true, 65107 => true, 65127 => true, 65132 => true, 65133 => true, 65134 => true, 65135 => true, 65141 => true, 65277 => true, 65278 => true, 65280 => true, 65440 => true, 65471 => true, 65472 => true, 65473 => true, 65480 => true, 65481 => true, 65488 => true, 65489 => true, 65496 => true, 65497 => true, 65501 => true, 65502 => true, 65503 => true, 65511 => true, 65519 => true, 65520 => true, 65521 => true, 65522 => true, 65523 => true, 65524 => true, 65525 => true, 65526 => true, 65527 => true, 65528 => true, 65529 => true, 65530 => true, 65531 => true, 65532 => true, 65533 => true, 65534 => true, 65535 => true, 65548 => true, 65575 => true, 65595 => true, 65598 => true, 65614 => true, 65615 => true, 65787 => true, 65788 => true, 65789 => true, 65790 => true, 65791 => true, 65795 => true, 65796 => true, 65797 => true, 65798 => true, 65844 => true, 65845 => true, 65846 => true, 65935 => true, 65949 => true, 65950 => true, 65951 => true, 66205 => true, 66206 => true, 66207 => true, 66257 => true, 66258 => true, 66259 => true, 66260 => true, 66261 => true, 66262 => true, 66263 => true, 66264 => true, 66265 => true, 66266 => true, 66267 => true, 66268 => true, 66269 => true, 66270 => true, 66271 => true, 66300 => true, 66301 => true, 66302 => true, 66303 => true, 66340 => true, 66341 => true, 66342 => true, 66343 => true, 66344 => true, 66345 => true, 66346 => true, 66347 => true, 66348 => true, 66379 => true, 66380 => true, 66381 => true, 66382 => true, 66383 => true, 66427 => true, 66428 => true, 66429 => true, 66430 => true, 66431 => true, 66462 => true, 66500 => true, 66501 => true, 66502 => true, 66503 => true, 66718 => true, 66719 => true, 66730 => true, 66731 => true, 66732 => true, 66733 => true, 66734 => true, 66735 => true, 66772 => true, 66773 => true, 66774 => true, 66775 => true, 66812 => true, 66813 => true, 66814 => true, 66815 => true, 66856 => true, 66857 => true, 66858 => true, 66859 => true, 66860 => true, 66861 => true, 66862 => true, 66863 => true, 66916 => true, 66917 => true, 66918 => true, 66919 => true, 66920 => true, 66921 => true, 66922 => true, 66923 => true, 66924 => true, 66925 => true, 66926 => true, 67383 => true, 67384 => true, 67385 => true, 67386 => true, 67387 => true, 67388 => true, 67389 => true, 67390 => true, 67391 => true, 67414 => true, 67415 => true, 67416 => true, 67417 => true, 67418 => true, 67419 => true, 67420 => true, 67421 => true, 67422 => true, 67423 => true, 67590 => true, 67591 => true, 67593 => true, 67638 => true, 67641 => true, 67642 => true, 67643 => true, 67645 => true, 67646 => true, 67670 => true, 67743 => true, 67744 => true, 67745 => true, 67746 => true, 67747 => true, 67748 => true, 67749 => true, 67750 => true, 67827 => true, 67830 => true, 67831 => true, 67832 => true, 67833 => true, 67834 => true, 67868 => true, 67869 => true, 67870 => true, 67898 => true, 67899 => true, 67900 => true, 67901 => true, 67902 => true, 68024 => true, 68025 => true, 68026 => true, 68027 => true, 68048 => true, 68049 => true, 68100 => true, 68103 => true, 68104 => true, 68105 => true, 68106 => true, 68107 => true, 68116 => true, 68120 => true, 68150 => true, 68151 => true, 68155 => true, 68156 => true, 68157 => true, 68158 => true, 68169 => true, 68170 => true, 68171 => true, 68172 => true, 68173 => true, 68174 => true, 68175 => true, 68185 => true, 68186 => true, 68187 => true, 68188 => true, 68189 => true, 68190 => true, 68191 => true, 68327 => true, 68328 => true, 68329 => true, 68330 => true, 68343 => true, 68344 => true, 68345 => true, 68346 => true, 68347 => true, 68348 => true, 68349 => true, 68350 => true, 68351 => true, 68406 => true, 68407 => true, 68408 => true, 68438 => true, 68439 => true, 68467 => true, 68468 => true, 68469 => true, 68470 => true, 68471 => true, 68498 => true, 68499 => true, 68500 => true, 68501 => true, 68502 => true, 68503 => true, 68504 => true, 68509 => true, 68510 => true, 68511 => true, 68512 => true, 68513 => true, 68514 => true, 68515 => true, 68516 => true, 68517 => true, 68518 => true, 68519 => true, 68520 => true, 68787 => true, 68788 => true, 68789 => true, 68790 => true, 68791 => true, 68792 => true, 68793 => true, 68794 => true, 68795 => true, 68796 => true, 68797 => true, 68798 => true, 68799 => true, 68851 => true, 68852 => true, 68853 => true, 68854 => true, 68855 => true, 68856 => true, 68857 => true, 68904 => true, 68905 => true, 68906 => true, 68907 => true, 68908 => true, 68909 => true, 68910 => true, 68911 => true, 69247 => true, 69290 => true, 69294 => true, 69295 => true, 69416 => true, 69417 => true, 69418 => true, 69419 => true, 69420 => true, 69421 => true, 69422 => true, 69423 => true, 69580 => true, 69581 => true, 69582 => true, 69583 => true, 69584 => true, 69585 => true, 69586 => true, 69587 => true, 69588 => true, 69589 => true, 69590 => true, 69591 => true, 69592 => true, 69593 => true, 69594 => true, 69595 => true, 69596 => true, 69597 => true, 69598 => true, 69599 => true, 69623 => true, 69624 => true, 69625 => true, 69626 => true, 69627 => true, 69628 => true, 69629 => true, 69630 => true, 69631 => true, 69710 => true, 69711 => true, 69712 => true, 69713 => true, 69744 => true, 69745 => true, 69746 => true, 69747 => true, 69748 => true, 69749 => true, 69750 => true, 69751 => true, 69752 => true, 69753 => true, 69754 => true, 69755 => true, 69756 => true, 69757 => true, 69758 => true, 69821 => true, 69826 => true, 69827 => true, 69828 => true, 69829 => true, 69830 => true, 69831 => true, 69832 => true, 69833 => true, 69834 => true, 69835 => true, 69836 => true, 69837 => true, 69838 => true, 69839 => true, 69865 => true, 69866 => true, 69867 => true, 69868 => true, 69869 => true, 69870 => true, 69871 => true, 69882 => true, 69883 => true, 69884 => true, 69885 => true, 69886 => true, 69887 => true, 69941 => true, 69960 => true, 69961 => true, 69962 => true, 69963 => true, 69964 => true, 69965 => true, 69966 => true, 69967 => true, 70007 => true, 70008 => true, 70009 => true, 70010 => true, 70011 => true, 70012 => true, 70013 => true, 70014 => true, 70015 => true, 70112 => true, 70133 => true, 70134 => true, 70135 => true, 70136 => true, 70137 => true, 70138 => true, 70139 => true, 70140 => true, 70141 => true, 70142 => true, 70143 => true, 70162 => true, 70279 => true, 70281 => true, 70286 => true, 70302 => true, 70314 => true, 70315 => true, 70316 => true, 70317 => true, 70318 => true, 70319 => true, 70379 => true, 70380 => true, 70381 => true, 70382 => true, 70383 => true, 70394 => true, 70395 => true, 70396 => true, 70397 => true, 70398 => true, 70399 => true, 70404 => true, 70413 => true, 70414 => true, 70417 => true, 70418 => true, 70441 => true, 70449 => true, 70452 => true, 70458 => true, 70469 => true, 70470 => true, 70473 => true, 70474 => true, 70478 => true, 70479 => true, 70481 => true, 70482 => true, 70483 => true, 70484 => true, 70485 => true, 70486 => true, 70488 => true, 70489 => true, 70490 => true, 70491 => true, 70492 => true, 70500 => true, 70501 => true, 70509 => true, 70510 => true, 70511 => true, 70748 => true, 70754 => true, 70755 => true, 70756 => true, 70757 => true, 70758 => true, 70759 => true, 70760 => true, 70761 => true, 70762 => true, 70763 => true, 70764 => true, 70765 => true, 70766 => true, 70767 => true, 70768 => true, 70769 => true, 70770 => true, 70771 => true, 70772 => true, 70773 => true, 70774 => true, 70775 => true, 70776 => true, 70777 => true, 70778 => true, 70779 => true, 70780 => true, 70781 => true, 70782 => true, 70783 => true, 70856 => true, 70857 => true, 70858 => true, 70859 => true, 70860 => true, 70861 => true, 70862 => true, 70863 => true, 71094 => true, 71095 => true, 71237 => true, 71238 => true, 71239 => true, 71240 => true, 71241 => true, 71242 => true, 71243 => true, 71244 => true, 71245 => true, 71246 => true, 71247 => true, 71258 => true, 71259 => true, 71260 => true, 71261 => true, 71262 => true, 71263 => true, 71277 => true, 71278 => true, 71279 => true, 71280 => true, 71281 => true, 71282 => true, 71283 => true, 71284 => true, 71285 => true, 71286 => true, 71287 => true, 71288 => true, 71289 => true, 71290 => true, 71291 => true, 71292 => true, 71293 => true, 71294 => true, 71295 => true, 71353 => true, 71354 => true, 71355 => true, 71356 => true, 71357 => true, 71358 => true, 71359 => true, 71451 => true, 71452 => true, 71468 => true, 71469 => true, 71470 => true, 71471 => true, 71923 => true, 71924 => true, 71925 => true, 71926 => true, 71927 => true, 71928 => true, 71929 => true, 71930 => true, 71931 => true, 71932 => true, 71933 => true, 71934 => true, 71943 => true, 71944 => true, 71946 => true, 71947 => true, 71956 => true, 71959 => true, 71990 => true, 71993 => true, 71994 => true, 72007 => true, 72008 => true, 72009 => true, 72010 => true, 72011 => true, 72012 => true, 72013 => true, 72014 => true, 72015 => true, 72104 => true, 72105 => true, 72152 => true, 72153 => true, 72165 => true, 72166 => true, 72167 => true, 72168 => true, 72169 => true, 72170 => true, 72171 => true, 72172 => true, 72173 => true, 72174 => true, 72175 => true, 72176 => true, 72177 => true, 72178 => true, 72179 => true, 72180 => true, 72181 => true, 72182 => true, 72183 => true, 72184 => true, 72185 => true, 72186 => true, 72187 => true, 72188 => true, 72189 => true, 72190 => true, 72191 => true, 72264 => true, 72265 => true, 72266 => true, 72267 => true, 72268 => true, 72269 => true, 72270 => true, 72271 => true, 72355 => true, 72356 => true, 72357 => true, 72358 => true, 72359 => true, 72360 => true, 72361 => true, 72362 => true, 72363 => true, 72364 => true, 72365 => true, 72366 => true, 72367 => true, 72368 => true, 72369 => true, 72370 => true, 72371 => true, 72372 => true, 72373 => true, 72374 => true, 72375 => true, 72376 => true, 72377 => true, 72378 => true, 72379 => true, 72380 => true, 72381 => true, 72382 => true, 72383 => true, 72713 => true, 72759 => true, 72774 => true, 72775 => true, 72776 => true, 72777 => true, 72778 => true, 72779 => true, 72780 => true, 72781 => true, 72782 => true, 72783 => true, 72813 => true, 72814 => true, 72815 => true, 72848 => true, 72849 => true, 72872 => true, 72967 => true, 72970 => true, 73015 => true, 73016 => true, 73017 => true, 73019 => true, 73022 => true, 73032 => true, 73033 => true, 73034 => true, 73035 => true, 73036 => true, 73037 => true, 73038 => true, 73039 => true, 73050 => true, 73051 => true, 73052 => true, 73053 => true, 73054 => true, 73055 => true, 73062 => true, 73065 => true, 73103 => true, 73106 => true, 73113 => true, 73114 => true, 73115 => true, 73116 => true, 73117 => true, 73118 => true, 73119 => true, 73649 => true, 73650 => true, 73651 => true, 73652 => true, 73653 => true, 73654 => true, 73655 => true, 73656 => true, 73657 => true, 73658 => true, 73659 => true, 73660 => true, 73661 => true, 73662 => true, 73663 => true, 73714 => true, 73715 => true, 73716 => true, 73717 => true, 73718 => true, 73719 => true, 73720 => true, 73721 => true, 73722 => true, 73723 => true, 73724 => true, 73725 => true, 73726 => true, 74863 => true, 74869 => true, 74870 => true, 74871 => true, 74872 => true, 74873 => true, 74874 => true, 74875 => true, 74876 => true, 74877 => true, 74878 => true, 74879 => true, 78895 => true, 78896 => true, 78897 => true, 78898 => true, 78899 => true, 78900 => true, 78901 => true, 78902 => true, 78903 => true, 78904 => true, 92729 => true, 92730 => true, 92731 => true, 92732 => true, 92733 => true, 92734 => true, 92735 => true, 92767 => true, 92778 => true, 92779 => true, 92780 => true, 92781 => true, 92910 => true, 92911 => true, 92918 => true, 92919 => true, 92920 => true, 92921 => true, 92922 => true, 92923 => true, 92924 => true, 92925 => true, 92926 => true, 92927 => true, 92998 => true, 92999 => true, 93000 => true, 93001 => true, 93002 => true, 93003 => true, 93004 => true, 93005 => true, 93006 => true, 93007 => true, 93018 => true, 93026 => true, 93048 => true, 93049 => true, 93050 => true, 93051 => true, 93052 => true, 94027 => true, 94028 => true, 94029 => true, 94030 => true, 94088 => true, 94089 => true, 94090 => true, 94091 => true, 94092 => true, 94093 => true, 94094 => true, 94181 => true, 94182 => true, 94183 => true, 94184 => true, 94185 => true, 94186 => true, 94187 => true, 94188 => true, 94189 => true, 94190 => true, 94191 => true, 94194 => true, 94195 => true, 94196 => true, 94197 => true, 94198 => true, 94199 => true, 94200 => true, 94201 => true, 94202 => true, 94203 => true, 94204 => true, 94205 => true, 94206 => true, 94207 => true, 100344 => true, 100345 => true, 100346 => true, 100347 => true, 100348 => true, 100349 => true, 100350 => true, 100351 => true, 110931 => true, 110932 => true, 110933 => true, 110934 => true, 110935 => true, 110936 => true, 110937 => true, 110938 => true, 110939 => true, 110940 => true, 110941 => true, 110942 => true, 110943 => true, 110944 => true, 110945 => true, 110946 => true, 110947 => true, 110952 => true, 110953 => true, 110954 => true, 110955 => true, 110956 => true, 110957 => true, 110958 => true, 110959 => true, 113771 => true, 113772 => true, 113773 => true, 113774 => true, 113775 => true, 113789 => true, 113790 => true, 113791 => true, 113801 => true, 113802 => true, 113803 => true, 113804 => true, 113805 => true, 113806 => true, 113807 => true, 113818 => true, 113819 => true, 119030 => true, 119031 => true, 119032 => true, 119033 => true, 119034 => true, 119035 => true, 119036 => true, 119037 => true, 119038 => true, 119039 => true, 119079 => true, 119080 => true, 119155 => true, 119156 => true, 119157 => true, 119158 => true, 119159 => true, 119160 => true, 119161 => true, 119162 => true, 119273 => true, 119274 => true, 119275 => true, 119276 => true, 119277 => true, 119278 => true, 119279 => true, 119280 => true, 119281 => true, 119282 => true, 119283 => true, 119284 => true, 119285 => true, 119286 => true, 119287 => true, 119288 => true, 119289 => true, 119290 => true, 119291 => true, 119292 => true, 119293 => true, 119294 => true, 119295 => true, 119540 => true, 119541 => true, 119542 => true, 119543 => true, 119544 => true, 119545 => true, 119546 => true, 119547 => true, 119548 => true, 119549 => true, 119550 => true, 119551 => true, 119639 => true, 119640 => true, 119641 => true, 119642 => true, 119643 => true, 119644 => true, 119645 => true, 119646 => true, 119647 => true, 119893 => true, 119965 => true, 119968 => true, 119969 => true, 119971 => true, 119972 => true, 119975 => true, 119976 => true, 119981 => true, 119994 => true, 119996 => true, 120004 => true, 120070 => true, 120075 => true, 120076 => true, 120085 => true, 120093 => true, 120122 => true, 120127 => true, 120133 => true, 120135 => true, 120136 => true, 120137 => true, 120145 => true, 120486 => true, 120487 => true, 120780 => true, 120781 => true, 121484 => true, 121485 => true, 121486 => true, 121487 => true, 121488 => true, 121489 => true, 121490 => true, 121491 => true, 121492 => true, 121493 => true, 121494 => true, 121495 => true, 121496 => true, 121497 => true, 121498 => true, 121504 => true, 122887 => true, 122905 => true, 122906 => true, 122914 => true, 122917 => true, 123181 => true, 123182 => true, 123183 => true, 123198 => true, 123199 => true, 123210 => true, 123211 => true, 123212 => true, 123213 => true, 123642 => true, 123643 => true, 123644 => true, 123645 => true, 123646 => true, 125125 => true, 125126 => true, 125260 => true, 125261 => true, 125262 => true, 125263 => true, 125274 => true, 125275 => true, 125276 => true, 125277 => true, 126468 => true, 126496 => true, 126499 => true, 126501 => true, 126502 => true, 126504 => true, 126515 => true, 126520 => true, 126522 => true, 126524 => true, 126525 => true, 126526 => true, 126527 => true, 126528 => true, 126529 => true, 126531 => true, 126532 => true, 126533 => true, 126534 => true, 126536 => true, 126538 => true, 126540 => true, 126544 => true, 126547 => true, 126549 => true, 126550 => true, 126552 => true, 126554 => true, 126556 => true, 126558 => true, 126560 => true, 126563 => true, 126565 => true, 126566 => true, 126571 => true, 126579 => true, 126584 => true, 126589 => true, 126591 => true, 126602 => true, 126620 => true, 126621 => true, 126622 => true, 126623 => true, 126624 => true, 126628 => true, 126634 => true, 127020 => true, 127021 => true, 127022 => true, 127023 => true, 127124 => true, 127125 => true, 127126 => true, 127127 => true, 127128 => true, 127129 => true, 127130 => true, 127131 => true, 127132 => true, 127133 => true, 127134 => true, 127135 => true, 127151 => true, 127152 => true, 127168 => true, 127184 => true, 127222 => true, 127223 => true, 127224 => true, 127225 => true, 127226 => true, 127227 => true, 127228 => true, 127229 => true, 127230 => true, 127231 => true, 127232 => true, 127491 => true, 127492 => true, 127493 => true, 127494 => true, 127495 => true, 127496 => true, 127497 => true, 127498 => true, 127499 => true, 127500 => true, 127501 => true, 127502 => true, 127503 => true, 127548 => true, 127549 => true, 127550 => true, 127551 => true, 127561 => true, 127562 => true, 127563 => true, 127564 => true, 127565 => true, 127566 => true, 127567 => true, 127570 => true, 127571 => true, 127572 => true, 127573 => true, 127574 => true, 127575 => true, 127576 => true, 127577 => true, 127578 => true, 127579 => true, 127580 => true, 127581 => true, 127582 => true, 127583 => true, 128728 => true, 128729 => true, 128730 => true, 128731 => true, 128732 => true, 128733 => true, 128734 => true, 128735 => true, 128749 => true, 128750 => true, 128751 => true, 128765 => true, 128766 => true, 128767 => true, 128884 => true, 128885 => true, 128886 => true, 128887 => true, 128888 => true, 128889 => true, 128890 => true, 128891 => true, 128892 => true, 128893 => true, 128894 => true, 128895 => true, 128985 => true, 128986 => true, 128987 => true, 128988 => true, 128989 => true, 128990 => true, 128991 => true, 129004 => true, 129005 => true, 129006 => true, 129007 => true, 129008 => true, 129009 => true, 129010 => true, 129011 => true, 129012 => true, 129013 => true, 129014 => true, 129015 => true, 129016 => true, 129017 => true, 129018 => true, 129019 => true, 129020 => true, 129021 => true, 129022 => true, 129023 => true, 129036 => true, 129037 => true, 129038 => true, 129039 => true, 129096 => true, 129097 => true, 129098 => true, 129099 => true, 129100 => true, 129101 => true, 129102 => true, 129103 => true, 129114 => true, 129115 => true, 129116 => true, 129117 => true, 129118 => true, 129119 => true, 129160 => true, 129161 => true, 129162 => true, 129163 => true, 129164 => true, 129165 => true, 129166 => true, 129167 => true, 129198 => true, 129199 => true, 129401 => true, 129484 => true, 129620 => true, 129621 => true, 129622 => true, 129623 => true, 129624 => true, 129625 => true, 129626 => true, 129627 => true, 129628 => true, 129629 => true, 129630 => true, 129631 => true, 129646 => true, 129647 => true, 129653 => true, 129654 => true, 129655 => true, 129659 => true, 129660 => true, 129661 => true, 129662 => true, 129663 => true, 129671 => true, 129672 => true, 129673 => true, 129674 => true, 129675 => true, 129676 => true, 129677 => true, 129678 => true, 129679 => true, 129705 => true, 129706 => true, 129707 => true, 129708 => true, 129709 => true, 129710 => true, 129711 => true, 129719 => true, 129720 => true, 129721 => true, 129722 => true, 129723 => true, 129724 => true, 129725 => true, 129726 => true, 129727 => true, 129731 => true, 129732 => true, 129733 => true, 129734 => true, 129735 => true, 129736 => true, 129737 => true, 129738 => true, 129739 => true, 129740 => true, 129741 => true, 129742 => true, 129743 => true, 129939 => true, 131070 => true, 131071 => true, 177973 => true, 177974 => true, 177975 => true, 177976 => true, 177977 => true, 177978 => true, 177979 => true, 177980 => true, 177981 => true, 177982 => true, 177983 => true, 178206 => true, 178207 => true, 183970 => true, 183971 => true, 183972 => true, 183973 => true, 183974 => true, 183975 => true, 183976 => true, 183977 => true, 183978 => true, 183979 => true, 183980 => true, 183981 => true, 183982 => true, 183983 => true, 194664 => true, 194676 => true, 194847 => true, 194911 => true, 195007 => true, 196606 => true, 196607 => true, 262142 => true, 262143 => true, 327678 => true, 327679 => true, 393214 => true, 393215 => true, 458750 => true, 458751 => true, 524286 => true, 524287 => true, 589822 => true, 589823 => true, 655358 => true, 655359 => true, 720894 => true, 720895 => true, 786430 => true, 786431 => true, 851966 => true, 851967 => true, 917502 => true, 917503 => true, 917504 => true, 917505 => true, 917506 => true, 917507 => true, 917508 => true, 917509 => true, 917510 => true, 917511 => true, 917512 => true, 917513 => true, 917514 => true, 917515 => true, 917516 => true, 917517 => true, 917518 => true, 917519 => true, 917520 => true, 917521 => true, 917522 => true, 917523 => true, 917524 => true, 917525 => true, 917526 => true, 917527 => true, 917528 => true, 917529 => true, 917530 => true, 917531 => true, 917532 => true, 917533 => true, 917534 => true, 917535 => true, 983038 => true, 983039 => true, 1048574 => true, 1048575 => true, 1114110 => true, 1114111 => true, ); polyfill-intl-idn/Resources/unidata/deviation.php000064400000000123150432043200016171 0ustar00 'ss', 962 => 'σ', 8204 => '', 8205 => '', ); polyfill-intl-idn/Resources/unidata/ignored.php000064400000011340150432043200015641 0ustar00 true, 847 => true, 6155 => true, 6156 => true, 6157 => true, 8203 => true, 8288 => true, 8292 => true, 65024 => true, 65025 => true, 65026 => true, 65027 => true, 65028 => true, 65029 => true, 65030 => true, 65031 => true, 65032 => true, 65033 => true, 65034 => true, 65035 => true, 65036 => true, 65037 => true, 65038 => true, 65039 => true, 65279 => true, 113824 => true, 113825 => true, 113826 => true, 113827 => true, 917760 => true, 917761 => true, 917762 => true, 917763 => true, 917764 => true, 917765 => true, 917766 => true, 917767 => true, 917768 => true, 917769 => true, 917770 => true, 917771 => true, 917772 => true, 917773 => true, 917774 => true, 917775 => true, 917776 => true, 917777 => true, 917778 => true, 917779 => true, 917780 => true, 917781 => true, 917782 => true, 917783 => true, 917784 => true, 917785 => true, 917786 => true, 917787 => true, 917788 => true, 917789 => true, 917790 => true, 917791 => true, 917792 => true, 917793 => true, 917794 => true, 917795 => true, 917796 => true, 917797 => true, 917798 => true, 917799 => true, 917800 => true, 917801 => true, 917802 => true, 917803 => true, 917804 => true, 917805 => true, 917806 => true, 917807 => true, 917808 => true, 917809 => true, 917810 => true, 917811 => true, 917812 => true, 917813 => true, 917814 => true, 917815 => true, 917816 => true, 917817 => true, 917818 => true, 917819 => true, 917820 => true, 917821 => true, 917822 => true, 917823 => true, 917824 => true, 917825 => true, 917826 => true, 917827 => true, 917828 => true, 917829 => true, 917830 => true, 917831 => true, 917832 => true, 917833 => true, 917834 => true, 917835 => true, 917836 => true, 917837 => true, 917838 => true, 917839 => true, 917840 => true, 917841 => true, 917842 => true, 917843 => true, 917844 => true, 917845 => true, 917846 => true, 917847 => true, 917848 => true, 917849 => true, 917850 => true, 917851 => true, 917852 => true, 917853 => true, 917854 => true, 917855 => true, 917856 => true, 917857 => true, 917858 => true, 917859 => true, 917860 => true, 917861 => true, 917862 => true, 917863 => true, 917864 => true, 917865 => true, 917866 => true, 917867 => true, 917868 => true, 917869 => true, 917870 => true, 917871 => true, 917872 => true, 917873 => true, 917874 => true, 917875 => true, 917876 => true, 917877 => true, 917878 => true, 917879 => true, 917880 => true, 917881 => true, 917882 => true, 917883 => true, 917884 => true, 917885 => true, 917886 => true, 917887 => true, 917888 => true, 917889 => true, 917890 => true, 917891 => true, 917892 => true, 917893 => true, 917894 => true, 917895 => true, 917896 => true, 917897 => true, 917898 => true, 917899 => true, 917900 => true, 917901 => true, 917902 => true, 917903 => true, 917904 => true, 917905 => true, 917906 => true, 917907 => true, 917908 => true, 917909 => true, 917910 => true, 917911 => true, 917912 => true, 917913 => true, 917914 => true, 917915 => true, 917916 => true, 917917 => true, 917918 => true, 917919 => true, 917920 => true, 917921 => true, 917922 => true, 917923 => true, 917924 => true, 917925 => true, 917926 => true, 917927 => true, 917928 => true, 917929 => true, 917930 => true, 917931 => true, 917932 => true, 917933 => true, 917934 => true, 917935 => true, 917936 => true, 917937 => true, 917938 => true, 917939 => true, 917940 => true, 917941 => true, 917942 => true, 917943 => true, 917944 => true, 917945 => true, 917946 => true, 917947 => true, 917948 => true, 917949 => true, 917950 => true, 917951 => true, 917952 => true, 917953 => true, 917954 => true, 917955 => true, 917956 => true, 917957 => true, 917958 => true, 917959 => true, 917960 => true, 917961 => true, 917962 => true, 917963 => true, 917964 => true, 917965 => true, 917966 => true, 917967 => true, 917968 => true, 917969 => true, 917970 => true, 917971 => true, 917972 => true, 917973 => true, 917974 => true, 917975 => true, 917976 => true, 917977 => true, 917978 => true, 917979 => true, 917980 => true, 917981 => true, 917982 => true, 917983 => true, 917984 => true, 917985 => true, 917986 => true, 917987 => true, 917988 => true, 917989 => true, 917990 => true, 917991 => true, 917992 => true, 917993 => true, 917994 => true, 917995 => true, 917996 => true, 917997 => true, 917998 => true, 917999 => true, ); polyfill-intl-idn/Resources/unidata/disallowed_STD3_mapped.php000064400000012502150432043200020465 0ustar00 ' ', 168 => ' ̈', 175 => ' ̄', 180 => ' ́', 184 => ' ̧', 728 => ' ̆', 729 => ' ̇', 730 => ' ̊', 731 => ' ̨', 732 => ' ̃', 733 => ' ̋', 890 => ' ι', 894 => ';', 900 => ' ́', 901 => ' ̈́', 8125 => ' ̓', 8127 => ' ̓', 8128 => ' ͂', 8129 => ' ̈͂', 8141 => ' ̓̀', 8142 => ' ̓́', 8143 => ' ̓͂', 8157 => ' ̔̀', 8158 => ' ̔́', 8159 => ' ̔͂', 8173 => ' ̈̀', 8174 => ' ̈́', 8175 => '`', 8189 => ' ́', 8190 => ' ̔', 8192 => ' ', 8193 => ' ', 8194 => ' ', 8195 => ' ', 8196 => ' ', 8197 => ' ', 8198 => ' ', 8199 => ' ', 8200 => ' ', 8201 => ' ', 8202 => ' ', 8215 => ' ̳', 8239 => ' ', 8252 => '!!', 8254 => ' ̅', 8263 => '??', 8264 => '?!', 8265 => '!?', 8287 => ' ', 8314 => '+', 8316 => '=', 8317 => '(', 8318 => ')', 8330 => '+', 8332 => '=', 8333 => '(', 8334 => ')', 8448 => 'a/c', 8449 => 'a/s', 8453 => 'c/o', 8454 => 'c/u', 9332 => '(1)', 9333 => '(2)', 9334 => '(3)', 9335 => '(4)', 9336 => '(5)', 9337 => '(6)', 9338 => '(7)', 9339 => '(8)', 9340 => '(9)', 9341 => '(10)', 9342 => '(11)', 9343 => '(12)', 9344 => '(13)', 9345 => '(14)', 9346 => '(15)', 9347 => '(16)', 9348 => '(17)', 9349 => '(18)', 9350 => '(19)', 9351 => '(20)', 9372 => '(a)', 9373 => '(b)', 9374 => '(c)', 9375 => '(d)', 9376 => '(e)', 9377 => '(f)', 9378 => '(g)', 9379 => '(h)', 9380 => '(i)', 9381 => '(j)', 9382 => '(k)', 9383 => '(l)', 9384 => '(m)', 9385 => '(n)', 9386 => '(o)', 9387 => '(p)', 9388 => '(q)', 9389 => '(r)', 9390 => '(s)', 9391 => '(t)', 9392 => '(u)', 9393 => '(v)', 9394 => '(w)', 9395 => '(x)', 9396 => '(y)', 9397 => '(z)', 10868 => '::=', 10869 => '==', 10870 => '===', 12288 => ' ', 12443 => ' ゙', 12444 => ' ゚', 12800 => '(ᄀ)', 12801 => '(ᄂ)', 12802 => '(ᄃ)', 12803 => '(ᄅ)', 12804 => '(ᄆ)', 12805 => '(ᄇ)', 12806 => '(ᄉ)', 12807 => '(ᄋ)', 12808 => '(ᄌ)', 12809 => '(ᄎ)', 12810 => '(ᄏ)', 12811 => '(ᄐ)', 12812 => '(ᄑ)', 12813 => '(ᄒ)', 12814 => '(가)', 12815 => '(나)', 12816 => '(다)', 12817 => '(라)', 12818 => '(마)', 12819 => '(바)', 12820 => '(사)', 12821 => '(아)', 12822 => '(자)', 12823 => '(차)', 12824 => '(카)', 12825 => '(타)', 12826 => '(파)', 12827 => '(하)', 12828 => '(주)', 12829 => '(오전)', 12830 => '(오후)', 12832 => '(一)', 12833 => '(二)', 12834 => '(三)', 12835 => '(四)', 12836 => '(五)', 12837 => '(六)', 12838 => '(七)', 12839 => '(八)', 12840 => '(九)', 12841 => '(十)', 12842 => '(月)', 12843 => '(火)', 12844 => '(水)', 12845 => '(木)', 12846 => '(金)', 12847 => '(土)', 12848 => '(日)', 12849 => '(株)', 12850 => '(有)', 12851 => '(社)', 12852 => '(名)', 12853 => '(特)', 12854 => '(財)', 12855 => '(祝)', 12856 => '(労)', 12857 => '(代)', 12858 => '(呼)', 12859 => '(学)', 12860 => '(監)', 12861 => '(企)', 12862 => '(資)', 12863 => '(協)', 12864 => '(祭)', 12865 => '(休)', 12866 => '(自)', 12867 => '(至)', 64297 => '+', 64606 => ' ٌّ', 64607 => ' ٍّ', 64608 => ' َّ', 64609 => ' ُّ', 64610 => ' ِّ', 64611 => ' ّٰ', 65018 => 'صلى الله عليه وسلم', 65019 => 'جل جلاله', 65040 => ',', 65043 => ':', 65044 => ';', 65045 => '!', 65046 => '?', 65075 => '_', 65076 => '_', 65077 => '(', 65078 => ')', 65079 => '{', 65080 => '}', 65095 => '[', 65096 => ']', 65097 => ' ̅', 65098 => ' ̅', 65099 => ' ̅', 65100 => ' ̅', 65101 => '_', 65102 => '_', 65103 => '_', 65104 => ',', 65108 => ';', 65109 => ':', 65110 => '?', 65111 => '!', 65113 => '(', 65114 => ')', 65115 => '{', 65116 => '}', 65119 => '#', 65120 => '&', 65121 => '*', 65122 => '+', 65124 => '<', 65125 => '>', 65126 => '=', 65128 => '\\', 65129 => '$', 65130 => '%', 65131 => '@', 65136 => ' ً', 65138 => ' ٌ', 65140 => ' ٍ', 65142 => ' َ', 65144 => ' ُ', 65146 => ' ِ', 65148 => ' ّ', 65150 => ' ْ', 65281 => '!', 65282 => '"', 65283 => '#', 65284 => '$', 65285 => '%', 65286 => '&', 65287 => '\'', 65288 => '(', 65289 => ')', 65290 => '*', 65291 => '+', 65292 => ',', 65295 => '/', 65306 => ':', 65307 => ';', 65308 => '<', 65309 => '=', 65310 => '>', 65311 => '?', 65312 => '@', 65339 => '[', 65340 => '\\', 65341 => ']', 65342 => '^', 65343 => '_', 65344 => '`', 65371 => '{', 65372 => '|', 65373 => '}', 65374 => '~', 65507 => ' ̄', 127233 => '0,', 127234 => '1,', 127235 => '2,', 127236 => '3,', 127237 => '4,', 127238 => '5,', 127239 => '6,', 127240 => '7,', 127241 => '8,', 127242 => '9,', 127248 => '(a)', 127249 => '(b)', 127250 => '(c)', 127251 => '(d)', 127252 => '(e)', 127253 => '(f)', 127254 => '(g)', 127255 => '(h)', 127256 => '(i)', 127257 => '(j)', 127258 => '(k)', 127259 => '(l)', 127260 => '(m)', 127261 => '(n)', 127262 => '(o)', 127263 => '(p)', 127264 => '(q)', 127265 => '(r)', 127266 => '(s)', 127267 => '(t)', 127268 => '(u)', 127269 => '(v)', 127270 => '(w)', 127271 => '(x)', 127272 => '(y)', 127273 => '(z)', ); polyfill-intl-idn/Resources/unidata/virama.php000064400000001525150432043200015475 0ustar00 9, 2509 => 9, 2637 => 9, 2765 => 9, 2893 => 9, 3021 => 9, 3149 => 9, 3277 => 9, 3387 => 9, 3388 => 9, 3405 => 9, 3530 => 9, 3642 => 9, 3770 => 9, 3972 => 9, 4153 => 9, 4154 => 9, 5908 => 9, 5940 => 9, 6098 => 9, 6752 => 9, 6980 => 9, 7082 => 9, 7083 => 9, 7154 => 9, 7155 => 9, 11647 => 9, 43014 => 9, 43052 => 9, 43204 => 9, 43347 => 9, 43456 => 9, 43766 => 9, 44013 => 9, 68159 => 9, 69702 => 9, 69759 => 9, 69817 => 9, 69939 => 9, 69940 => 9, 70080 => 9, 70197 => 9, 70378 => 9, 70477 => 9, 70722 => 9, 70850 => 9, 71103 => 9, 71231 => 9, 71350 => 9, 71467 => 9, 71737 => 9, 71997 => 9, 71998 => 9, 72160 => 9, 72244 => 9, 72263 => 9, 72345 => 9, 72767 => 9, 73028 => 9, 73029 => 9, 73111 => 9, ); polyfill-intl-idn/Info.php000064400000000755150432043200011516 0ustar00 and Trevor Rowbotham * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Intl\Idn; /** * @internal */ class Info { public $bidiDomain = false; public $errors = 0; public $validBidiDomain = true; public $transitionalDifferent = false; } polyfill-intl-idn/README.md000064400000000725150432043200011366 0ustar00Symfony Polyfill / Intl: Idn ============================ This component provides [`idn_to_ascii`](https://php.net/idn-to-ascii) and [`idn_to_utf8`](https://php.net/idn-to-utf8) functions to users who run php versions without the [Intl](https://php.net/intl) extension. More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= This library is released under the [MIT license](LICENSE). polyfill-intl-idn/bootstrap80.php000064400000007634150432043200013013 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Intl\Idn as p; if (!defined('U_IDNA_PROHIBITED_ERROR')) { define('U_IDNA_PROHIBITED_ERROR', 66560); } if (!defined('U_IDNA_ERROR_START')) { define('U_IDNA_ERROR_START', 66560); } if (!defined('U_IDNA_UNASSIGNED_ERROR')) { define('U_IDNA_UNASSIGNED_ERROR', 66561); } if (!defined('U_IDNA_CHECK_BIDI_ERROR')) { define('U_IDNA_CHECK_BIDI_ERROR', 66562); } if (!defined('U_IDNA_STD3_ASCII_RULES_ERROR')) { define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); } if (!defined('U_IDNA_ACE_PREFIX_ERROR')) { define('U_IDNA_ACE_PREFIX_ERROR', 66564); } if (!defined('U_IDNA_VERIFICATION_ERROR')) { define('U_IDNA_VERIFICATION_ERROR', 66565); } if (!defined('U_IDNA_LABEL_TOO_LONG_ERROR')) { define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); } if (!defined('U_IDNA_ZERO_LENGTH_LABEL_ERROR')) { define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); } if (!defined('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR')) { define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); } if (!defined('U_IDNA_ERROR_LIMIT')) { define('U_IDNA_ERROR_LIMIT', 66569); } if (!defined('U_STRINGPREP_PROHIBITED_ERROR')) { define('U_STRINGPREP_PROHIBITED_ERROR', 66560); } if (!defined('U_STRINGPREP_UNASSIGNED_ERROR')) { define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); } if (!defined('U_STRINGPREP_CHECK_BIDI_ERROR')) { define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); } if (!defined('IDNA_DEFAULT')) { define('IDNA_DEFAULT', 0); } if (!defined('IDNA_ALLOW_UNASSIGNED')) { define('IDNA_ALLOW_UNASSIGNED', 1); } if (!defined('IDNA_USE_STD3_RULES')) { define('IDNA_USE_STD3_RULES', 2); } if (!defined('IDNA_CHECK_BIDI')) { define('IDNA_CHECK_BIDI', 4); } if (!defined('IDNA_CHECK_CONTEXTJ')) { define('IDNA_CHECK_CONTEXTJ', 8); } if (!defined('IDNA_NONTRANSITIONAL_TO_ASCII')) { define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); } if (!defined('IDNA_NONTRANSITIONAL_TO_UNICODE')) { define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); } if (!defined('INTL_IDNA_VARIANT_UTS46')) { define('INTL_IDNA_VARIANT_UTS46', 1); } if (!defined('IDNA_ERROR_EMPTY_LABEL')) { define('IDNA_ERROR_EMPTY_LABEL', 1); } if (!defined('IDNA_ERROR_LABEL_TOO_LONG')) { define('IDNA_ERROR_LABEL_TOO_LONG', 2); } if (!defined('IDNA_ERROR_DOMAIN_NAME_TOO_LONG')) { define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); } if (!defined('IDNA_ERROR_LEADING_HYPHEN')) { define('IDNA_ERROR_LEADING_HYPHEN', 8); } if (!defined('IDNA_ERROR_TRAILING_HYPHEN')) { define('IDNA_ERROR_TRAILING_HYPHEN', 16); } if (!defined('IDNA_ERROR_HYPHEN_3_4')) { define('IDNA_ERROR_HYPHEN_3_4', 32); } if (!defined('IDNA_ERROR_LEADING_COMBINING_MARK')) { define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); } if (!defined('IDNA_ERROR_DISALLOWED')) { define('IDNA_ERROR_DISALLOWED', 128); } if (!defined('IDNA_ERROR_PUNYCODE')) { define('IDNA_ERROR_PUNYCODE', 256); } if (!defined('IDNA_ERROR_LABEL_HAS_DOT')) { define('IDNA_ERROR_LABEL_HAS_DOT', 512); } if (!defined('IDNA_ERROR_INVALID_ACE_LABEL')) { define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); } if (!defined('IDNA_ERROR_BIDI')) { define('IDNA_ERROR_BIDI', 2048); } if (!defined('IDNA_ERROR_CONTEXTJ')) { define('IDNA_ERROR_CONTEXTJ', 4096); } if (!function_exists('idn_to_ascii')) { function idn_to_ascii(?string $domain, ?int $flags = 0, ?int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = null): string|false { return p\Idn::idn_to_ascii((string) $domain, (int) $flags, (int) $variant, $idna_info); } } if (!function_exists('idn_to_utf8')) { function idn_to_utf8(?string $domain, ?int $flags = 0, ?int $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = null): string|false { return p\Idn::idn_to_utf8((string) $domain, (int) $flags, (int) $variant, $idna_info); } } polyfill-intl-idn/bootstrap.php000064400000011021150432043200012624 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Intl\Idn as p; if (extension_loaded('intl')) { return; } if (\PHP_VERSION_ID >= 80000) { return require __DIR__.'/bootstrap80.php'; } if (!defined('U_IDNA_PROHIBITED_ERROR')) { define('U_IDNA_PROHIBITED_ERROR', 66560); } if (!defined('U_IDNA_ERROR_START')) { define('U_IDNA_ERROR_START', 66560); } if (!defined('U_IDNA_UNASSIGNED_ERROR')) { define('U_IDNA_UNASSIGNED_ERROR', 66561); } if (!defined('U_IDNA_CHECK_BIDI_ERROR')) { define('U_IDNA_CHECK_BIDI_ERROR', 66562); } if (!defined('U_IDNA_STD3_ASCII_RULES_ERROR')) { define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); } if (!defined('U_IDNA_ACE_PREFIX_ERROR')) { define('U_IDNA_ACE_PREFIX_ERROR', 66564); } if (!defined('U_IDNA_VERIFICATION_ERROR')) { define('U_IDNA_VERIFICATION_ERROR', 66565); } if (!defined('U_IDNA_LABEL_TOO_LONG_ERROR')) { define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); } if (!defined('U_IDNA_ZERO_LENGTH_LABEL_ERROR')) { define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); } if (!defined('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR')) { define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); } if (!defined('U_IDNA_ERROR_LIMIT')) { define('U_IDNA_ERROR_LIMIT', 66569); } if (!defined('U_STRINGPREP_PROHIBITED_ERROR')) { define('U_STRINGPREP_PROHIBITED_ERROR', 66560); } if (!defined('U_STRINGPREP_UNASSIGNED_ERROR')) { define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); } if (!defined('U_STRINGPREP_CHECK_BIDI_ERROR')) { define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); } if (!defined('IDNA_DEFAULT')) { define('IDNA_DEFAULT', 0); } if (!defined('IDNA_ALLOW_UNASSIGNED')) { define('IDNA_ALLOW_UNASSIGNED', 1); } if (!defined('IDNA_USE_STD3_RULES')) { define('IDNA_USE_STD3_RULES', 2); } if (!defined('IDNA_CHECK_BIDI')) { define('IDNA_CHECK_BIDI', 4); } if (!defined('IDNA_CHECK_CONTEXTJ')) { define('IDNA_CHECK_CONTEXTJ', 8); } if (!defined('IDNA_NONTRANSITIONAL_TO_ASCII')) { define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); } if (!defined('IDNA_NONTRANSITIONAL_TO_UNICODE')) { define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); } if (!defined('INTL_IDNA_VARIANT_2003')) { define('INTL_IDNA_VARIANT_2003', 0); } if (!defined('INTL_IDNA_VARIANT_UTS46')) { define('INTL_IDNA_VARIANT_UTS46', 1); } if (!defined('IDNA_ERROR_EMPTY_LABEL')) { define('IDNA_ERROR_EMPTY_LABEL', 1); } if (!defined('IDNA_ERROR_LABEL_TOO_LONG')) { define('IDNA_ERROR_LABEL_TOO_LONG', 2); } if (!defined('IDNA_ERROR_DOMAIN_NAME_TOO_LONG')) { define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); } if (!defined('IDNA_ERROR_LEADING_HYPHEN')) { define('IDNA_ERROR_LEADING_HYPHEN', 8); } if (!defined('IDNA_ERROR_TRAILING_HYPHEN')) { define('IDNA_ERROR_TRAILING_HYPHEN', 16); } if (!defined('IDNA_ERROR_HYPHEN_3_4')) { define('IDNA_ERROR_HYPHEN_3_4', 32); } if (!defined('IDNA_ERROR_LEADING_COMBINING_MARK')) { define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); } if (!defined('IDNA_ERROR_DISALLOWED')) { define('IDNA_ERROR_DISALLOWED', 128); } if (!defined('IDNA_ERROR_PUNYCODE')) { define('IDNA_ERROR_PUNYCODE', 256); } if (!defined('IDNA_ERROR_LABEL_HAS_DOT')) { define('IDNA_ERROR_LABEL_HAS_DOT', 512); } if (!defined('IDNA_ERROR_INVALID_ACE_LABEL')) { define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); } if (!defined('IDNA_ERROR_BIDI')) { define('IDNA_ERROR_BIDI', 2048); } if (!defined('IDNA_ERROR_CONTEXTJ')) { define('IDNA_ERROR_CONTEXTJ', 4096); } if (\PHP_VERSION_ID < 70400) { if (!function_exists('idn_to_ascii')) { function idn_to_ascii($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_2003, &$idna_info = null) { return p\Idn::idn_to_ascii($domain, $flags, $variant, $idna_info); } } if (!function_exists('idn_to_utf8')) { function idn_to_utf8($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_2003, &$idna_info = null) { return p\Idn::idn_to_utf8($domain, $flags, $variant, $idna_info); } } } else { if (!function_exists('idn_to_ascii')) { function idn_to_ascii($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_UTS46, &$idna_info = null) { return p\Idn::idn_to_ascii($domain, $flags, $variant, $idna_info); } } if (!function_exists('idn_to_utf8')) { function idn_to_utf8($domain, $flags = 0, $variant = \INTL_IDNA_VARIANT_UTS46, &$idna_info = null) { return p\Idn::idn_to_utf8($domain, $flags, $variant, $idna_info); } } } polyfill-intl-idn/composer.json000064400000002324150432043200012626 0ustar00{ "name": "symfony/polyfill-intl-idn", "type": "library", "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "idn"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Laurent Bassin", "email": "laurent@bassin.info" }, { "name": "Trevor Rowbotham", "email": "trevor.rowbotham@pm.me" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1", "symfony/polyfill-intl-normalizer": "^1.10", "symfony/polyfill-php72": "^1.10" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" }, "files": [ "bootstrap.php" ] }, "suggest": { "ext-intl": "For best performance" }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-intl-idn/Idn.php000064400000073263150432043200011341 0ustar00 and Trevor Rowbotham * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Intl\Idn; use Exception; use Normalizer; use Symfony\Polyfill\Intl\Idn\Resources\unidata\DisallowedRanges; use Symfony\Polyfill\Intl\Idn\Resources\unidata\Regex; /** * @see https://www.unicode.org/reports/tr46/ * * @internal */ final class Idn { public const ERROR_EMPTY_LABEL = 1; public const ERROR_LABEL_TOO_LONG = 2; public const ERROR_DOMAIN_NAME_TOO_LONG = 4; public const ERROR_LEADING_HYPHEN = 8; public const ERROR_TRAILING_HYPHEN = 0x10; public const ERROR_HYPHEN_3_4 = 0x20; public const ERROR_LEADING_COMBINING_MARK = 0x40; public const ERROR_DISALLOWED = 0x80; public const ERROR_PUNYCODE = 0x100; public const ERROR_LABEL_HAS_DOT = 0x200; public const ERROR_INVALID_ACE_LABEL = 0x400; public const ERROR_BIDI = 0x800; public const ERROR_CONTEXTJ = 0x1000; public const ERROR_CONTEXTO_PUNCTUATION = 0x2000; public const ERROR_CONTEXTO_DIGITS = 0x4000; public const INTL_IDNA_VARIANT_2003 = 0; public const INTL_IDNA_VARIANT_UTS46 = 1; public const IDNA_DEFAULT = 0; public const IDNA_ALLOW_UNASSIGNED = 1; public const IDNA_USE_STD3_RULES = 2; public const IDNA_CHECK_BIDI = 4; public const IDNA_CHECK_CONTEXTJ = 8; public const IDNA_NONTRANSITIONAL_TO_ASCII = 16; public const IDNA_NONTRANSITIONAL_TO_UNICODE = 32; public const MAX_DOMAIN_SIZE = 253; public const MAX_LABEL_SIZE = 63; public const BASE = 36; public const TMIN = 1; public const TMAX = 26; public const SKEW = 38; public const DAMP = 700; public const INITIAL_BIAS = 72; public const INITIAL_N = 128; public const DELIMITER = '-'; public const MAX_INT = 2147483647; /** * Contains the numeric value of a basic code point (for use in representing integers) in the * range 0 to BASE-1, or -1 if b is does not represent a value. * * @var array */ private static $basicToDigit = [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, ]; /** * @var array */ private static $virama; /** * @var array */ private static $mapped; /** * @var array */ private static $ignored; /** * @var array */ private static $deviation; /** * @var array */ private static $disallowed; /** * @var array */ private static $disallowed_STD3_mapped; /** * @var array */ private static $disallowed_STD3_valid; /** * @var bool */ private static $mappingTableLoaded = false; /** * @see https://www.unicode.org/reports/tr46/#ToASCII * * @param string $domainName * @param int $options * @param int $variant * @param array $idna_info * * @return string|false */ public static function idn_to_ascii($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = []) { if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { @trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED); } $options = [ 'CheckHyphens' => true, 'CheckBidi' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 !== ($options & self::IDNA_CHECK_BIDI), 'CheckJoiners' => self::INTL_IDNA_VARIANT_UTS46 === $variant && 0 !== ($options & self::IDNA_CHECK_CONTEXTJ), 'UseSTD3ASCIIRules' => 0 !== ($options & self::IDNA_USE_STD3_RULES), 'Transitional_Processing' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 === ($options & self::IDNA_NONTRANSITIONAL_TO_ASCII), 'VerifyDnsLength' => true, ]; $info = new Info(); $labels = self::process((string) $domainName, $options, $info); foreach ($labels as $i => $label) { // Only convert labels to punycode that contain non-ASCII code points if (1 === preg_match('/[^\x00-\x7F]/', $label)) { try { $label = 'xn--'.self::punycodeEncode($label); } catch (Exception $e) { $info->errors |= self::ERROR_PUNYCODE; } $labels[$i] = $label; } } if ($options['VerifyDnsLength']) { self::validateDomainAndLabelLength($labels, $info); } $idna_info = [ 'result' => implode('.', $labels), 'isTransitionalDifferent' => $info->transitionalDifferent, 'errors' => $info->errors, ]; return 0 === $info->errors ? $idna_info['result'] : false; } /** * @see https://www.unicode.org/reports/tr46/#ToUnicode * * @param string $domainName * @param int $options * @param int $variant * @param array $idna_info * * @return string|false */ public static function idn_to_utf8($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = []) { if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { @trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED); } $info = new Info(); $labels = self::process((string) $domainName, [ 'CheckHyphens' => true, 'CheckBidi' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 !== ($options & self::IDNA_CHECK_BIDI), 'CheckJoiners' => self::INTL_IDNA_VARIANT_UTS46 === $variant && 0 !== ($options & self::IDNA_CHECK_CONTEXTJ), 'UseSTD3ASCIIRules' => 0 !== ($options & self::IDNA_USE_STD3_RULES), 'Transitional_Processing' => self::INTL_IDNA_VARIANT_2003 === $variant || 0 === ($options & self::IDNA_NONTRANSITIONAL_TO_UNICODE), ], $info); $idna_info = [ 'result' => implode('.', $labels), 'isTransitionalDifferent' => $info->transitionalDifferent, 'errors' => $info->errors, ]; return 0 === $info->errors ? $idna_info['result'] : false; } /** * @param string $label * * @return bool */ private static function isValidContextJ(array $codePoints, $label) { if (!isset(self::$virama)) { self::$virama = require __DIR__.\DIRECTORY_SEPARATOR.'Resources'.\DIRECTORY_SEPARATOR.'unidata'.\DIRECTORY_SEPARATOR.'virama.php'; } $offset = 0; foreach ($codePoints as $i => $codePoint) { if (0x200C !== $codePoint && 0x200D !== $codePoint) { continue; } if (!isset($codePoints[$i - 1])) { return false; } // If Canonical_Combining_Class(Before(cp)) .eq. Virama Then True; if (isset(self::$virama[$codePoints[$i - 1]])) { continue; } // If RegExpMatch((Joining_Type:{L,D})(Joining_Type:T)*\u200C(Joining_Type:T)*(Joining_Type:{R,D})) Then // True; // Generated RegExp = ([Joining_Type:{L,D}][Joining_Type:T]*\u200C[Joining_Type:T]*)[Joining_Type:{R,D}] if (0x200C === $codePoint && 1 === preg_match(Regex::ZWNJ, $label, $matches, \PREG_OFFSET_CAPTURE, $offset)) { $offset += \strlen($matches[1][0]); continue; } return false; } return true; } /** * @see https://www.unicode.org/reports/tr46/#ProcessingStepMap * * @param string $input * @param array $options * * @return string */ private static function mapCodePoints($input, array $options, Info $info) { $str = ''; $useSTD3ASCIIRules = $options['UseSTD3ASCIIRules']; $transitional = $options['Transitional_Processing']; foreach (self::utf8Decode($input) as $codePoint) { $data = self::lookupCodePointStatus($codePoint, $useSTD3ASCIIRules); switch ($data['status']) { case 'disallowed': $info->errors |= self::ERROR_DISALLOWED; // no break. case 'valid': $str .= mb_chr($codePoint, 'utf-8'); break; case 'ignored': // Do nothing. break; case 'mapped': $str .= $data['mapping']; break; case 'deviation': $info->transitionalDifferent = true; $str .= ($transitional ? $data['mapping'] : mb_chr($codePoint, 'utf-8')); break; } } return $str; } /** * @see https://www.unicode.org/reports/tr46/#Processing * * @param string $domain * @param array $options * * @return array */ private static function process($domain, array $options, Info $info) { // If VerifyDnsLength is not set, we are doing ToUnicode otherwise we are doing ToASCII and // we need to respect the VerifyDnsLength option. $checkForEmptyLabels = !isset($options['VerifyDnsLength']) || $options['VerifyDnsLength']; if ($checkForEmptyLabels && '' === $domain) { $info->errors |= self::ERROR_EMPTY_LABEL; return [$domain]; } // Step 1. Map each code point in the domain name string $domain = self::mapCodePoints($domain, $options, $info); // Step 2. Normalize the domain name string to Unicode Normalization Form C. if (!Normalizer::isNormalized($domain, Normalizer::FORM_C)) { $domain = Normalizer::normalize($domain, Normalizer::FORM_C); } // Step 3. Break the string into labels at U+002E (.) FULL STOP. $labels = explode('.', $domain); $lastLabelIndex = \count($labels) - 1; // Step 4. Convert and validate each label in the domain name string. foreach ($labels as $i => $label) { $validationOptions = $options; if ('xn--' === substr($label, 0, 4)) { try { $label = self::punycodeDecode(substr($label, 4)); } catch (Exception $e) { $info->errors |= self::ERROR_PUNYCODE; continue; } $validationOptions['Transitional_Processing'] = false; $labels[$i] = $label; } self::validateLabel($label, $info, $validationOptions, $i > 0 && $i === $lastLabelIndex); } if ($info->bidiDomain && !$info->validBidiDomain) { $info->errors |= self::ERROR_BIDI; } // Any input domain name string that does not record an error has been successfully // processed according to this specification. Conversely, if an input domain_name string // causes an error, then the processing of the input domain_name string fails. Determining // what to do with error input is up to the caller, and not in the scope of this document. return $labels; } /** * @see https://tools.ietf.org/html/rfc5893#section-2 * * @param string $label */ private static function validateBidiLabel($label, Info $info) { if (1 === preg_match(Regex::RTL_LABEL, $label)) { $info->bidiDomain = true; // Step 1. The first character must be a character with Bidi property L, R, or AL. // If it has the R or AL property, it is an RTL label if (1 !== preg_match(Regex::BIDI_STEP_1_RTL, $label)) { $info->validBidiDomain = false; return; } // Step 2. In an RTL label, only characters with the Bidi properties R, AL, AN, EN, ES, // CS, ET, ON, BN, or NSM are allowed. if (1 === preg_match(Regex::BIDI_STEP_2, $label)) { $info->validBidiDomain = false; return; } // Step 3. In an RTL label, the end of the label must be a character with Bidi property // R, AL, EN, or AN, followed by zero or more characters with Bidi property NSM. if (1 !== preg_match(Regex::BIDI_STEP_3, $label)) { $info->validBidiDomain = false; return; } // Step 4. In an RTL label, if an EN is present, no AN may be present, and vice versa. if (1 === preg_match(Regex::BIDI_STEP_4_AN, $label) && 1 === preg_match(Regex::BIDI_STEP_4_EN, $label)) { $info->validBidiDomain = false; return; } return; } // We are a LTR label // Step 1. The first character must be a character with Bidi property L, R, or AL. // If it has the L property, it is an LTR label. if (1 !== preg_match(Regex::BIDI_STEP_1_LTR, $label)) { $info->validBidiDomain = false; return; } // Step 5. In an LTR label, only characters with the Bidi properties L, EN, // ES, CS, ET, ON, BN, or NSM are allowed. if (1 === preg_match(Regex::BIDI_STEP_5, $label)) { $info->validBidiDomain = false; return; } // Step 6.In an LTR label, the end of the label must be a character with Bidi property L or // EN, followed by zero or more characters with Bidi property NSM. if (1 !== preg_match(Regex::BIDI_STEP_6, $label)) { $info->validBidiDomain = false; return; } } /** * @param array $labels */ private static function validateDomainAndLabelLength(array $labels, Info $info) { $maxDomainSize = self::MAX_DOMAIN_SIZE; $length = \count($labels); // Number of "." delimiters. $domainLength = $length - 1; // If the last label is empty and it is not the first label, then it is the root label. // Increase the max size by 1, making it 254, to account for the root label's "." // delimiter. This also means we don't need to check the last label's length for being too // long. if ($length > 1 && '' === $labels[$length - 1]) { ++$maxDomainSize; --$length; } for ($i = 0; $i < $length; ++$i) { $bytes = \strlen($labels[$i]); $domainLength += $bytes; if ($bytes > self::MAX_LABEL_SIZE) { $info->errors |= self::ERROR_LABEL_TOO_LONG; } } if ($domainLength > $maxDomainSize) { $info->errors |= self::ERROR_DOMAIN_NAME_TOO_LONG; } } /** * @see https://www.unicode.org/reports/tr46/#Validity_Criteria * * @param string $label * @param array $options * @param bool $canBeEmpty */ private static function validateLabel($label, Info $info, array $options, $canBeEmpty) { if ('' === $label) { if (!$canBeEmpty && (!isset($options['VerifyDnsLength']) || $options['VerifyDnsLength'])) { $info->errors |= self::ERROR_EMPTY_LABEL; } return; } // Step 1. The label must be in Unicode Normalization Form C. if (!Normalizer::isNormalized($label, Normalizer::FORM_C)) { $info->errors |= self::ERROR_INVALID_ACE_LABEL; } $codePoints = self::utf8Decode($label); if ($options['CheckHyphens']) { // Step 2. If CheckHyphens, the label must not contain a U+002D HYPHEN-MINUS character // in both the thrid and fourth positions. if (isset($codePoints[2], $codePoints[3]) && 0x002D === $codePoints[2] && 0x002D === $codePoints[3]) { $info->errors |= self::ERROR_HYPHEN_3_4; } // Step 3. If CheckHyphens, the label must neither begin nor end with a U+002D // HYPHEN-MINUS character. if ('-' === substr($label, 0, 1)) { $info->errors |= self::ERROR_LEADING_HYPHEN; } if ('-' === substr($label, -1, 1)) { $info->errors |= self::ERROR_TRAILING_HYPHEN; } } // Step 4. The label must not contain a U+002E (.) FULL STOP. if (false !== strpos($label, '.')) { $info->errors |= self::ERROR_LABEL_HAS_DOT; } // Step 5. The label must not begin with a combining mark, that is: General_Category=Mark. if (1 === preg_match(Regex::COMBINING_MARK, $label)) { $info->errors |= self::ERROR_LEADING_COMBINING_MARK; } // Step 6. Each code point in the label must only have certain status values according to // Section 5, IDNA Mapping Table: $transitional = $options['Transitional_Processing']; $useSTD3ASCIIRules = $options['UseSTD3ASCIIRules']; foreach ($codePoints as $codePoint) { $data = self::lookupCodePointStatus($codePoint, $useSTD3ASCIIRules); $status = $data['status']; if ('valid' === $status || (!$transitional && 'deviation' === $status)) { continue; } $info->errors |= self::ERROR_DISALLOWED; break; } // Step 7. If CheckJoiners, the label must satisify the ContextJ rules from Appendix A, in // The Unicode Code Points and Internationalized Domain Names for Applications (IDNA) // [IDNA2008]. if ($options['CheckJoiners'] && !self::isValidContextJ($codePoints, $label)) { $info->errors |= self::ERROR_CONTEXTJ; } // Step 8. If CheckBidi, and if the domain name is a Bidi domain name, then the label must // satisfy all six of the numbered conditions in [IDNA2008] RFC 5893, Section 2. if ($options['CheckBidi'] && (!$info->bidiDomain || $info->validBidiDomain)) { self::validateBidiLabel($label, $info); } } /** * @see https://tools.ietf.org/html/rfc3492#section-6.2 * * @param string $input * * @return string */ private static function punycodeDecode($input) { $n = self::INITIAL_N; $out = 0; $i = 0; $bias = self::INITIAL_BIAS; $lastDelimIndex = strrpos($input, self::DELIMITER); $b = false === $lastDelimIndex ? 0 : $lastDelimIndex; $inputLength = \strlen($input); $output = []; $bytes = array_map('ord', str_split($input)); for ($j = 0; $j < $b; ++$j) { if ($bytes[$j] > 0x7F) { throw new Exception('Invalid input'); } $output[$out++] = $input[$j]; } if ($b > 0) { ++$b; } for ($in = $b; $in < $inputLength; ++$out) { $oldi = $i; $w = 1; for ($k = self::BASE; /* no condition */; $k += self::BASE) { if ($in >= $inputLength) { throw new Exception('Invalid input'); } $digit = self::$basicToDigit[$bytes[$in++] & 0xFF]; if ($digit < 0) { throw new Exception('Invalid input'); } if ($digit > intdiv(self::MAX_INT - $i, $w)) { throw new Exception('Integer overflow'); } $i += $digit * $w; if ($k <= $bias) { $t = self::TMIN; } elseif ($k >= $bias + self::TMAX) { $t = self::TMAX; } else { $t = $k - $bias; } if ($digit < $t) { break; } $baseMinusT = self::BASE - $t; if ($w > intdiv(self::MAX_INT, $baseMinusT)) { throw new Exception('Integer overflow'); } $w *= $baseMinusT; } $outPlusOne = $out + 1; $bias = self::adaptBias($i - $oldi, $outPlusOne, 0 === $oldi); if (intdiv($i, $outPlusOne) > self::MAX_INT - $n) { throw new Exception('Integer overflow'); } $n += intdiv($i, $outPlusOne); $i %= $outPlusOne; array_splice($output, $i++, 0, [mb_chr($n, 'utf-8')]); } return implode('', $output); } /** * @see https://tools.ietf.org/html/rfc3492#section-6.3 * * @param string $input * * @return string */ private static function punycodeEncode($input) { $n = self::INITIAL_N; $delta = 0; $out = 0; $bias = self::INITIAL_BIAS; $inputLength = 0; $output = ''; $iter = self::utf8Decode($input); foreach ($iter as $codePoint) { ++$inputLength; if ($codePoint < 0x80) { $output .= \chr($codePoint); ++$out; } } $h = $out; $b = $out; if ($b > 0) { $output .= self::DELIMITER; ++$out; } while ($h < $inputLength) { $m = self::MAX_INT; foreach ($iter as $codePoint) { if ($codePoint >= $n && $codePoint < $m) { $m = $codePoint; } } if ($m - $n > intdiv(self::MAX_INT - $delta, $h + 1)) { throw new Exception('Integer overflow'); } $delta += ($m - $n) * ($h + 1); $n = $m; foreach ($iter as $codePoint) { if ($codePoint < $n && 0 === ++$delta) { throw new Exception('Integer overflow'); } if ($codePoint === $n) { $q = $delta; for ($k = self::BASE; /* no condition */; $k += self::BASE) { if ($k <= $bias) { $t = self::TMIN; } elseif ($k >= $bias + self::TMAX) { $t = self::TMAX; } else { $t = $k - $bias; } if ($q < $t) { break; } $qMinusT = $q - $t; $baseMinusT = self::BASE - $t; $output .= self::encodeDigit($t + ($qMinusT) % ($baseMinusT), false); ++$out; $q = intdiv($qMinusT, $baseMinusT); } $output .= self::encodeDigit($q, false); ++$out; $bias = self::adaptBias($delta, $h + 1, $h === $b); $delta = 0; ++$h; } } ++$delta; ++$n; } return $output; } /** * @see https://tools.ietf.org/html/rfc3492#section-6.1 * * @param int $delta * @param int $numPoints * @param bool $firstTime * * @return int */ private static function adaptBias($delta, $numPoints, $firstTime) { // xxx >> 1 is a faster way of doing intdiv(xxx, 2) $delta = $firstTime ? intdiv($delta, self::DAMP) : $delta >> 1; $delta += intdiv($delta, $numPoints); $k = 0; while ($delta > ((self::BASE - self::TMIN) * self::TMAX) >> 1) { $delta = intdiv($delta, self::BASE - self::TMIN); $k += self::BASE; } return $k + intdiv((self::BASE - self::TMIN + 1) * $delta, $delta + self::SKEW); } /** * @param int $d * @param bool $flag * * @return string */ private static function encodeDigit($d, $flag) { return \chr($d + 22 + 75 * ($d < 26 ? 1 : 0) - (($flag ? 1 : 0) << 5)); } /** * Takes a UTF-8 encoded string and converts it into a series of integer code points. Any * invalid byte sequences will be replaced by a U+FFFD replacement code point. * * @see https://encoding.spec.whatwg.org/#utf-8-decoder * * @param string $input * * @return array */ private static function utf8Decode($input) { $bytesSeen = 0; $bytesNeeded = 0; $lowerBoundary = 0x80; $upperBoundary = 0xBF; $codePoint = 0; $codePoints = []; $length = \strlen($input); for ($i = 0; $i < $length; ++$i) { $byte = \ord($input[$i]); if (0 === $bytesNeeded) { if ($byte >= 0x00 && $byte <= 0x7F) { $codePoints[] = $byte; continue; } if ($byte >= 0xC2 && $byte <= 0xDF) { $bytesNeeded = 1; $codePoint = $byte & 0x1F; } elseif ($byte >= 0xE0 && $byte <= 0xEF) { if (0xE0 === $byte) { $lowerBoundary = 0xA0; } elseif (0xED === $byte) { $upperBoundary = 0x9F; } $bytesNeeded = 2; $codePoint = $byte & 0xF; } elseif ($byte >= 0xF0 && $byte <= 0xF4) { if (0xF0 === $byte) { $lowerBoundary = 0x90; } elseif (0xF4 === $byte) { $upperBoundary = 0x8F; } $bytesNeeded = 3; $codePoint = $byte & 0x7; } else { $codePoints[] = 0xFFFD; } continue; } if ($byte < $lowerBoundary || $byte > $upperBoundary) { $codePoint = 0; $bytesNeeded = 0; $bytesSeen = 0; $lowerBoundary = 0x80; $upperBoundary = 0xBF; --$i; $codePoints[] = 0xFFFD; continue; } $lowerBoundary = 0x80; $upperBoundary = 0xBF; $codePoint = ($codePoint << 6) | ($byte & 0x3F); if (++$bytesSeen !== $bytesNeeded) { continue; } $codePoints[] = $codePoint; $codePoint = 0; $bytesNeeded = 0; $bytesSeen = 0; } // String unexpectedly ended, so append a U+FFFD code point. if (0 !== $bytesNeeded) { $codePoints[] = 0xFFFD; } return $codePoints; } /** * @param int $codePoint * @param bool $useSTD3ASCIIRules * * @return array{status: string, mapping?: string} */ private static function lookupCodePointStatus($codePoint, $useSTD3ASCIIRules) { if (!self::$mappingTableLoaded) { self::$mappingTableLoaded = true; self::$mapped = require __DIR__.'/Resources/unidata/mapped.php'; self::$ignored = require __DIR__.'/Resources/unidata/ignored.php'; self::$deviation = require __DIR__.'/Resources/unidata/deviation.php'; self::$disallowed = require __DIR__.'/Resources/unidata/disallowed.php'; self::$disallowed_STD3_mapped = require __DIR__.'/Resources/unidata/disallowed_STD3_mapped.php'; self::$disallowed_STD3_valid = require __DIR__.'/Resources/unidata/disallowed_STD3_valid.php'; } if (isset(self::$mapped[$codePoint])) { return ['status' => 'mapped', 'mapping' => self::$mapped[$codePoint]]; } if (isset(self::$ignored[$codePoint])) { return ['status' => 'ignored']; } if (isset(self::$deviation[$codePoint])) { return ['status' => 'deviation', 'mapping' => self::$deviation[$codePoint]]; } if (isset(self::$disallowed[$codePoint]) || DisallowedRanges::inRange($codePoint)) { return ['status' => 'disallowed']; } $isDisallowedMapped = isset(self::$disallowed_STD3_mapped[$codePoint]); if ($isDisallowedMapped || isset(self::$disallowed_STD3_valid[$codePoint])) { $status = 'disallowed'; if (!$useSTD3ASCIIRules) { $status = $isDisallowedMapped ? 'mapped' : 'valid'; } if ($isDisallowedMapped) { return ['status' => $status, 'mapping' => self::$disallowed_STD3_mapped[$codePoint]]; } return ['status' => $status]; } return ['status' => 'valid']; } } polyfill-intl-idn/LICENSE000064400000002127150432043200011112 0ustar00Copyright (c) 2018-2019 Fabien Potencier and Trevor Rowbotham Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. error-handler/Resources/bin/extract-tentative-return-types.php000064400000003601150432043200020666 0ustar00#!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ // Run from the root of the php-src repository, this script generates // a table with all the methods that have a tentative return type. // // Usage: find -name *.stub.php | sort | /path/to/extract-tentative-return-types.php > /path/to/TentativeTypes.php echo << * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Internal; /** * This class has been generated by extract-tentative-return-types.php. * * @internal */ class TentativeTypes { public const RETURN_TYPES = [ EOPHP; while (false !== $file = fgets(STDIN)) { $code = file_get_contents(substr($file, 0, -1)); if (!str_contains($code, '@tentative-return-type')) { continue; } $code = preg_split('{^\s*(?:(?:abstract )?class|interface|trait) ([^\s]++)}m', $code, -1, \PREG_SPLIT_DELIM_CAPTURE); if (1 === count($code)) { continue; } for ($i = 1; null !== $class = $code[$i] ?? null; $i += 2) { $methods = $code[1 + $i]; if (!str_contains($methods, '@tentative-return-type')) { continue; } echo " '$class' => [\n"; preg_replace_callback('{@tentative-return-type.*?[\s]function ([^(]++)[^)]++\)\s*+:\s*+([^\n;\{]++)}s', function ($m) { $m[2] = str_replace(' ', '', $m[2]); echo " '$m[1]' => '$m[2]',\n"; return ''; }, $methods); echo " ],\n"; } } echo << * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if (\in_array('-h', $argv) || \in_array('--help', $argv)) { echo implode(PHP_EOL, [ ' Patches type declarations based on "@return" PHPDoc and triggers deprecations for', ' incompatible method declarations.', '', ' This assists you to make your package compatible with Symfony 6, but it can be used', ' for any class/package.', '', ' Available configuration via environment variables:', ' SYMFONY_PATCH_TYPE_DECLARATIONS', ' An url-encoded string to change the behavior of the script. Available parameters:', ' - "force": any value enables deprecation notices - can be any of:', ' - "phpdoc" to patch only docblock annotations', ' - "2" to add all possible return types', ' - "1" to add return types but only to tests/final/internal/private methods', ' - "php": the target version of PHP - e.g. "7.1" doesn\'t generate "object" types', ' - "deprecations": "1" to trigger a deprecation notice when a child class misses a', ' return type while the parent declares an "@return" annotation', '', ' SYMFONY_PATCH_TYPE_EXCLUDE', ' A regex matched against the full path to the class - any match will be excluded', '', ' Example: "SYMFONY_PATCH_TYPE_DECLARATIONS=php=7.4 ./patch-type-declarations"', ]); exit; } if (false === getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) { putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=force=2'); echo 'No SYMFONY_PATCH_TYPE_DECLARATIONS env var set, patching type declarations in all methods (run the command with "-h" for more information).'.PHP_EOL; } if (is_file($autoload = __DIR__.'/../../../../autoload.php')) { // noop } elseif (is_file($autoload = __DIR__.'/../../../../../../../autoload.php')) { // noop } else { echo PHP_EOL.' /!\ Cannot find the Composer autoloader, did you forget to run "composer install"?'.PHP_EOL; exit(1); } if (is_file($phpunitAutoload = dirname($autoload).'/bin/.phpunit/phpunit/vendor/autoload.php')) { require $phpunitAutoload; } $loader = require $autoload; Symfony\Component\ErrorHandler\DebugClassLoader::enable(); $deprecations = []; set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations) { if (\E_USER_DEPRECATED !== $type) { return; } [,,,,, $class,] = explode('"', $msg); $deprecations[$class][] = $msg; }); $exclude = getenv('SYMFONY_PATCH_TYPE_EXCLUDE') ?: null; foreach ($loader->getClassMap() as $class => $file) { if (false !== strpos($file = realpath($file), '/vendor/')) { continue; } if ($exclude && preg_match($exclude, $file)) { continue; } class_exists($class); } Symfony\Component\ErrorHandler\DebugClassLoader::checkClasses(); foreach ($deprecations as $class => $classDeprecations) { echo $class.' ('.\count($classDeprecations).')'.PHP_EOL; echo implode(PHP_EOL, $classDeprecations).PHP_EOL.PHP_EOL; } if ($deprecations && false !== strpos(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?? '', 'force')) { echo 'These deprecations might be fixed by the patch script, run this again to check for type deprecations.'.PHP_EOL; } error-handler/Resources/assets/css/exception.css000064400000033513150432043200016062 0ustar00/* This file is based on WebProfilerBundle/Resources/views/Profiler/profiler.css.twig. If you make any change in this file, verify the same change is needed in the other file. */ :root { --font-sans-serif: Helvetica, Arial, sans-serif; --page-background: #f9f9f9; --color-text: #222; /* when updating any of these colors, do the same in toolbar.css.twig */ --color-success: #4f805d; --color-warning: #a46a1f; --color-error: #b0413e; --color-muted: #999; --tab-background: #fff; --tab-color: #444; --tab-active-background: #666; --tab-active-color: #fafafa; --tab-disabled-background: #f5f5f5; --tab-disabled-color: #999; --metric-value-background: #fff; --metric-value-color: inherit; --metric-unit-color: #999; --metric-label-background: #e0e0e0; --metric-label-color: inherit; --table-border: #e0e0e0; --table-background: #fff; --table-header: #e0e0e0; --trace-selected-background: #F7E5A1; --tree-active-background: #F7E5A1; --exception-title-color: var(--base-2); --shadow: 0px 0px 1px rgba(128, 128, 128, .2); --border: 1px solid #e0e0e0; --background-error: var(--color-error); --highlight-comment: #969896; --highlight-default: #222222; --highlight-keyword: #a71d5d; --highlight-string: #183691; --base-0: #fff; --base-1: #f5f5f5; --base-2: #e0e0e0; --base-3: #ccc; --base-4: #666; --base-5: #444; --base-6: #222; } .theme-dark { --page-background: #36393e; --color-text: #e0e0e0; --color-muted: #777; --color-error: #d43934; --tab-background: #555; --tab-color: #ccc; --tab-active-background: #888; --tab-active-color: #fafafa; --tab-disabled-background: var(--page-background); --tab-disabled-color: #777; --metric-value-background: #555; --metric-value-color: inherit; --metric-unit-color: #999; --metric-label-background: #777; --metric-label-color: #e0e0e0; --trace-selected-background: #71663acc; --table-border: #444; --table-background: #333; --table-header: #555; --info-background: rgba(79, 148, 195, 0.5); --tree-active-background: var(--metric-label-background); --exception-title-color: var(--base-2); --shadow: 0px 0px 1px rgba(32, 32, 32, .2); --border: 1px solid #666; --background-error: #b0413e; --highlight-comment: #dedede; --highlight-default: var(--base-6); --highlight-keyword: #ff413c; --highlight-string: #70a6fd; --base-0: #2e3136; --base-1: #444; --base-2: #666; --base-3: #666; --base-4: #666; --base-5: #e0e0e0; --base-6: #f5f5f5; --card-label-background: var(--tab-active-background); --card-label-color: var(--tab-active-color); } html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0} html { /* always display the vertical scrollbar to avoid jumps when toggling contents */ overflow-y: scroll; } body { background-color: var(--page-background); color: var(--base-6); font: 14px/1.4 Helvetica, Arial, sans-serif; padding-bottom: 45px; } a { cursor: pointer; text-decoration: none; } a:hover { text-decoration: underline; } abbr[title] { border-bottom: none; cursor: help; text-decoration: none; } code, pre { font: 13px/1.5 Consolas, Monaco, Menlo, "Ubuntu Mono", "Liberation Mono", monospace; } table, tr, th, td { background: var(--base-0); border-collapse: collapse; vertical-align: top; } table { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; width: 100%; } table th, table td { border: solid var(--base-2); border-width: 1px 0; padding: 8px 10px; } table th { background-color: var(--base-2); font-weight: bold; text-align: left; } .m-t-5 { margin-top: 5px; } .hidden-xs-down { display: none; } .block { display: block; } .full-width { width: 100%; } .hidden { display: none; } .prewrap { white-space: pre-wrap; } .nowrap { white-space: nowrap; } .newline { display: block; } .break-long-words { word-wrap: break-word; overflow-wrap: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; min-width: 0; } .text-small { font-size: 12px !important; } .text-muted { color: #999; } .text-bold { font-weight: bold; } .empty { border: 4px dashed var(--base-2); color: #999; margin: 1em 0; padding: .5em 2em; } .status-success { background: rgba(94, 151, 110, 0.3); } .status-warning { background: rgba(240, 181, 24, 0.3); } .status-error { background: rgba(176, 65, 62, 0.2); } .status-success td, .status-warning td, .status-error td { background: transparent; } tr.status-error td, tr.status-warning td { border-bottom: 1px solid var(--base-2); border-top: 1px solid var(--base-2); } .status-warning .colored { color: #A46A1F; } .status-error .colored { color: var(--color-error); } .sf-toggle { cursor: pointer; position: relative; } .sf-toggle-content { -moz-transition: display .25s ease; -webkit-transition: display .25s ease; transition: display .25s ease; } .sf-toggle-content.sf-toggle-hidden { display: none; } .sf-toggle-content.sf-toggle-visible { display: block; } thead.sf-toggle-content.sf-toggle-visible, tbody.sf-toggle-content.sf-toggle-visible { display: table-row-group; } .sf-toggle-off .icon-close, .sf-toggle-on .icon-open { display: none; } .sf-toggle-off .icon-open, .sf-toggle-on .icon-close { display: block; } .tab-navigation { margin: 0 0 1em 0; padding: 0; } .tab-navigation li { background: var(--tab-background); border: 1px solid var(--table-border); color: var(--tab-color); cursor: pointer; display: inline-block; font-size: 16px; margin: 0 0 0 -1px; padding: .5em .75em; z-index: 1; } .tab-navigation li .badge { background-color: var(--base-1); color: var(--base-4); display: inline-block; font-size: 14px; font-weight: bold; margin-left: 8px; min-width: 10px; padding: 1px 6px; text-align: center; white-space: nowrap; } .tab-navigation li.disabled { background: var(--tab-disabled-background); color: var(--tab-disabled-color); } .tab-navigation li.active { background: var(--tab-active-background); color: var(--tab-active-color); z-index: 1100; } .tab-navigation li.active .badge { background-color: var(--base-5); color: var(--base-2); } .tab-content > *:first-child { margin-top: 0; } .tab-navigation li .badge.status-warning { background: var(--color-warning); color: #FFF; } .tab-navigation li .badge.status-error { background: var(--background-error); color: #FFF; } .sf-tabs .tab:not(:first-child) { display: none; } [data-filters] { position: relative; } [data-filtered] { cursor: pointer; } [data-filtered]:after { content: '\00a0\25BE'; } [data-filtered]:hover .filter-list li { display: inline-flex; } [class*="filter-hidden-"] { display: none; } .filter-list { position: absolute; border: var(--border); box-shadow: var(--shadow); margin: 0; padding: 0; display: flex; flex-direction: column; } .filter-list :after { content: ''; } .filter-list li { background: var(--tab-disabled-background); border-bottom: var(--border); color: var(--tab-disabled-color); display: none; list-style: none; margin: 0; padding: 5px 10px; text-align: left; font-weight: normal; } .filter-list li.active { background: var(--tab-background); color: var(--tab-color); } .filter-list li.last-active { background: var(--tab-active-background); color: var(--tab-active-color); } .filter-list-level li { cursor: s-resize; } .filter-list-level li.active { cursor: n-resize; } .filter-list-level li.last-active { cursor: default; } .filter-list-level li.last-active:before { content: '\2714\00a0'; } .filter-list-choice li:before { content: '\2714\00a0'; color: transparent; } .filter-list-choice li.active:before { color: unset; } .container { max-width: 1024px; margin: 0 auto; padding: 0 15px; } .container::after { content: ""; display: table; clear: both; } header { background-color: #222; color: rgba(255, 255, 255, 0.75); font-size: 13px; height: 33px; line-height: 33px; padding: 0; } header .container { display: flex; justify-content: space-between; } .logo { flex: 1; font-size: 13px; font-weight: normal; margin: 0; padding: 0; } .logo svg { height: 18px; width: 18px; opacity: .8; vertical-align: -5px; } .help-link { margin-left: 15px; } .help-link a { color: inherit; } .help-link .icon svg { height: 15px; width: 15px; opacity: .7; vertical-align: -2px; } .help-link a:hover { color: #EEE; text-decoration: none; } .help-link a:hover svg { opacity: .9; } .exception-summary { background: var(--background-error); border-bottom: 2px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, .3); flex: 0 0 auto; margin-bottom: 15px; } .exception-metadata { background: rgba(0, 0, 0, 0.1); padding: 7px 0; } .exception-metadata .container { display: flex; flex-direction: row; justify-content: space-between; } .exception-metadata h2, .exception-metadata h2 > a { color: rgba(255, 255, 255, 0.8); font-size: 13px; font-weight: 400; margin: 0; } .exception-http small { font-size: 13px; opacity: .7; } .exception-hierarchy { flex: 1; } .exception-hierarchy .icon { margin: 0 3px; opacity: .7; } .exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; } .exception-without-message .exception-message-wrapper { display: none; } .exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 15px 8px; } .exception-message { flex-grow: 1; } .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } .exception-message.long { font-size: 18px; } .exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } .exception-message a:hover { border-bottom-color: #ffffff; } .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } .trace + .trace { margin-top: 30px; } .trace-head { background-color: var(--base-2); padding: 10px; position: relative; } .trace-head .trace-class { color: var(--base-6); font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } .trace-head .trace-namespace { color: #999; display: block; font-size: 13px; } .trace-head .icon { position: absolute; right: 0; top: 0; } .trace-head .icon svg { fill: var(--base-5); height: 24px; width: 24px; } .trace-details { background: var(--base-0); border: var(--border); box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; table-layout: fixed; } .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } .trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; } .trace-line + .trace-line { border-top: var(--border); } .trace-line:hover { background: var(--base-1); } .trace-line a { color: var(--base-6); } .trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; } .trace-line .icon svg { fill: var(--base-5); height: 16px; width: 16px; } .trace-line .icon.icon-copy { left: auto; top: auto; padding-left: 5px; display: none } .trace-line:hover .icon.icon-copy:not(.hidden) { display: inline-block } .trace-line-header { padding-left: 36px; padding-right: 10px; } .trace-file-path, .trace-file-path a { color: var(--base-6); font-size: 13px; } .trace-class { color: var(--color-error); } .trace-type { padding: 0 2px; } .trace-method { color: var(--color-error); font-weight: bold; } .trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } .trace-code { background: var(--base-0); font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; } .trace-code ol { margin: 0; float: left; } .trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } .trace-code li + li { margin-top: 5px; } .trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; } .trace-code li code { color: var(--base-6); white-space: nowrap; } .trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } @media (min-width: 575px) { .hidden-xs-down { display: initial; } .help-link { margin-left: 30px; } } error-handler/Resources/assets/css/exception_full.css000064400000005300150432043200017075 0ustar00.sf-reset .traces { padding-bottom: 14px; } .sf-reset .traces li { font-size: 12px; color: #868686; padding: 5px 4px; list-style-type: decimal; margin-left: 20px; } .sf-reset #logs .traces li.error { font-style: normal; color: #AA3333; background: #f9ecec; } .sf-reset #logs .traces li.warning { font-style: normal; background: #ffcc00; } /* fix for Opera not liking empty
  • */ .sf-reset .traces li:after { content: "\00A0"; } .sf-reset .trace { border: 1px solid #D3D3D3; padding: 10px; overflow: auto; margin: 10px 0 20px; } .sf-reset .block-exception { -moz-border-radius: 16px; -webkit-border-radius: 16px; border-radius: 16px; margin-bottom: 20px; background-color: #f6f6f6; border: 1px solid #dfdfdf; padding: 30px 28px; word-wrap: break-word; overflow: hidden; } .sf-reset .block-exception div { color: #313131; font-size: 10px; } .sf-reset .block-exception-detected .illustration-exception, .sf-reset .block-exception-detected .text-exception { float: left; } .sf-reset .block-exception-detected .illustration-exception { width: 152px; } .sf-reset .block-exception-detected .text-exception { width: 670px; padding: 30px 44px 24px 46px; position: relative; } .sf-reset .text-exception .open-quote, .sf-reset .text-exception .close-quote { font-family: Arial, Helvetica, sans-serif; position: absolute; color: #C9C9C9; font-size: 8em; } .sf-reset .open-quote { top: 0; left: 0; } .sf-reset .close-quote { bottom: -0.5em; right: 50px; } .sf-reset .block-exception p { font-family: Arial, Helvetica, sans-serif; } .sf-reset .block-exception p a, .sf-reset .block-exception p a:hover { color: #565656; } .sf-reset .logs h2 { float: left; width: 654px; } .sf-reset .error-count, .sf-reset .support { float: right; width: 170px; text-align: right; } .sf-reset .error-count span { display: inline-block; background-color: #aacd4e; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; padding: 4px; color: white; margin-right: 2px; font-size: 11px; font-weight: bold; } .sf-reset .support a { display: inline-block; -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; padding: 4px; color: #000000; margin-right: 2px; font-size: 11px; font-weight: bold; } .sf-reset .toggle { vertical-align: middle; } .sf-reset .linked ul, .sf-reset .linked li { display: inline; } .sf-reset #output-content { color: #000; font-size: 12px; } .sf-reset #traces-text pre { white-space: pre; font-size: 12px; font-family: monospace; } error-handler/Resources/assets/css/error.css000064400000000423150432043200015207 0ustar00body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; } .container { margin: 30px; max-width: 600px; } h1 { color: #dc3545; font-size: 24px; } h2 { font-size: 18px; } error-handler/Resources/assets/images/icon-support.svg000064400000001172150432043200017206 0ustar00 error-handler/Resources/assets/images/icon-book.svg000064400000001621150432043200016423 0ustar00 error-handler/Resources/assets/images/favicon.png.base64000064400000002327150432043200017244 0ustar00data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAgCAYAAAABtRhCAAADVUlEQVRIx82XX0jTURTHLYPyqZdefQx66CEo80+aYpoIkqzUikz6Z5klQoWUWYRIJYEUGpQ+lIr9U5dOTLdCtkmWZis3rbnC5fw/neYW002307mX/cZvP3/7o1PwwOdh95x7vnf39zvnd29AgBer2xO6DclAXiMqZAqxIiNIN/IYSUS2BPhjmGATchUxI+ADWiRhpWK7HKuHFVBFdmU5YvnI4grFGCaReF/EBH4KsZlGgj2JBTuCYBWRIYF8YoEOJ6wBt/gEs7mBbyOjQXruPLSdOgPCiEiPSUUHDoL8Ug5IUo9B/d5wrt+G7OAKNrODPuVdB6vRCIzN6SdBlpW9RIgk/1FeAXabzRlrUPVCS/JhbmwudztnGeeH9AyXBIwtmM3wLinZJZHifjHw2V+NBoRh+9ixQrbgbnaSIcl7cGea6hoXQbNe7za241oeO5Z0p42M4BV2EqP2D50wo+6HzvwC6C4sApNOR8cmOrtcnhtj2kYRyC9eBvXzKrBZrXSs72kFd1t3MoKVbMekQkEnSNKOO8fac3LpmK6l1TlGtsxmsdKFsecPYgwxst0cwROMYDXboSotg0WLBRqjY51jLYcENElXwW2XJKPydvoI2GN9T8rBtrAArYIUruBJXkFheCQYlCpQP6uk5dAQFQNaUROMSGVQFxLmkoQsxDJrhLbTZ+nvVsERME9MgPJRKV/58AsyomTSzE813WLFvWK++qI0xSfQl8k8Pg46sYRuv5t6dS+4RqxDwaa4BGjYH+NTQvKScIp9+YL/hoZh3jDtLRHtt2C3g6bmhX+CpsFBWg7ilDSPgj0lD2ncr5ev/BP8VvyAJhqVyZeUhPOrEhEFxgEtjft846Z/guQTNT89Q5P9flMLoth4F7808wKtWWKzAwNQHxrh/1vaid2F+XpYTSbQf1XA2McOmOpROnvpvMEA4tSjq1cW0sws2gCYxswY6TKkvzYnJq1NHZLnRU4BX+4U0uburvusu8Kv8iHY7qefkM4IFngJHEOUXmLEPgiGsI8YnlZILit3vSSLRTQe/MPIZva5pshNIEmyFQlCvruJKXPkCEfmePzkphXHdzZNQdoRI9KPlBAxlj/I8U97ERPS5bjGbWDFbEdqHVe5caTBeZZx2H/IMvzeN15yoQAAAABJRU5ErkJggg== error-handler/Resources/assets/images/icon-minus-square.svg000064400000000521150432043200020120 0ustar00 error-handler/Resources/assets/images/symfony-logo.svg000064400000001656150432043200017215 0ustar00 error-handler/Resources/assets/images/chevron-right.svg000064400000000424150432043200017322 0ustar00 error-handler/Resources/assets/images/icon-copy.svg000064400000000411150432043200016437 0ustar00error-handler/Resources/assets/images/icon-plus-square.svg000064400000000672150432043200017757 0ustar00 error-handler/Resources/assets/images/icon-plus-square-o.svg000064400000001016150432043200020204 0ustar00 error-handler/Resources/assets/images/icon-minus-square-o.svg000064400000000660150432043200020360 0ustar00 error-handler/Resources/assets/images/symfony-ghost.svg.php000064400000017764150432043200020176 0ustar00addElementToGhost(); ?> error-handler/Resources/assets/js/exception.js000064400000036127150432043200015536 0ustar00/* This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. If you make any change in this file, verify the same change is needed in the other file. */ /* .tab'); var tabNavigation = document.createElement('ul'); tabNavigation.className = 'tab-navigation'; var selectedTabId = 'tab-' + i + '-0'; /* select the first tab by default */ for (var j = 0; j < tabs.length; j++) { var tabId = 'tab-' + i + '-' + j; var tabTitle = tabs[j].querySelector('.tab-title').innerHTML; var tabNavigationItem = document.createElement('li'); tabNavigationItem.setAttribute('data-tab-id', tabId); if (hasClass(tabs[j], 'active')) { selectedTabId = tabId; } if (hasClass(tabs[j], 'disabled')) { addClass(tabNavigationItem, 'disabled'); } tabNavigationItem.innerHTML = tabTitle; tabNavigation.appendChild(tabNavigationItem); var tabContent = tabs[j].querySelector('.tab-content'); tabContent.parentElement.setAttribute('id', tabId); } tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild); addClass(document.querySelector('[data-tab-id="' + selectedTabId + '"]'), 'active'); } /* display the active tab and add the 'click' event listeners */ for (i = 0; i < tabGroups.length; i++) { tabNavigation = tabGroups[i].querySelectorAll(':scope >.tab-navigation li'); for (j = 0; j < tabNavigation.length; j++) { tabId = tabNavigation[j].getAttribute('data-tab-id'); document.getElementById(tabId).querySelector('.tab-title').className = 'hidden'; if (hasClass(tabNavigation[j], 'active')) { document.getElementById(tabId).className = 'block'; } else { document.getElementById(tabId).className = 'hidden'; } tabNavigation[j].addEventListener('click', function(e) { var activeTab = e.target || e.srcElement; /* needed because when the tab contains HTML contents, user can click */ /* on any of those elements instead of their parent '
  • ' element */ while (activeTab.tagName.toLowerCase() !== 'li') { activeTab = activeTab.parentNode; } /* get the full list of tabs through the parent of the active tab element */ var tabNavigation = activeTab.parentNode.children; for (var k = 0; k < tabNavigation.length; k++) { var tabId = tabNavigation[k].getAttribute('data-tab-id'); document.getElementById(tabId).className = 'hidden'; removeClass(tabNavigation[k], 'active'); } addClass(activeTab, 'active'); var activeTabId = activeTab.getAttribute('data-tab-id'); document.getElementById(activeTabId).className = 'block'; }); } tabGroups[i].setAttribute('data-processed', 'true'); } }, createToggles: function() { var toggles = document.querySelectorAll('.sf-toggle:not([data-processed=true])'); for (var i = 0; i < toggles.length; i++) { var elementSelector = toggles[i].getAttribute('data-toggle-selector'); var element = document.querySelector(elementSelector); addClass(element, 'sf-toggle-content'); if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') { addClass(toggles[i], 'sf-toggle-on'); addClass(element, 'sf-toggle-visible'); } else { addClass(toggles[i], 'sf-toggle-off'); addClass(element, 'sf-toggle-hidden'); } addEventListener(toggles[i], 'click', function(e) { e.preventDefault(); if ('' !== window.getSelection().toString()) { /* Don't do anything on text selection */ return; } var toggle = e.target || e.srcElement; /* needed because when the toggle contains HTML contents, user can click */ /* on any of those elements instead of their parent '.sf-toggle' element */ while (!hasClass(toggle, 'sf-toggle')) { toggle = toggle.parentNode; } var element = document.querySelector(toggle.getAttribute('data-toggle-selector')); toggleClass(toggle, 'sf-toggle-on'); toggleClass(toggle, 'sf-toggle-off'); toggleClass(element, 'sf-toggle-hidden'); toggleClass(element, 'sf-toggle-visible'); /* the toggle doesn't change its contents when clicking on it */ if (!toggle.hasAttribute('data-toggle-alt-content')) { return; } if (!toggle.hasAttribute('data-toggle-original-content')) { toggle.setAttribute('data-toggle-original-content', toggle.innerHTML); } var currentContent = toggle.innerHTML; var originalContent = toggle.getAttribute('data-toggle-original-content'); var altContent = toggle.getAttribute('data-toggle-alt-content'); toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; }); /* Prevents from disallowing clicks on links inside toggles */ var toggleLinks = toggles[i].querySelectorAll('a'); for (var j = 0; j < toggleLinks.length; j++) { addEventListener(toggleLinks[j], 'click', function(e) { e.stopPropagation(); }); } /* Prevents from disallowing clicks on "copy to clipboard" elements inside toggles */ var copyToClipboardElements = toggles[i].querySelectorAll('span[data-clipboard-text]'); for (var k = 0; k < copyToClipboardElements.length; k++) { addEventListener(copyToClipboardElements[k], 'click', function(e) { e.stopPropagation(); }); } toggles[i].setAttribute('data-processed', 'true'); } }, createFilters: function() { document.querySelectorAll('[data-filters] [data-filter]').forEach(function (filter) { var filters = filter.closest('[data-filters]'), type = 'choice', name = filter.dataset.filter, ucName = name.charAt(0).toUpperCase()+name.slice(1), list = document.createElement('ul'), values = filters.dataset['filter'+ucName] || filters.querySelectorAll('[data-filter-'+name+']'), labels = {}, defaults = null, indexed = {}, processed = {}; if (typeof values === 'string') { type = 'level'; labels = values.split(','); values = values.toLowerCase().split(','); defaults = values.length - 1; } addClass(list, 'filter-list'); addClass(list, 'filter-list-'+type); values.forEach(function (value, i) { if (value instanceof HTMLElement) { value = value.dataset['filter'+ucName]; } if (value in processed) { return; } var option = document.createElement('li'), label = i in labels ? labels[i] : value, active = false, matches; if ('' === label) { option.innerHTML = '(none)'; } else { option.innerText = label; } option.dataset.filter = value; option.setAttribute('title', 1 === (matches = filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').length) ? 'Matches 1 row' : 'Matches '+matches+' rows'); indexed[value] = i; list.appendChild(option); addEventListener(option, 'click', function () { if ('choice' === type) { filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { if (option.dataset.filter === row.dataset['filter'+ucName]) { toggleClass(row, 'filter-hidden-'+name); } }); toggleClass(option, 'active'); } else if ('level' === type) { if (i === this.parentNode.querySelectorAll('.active').length - 1) { return; } this.parentNode.querySelectorAll('li').forEach(function (currentOption, j) { if (j <= i) { addClass(currentOption, 'active'); if (i === j) { addClass(currentOption, 'last-active'); } else { removeClass(currentOption, 'last-active'); } } else { removeClass(currentOption, 'active'); removeClass(currentOption, 'last-active'); } }); filters.querySelectorAll('[data-filter-'+name+']').forEach(function (row) { if (i < indexed[row.dataset['filter'+ucName]]) { addClass(row, 'filter-hidden-'+name); } else { removeClass(row, 'filter-hidden-'+name); } }); } }); if ('choice' === type) { active = null === defaults || 0 <= defaults.indexOf(value); } else if ('level' === type) { active = i <= defaults; if (active && i === defaults) { addClass(option, 'last-active'); } } if (active) { addClass(option, 'active'); } else { filters.querySelectorAll('[data-filter-'+name+'="'+value+'"]').forEach(function (row) { toggleClass(row, 'filter-hidden-'+name); }); } processed[value] = true; }); if (1 < list.childNodes.length) { filter.appendChild(list); filter.dataset.filtered = ''; } }); } }; })(); Sfjs.addEventListener(document, 'DOMContentLoaded', function() { Sfjs.createTabs(); Sfjs.createToggles(); Sfjs.createFilters(); }); } /*]]>*/ error-handler/Resources/views/trace.html.php000064400000005004150432043200015161 0ustar00
    include('assets/images/icon-minus-square.svg'); ?> include('assets/images/icon-plus-square.svg'); ?> abbrClass($trace['class']); ?>(formatArgs($trace['args']); ?>) getFileLink($trace['file'], $lineNumber); $filePath = strtr(strip_tags($this->formatFile($trace['file'], $lineNumber)), [' at line '.$lineNumber => '']); $filePathParts = explode(\DIRECTORY_SEPARATOR, $filePath); ?> in (line )
    fileExcerpt($trace['file'], $trace['line'], 5), [ '#DD0000' => 'var(--highlight-string)', '#007700' => 'var(--highlight-keyword)', '#0000BB' => 'var(--highlight-default)', '#FF8000' => 'var(--highlight-comment)', ]); ?>
    error-handler/Resources/views/exception_full.html.php000064400000003461150432043200017110 0ustar00 <?= $_message; ?>

    include('assets/images/symfony-logo.svg'); ?> Symfony Exception

    include('views/exception.html.php', $context); ?> error-handler/Resources/views/logs.html.php000064400000004133150432043200015031 0ustar00= 400) { $status = 'error'; } elseif ($log['priority'] >= 300) { $status = 'warning'; } else { $severity = 0; if (($exception = $log['context']['exception'] ?? null) instanceof \ErrorException || $exception instanceof \Symfony\Component\ErrorHandler\Exception\SilencedErrorContext) { $severity = $exception->getSeverity(); } $status = \E_DEPRECATED === $severity || \E_USER_DEPRECATED === $severity ? 'warning' : 'normal'; } ?> data-filter-channel="escape($log['channel']); ?>">
    Level Channel Message
    escape($log['priorityName']); ?> escape($log['channel']); ?> formatLogMessage($log['message'], $log['context']); ?>
    escape(json_encode($log['context'], \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES)); ?>
    error-handler/Resources/views/traces.html.php000064400000004611150432043200015347 0ustar00
    include('assets/images/icon-minus-square-o.svg'); ?> include('assets/images/icon-plus-square-o.svg'); ?>

    1) { ?>

    escape($exception['message']); ?>

    $trace) { $isVendorTrace = $trace['file'] && (false !== mb_strpos($trace['file'], '/vendor/') || false !== mb_strpos($trace['file'], '/var/cache/')); $displayCodeSnippet = $isFirstUserCode && !$isVendorTrace; if ($displayCodeSnippet) { $isFirstUserCode = false; } ?>
    include('views/trace.html.php', [ 'prefix' => $index, 'i' => $i, 'trace' => $trace, 'style' => $isVendorTrace ? 'compact' : ($displayCodeSnippet ? 'expanded' : ''), ]); ?>
    error-handler/Resources/views/traces_text.html.php000064400000004020150432043200016405 0ustar00
    1) { ?> [/] include('assets/images/icon-minus-square-o.svg'); ?> include('assets/images/icon-plus-square-o.svg'); ?>
    escape($exception['class']).":\n";
                        if ($exception['message']) {
                            echo $this->escape($exception['message'])."\n";
                        }
    
                        foreach ($exception['trace'] as $trace) {
                            echo "\n  ";
                            if ($trace['function']) {
                                echo $this->escape('at '.$trace['class'].$trace['type'].$trace['function']).'('.(isset($trace['args']) ? $this->formatArgsAsText($trace['args']) : '').')';
                            }
                            if ($trace['file'] && $trace['line']) {
                                echo($trace['function'] ? "\n     (" : 'at ').strtr(strip_tags($this->formatFile($trace['file'], $trace['line'])), [' at line '.$trace['line'] => '']).':'.$trace['line'].($trace['function'] ? ')' : '');
                            }
                        }
    ?>
                    
    error-handler/Resources/views/exception.html.php000064400000010676150432043200016074 0ustar00

    formatFileFromText(nl2br($exceptionMessage)); ?>

    include('assets/images/symfony-ghost.svg.php'); ?>
    toArray(); $exceptionWithUserCode = []; $exceptionAsArrayCount = count($exceptionAsArray); $last = $exceptionAsArrayCount - 1; foreach ($exceptionAsArray as $i => $e) { foreach ($e['trace'] as $trace) { if ($trace['file'] && false === mb_strpos($trace['file'], '/vendor/') && false === mb_strpos($trace['file'], '/var/cache/') && $i < $last) { $exceptionWithUserCode[] = $i; } } } ?>

    1) { ?> Exceptions Exception

    $e) { echo $this->include('views/traces.html.php', [ 'exception' => $e, 'index' => $i + 1, 'expand' => in_array($i, $exceptionWithUserCode, true) || ([] === $exceptionWithUserCode && 0 === $i), ]); } ?>

    Logs countErrors()) { ?>countErrors(); ?>

    getLogs()) { ?> include('views/logs.html.php', ['logs' => $logger->getLogs()]); ?>

    No log messages

    1) { ?> Stack Traces Stack Trace

    $e) { echo $this->include('views/traces_text.html.php', [ 'exception' => $e, 'index' => $i + 1, 'numExceptions' => $exceptionAsArrayCount, ]); } ?>

    Output content

    error-handler/Resources/views/error.html.php000064400000001171150432043200015215 0ustar00 An Error Occurred: <?= $statusText; ?>

    Oops! An Error Occurred

    The server returned a " ".

    Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.

    error-handler/Debug.php000064400000002122150432043200011035 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler; /** * Registers all the debug tools. * * @author Fabien Potencier */ class Debug { public static function enable(): ErrorHandler { error_reporting(-1); if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { ini_set('display_errors', 0); } elseif (!filter_var(ini_get('log_errors'), \FILTER_VALIDATE_BOOLEAN) || ini_get('error_log')) { // CLI - display errors only if they're not already logged to STDERR ini_set('display_errors', 1); } @ini_set('zend.assertions', 1); ini_set('assert.active', 1); ini_set('assert.warning', 0); ini_set('assert.exception', 1); DebugClassLoader::enable(); return ErrorHandler::register(new ErrorHandler(new BufferingLogger(), true)); } } error-handler/ErrorHandler.php000064400000072265150432043200012415 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler; use Psr\Log\LoggerInterface; use Psr\Log\LogLevel; use Symfony\Component\ErrorHandler\Error\FatalError; use Symfony\Component\ErrorHandler\Error\OutOfMemoryError; use Symfony\Component\ErrorHandler\ErrorEnhancer\ClassNotFoundErrorEnhancer; use Symfony\Component\ErrorHandler\ErrorEnhancer\ErrorEnhancerInterface; use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer; use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer; use Symfony\Component\ErrorHandler\ErrorRenderer\CliErrorRenderer; use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer; use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; /** * A generic ErrorHandler for the PHP engine. * * Provides five bit fields that control how errors are handled: * - thrownErrors: errors thrown as \ErrorException * - loggedErrors: logged errors, when not @-silenced * - scopedErrors: errors thrown or logged with their local context * - tracedErrors: errors logged with their stack trace * - screamedErrors: never @-silenced errors * * Each error level can be logged by a dedicated PSR-3 logger object. * Screaming only applies to logging. * Throwing takes precedence over logging. * Uncaught exceptions are logged as E_ERROR. * E_DEPRECATED and E_USER_DEPRECATED levels never throw. * E_RECOVERABLE_ERROR and E_USER_ERROR levels always throw. * Non catchable errors that can be detected at shutdown time are logged when the scream bit field allows so. * As errors have a performance cost, repeated errors are all logged, so that the developer * can see them and weight them as more important to fix than others of the same level. * * @author Nicolas Grekas * @author Grégoire Pineau * * @final */ class ErrorHandler { private $levels = [ \E_DEPRECATED => 'Deprecated', \E_USER_DEPRECATED => 'User Deprecated', \E_NOTICE => 'Notice', \E_USER_NOTICE => 'User Notice', \E_STRICT => 'Runtime Notice', \E_WARNING => 'Warning', \E_USER_WARNING => 'User Warning', \E_COMPILE_WARNING => 'Compile Warning', \E_CORE_WARNING => 'Core Warning', \E_USER_ERROR => 'User Error', \E_RECOVERABLE_ERROR => 'Catchable Fatal Error', \E_COMPILE_ERROR => 'Compile Error', \E_PARSE => 'Parse Error', \E_ERROR => 'Error', \E_CORE_ERROR => 'Core Error', ]; private $loggers = [ \E_DEPRECATED => [null, LogLevel::INFO], \E_USER_DEPRECATED => [null, LogLevel::INFO], \E_NOTICE => [null, LogLevel::WARNING], \E_USER_NOTICE => [null, LogLevel::WARNING], \E_STRICT => [null, LogLevel::WARNING], \E_WARNING => [null, LogLevel::WARNING], \E_USER_WARNING => [null, LogLevel::WARNING], \E_COMPILE_WARNING => [null, LogLevel::WARNING], \E_CORE_WARNING => [null, LogLevel::WARNING], \E_USER_ERROR => [null, LogLevel::CRITICAL], \E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL], \E_COMPILE_ERROR => [null, LogLevel::CRITICAL], \E_PARSE => [null, LogLevel::CRITICAL], \E_ERROR => [null, LogLevel::CRITICAL], \E_CORE_ERROR => [null, LogLevel::CRITICAL], ]; private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED private $tracedErrors = 0x77FB; // E_ALL - E_STRICT - E_PARSE private $screamedErrors = 0x55; // E_ERROR + E_CORE_ERROR + E_COMPILE_ERROR + E_PARSE private $loggedErrors = 0; private $configureException; private $debug; private $isRecursive = 0; private $isRoot = false; private $exceptionHandler; private $bootstrappingLogger; private static $reservedMemory; private static $toStringException; private static $silencedErrorCache = []; private static $silencedErrorCount = 0; private static $exitCode = 0; /** * Registers the error handler. */ public static function register(self $handler = null, bool $replace = true): self { if (null === self::$reservedMemory) { self::$reservedMemory = str_repeat('x', 32768); register_shutdown_function(__CLASS__.'::handleFatalError'); } if ($handlerIsNew = null === $handler) { $handler = new static(); } if (null === $prev = set_error_handler([$handler, 'handleError'])) { restore_error_handler(); // Specifying the error types earlier would expose us to https://bugs.php.net/63206 set_error_handler([$handler, 'handleError'], $handler->thrownErrors | $handler->loggedErrors); $handler->isRoot = true; } if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) { $handler = $prev[0]; $replace = false; } if (!$replace && $prev) { restore_error_handler(); $handlerIsRegistered = \is_array($prev) && $handler === $prev[0]; } else { $handlerIsRegistered = true; } if (\is_array($prev = set_exception_handler([$handler, 'handleException'])) && $prev[0] instanceof self) { restore_exception_handler(); if (!$handlerIsRegistered) { $handler = $prev[0]; } elseif ($handler !== $prev[0] && $replace) { set_exception_handler([$handler, 'handleException']); $p = $prev[0]->setExceptionHandler(null); $handler->setExceptionHandler($p); $prev[0]->setExceptionHandler($p); } } else { $handler->setExceptionHandler($prev ?? [$handler, 'renderException']); } $handler->throwAt(\E_ALL & $handler->thrownErrors, true); return $handler; } /** * Calls a function and turns any PHP error into \ErrorException. * * @return mixed What $function(...$arguments) returns * * @throws \ErrorException When $function(...$arguments) triggers a PHP error */ public static function call(callable $function, ...$arguments) { set_error_handler(static function (int $type, string $message, string $file, int $line) { if (__FILE__ === $file) { $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3); $file = $trace[2]['file'] ?? $file; $line = $trace[2]['line'] ?? $line; } throw new \ErrorException($message, 0, $type, $file, $line); }); try { return $function(...$arguments); } finally { restore_error_handler(); } } public function __construct(BufferingLogger $bootstrappingLogger = null, bool $debug = false) { if ($bootstrappingLogger) { $this->bootstrappingLogger = $bootstrappingLogger; $this->setDefaultLogger($bootstrappingLogger); } $traceReflector = new \ReflectionProperty(\Exception::class, 'trace'); $traceReflector->setAccessible(true); $this->configureException = \Closure::bind(static function ($e, $trace, $file = null, $line = null) use ($traceReflector) { $traceReflector->setValue($e, $trace); $e->file = $file ?? $e->file; $e->line = $line ?? $e->line; }, null, new class() extends \Exception { }); $this->debug = $debug; } /** * Sets a logger to non assigned errors levels. * * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels * @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants * @param bool $replace Whether to replace or not any existing logger */ public function setDefaultLogger(LoggerInterface $logger, $levels = \E_ALL, bool $replace = false): void { $loggers = []; if (\is_array($levels)) { foreach ($levels as $type => $logLevel) { if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) { $loggers[$type] = [$logger, $logLevel]; } } } else { if (null === $levels) { $levels = \E_ALL; } foreach ($this->loggers as $type => $log) { if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) { $log[0] = $logger; $loggers[$type] = $log; } } } $this->setLoggers($loggers); } /** * Sets a logger for each error level. * * @param array $loggers Error levels to [LoggerInterface|null, LogLevel::*] map * * @return array The previous map * * @throws \InvalidArgumentException */ public function setLoggers(array $loggers): array { $prevLogged = $this->loggedErrors; $prev = $this->loggers; $flush = []; foreach ($loggers as $type => $log) { if (!isset($prev[$type])) { throw new \InvalidArgumentException('Unknown error type: '.$type); } if (!\is_array($log)) { $log = [$log]; } elseif (!\array_key_exists(0, $log)) { throw new \InvalidArgumentException('No logger provided.'); } if (null === $log[0]) { $this->loggedErrors &= ~$type; } elseif ($log[0] instanceof LoggerInterface) { $this->loggedErrors |= $type; } else { throw new \InvalidArgumentException('Invalid logger provided.'); } $this->loggers[$type] = $log + $prev[$type]; if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) { $flush[$type] = $type; } } $this->reRegister($prevLogged | $this->thrownErrors); if ($flush) { foreach ($this->bootstrappingLogger->cleanLogs() as $log) { $type = ThrowableUtils::getSeverity($log[2]['exception']); if (!isset($flush[$type])) { $this->bootstrappingLogger->log($log[0], $log[1], $log[2]); } elseif ($this->loggers[$type][0]) { $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]); } } } return $prev; } /** * Sets a user exception handler. * * @param callable(\Throwable $e)|null $handler * * @return callable|null The previous exception handler */ public function setExceptionHandler(?callable $handler): ?callable { $prev = $this->exceptionHandler; $this->exceptionHandler = $handler; return $prev; } /** * Sets the PHP error levels that throw an exception when a PHP error occurs. * * @param int $levels A bit field of E_* constants for thrown errors * @param bool $replace Replace or amend the previous value * * @return int The previous value */ public function throwAt(int $levels, bool $replace = false): int { $prev = $this->thrownErrors; $this->thrownErrors = ($levels | \E_RECOVERABLE_ERROR | \E_USER_ERROR) & ~\E_USER_DEPRECATED & ~\E_DEPRECATED; if (!$replace) { $this->thrownErrors |= $prev; } $this->reRegister($prev | $this->loggedErrors); return $prev; } /** * Sets the PHP error levels for which local variables are preserved. * * @param int $levels A bit field of E_* constants for scoped errors * @param bool $replace Replace or amend the previous value * * @return int The previous value */ public function scopeAt(int $levels, bool $replace = false): int { $prev = $this->scopedErrors; $this->scopedErrors = $levels; if (!$replace) { $this->scopedErrors |= $prev; } return $prev; } /** * Sets the PHP error levels for which the stack trace is preserved. * * @param int $levels A bit field of E_* constants for traced errors * @param bool $replace Replace or amend the previous value * * @return int The previous value */ public function traceAt(int $levels, bool $replace = false): int { $prev = $this->tracedErrors; $this->tracedErrors = $levels; if (!$replace) { $this->tracedErrors |= $prev; } return $prev; } /** * Sets the error levels where the @-operator is ignored. * * @param int $levels A bit field of E_* constants for screamed errors * @param bool $replace Replace or amend the previous value * * @return int The previous value */ public function screamAt(int $levels, bool $replace = false): int { $prev = $this->screamedErrors; $this->screamedErrors = $levels; if (!$replace) { $this->screamedErrors |= $prev; } return $prev; } /** * Re-registers as a PHP error handler if levels changed. */ private function reRegister(int $prev): void { if ($prev !== $this->thrownErrors | $this->loggedErrors) { $handler = set_error_handler('var_dump'); $handler = \is_array($handler) ? $handler[0] : null; restore_error_handler(); if ($handler === $this) { restore_error_handler(); if ($this->isRoot) { set_error_handler([$this, 'handleError'], $this->thrownErrors | $this->loggedErrors); } else { set_error_handler([$this, 'handleError']); } } } } /** * Handles errors by filtering then logging them according to the configured bit fields. * * @return bool Returns false when no handling happens so that the PHP engine can handle the error itself * * @throws \ErrorException When $this->thrownErrors requests so * * @internal */ public function handleError(int $type, string $message, string $file, int $line): bool { if (\PHP_VERSION_ID >= 70300 && \E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) { $type = \E_DEPRECATED; } // Level is the current error reporting level to manage silent error. $level = error_reporting(); $silenced = 0 === ($level & $type); // Strong errors are not authorized to be silenced. $level |= \E_RECOVERABLE_ERROR | \E_USER_ERROR | \E_DEPRECATED | \E_USER_DEPRECATED; $log = $this->loggedErrors & $type; $throw = $this->thrownErrors & $type & $level; $type &= $level | $this->screamedErrors; // Never throw on warnings triggered by assert() if (\E_WARNING === $type && 'a' === $message[0] && 0 === strncmp($message, 'assert(): ', 10)) { $throw = 0; } if (!$type || (!$log && !$throw)) { return false; } $logMessage = $this->levels[$type].': '.$message; if (null !== self::$toStringException) { $errorAsException = self::$toStringException; self::$toStringException = null; } elseif (!$throw && !($type & $level)) { if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : []; $errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace); } elseif (isset(self::$silencedErrorCache[$id][$message])) { $lightTrace = null; $errorAsException = self::$silencedErrorCache[$id][$message]; ++$errorAsException->count; } else { $lightTrace = []; $errorAsException = null; } if (100 < ++self::$silencedErrorCount) { self::$silencedErrorCache = $lightTrace = []; self::$silencedErrorCount = 1; } if ($errorAsException) { self::$silencedErrorCache[$id][$message] = $errorAsException; } if (null === $lightTrace) { return true; } } else { if (false !== strpos($message, '@anonymous')) { $backtrace = debug_backtrace(false, 5); for ($i = 1; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['function'], $backtrace[$i]['args'][0]) && ('trigger_error' === $backtrace[$i]['function'] || 'user_error' === $backtrace[$i]['function']) ) { if ($backtrace[$i]['args'][0] !== $message) { $message = $this->parseAnonymousClass($backtrace[$i]['args'][0]); $logMessage = $this->levels[$type].': '.$message; } break; } } } $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); if ($throw || $this->tracedErrors & $type) { $backtrace = $errorAsException->getTrace(); $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); ($this->configureException)($errorAsException, $lightTrace, $file, $line); } else { ($this->configureException)($errorAsException, []); $backtrace = []; } } if ($throw) { if (\PHP_VERSION_ID < 70400 && \E_USER_ERROR & $type) { for ($i = 1; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function']) && '__toString' === $backtrace[$i]['function'] && '->' === $backtrace[$i]['type'] && !isset($backtrace[$i - 1]['class']) && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) ) { // Here, we know trigger_error() has been called from __toString(). // PHP triggers a fatal error when throwing from __toString(). // A small convention allows working around the limitation: // given a caught $e exception in __toString(), quitting the method with // `return trigger_error($e, E_USER_ERROR);` allows this error handler // to make $e get through the __toString() barrier. $context = 4 < \func_num_args() ? (func_get_arg(4) ?: []) : []; foreach ($context as $e) { if ($e instanceof \Throwable && $e->__toString() === $message) { self::$toStringException = $e; return true; } } // Display the original error message instead of the default one. $this->handleException($errorAsException); // Stop the process by giving back the error to the native handler. return false; } } } throw $errorAsException; } if ($this->isRecursive) { $log = 0; } else { if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) { $currentErrorHandler = set_error_handler('var_dump'); restore_error_handler(); } try { $this->isRecursive = true; $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []); } finally { $this->isRecursive = false; if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) { set_error_handler($currentErrorHandler); } } } return !$silenced && $type && $log; } /** * Handles an exception by logging then forwarding it to another handler. * * @internal */ public function handleException(\Throwable $exception) { $handlerException = null; if (!$exception instanceof FatalError) { self::$exitCode = 255; $type = ThrowableUtils::getSeverity($exception); } else { $type = $exception->getError()['type']; } if ($this->loggedErrors & $type) { if (false !== strpos($message = $exception->getMessage(), "@anonymous\0")) { $message = $this->parseAnonymousClass($message); } if ($exception instanceof FatalError) { $message = 'Fatal '.$message; } elseif ($exception instanceof \Error) { $message = 'Uncaught Error: '.$message; } elseif ($exception instanceof \ErrorException) { $message = 'Uncaught '.$message; } else { $message = 'Uncaught Exception: '.$message; } try { $this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]); } catch (\Throwable $handlerException) { } } if (!$exception instanceof OutOfMemoryError) { foreach ($this->getErrorEnhancers() as $errorEnhancer) { if ($e = $errorEnhancer->enhance($exception)) { $exception = $e; break; } } } $exceptionHandler = $this->exceptionHandler; $this->exceptionHandler = [$this, 'renderException']; if (null === $exceptionHandler || $exceptionHandler === $this->exceptionHandler) { $this->exceptionHandler = null; } try { if (null !== $exceptionHandler) { return $exceptionHandler($exception); } $handlerException = $handlerException ?: $exception; } catch (\Throwable $handlerException) { } if ($exception === $handlerException && null === $this->exceptionHandler) { self::$reservedMemory = null; // Disable the fatal error handler throw $exception; // Give back $exception to the native handler } $loggedErrors = $this->loggedErrors; if ($exception === $handlerException) { $this->loggedErrors &= ~$type; } try { $this->handleException($handlerException); } finally { $this->loggedErrors = $loggedErrors; } } /** * Shutdown registered function for handling PHP fatal errors. * * @param array|null $error An array as returned by error_get_last() * * @internal */ public static function handleFatalError(array $error = null): void { if (null === self::$reservedMemory) { return; } $handler = self::$reservedMemory = null; $handlers = []; $previousHandler = null; $sameHandlerLimit = 10; while (!\is_array($handler) || !$handler[0] instanceof self) { $handler = set_exception_handler('var_dump'); restore_exception_handler(); if (!$handler) { break; } restore_exception_handler(); if ($handler !== $previousHandler) { array_unshift($handlers, $handler); $previousHandler = $handler; } elseif (0 === --$sameHandlerLimit) { $handler = null; break; } } foreach ($handlers as $h) { set_exception_handler($h); } if (!$handler) { return; } if ($handler !== $h) { $handler[0]->setExceptionHandler($h); } $handler = $handler[0]; $handlers = []; if ($exit = null === $error) { $error = error_get_last(); } if ($error && $error['type'] &= \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR) { // Let's not throw anymore but keep logging $handler->throwAt(0, true); $trace = $error['backtrace'] ?? null; if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) { $fatalError = new OutOfMemoryError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, false, $trace); } else { $fatalError = new FatalError($handler->levels[$error['type']].': '.$error['message'], 0, $error, 2, true, $trace); } } else { $fatalError = null; } try { if (null !== $fatalError) { self::$exitCode = 255; $handler->handleException($fatalError); } } catch (FatalError $e) { // Ignore this re-throw } if ($exit && self::$exitCode) { $exitCode = self::$exitCode; register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); } } /** * Renders the given exception. * * As this method is mainly called during boot where nothing is yet available, * the output is always either HTML or CLI depending where PHP runs. */ private function renderException(\Throwable $exception): void { $renderer = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliErrorRenderer() : new HtmlErrorRenderer($this->debug); $exception = $renderer->render($exception); if (!headers_sent()) { http_response_code($exception->getStatusCode()); foreach ($exception->getHeaders() as $name => $value) { header($name.': '.$value, false); } } echo $exception->getAsString(); } /** * Override this method if you want to define more error enhancers. * * @return ErrorEnhancerInterface[] */ protected function getErrorEnhancers(): iterable { return [ new UndefinedFunctionErrorEnhancer(), new UndefinedMethodErrorEnhancer(), new ClassNotFoundErrorEnhancer(), ]; } /** * Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader. */ private function cleanTrace(array $backtrace, int $type, string &$file, int &$line, bool $throw): array { $lightTrace = $backtrace; for ($i = 0; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { $lightTrace = \array_slice($lightTrace, 1 + $i); break; } } if (\E_USER_DEPRECATED === $type) { for ($i = 0; isset($lightTrace[$i]); ++$i) { if (!isset($lightTrace[$i]['file'], $lightTrace[$i]['line'], $lightTrace[$i]['function'])) { continue; } if (!isset($lightTrace[$i]['class']) && 'trigger_deprecation' === $lightTrace[$i]['function']) { $file = $lightTrace[$i]['file']; $line = $lightTrace[$i]['line']; $lightTrace = \array_slice($lightTrace, 1 + $i); break; } } } if (class_exists(DebugClassLoader::class, false)) { for ($i = \count($lightTrace) - 2; 0 < $i; --$i) { if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) { array_splice($lightTrace, --$i, 2); } } } if (!($throw || $this->scopedErrors & $type)) { for ($i = 0; isset($lightTrace[$i]); ++$i) { unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); } } return $lightTrace; } /** * Parse the error message by removing the anonymous class notation * and using the parent class instead if possible. */ private function parseAnonymousClass(string $message): string { return preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', static function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $message); } } error-handler/README.md000064400000002475150432043200010570 0ustar00ErrorHandler Component ====================== The ErrorHandler component provides tools to manage errors and ease debugging PHP code. Getting Started --------------- ``` $ composer require symfony/error-handler ``` ```php use Symfony\Component\ErrorHandler\Debug; use Symfony\Component\ErrorHandler\ErrorHandler; use Symfony\Component\ErrorHandler\DebugClassLoader; Debug::enable(); // or enable only one feature //ErrorHandler::register(); //DebugClassLoader::enable(); // If you want a custom generic template when debug is not enabled // HtmlErrorRenderer::setTemplate('/path/to/custom/error.html.php'); $data = ErrorHandler::call(static function () use ($filename, $datetimeFormat) { // if any code executed inside this anonymous function fails, a PHP exception // will be thrown, even if the code uses the '@' PHP silence operator $data = json_decode(file_get_contents($filename), true); $data['read_at'] = date($datetimeFormat); file_put_contents($filename, json_encode($data)); return $data; }); ``` Resources --------- * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) error-handler/ThrowableUtils.php000064400000001577150432043200012774 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler; use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; /** * @internal */ class ThrowableUtils { /** * @param SilencedErrorContext|\Throwable */ public static function getSeverity($throwable): int { if ($throwable instanceof \ErrorException || $throwable instanceof SilencedErrorContext) { return $throwable->getSeverity(); } if ($throwable instanceof \ParseError) { return \E_PARSE; } if ($throwable instanceof \TypeError) { return \E_RECOVERABLE_ERROR; } return \E_ERROR; } } error-handler/DebugClassLoader.php000064400000132251150432043200013161 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler; use Composer\InstalledVersions; use Doctrine\Common\Persistence\Proxy as LegacyProxy; use Doctrine\Persistence\Proxy; use Mockery\MockInterface; use Phake\IMock; use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation; use PHPUnit\Framework\MockObject\MockObject; use Prophecy\Prophecy\ProphecySubjectInterface; use ProxyManager\Proxy\ProxyInterface; use Symfony\Component\ErrorHandler\Internal\TentativeTypes; /** * Autoloader checking if the class is really defined in the file found. * * The ClassLoader will wrap all registered autoloaders * and will throw an exception if a file is found but does * not declare the class. * * It can also patch classes to turn docblocks into actual return types. * This behavior is controlled by the SYMFONY_PATCH_TYPE_DECLARATIONS env var, * which is a url-encoded array with the follow parameters: * - "force": any value enables deprecation notices - can be any of: * - "phpdoc" to patch only docblock annotations * - "2" to add all possible return types * - "1" to add return types but only to tests/final/internal/private methods * - "php": the target version of PHP - e.g. "7.1" doesn't generate "object" types * - "deprecations": "1" to trigger a deprecation notice when a child class misses a * return type while the parent declares an "@return" annotation * * Note that patching doesn't care about any coding style so you'd better to run * php-cs-fixer after, with rules "phpdoc_trim_consecutive_blank_line_separation" * and "no_superfluous_phpdoc_tags" enabled typically. * * @author Fabien Potencier * @author Christophe Coevoet * @author Nicolas Grekas * @author Guilhem Niot */ class DebugClassLoader { private const SPECIAL_RETURN_TYPES = [ 'void' => 'void', 'null' => 'null', 'resource' => 'resource', 'boolean' => 'bool', 'true' => 'bool', 'false' => 'false', 'integer' => 'int', 'array' => 'array', 'bool' => 'bool', 'callable' => 'callable', 'float' => 'float', 'int' => 'int', 'iterable' => 'iterable', 'object' => 'object', 'string' => 'string', 'self' => 'self', 'parent' => 'parent', 'mixed' => 'mixed', 'static' => 'static', '$this' => 'static', 'list' => 'array', ]; private const BUILTIN_RETURN_TYPES = [ 'void' => true, 'array' => true, 'false' => true, 'bool' => true, 'callable' => true, 'float' => true, 'int' => true, 'iterable' => true, 'object' => true, 'string' => true, 'self' => true, 'parent' => true, 'mixed' => true, 'static' => true, ]; private const MAGIC_METHODS = [ '__isset' => 'bool', '__sleep' => 'array', '__toString' => 'string', '__debugInfo' => 'array', '__serialize' => 'array', ]; private $classLoader; private $isFinder; private $loaded = []; private $patchTypes; private static $caseCheck; private static $checkedClasses = []; private static $final = []; private static $finalMethods = []; private static $deprecated = []; private static $internal = []; private static $internalMethods = []; private static $annotatedParameters = []; private static $darwinCache = ['/' => ['/', []]]; private static $method = []; private static $returnTypes = []; private static $methodTraits = []; private static $fileOffsets = []; public function __construct(callable $classLoader) { $this->classLoader = $classLoader; $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile'); parse_str(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?: '', $this->patchTypes); $this->patchTypes += [ 'force' => null, 'php' => \PHP_MAJOR_VERSION.'.'.\PHP_MINOR_VERSION, 'deprecations' => \PHP_VERSION_ID >= 70400, ]; if ('phpdoc' === $this->patchTypes['force']) { $this->patchTypes['force'] = 'docblock'; } if (!isset(self::$caseCheck)) { $file = is_file(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR); $i = strrpos($file, \DIRECTORY_SEPARATOR); $dir = substr($file, 0, 1 + $i); $file = substr($file, 1 + $i); $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); $test = realpath($dir.$test); if (false === $test || false === $i) { // filesystem is case sensitive self::$caseCheck = 0; } elseif (substr($test, -\strlen($file)) === $file) { // filesystem is case insensitive and realpath() normalizes the case of characters self::$caseCheck = 1; } elseif ('Darwin' === \PHP_OS_FAMILY) { // on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters self::$caseCheck = 2; } else { // filesystem case checks failed, fallback to disabling them self::$caseCheck = 0; } } } public function getClassLoader(): callable { return $this->classLoader; } /** * Wraps all autoloaders. */ public static function enable(): void { // Ensures we don't hit https://bugs.php.net/42098 class_exists(\Symfony\Component\ErrorHandler\ErrorHandler::class); class_exists(\Psr\Log\LogLevel::class); if (!\is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (!\is_array($function) || !$function[0] instanceof self) { $function = [new static($function), 'loadClass']; } spl_autoload_register($function); } } /** * Disables the wrapping. */ public static function disable(): void { if (!\is_array($functions = spl_autoload_functions())) { return; } foreach ($functions as $function) { spl_autoload_unregister($function); } foreach ($functions as $function) { if (\is_array($function) && $function[0] instanceof self) { $function = $function[0]->getClassLoader(); } spl_autoload_register($function); } } public static function checkClasses(): bool { if (!\is_array($functions = spl_autoload_functions())) { return false; } $loader = null; foreach ($functions as $function) { if (\is_array($function) && $function[0] instanceof self) { $loader = $function[0]; break; } } if (null === $loader) { return false; } static $offsets = [ 'get_declared_interfaces' => 0, 'get_declared_traits' => 0, 'get_declared_classes' => 0, ]; foreach ($offsets as $getSymbols => $i) { $symbols = $getSymbols(); for (; $i < \count($symbols); ++$i) { if (!is_subclass_of($symbols[$i], MockObject::class) && !is_subclass_of($symbols[$i], ProphecySubjectInterface::class) && !is_subclass_of($symbols[$i], Proxy::class) && !is_subclass_of($symbols[$i], ProxyInterface::class) && !is_subclass_of($symbols[$i], LegacyProxy::class) && !is_subclass_of($symbols[$i], MockInterface::class) && !is_subclass_of($symbols[$i], IMock::class) ) { $loader->checkClass($symbols[$i]); } } $offsets[$getSymbols] = $i; } return true; } public function findFile(string $class): ?string { return $this->isFinder ? ($this->classLoader[0]->findFile($class) ?: null) : null; } /** * Loads the given class or interface. * * @throws \RuntimeException */ public function loadClass(string $class): void { $e = error_reporting(error_reporting() | \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR); try { if ($this->isFinder && !isset($this->loaded[$class])) { $this->loaded[$class] = true; if (!$file = $this->classLoader[0]->findFile($class) ?: '') { // no-op } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) { include $file; return; } elseif (false === include $file) { return; } } else { ($this->classLoader)($class); $file = ''; } } finally { error_reporting($e); } $this->checkClass($class, $file); } private function checkClass(string $class, string $file = null): void { $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); if (null !== $file && $class && '\\' === $class[0]) { $class = substr($class, 1); } if ($exists) { if (isset(self::$checkedClasses[$class])) { return; } self::$checkedClasses[$class] = true; $refl = new \ReflectionClass($class); if (null === $file && $refl->isInternal()) { return; } $name = $refl->getName(); if ($name !== $class && 0 === strcasecmp($name, $class)) { throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); } $deprecations = $this->checkAnnotations($refl, $name); foreach ($deprecations as $message) { @trigger_error($message, \E_USER_DEPRECATED); } } if (!$file) { return; } if (!$exists) { if (false !== strpos($class, '/')) { throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); } throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); } if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) { throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2])); } } public function checkAnnotations(\ReflectionClass $refl, string $class): array { if ( 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV7' === $class || 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV6' === $class ) { return []; } $deprecations = []; $className = false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class; // Don't trigger deprecations for classes in the same vendor if ($class !== $className) { $vendor = preg_match('/^namespace ([^;\\\\\s]++)[;\\\\]/m', @file_get_contents($refl->getFileName()), $vendor) ? $vendor[1].'\\' : ''; $vendorLen = \strlen($vendor); } elseif (2 > $vendorLen = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) { $vendorLen = 0; $vendor = ''; } else { $vendor = str_replace('_', '\\', substr($class, 0, $vendorLen)); } $parent = get_parent_class($class) ?: null; self::$returnTypes[$class] = []; // Detect annotations on the class if ($doc = $this->parsePhpDoc($refl)) { foreach (['final', 'deprecated', 'internal'] as $annotation) { if (null !== $description = $doc[$annotation][0] ?? null) { self::${$annotation}[$class] = '' !== $description ? ' '.$description.(preg_match('/[.!]$/', $description) ? '' : '.') : '.'; } } if ($refl->isInterface() && isset($doc['method'])) { foreach ($doc['method'] as $name => [$static, $returnType, $signature, $description]) { self::$method[$class][] = [$class, $static, $returnType, $name.$signature, $description]; if ('' !== $returnType) { $this->setReturnType($returnType, $refl->name, $name, $refl->getFileName(), $parent); } } } } $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent); if ($parent) { $parentAndOwnInterfaces[$parent] = $parent; if (!isset(self::$checkedClasses[$parent])) { $this->checkClass($parent); } if (isset(self::$final[$parent])) { $deprecations[] = sprintf('The "%s" class is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $className); } } // Detect if the parent is annotated foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) { if (!isset(self::$checkedClasses[$use])) { $this->checkClass($use); } if (isset(self::$deprecated[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && !isset(self::$deprecated[$class])) { $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait'); $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s', $className, $type, $verb, $use, self::$deprecated[$use]); } if (isset(self::$internal[$use]) && strncmp($vendor, str_replace('_', '\\', $use), $vendorLen)) { $deprecations[] = sprintf('The "%s" %s is considered internal%s It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $className); } if (isset(self::$method[$use])) { if ($refl->isAbstract()) { if (isset(self::$method[$class])) { self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]); } else { self::$method[$class] = self::$method[$use]; } } elseif (!$refl->isInterface()) { if (!strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && 0 === strpos($className, 'Symfony\\') && (!class_exists(InstalledVersions::class) || 'symfony/symfony' !== InstalledVersions::getRootPackage()['name']) ) { // skip "same vendor" @method deprecations for Symfony\* classes unless symfony/symfony is being tested continue; } $hasCall = $refl->hasMethod('__call'); $hasStaticCall = $refl->hasMethod('__callStatic'); foreach (self::$method[$use] as [$interface, $static, $returnType, $name, $description]) { if ($static ? $hasStaticCall : $hasCall) { continue; } $realName = substr($name, 0, strpos($name, '(')); if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) { $deprecations[] = sprintf('Class "%s" should implement method "%s::%s%s"%s', $className, ($static ? 'static ' : '').$interface, $name, $returnType ? ': '.$returnType : '', null === $description ? '.' : ': '.$description); } } } } } if (trait_exists($class)) { $file = $refl->getFileName(); foreach ($refl->getMethods() as $method) { if ($method->getFileName() === $file) { self::$methodTraits[$file][$method->getStartLine()] = $class; } } return $deprecations; } // Inherit @final, @internal, @param and @return annotations for methods self::$finalMethods[$class] = []; self::$internalMethods[$class] = []; self::$annotatedParameters[$class] = []; foreach ($parentAndOwnInterfaces as $use) { foreach (['finalMethods', 'internalMethods', 'annotatedParameters', 'returnTypes'] as $property) { if (isset(self::${$property}[$use])) { self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use]; } } if (null !== (TentativeTypes::RETURN_TYPES[$use] ?? null)) { foreach (TentativeTypes::RETURN_TYPES[$use] as $method => $returnType) { $returnType = explode('|', $returnType); foreach ($returnType as $i => $t) { if ('?' !== $t && !isset(self::BUILTIN_RETURN_TYPES[$t])) { $returnType[$i] = '\\'.$t; } } $returnType = implode('|', $returnType); self::$returnTypes[$class] += [$method => [$returnType, 0 === strpos($returnType, '?') ? substr($returnType, 1).'|null' : $returnType, $use, '']]; } } } foreach ($refl->getMethods() as $method) { if ($method->class !== $class) { continue; } if (null === $ns = self::$methodTraits[$method->getFileName()][$method->getStartLine()] ?? null) { $ns = $vendor; $len = $vendorLen; } elseif (2 > $len = 1 + (strpos($ns, '\\') ?: strpos($ns, '_'))) { $len = 0; $ns = ''; } else { $ns = str_replace('_', '\\', substr($ns, 0, $len)); } if ($parent && isset(self::$finalMethods[$parent][$method->name])) { [$declaringClass, $message] = self::$finalMethods[$parent][$method->name]; $deprecations[] = sprintf('The "%s::%s()" method is considered final%s It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); } if (isset(self::$internalMethods[$class][$method->name])) { [$declaringClass, $message] = self::$internalMethods[$class][$method->name]; if (strncmp($ns, $declaringClass, $len)) { $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $className); } } // To read method annotations $doc = $this->parsePhpDoc($method); if (isset(self::$annotatedParameters[$class][$method->name])) { $definedParameters = []; foreach ($method->getParameters() as $parameter) { $definedParameters[$parameter->name] = true; } foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) { if (!isset($definedParameters[$parameterName]) && !isset($doc['param'][$parameterName])) { $deprecations[] = sprintf($deprecation, $className); } } } $forcePatchTypes = $this->patchTypes['force']; if ($canAddReturnType = null !== $forcePatchTypes && false === strpos($method->getFileName(), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) { if ('void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) { $this->patchTypes['force'] = $forcePatchTypes ?: 'docblock'; } $canAddReturnType = 2 === (int) $forcePatchTypes || false !== stripos($method->getFileName(), \DIRECTORY_SEPARATOR.'Tests'.\DIRECTORY_SEPARATOR) || $refl->isFinal() || $method->isFinal() || $method->isPrivate() || ('.' === (self::$internal[$class] ?? null) && !$refl->isAbstract()) || '.' === (self::$final[$class] ?? null) || '' === ($doc['final'][0] ?? null) || '' === ($doc['internal'][0] ?? null) ; } if (null !== ($returnType = self::$returnTypes[$class][$method->name] ?? null) && 'docblock' === $this->patchTypes['force'] && !$method->hasReturnType() && isset(TentativeTypes::RETURN_TYPES[$returnType[2]][$method->name])) { $this->patchReturnTypeWillChange($method); } if (null !== ($returnType ?? $returnType = self::MAGIC_METHODS[$method->name] ?? null) && !$method->hasReturnType() && !isset($doc['return'])) { [$normalizedType, $returnType, $declaringClass, $declaringFile] = \is_string($returnType) ? [$returnType, $returnType, '', ''] : $returnType; if ($canAddReturnType && 'docblock' !== $this->patchTypes['force']) { $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); } if (!isset($doc['deprecated']) && strncmp($ns, $declaringClass, $len)) { if ('docblock' === $this->patchTypes['force']) { $this->patchMethod($method, $returnType, $declaringFile, $normalizedType); } elseif ('' !== $declaringClass && $this->patchTypes['deprecations']) { $deprecations[] = sprintf('Method "%s::%s()" might add "%s" as a native return type declaration in the future. Do the same in %s "%s" now to avoid errors or add an explicit @return annotation to suppress this message.', $declaringClass, $method->name, $normalizedType, interface_exists($declaringClass) ? 'implementation' : 'child class', $className); } } } if (!$doc) { $this->patchTypes['force'] = $forcePatchTypes; continue; } if (isset($doc['return']) || 'void' !== (self::MAGIC_METHODS[$method->name] ?? 'void')) { $this->setReturnType($doc['return'] ?? self::MAGIC_METHODS[$method->name], $method->class, $method->name, $method->getFileName(), $parent, $method->getReturnType()); if (isset(self::$returnTypes[$class][$method->name][0]) && $canAddReturnType) { $this->fixReturnStatements($method, self::$returnTypes[$class][$method->name][0]); } if ($method->isPrivate()) { unset(self::$returnTypes[$class][$method->name]); } } $this->patchTypes['force'] = $forcePatchTypes; if ($method->isPrivate()) { continue; } $finalOrInternal = false; foreach (['final', 'internal'] as $annotation) { if (null !== $description = $doc[$annotation][0] ?? null) { self::${$annotation.'Methods'}[$class][$method->name] = [$class, '' !== $description ? ' '.$description.(preg_match('/[[:punct:]]$/', $description) ? '' : '.') : '.']; $finalOrInternal = true; } } if ($finalOrInternal || $method->isConstructor() || !isset($doc['param']) || StatelessInvocation::class === $class) { continue; } if (!isset(self::$annotatedParameters[$class][$method->name])) { $definedParameters = []; foreach ($method->getParameters() as $parameter) { $definedParameters[$parameter->name] = true; } } foreach ($doc['param'] as $parameterName => $parameterType) { if (!isset($definedParameters[$parameterName])) { self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its %s "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, interface_exists($className) ? 'interface' : 'parent class', $className); } } } return $deprecations; } public function checkCase(\ReflectionClass $refl, string $file, string $class): ?array { $real = explode('\\', $class.strrchr($file, '.')); $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file)); $i = \count($tail) - 1; $j = \count($real) - 1; while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { --$i; --$j; } array_splice($tail, 0, $i + 1); if (!$tail) { return null; } $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail); $tailLen = \strlen($tail); $real = $refl->getFileName(); if (2 === self::$caseCheck) { $real = $this->darwinRealpath($real); } if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) ) { return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)]; } return null; } /** * `realpath` on MacOSX doesn't normalize the case of characters. */ private function darwinRealpath(string $real): string { $i = 1 + strrpos($real, '/'); $file = substr($real, $i); $real = substr($real, 0, $i); if (isset(self::$darwinCache[$real])) { $kDir = $real; } else { $kDir = strtolower($real); if (isset(self::$darwinCache[$kDir])) { $real = self::$darwinCache[$kDir][0]; } else { $dir = getcwd(); if (!@chdir($real)) { return $real.$file; } $real = getcwd().'/'; chdir($dir); $dir = $real; $k = $kDir; $i = \strlen($dir) - 1; while (!isset(self::$darwinCache[$k])) { self::$darwinCache[$k] = [$dir, []]; self::$darwinCache[$dir] = &self::$darwinCache[$k]; while ('/' !== $dir[--$i]) { } $k = substr($k, 0, ++$i); $dir = substr($dir, 0, $i--); } } } $dirFiles = self::$darwinCache[$kDir][1]; if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) { // Get the file name from "file_name.php(123) : eval()'d code" $file = substr($file, 0, strrpos($file, '(', -17)); } if (isset($dirFiles[$file])) { return $real.$dirFiles[$file]; } $kFile = strtolower($file); if (!isset($dirFiles[$kFile])) { foreach (scandir($real, 2) as $f) { if ('.' !== $f[0]) { $dirFiles[$f] = $f; if ($f === $file) { $kFile = $k = $file; } elseif ($f !== $k = strtolower($f)) { $dirFiles[$k] = $f; } } } self::$darwinCache[$kDir][1] = $dirFiles; } return $real.$dirFiles[$kFile]; } /** * `class_implements` includes interfaces from the parents so we have to manually exclude them. * * @return string[] */ private function getOwnInterfaces(string $class, ?string $parent): array { $ownInterfaces = class_implements($class, false); if ($parent) { foreach (class_implements($parent, false) as $interface) { unset($ownInterfaces[$interface]); } } foreach ($ownInterfaces as $interface) { foreach (class_implements($interface) as $interface) { unset($ownInterfaces[$interface]); } } return $ownInterfaces; } private function setReturnType(string $types, string $class, string $method, string $filename, ?string $parent, \ReflectionType $returnType = null): void { if ('__construct' === $method) { return; } if ($nullable = 0 === strpos($types, 'null|')) { $types = substr($types, 5); } elseif ($nullable = '|null' === substr($types, -5)) { $types = substr($types, 0, -5); } $arrayType = ['array' => 'array']; $typesMap = []; $glue = false !== strpos($types, '&') ? '&' : '|'; foreach (explode($glue, $types) as $t) { $t = self::SPECIAL_RETURN_TYPES[strtolower($t)] ?? $t; $typesMap[$this->normalizeType($t, $class, $parent, $returnType)][$t] = $t; } if (isset($typesMap['array'])) { if (isset($typesMap['Traversable']) || isset($typesMap['\Traversable'])) { $typesMap['iterable'] = $arrayType !== $typesMap['array'] ? $typesMap['array'] : ['iterable']; unset($typesMap['array'], $typesMap['Traversable'], $typesMap['\Traversable']); } elseif ($arrayType !== $typesMap['array'] && isset(self::$returnTypes[$class][$method]) && !$returnType) { return; } } if (isset($typesMap['array']) && isset($typesMap['iterable'])) { if ($arrayType !== $typesMap['array']) { $typesMap['iterable'] = $typesMap['array']; } unset($typesMap['array']); } $iterable = $object = true; foreach ($typesMap as $n => $t) { if ('null' !== $n) { $iterable = $iterable && (\in_array($n, ['array', 'iterable']) || false !== strpos($n, 'Iterator')); $object = $object && (\in_array($n, ['callable', 'object', '$this', 'static']) || !isset(self::SPECIAL_RETURN_TYPES[$n])); } } $phpTypes = []; $docTypes = []; foreach ($typesMap as $n => $t) { if ('null' === $n) { $nullable = true; continue; } $docTypes[] = $t; if ('mixed' === $n || 'void' === $n) { $nullable = false; $phpTypes = ['' => $n]; continue; } if ('resource' === $n) { // there is no native type for "resource" return; } if (!isset($phpTypes[''])) { $phpTypes[] = $n; } } $docTypes = array_merge([], ...$docTypes); if (!$phpTypes) { return; } if (1 < \count($phpTypes)) { if ($iterable && '8.0' > $this->patchTypes['php']) { $phpTypes = $docTypes = ['iterable']; } elseif ($object && 'object' === $this->patchTypes['force']) { $phpTypes = $docTypes = ['object']; } elseif ('8.0' > $this->patchTypes['php']) { // ignore multi-types return declarations return; } } $phpType = sprintf($nullable ? (1 < \count($phpTypes) ? '%s|null' : '?%s') : '%s', implode($glue, $phpTypes)); $docType = sprintf($nullable ? '%s|null' : '%s', implode($glue, $docTypes)); self::$returnTypes[$class][$method] = [$phpType, $docType, $class, $filename]; } private function normalizeType(string $type, string $class, ?string $parent, ?\ReflectionType $returnType): string { if (isset(self::SPECIAL_RETURN_TYPES[$lcType = strtolower($type)])) { if ('parent' === $lcType = self::SPECIAL_RETURN_TYPES[$lcType]) { $lcType = null !== $parent ? '\\'.$parent : 'parent'; } elseif ('self' === $lcType) { $lcType = '\\'.$class; } return $lcType; } // We could resolve "use" statements to return the FQDN // but this would be too expensive for a runtime checker if ('[]' !== substr($type, -2)) { return $type; } if ($returnType instanceof \ReflectionNamedType) { $type = $returnType->getName(); if ('mixed' !== $type) { return isset(self::SPECIAL_RETURN_TYPES[$type]) ? $type : '\\'.$type; } } return 'array'; } /** * Utility method to add #[ReturnTypeWillChange] where php triggers deprecations. */ private function patchReturnTypeWillChange(\ReflectionMethod $method) { if (\PHP_VERSION_ID >= 80000 && \count($method->getAttributes(\ReturnTypeWillChange::class))) { return; } if (!is_file($file = $method->getFileName())) { return; } $fileOffset = self::$fileOffsets[$file] ?? 0; $code = file($file); $startLine = $method->getStartLine() + $fileOffset - 2; if (false !== stripos($code[$startLine], 'ReturnTypeWillChange')) { return; } $code[$startLine] .= " #[\\ReturnTypeWillChange]\n"; self::$fileOffsets[$file] = 1 + $fileOffset; file_put_contents($file, $code); } /** * Utility method to add @return annotations to the Symfony code-base where it triggers self-deprecations. */ private function patchMethod(\ReflectionMethod $method, string $returnType, string $declaringFile, string $normalizedType) { static $patchedMethods = []; static $useStatements = []; if (!is_file($file = $method->getFileName()) || isset($patchedMethods[$file][$startLine = $method->getStartLine()])) { return; } $patchedMethods[$file][$startLine] = true; $fileOffset = self::$fileOffsets[$file] ?? 0; $startLine += $fileOffset - 2; if ($nullable = '|null' === substr($returnType, -5)) { $returnType = substr($returnType, 0, -5); } $glue = false !== strpos($returnType, '&') ? '&' : '|'; $returnType = explode($glue, $returnType); $code = file($file); foreach ($returnType as $i => $type) { if (preg_match('/((?:\[\])+)$/', $type, $m)) { $type = substr($type, 0, -\strlen($m[1])); $format = '%s'.$m[1]; } else { $format = null; } if (isset(self::SPECIAL_RETURN_TYPES[$type]) || ('\\' === $type[0] && !$p = strrpos($type, '\\', 1))) { continue; } [$namespace, $useOffset, $useMap] = $useStatements[$file] ?? $useStatements[$file] = self::getUseStatements($file); if ('\\' !== $type[0]) { [$declaringNamespace, , $declaringUseMap] = $useStatements[$declaringFile] ?? $useStatements[$declaringFile] = self::getUseStatements($declaringFile); $p = strpos($type, '\\', 1); $alias = $p ? substr($type, 0, $p) : $type; if (isset($declaringUseMap[$alias])) { $type = '\\'.$declaringUseMap[$alias].($p ? substr($type, $p) : ''); } else { $type = '\\'.$declaringNamespace.$type; } $p = strrpos($type, '\\', 1); } $alias = substr($type, 1 + $p); $type = substr($type, 1); if (!isset($useMap[$alias]) && (class_exists($c = $namespace.$alias) || interface_exists($c) || trait_exists($c))) { $useMap[$alias] = $c; } if (!isset($useMap[$alias])) { $useStatements[$file][2][$alias] = $type; $code[$useOffset] = "use $type;\n".$code[$useOffset]; ++$fileOffset; } elseif ($useMap[$alias] !== $type) { $alias .= 'FIXME'; $useStatements[$file][2][$alias] = $type; $code[$useOffset] = "use $type as $alias;\n".$code[$useOffset]; ++$fileOffset; } $returnType[$i] = null !== $format ? sprintf($format, $alias) : $alias; } if ('docblock' === $this->patchTypes['force'] || ('object' === $normalizedType && '7.1' === $this->patchTypes['php'])) { $returnType = implode($glue, $returnType).($nullable ? '|null' : ''); if (false !== strpos($code[$startLine], '#[')) { --$startLine; } if ($method->getDocComment()) { $code[$startLine] = " * @return $returnType\n".$code[$startLine]; } else { $code[$startLine] .= <<fixReturnStatements($method, $normalizedType); } private static function getUseStatements(string $file): array { $namespace = ''; $useMap = []; $useOffset = 0; if (!is_file($file)) { return [$namespace, $useOffset, $useMap]; } $file = file($file); for ($i = 0; $i < \count($file); ++$i) { if (preg_match('/^(class|interface|trait|abstract) /', $file[$i])) { break; } if (0 === strpos($file[$i], 'namespace ')) { $namespace = substr($file[$i], \strlen('namespace '), -2).'\\'; $useOffset = $i + 2; } if (0 === strpos($file[$i], 'use ')) { $useOffset = $i; for (; 0 === strpos($file[$i], 'use '); ++$i) { $u = explode(' as ', substr($file[$i], 4, -2), 2); if (1 === \count($u)) { $p = strrpos($u[0], '\\'); $useMap[substr($u[0], false !== $p ? 1 + $p : 0)] = $u[0]; } else { $useMap[$u[1]] = $u[0]; } } break; } } return [$namespace, $useOffset, $useMap]; } private function fixReturnStatements(\ReflectionMethod $method, string $returnType) { if ('docblock' !== $this->patchTypes['force']) { if ('7.1' === $this->patchTypes['php'] && 'object' === ltrim($returnType, '?')) { return; } if ('7.4' > $this->patchTypes['php'] && $method->hasReturnType()) { return; } if ('8.0' > $this->patchTypes['php'] && (false !== strpos($returnType, '|') || \in_array($returnType, ['mixed', 'static'], true))) { return; } if ('8.1' > $this->patchTypes['php'] && false !== strpos($returnType, '&')) { return; } } if (!is_file($file = $method->getFileName())) { return; } $fixedCode = $code = file($file); $i = (self::$fileOffsets[$file] ?? 0) + $method->getStartLine(); if ('?' !== $returnType && 'docblock' !== $this->patchTypes['force']) { $fixedCode[$i - 1] = preg_replace('/\)(?::[^;\n]++)?(;?\n)/', "): $returnType\\1", $code[$i - 1]); } $end = $method->isGenerator() ? $i : $method->getEndLine(); for (; $i < $end; ++$i) { if ('void' === $returnType) { $fixedCode[$i] = str_replace(' return null;', ' return;', $code[$i]); } elseif ('mixed' === $returnType || '?' === $returnType[0]) { $fixedCode[$i] = str_replace(' return;', ' return null;', $code[$i]); } else { $fixedCode[$i] = str_replace(' return;', " return $returnType!?;", $code[$i]); } } if ($fixedCode !== $code) { file_put_contents($file, $fixedCode); } } /** * @param \ReflectionClass|\ReflectionMethod|\ReflectionProperty $reflector */ private function parsePhpDoc(\Reflector $reflector): array { if (!$doc = $reflector->getDocComment()) { return []; } $tagName = ''; $tagContent = ''; $tags = []; foreach (explode("\n", substr($doc, 3, -2)) as $line) { $line = ltrim($line); $line = ltrim($line, '*'); if ('' === $line = trim($line)) { if ('' !== $tagName) { $tags[$tagName][] = $tagContent; } $tagName = $tagContent = ''; continue; } if ('@' === $line[0]) { if ('' !== $tagName) { $tags[$tagName][] = $tagContent; $tagContent = ''; } if (preg_match('{^@([-a-zA-Z0-9_:]++)(\s|$)}', $line, $m)) { $tagName = $m[1]; $tagContent = str_replace("\t", ' ', ltrim(substr($line, 2 + \strlen($tagName)))); } else { $tagName = ''; } } elseif ('' !== $tagName) { $tagContent .= ' '.str_replace("\t", ' ', $line); } } if ('' !== $tagName) { $tags[$tagName][] = $tagContent; } foreach ($tags['method'] ?? [] as $i => $method) { unset($tags['method'][$i]); $parts = preg_split('{(\s++|\((?:[^()]*+|(?R))*\)(?: *: *[^ ]++)?|<(?:[^<>]*+|(?R))*>|\{(?:[^{}]*+|(?R))*\})}', $method, -1, \PREG_SPLIT_DELIM_CAPTURE); $returnType = ''; $static = 'static' === $parts[0]; for ($i = $static ? 2 : 0; null !== $p = $parts[$i] ?? null; $i += 2) { if (\in_array($p, ['', '|', '&', 'callable'], true) || \in_array(substr($returnType, -1), ['|', '&'], true)) { $returnType .= trim($parts[$i - 1] ?? '').$p; continue; } $signature = '(' === ($parts[$i + 1][0] ?? '(') ? $parts[$i + 1] ?? '()' : null; if (null === $signature && '' === $returnType) { $returnType = $p; continue; } if ($static && 2 === $i) { $static = false; $returnType = 'static'; } if (\in_array($description = trim(implode('', \array_slice($parts, 2 + $i))), ['', '.'], true)) { $description = null; } elseif (!preg_match('/[.!]$/', $description)) { $description .= '.'; } $tags['method'][$p] = [$static, $returnType, $signature ?? '()', $description]; break; } } foreach ($tags['param'] ?? [] as $i => $param) { unset($tags['param'][$i]); if (\strlen($param) !== strcspn($param, '<{(')) { $param = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $param); } if (false === $i = strpos($param, '$')) { continue; } $type = 0 === $i ? '' : rtrim(substr($param, 0, $i), ' &'); $param = substr($param, 1 + $i, (strpos($param, ' ', $i) ?: (1 + $i + \strlen($param))) - $i - 1); $tags['param'][$param] = $type; } foreach (['var', 'return'] as $k) { if (null === $v = $tags[$k][0] ?? null) { continue; } if (\strlen($v) !== strcspn($v, '<{(')) { $v = preg_replace('{\(([^()]*+|(?R))*\)(?: *: *[^ ]++)?|<([^<>]*+|(?R))*>|\{([^{}]*+|(?R))*\}}', '', $v); } $tags[$k] = substr($v, 0, strpos($v, ' ') ?: \strlen($v)) ?: null; } return $tags; } } error-handler/BufferingLogger.php000064400000003767150432043200013076 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler; use Psr\Log\AbstractLogger; /** * A buffering logger that stacks logs for later. * * @author Nicolas Grekas */ class BufferingLogger extends AbstractLogger { private $logs = []; public function log($level, $message, array $context = []): void { $this->logs[] = [$level, $message, $context]; } public function cleanLogs(): array { $logs = $this->logs; $this->logs = []; return $logs; } /** * @return array */ public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { foreach ($this->logs as [$level, $message, $context]) { if (false !== strpos($message, '{')) { foreach ($context as $key => $val) { if (null === $val || is_scalar($val) || (\is_object($val) && \is_callable([$val, '__toString']))) { $message = str_replace("{{$key}}", $val, $message); } elseif ($val instanceof \DateTimeInterface) { $message = str_replace("{{$key}}", $val->format(\DateTime::RFC3339), $message); } elseif (\is_object($val)) { $message = str_replace("{{$key}}", '[object '.\get_class($val).']', $message); } else { $message = str_replace("{{$key}}", '['.\gettype($val).']', $message); } } } error_log(sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message)); } } } error-handler/Error/UndefinedFunctionError.php000064400000001601150432043200015522 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Error; class UndefinedFunctionError extends \Error { /** * {@inheritdoc} */ public function __construct(string $message, \Throwable $previous) { parent::__construct($message, $previous->getCode(), $previous->getPrevious()); foreach ([ 'file' => $previous->getFile(), 'line' => $previous->getLine(), 'trace' => $previous->getTrace(), ] as $property => $value) { $refl = new \ReflectionProperty(\Error::class, $property); $refl->setAccessible(true); $refl->setValue($this, $value); } } } error-handler/Error/UndefinedMethodError.php000064400000001577150432043200015171 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Error; class UndefinedMethodError extends \Error { /** * {@inheritdoc} */ public function __construct(string $message, \Throwable $previous) { parent::__construct($message, $previous->getCode(), $previous->getPrevious()); foreach ([ 'file' => $previous->getFile(), 'line' => $previous->getLine(), 'trace' => $previous->getTrace(), ] as $property => $value) { $refl = new \ReflectionProperty(\Error::class, $property); $refl->setAccessible(true); $refl->setValue($this, $value); } } } error-handler/Error/FatalError.php000064400000005415150432043200013151 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Error; class FatalError extends \Error { private $error; /** * {@inheritdoc} * * @param array $error An array as returned by error_get_last() */ public function __construct(string $message, int $code, array $error, int $traceOffset = null, bool $traceArgs = true, array $trace = null) { parent::__construct($message, $code); $this->error = $error; if (null !== $trace) { if (!$traceArgs) { foreach ($trace as &$frame) { unset($frame['args'], $frame['this'], $frame); } } } elseif (null !== $traceOffset) { if (\function_exists('xdebug_get_function_stack') && $trace = @xdebug_get_function_stack()) { if (0 < $traceOffset) { array_splice($trace, -$traceOffset); } foreach ($trace as &$frame) { if (!isset($frame['type'])) { // XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695 if (isset($frame['class'])) { $frame['type'] = '::'; } } elseif ('dynamic' === $frame['type']) { $frame['type'] = '->'; } elseif ('static' === $frame['type']) { $frame['type'] = '::'; } // XDebug also has a different name for the parameters array if (!$traceArgs) { unset($frame['params'], $frame['args']); } elseif (isset($frame['params']) && !isset($frame['args'])) { $frame['args'] = $frame['params']; unset($frame['params']); } } unset($frame); $trace = array_reverse($trace); } else { $trace = []; } } foreach ([ 'file' => $error['file'], 'line' => $error['line'], 'trace' => $trace, ] as $property => $value) { if (null !== $value) { $refl = new \ReflectionProperty(\Error::class, $property); $refl->setAccessible(true); $refl->setValue($this, $value); } } } /** * {@inheritdoc} */ public function getError(): array { return $this->error; } } error-handler/Error/OutOfMemoryError.php000064400000000515150432043200014343 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Error; class OutOfMemoryError extends FatalError { } error-handler/Error/ClassNotFoundError.php000064400000001575150432043200014647 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Error; class ClassNotFoundError extends \Error { /** * {@inheritdoc} */ public function __construct(string $message, \Throwable $previous) { parent::__construct($message, $previous->getCode(), $previous->getPrevious()); foreach ([ 'file' => $previous->getFile(), 'line' => $previous->getLine(), 'trace' => $previous->getTrace(), ] as $property => $value) { $refl = new \ReflectionProperty(\Error::class, $property); $refl->setAccessible(true); $refl->setValue($this, $value); } } } error-handler/CHANGELOG.md000064400000001174150432043200011115 0ustar00CHANGELOG ========= 5.4 --- * Make `DebugClassLoader` trigger deprecation notices on missing return types * Add `SYMFONY_PATCH_TYPE_DECLARATIONS='force=2'` mode to `DebugClassLoader` to turn annotations into native return types 5.2.0 ----- * added the ability to set `HtmlErrorRenderer::$template` to a custom template to render when not in debug mode. 5.1.0 ----- * The `HtmlErrorRenderer` and `SerializerErrorRenderer` add `X-Debug-Exception` and `X-Debug-Exception-File` headers in debug mode. 4.4.0 ----- * added the component * added `ErrorHandler::call()` method utility to turn any PHP error into `\ErrorException` error-handler/ErrorRenderer/ErrorRendererInterface.php000064400000001206150432043200017172 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorRenderer; use Symfony\Component\ErrorHandler\Exception\FlattenException; /** * Formats an exception to be used as response content. * * @author Yonel Ceruto */ interface ErrorRendererInterface { /** * Renders a Throwable as a FlattenException. */ public function render(\Throwable $exception): FlattenException; } error-handler/ErrorRenderer/CliErrorRenderer.php000064400000002564150432043200016011 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorRenderer; use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\CliDumper; // Help opcache.preload discover always-needed symbols class_exists(CliDumper::class); /** * @author Nicolas Grekas */ class CliErrorRenderer implements ErrorRendererInterface { /** * {@inheritdoc} */ public function render(\Throwable $exception): FlattenException { $cloner = new VarCloner(); $dumper = new class() extends CliDumper { protected function supportsColors(): bool { $outputStream = $this->outputStream; $this->outputStream = fopen('php://stdout', 'w'); try { return parent::supportsColors(); } finally { $this->outputStream = $outputStream; } } }; return FlattenException::createFromThrowable($exception) ->setAsString($dumper->dump($cloner->cloneVar($exception), true)); } } error-handler/ErrorRenderer/SerializerErrorRenderer.php000064400000007044150432043200017411 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorRenderer; use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Serializer\Exception\NotEncodableValueException; use Symfony\Component\Serializer\SerializerInterface; /** * Formats an exception using Serializer for rendering. * * @author Nicolas Grekas */ class SerializerErrorRenderer implements ErrorRendererInterface { private $serializer; private $format; private $fallbackErrorRenderer; private $debug; /** * @param string|callable(FlattenException) $format The format as a string or a callable that should return it * formats not supported by Request::getMimeTypes() should be given as mime types * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it */ public function __construct(SerializerInterface $serializer, $format, ErrorRendererInterface $fallbackErrorRenderer = null, $debug = false) { if (!\is_string($format) && !\is_callable($format)) { throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($format))); } if (!\is_bool($debug) && !\is_callable($debug)) { throw new \TypeError(sprintf('Argument 4 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug))); } $this->serializer = $serializer; $this->format = $format; $this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer(); $this->debug = $debug; } /** * {@inheritdoc} */ public function render(\Throwable $exception): FlattenException { $headers = []; $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); if ($debug) { $headers['X-Debug-Exception'] = rawurlencode($exception->getMessage()); $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); } $flattenException = FlattenException::createFromThrowable($exception, null, $headers); try { $format = \is_string($this->format) ? $this->format : ($this->format)($flattenException); $headers = [ 'Content-Type' => Request::getMimeTypes($format)[0] ?? $format, 'Vary' => 'Accept', ]; return $flattenException->setAsString($this->serializer->serialize($flattenException, $format, [ 'exception' => $exception, 'debug' => $debug, ])) ->setHeaders($flattenException->getHeaders() + $headers); } catch (NotEncodableValueException $e) { return $this->fallbackErrorRenderer->render($exception); } } public static function getPreferredFormat(RequestStack $requestStack): \Closure { return static function () use ($requestStack) { if (!$request = $requestStack->getCurrentRequest()) { throw new NotEncodableValueException(); } return $request->getPreferredFormat(); }; } } error-handler/ErrorRenderer/HtmlErrorRenderer.php000064400000056347150432043200016216 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorRenderer; use Psr\Log\LoggerInterface; use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; /** * @author Yonel Ceruto */ class HtmlErrorRenderer implements ErrorRendererInterface { private const GHOST_ADDONS = [ '02-14' => self::GHOST_HEART, '02-29' => self::GHOST_PLUS, '10-18' => self::GHOST_GIFT, ]; private const GHOST_GIFT = 'M124.00534057617188,5.3606138080358505 C124.40059661865234,4.644828304648399 125.1237564086914,3.712414965033531 123.88127899169922,3.487462028861046 C123.53517150878906,3.3097832053899765 123.18894958496094,2.9953975528478622 122.8432846069336,3.345616325736046 C122.07421112060547,3.649444565176964 121.40750122070312,4.074306473135948 122.2164306640625,4.869479164481163 C122.57514953613281,5.3830065578222275 122.90142822265625,6.503447040915489 123.3077621459961,6.626829609274864 C123.55027770996094,6.210384353995323 123.7774658203125,5.785196766257286 124.00534057617188,5.3606138080358505 zM122.30630493164062,7.336987480521202 C121.60028076171875,6.076864704489708 121.03211975097656,4.72498320043087 120.16796875,3.562500938773155 C119.11695098876953,2.44033907353878 117.04605865478516,2.940566048026085 116.57544708251953,4.387995228171349 C115.95028686523438,5.819030746817589 117.2991714477539,7.527640804648399 118.826171875,7.348545059561729 C119.98493194580078,7.367936596274376 121.15027618408203,7.420116886496544 122.30630493164062,7.336987480521202 zM128.1732177734375,7.379541382193565 C129.67486572265625,7.17823551595211 130.53842163085938,5.287807449698448 129.68344116210938,4.032590612769127 C128.92578125,2.693056806921959 126.74605560302734,2.6463639587163925 125.98509216308594,4.007616028189659 C125.32617950439453,5.108129009604454 124.75428009033203,6.258124336600304 124.14962768554688,7.388818249106407 C125.48638916015625,7.465229496359825 126.8357162475586,7.447416767477989 128.1732177734375,7.379541382193565 zM130.6601104736328,8.991325363516808 C131.17202758789062,8.540884003043175 133.1543731689453,8.009847149252892 131.65304565429688,7.582054600119591 C131.2811279296875,7.476506695151329 130.84751892089844,6.99234913289547 130.5132598876953,7.124847874045372 C129.78744506835938,8.02728746831417 128.67140197753906,8.55669592320919 127.50616455078125,8.501235947012901 C127.27806091308594,8.576229080557823 126.11459350585938,8.38720129430294 126.428955078125,8.601900085806847 C127.25099182128906,9.070617660880089 128.0523223876953,9.579657539725304 128.902587890625,9.995706543326378 C129.49813842773438,9.678531631827354 130.0761260986328,9.329126343131065 130.6601104736328,8.991325363516808 zM118.96446990966797,9.246344551444054 C119.4022445678711,8.991325363516808 119.84001922607422,8.736305221915245 120.27779388427734,8.481284126639366 C118.93965911865234,8.414779648184776 117.40827941894531,8.607666000723839 116.39698791503906,7.531384453177452 C116.11186981201172,7.212117180228233 115.83845520019531,6.846597656607628 115.44329071044922,7.248530372977257 C114.96995544433594,7.574637398123741 113.5140609741211,7.908811077475548 114.63501739501953,8.306883797049522 C115.61112976074219,8.883499130606651 116.58037567138672,9.474181160330772 117.58061218261719,10.008124336600304 C118.05723571777344,9.784612640738487 118.50651550292969,9.5052699893713 118.96446990966797,9.246344551444054 zM125.38018035888672,12.091858848929405 C125.9474868774414,11.636047348380089 127.32159423828125,11.201767906546593 127.36749267578125,10.712632164359093 C126.08487701416016,9.974547371268272 124.83960723876953,9.152772888541222 123.49772644042969,8.528907760977745 C123.03594207763672,8.353693947196007 122.66152954101562,8.623294815421104 122.28982543945312,8.857431396842003 C121.19065856933594,9.51122473180294 120.06505584716797,10.12446115911007 119.00167083740234,10.835315689444542 C120.39238739013672,11.69529627263546 121.79983520507812,12.529837593436241 123.22095489501953,13.338589653372765 C123.94580841064453,12.932025894522667 124.66128540039062,12.508862480521202 125.38018035888672,12.091858848929405 zM131.07164001464844,13.514615997672081 C131.66018676757812,13.143282875418663 132.2487335205078,12.771927818655968 132.8372802734375,12.400571808218956 C132.8324737548828,11.156818374991417 132.8523406982422,9.912529930472374 132.81829833984375,8.669195160269737 C131.63046264648438,9.332009300589561 130.45948791503906,10.027913078665733 129.30828857421875,10.752535805106163 C129.182373046875,12.035354599356651 129.24623107910156,13.33940313756466 129.27359008789062,14.628684982657433 C129.88104248046875,14.27079389989376 130.4737548828125,13.888019546866417 131.07164001464844,13.514640793204308 zM117.26847839355469,12.731024727225304 C117.32825469970703,11.67083452641964 117.45709991455078,10.46224020421505 116.17853546142578,10.148179039359093 C115.37110900878906,9.77159021794796 114.25194549560547,8.806716904044151 113.62991333007812,8.81639002263546 C113.61052703857422,10.0110072940588 113.62078857421875,11.20585821568966 113.61869049072266,12.400571808218956 C114.81139373779297,13.144886955618858 115.98292541503906,13.925040230154991 117.20137023925781,14.626662239432335 C117.31951141357422,14.010867103934288 117.24227905273438,13.35805033147335 117.26847839355469,12.731024727225304 zM125.80937957763672,16.836034759879112 C126.51483917236328,16.390663132071495 127.22030639648438,15.945291504263878 127.92576599121094,15.49991987645626 C127.92250061035156,14.215868934988976 127.97560119628906,12.929980263113976 127.91757202148438,11.647302612662315 C127.14225769042969,11.869626984000206 126.25550079345703,12.556857094168663 125.43866729736328,12.983742699027061 C124.82704162597656,13.342005714774132 124.21542358398438,13.700271591544151 123.60379028320312,14.05853746831417 C123.61585235595703,15.429577812552452 123.57081604003906,16.803131088614464 123.64839172363281,18.172149643301964 C124.37957000732422,17.744937881827354 125.09130859375,17.284801468253136 125.80937957763672,16.836034759879112 zM122.8521499633789,16.115344032645226 C122.8521499633789,15.429741844534874 122.8521499633789,14.744139656424522 122.8521499633789,14.05853746831417 C121.43595123291016,13.230924591422081 120.02428436279297,12.395455345511436 118.60256958007812,11.577354416251183 C118.52394104003906,12.888403877615929 118.56887817382812,14.204405769705772 118.55702209472656,15.517732605338097 C119.97289276123047,16.4041957706213 121.37410736083984,17.314891800284386 122.80789947509766,18.172149643301964 C122.86368560791016,17.488990768790245 122.84332275390625,16.800363525748253 122.8521499633789,16.115344032645226 zM131.10684204101562,18.871450409293175 C131.68399047851562,18.48711584508419 132.2611541748047,18.10278509557247 132.8383026123047,17.718475326895714 C132.81423950195312,16.499977096915245 132.89776611328125,15.264989838004112 132.77627563476562,14.05993078649044 C131.5760040283203,14.744719490408897 130.41763305664062,15.524359688162804 129.23875427246094,16.255397781729698 C129.26707458496094,17.516149505972862 129.18060302734375,18.791316971182823 129.3108367919922,20.041303619742393 C129.91973876953125,19.667551025748253 130.51010131835938,19.264152511954308 131.10684204101562,18.871450409293175 zM117.2557373046875,18.188333496451378 C117.25104522705078,17.549470886588097 117.24633026123047,16.91058538854122 117.24163055419922,16.271720871329308 C116.04924774169922,15.525708183646202 114.87187957763672,14.75476549565792 113.66158294677734,14.038097366690636 C113.5858383178711,15.262084946036339 113.62901306152344,16.49083898961544 113.61761474609375,17.717010483145714 C114.82051086425781,18.513254150748253 116.00987243652344,19.330610260367393 117.22888946533203,20.101993545889854 C117.27559661865234,19.466014847159386 117.25241088867188,18.825733169913292 117.2557373046875,18.188333496451378 zM125.8398666381836,22.38675306737423 C126.54049682617188,21.921453461050987 127.24110412597656,21.456151947379112 127.94172668457031,20.99083136022091 C127.94009399414062,19.693386062979698 127.96646118164062,18.395381912589073 127.93160247802734,17.098379120230675 C126.50540924072266,17.97775076329708 125.08877563476562,18.873308166861534 123.68258666992188,19.78428266942501 C123.52366638183594,21.03710363805294 123.626708984375,22.32878302037716 123.62647247314453,23.595300659537315 C124.06291198730469,23.86113165318966 125.1788101196289,22.68297766149044 125.8398666381836,22.38675306737423 zM122.8521499633789,21.83134649693966 C122.76741790771484,20.936696991324425 123.21651458740234,19.67745779454708 122.0794677734375,19.330633148550987 C120.93280029296875,18.604360565543175 119.7907485961914,17.870157226920128 118.62899780273438,17.16818617284298 C118.45966339111328,18.396427139639854 118.63676452636719,19.675991043448448 118.50668334960938,20.919256195425987 C119.89984130859375,21.92635916173458 121.32942199707031,22.88914106786251 122.78502655029297,23.803510650992393 C122.90177917480469,23.1627406924963 122.82917022705078,22.48402212560177 122.8521499633789,21.83134649693966 zM117.9798355102539,21.59483526647091 C116.28416442871094,20.46288488805294 114.58848571777344,19.330957397818565 112.892822265625,18.199007019400597 C112.89473724365234,14.705654129385948 112.84647369384766,11.211485847830772 112.90847778320312,7.718807205557823 C113.7575912475586,7.194885239005089 114.66117858886719,6.765397056937218 115.5350341796875,6.284702762961388 C114.97061157226562,4.668964847922325 115.78496551513672,2.7054970115423203 117.42159271240234,2.1007001250982285 C118.79354095458984,1.537783369421959 120.44731903076172,2.0457767099142075 121.32200622558594,3.23083733022213 C121.95732116699219,2.9050118774175644 122.59264373779297,2.5791852325201035 123.22796630859375,2.253336176276207 C123.86669921875,2.5821153968572617 124.50543975830078,2.9108948558568954 125.1441650390625,3.23967407643795 C126.05941009521484,2.154020771384239 127.62747192382812,1.5344576686620712 128.986328125,2.1429056972265244 C130.61741638183594,2.716217741370201 131.50650024414062,4.675290569663048 130.9215545654297,6.2884936183691025 C131.8018341064453,6.78548763692379 132.7589111328125,7.1738648265600204 133.5660400390625,7.780336365103722 C133.60182189941406,11.252970680594444 133.56637573242188,14.726140961050987 133.5631103515625,18.199007019400597 C130.18914794921875,20.431867584586143 126.86984252929688,22.74994657933712 123.44108581542969,24.897907242178917 C122.44406127929688,24.897628769278526 121.5834732055664,23.815067276358604 120.65831756591797,23.37616156041622 C119.76387023925781,22.784828171133995 118.87168884277344,22.19007681310177 117.9798355102539,21.59483526647091 z'; private const GHOST_HEART = 'M125.91386369681868,8.305165958366445 C128.95033202169043,-0.40540639102854037 140.8469835342744,8.305165958366445 125.91386369681868,19.504526138305664 C110.98208663272044,8.305165958366445 122.87795231771452,-0.40540639102854037 125.91386369681868,8.305165958366445 z'; private const GHOST_PLUS = 'M111.36824226379395,8.969108581542969 L118.69175148010254,8.969108581542969 L118.69175148010254,1.6455793380737305 L126.20429420471191,1.6455793380737305 L126.20429420471191,8.969108581542969 L133.52781105041504,8.969108581542969 L133.52781105041504,16.481630325317383 L126.20429420471191,16.481630325317383 L126.20429420471191,23.805158615112305 L118.69175148010254,23.805158615112305 L118.69175148010254,16.481630325317383 L111.36824226379395,16.481630325317383 z'; private $debug; private $charset; private $fileLinkFormat; private $projectDir; private $outputBuffer; private $logger; private static $template = 'views/error.html.php'; /** * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it * @param string|FileLinkFormatter|null $fileLinkFormat * @param bool|callable $outputBuffer The output buffer as a string or a callable that should return it */ public function __construct($debug = false, string $charset = null, $fileLinkFormat = null, string $projectDir = null, $outputBuffer = '', LoggerInterface $logger = null) { if (!\is_bool($debug) && !\is_callable($debug)) { throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, \gettype($debug))); } if (!\is_string($outputBuffer) && !\is_callable($outputBuffer)) { throw new \TypeError(sprintf('Argument 5 passed to "%s()" must be a string or a callable, "%s" given.', __METHOD__, \gettype($outputBuffer))); } $this->debug = $debug; $this->charset = $charset ?: (ini_get('default_charset') ?: 'UTF-8'); $this->fileLinkFormat = $fileLinkFormat ?: (ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format')); $this->projectDir = $projectDir; $this->outputBuffer = $outputBuffer; $this->logger = $logger; } /** * {@inheritdoc} */ public function render(\Throwable $exception): FlattenException { $headers = ['Content-Type' => 'text/html; charset='.$this->charset]; if (\is_bool($this->debug) ? $this->debug : ($this->debug)($exception)) { $headers['X-Debug-Exception'] = rawurlencode($exception->getMessage()); $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); } $exception = FlattenException::createFromThrowable($exception, null, $headers); return $exception->setAsString($this->renderException($exception)); } /** * Gets the HTML content associated with the given exception. */ public function getBody(FlattenException $exception): string { return $this->renderException($exception, 'views/exception.html.php'); } /** * Gets the stylesheet associated with the given exception. */ public function getStylesheet(): string { if (!$this->debug) { return $this->include('assets/css/error.css'); } return $this->include('assets/css/exception.css'); } public static function isDebug(RequestStack $requestStack, bool $debug): \Closure { return static function () use ($requestStack, $debug): bool { if (!$request = $requestStack->getCurrentRequest()) { return $debug; } return $debug && $request->attributes->getBoolean('showException', true); }; } public static function getAndCleanOutputBuffer(RequestStack $requestStack): \Closure { return static function () use ($requestStack): string { if (!$request = $requestStack->getCurrentRequest()) { return ''; } $startObLevel = $request->headers->get('X-Php-Ob-Level', -1); if (ob_get_level() <= $startObLevel) { return ''; } Response::closeOutputBuffers($startObLevel + 1, true); return ob_get_clean(); }; } private function renderException(FlattenException $exception, string $debugTemplate = 'views/exception_full.html.php'): string { $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); $statusText = $this->escape($exception->getStatusText()); $statusCode = $this->escape($exception->getStatusCode()); if (!$debug) { return $this->include(self::$template, [ 'statusText' => $statusText, 'statusCode' => $statusCode, ]); } $exceptionMessage = $this->escape($exception->getMessage()); return $this->include($debugTemplate, [ 'exception' => $exception, 'exceptionMessage' => $exceptionMessage, 'statusText' => $statusText, 'statusCode' => $statusCode, 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, 'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(), ]); } /** * Formats an array as a string. */ private function formatArgs(array $args): string { $result = []; foreach ($args as $key => $item) { if ('object' === $item[0]) { $formattedValue = sprintf('object(%s)', $this->abbrClass($item[1])); } elseif ('array' === $item[0]) { $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); } elseif ('null' === $item[0]) { $formattedValue = 'null'; } elseif ('boolean' === $item[0]) { $formattedValue = ''.strtolower(var_export($item[1], true)).''; } elseif ('resource' === $item[0]) { $formattedValue = 'resource'; } else { $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true))); } $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escape($key), $formattedValue); } return implode(', ', $result); } private function formatArgsAsText(array $args) { return strip_tags($this->formatArgs($args)); } private function escape(string $string): string { return htmlspecialchars($string, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset); } private function abbrClass(string $class): string { $parts = explode('\\', $class); $short = array_pop($parts); return sprintf('%s', $class, $short); } private function getFileRelative(string $file): ?string { $file = str_replace('\\', '/', $file); if (null !== $this->projectDir && 0 === strpos($file, $this->projectDir)) { return ltrim(substr($file, \strlen($this->projectDir)), '/'); } return null; } /** * Returns the link for a given file/line pair. * * @return string|false */ private function getFileLink(string $file, int $line) { if ($fmt = $this->fileLinkFormat) { return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); } return false; } /** * Formats a file path. * * @param string $file An absolute file path * @param int $line The line number * @param string $text Use this text for the link rather than the file path */ private function formatFile(string $file, int $line, string $text = null): string { $file = trim($file); if (null === $text) { $text = $file; if (null !== $rel = $this->getFileRelative($text)) { $rel = explode('/', $rel, 2); $text = sprintf('%s%s', $this->projectDir, $rel[0], '/'.($rel[1] ?? '')); } } if (0 < $line) { $text .= ' at line '.$line; } if (false !== $link = $this->getFileLink($file, $line)) { return sprintf('%s', $this->escape($link), $text); } return $text; } /** * Returns an excerpt of a code file around the given line number. * * @param string $file A file path * @param int $line The selected line number * @param int $srcContext The number of displayed lines around or -1 for the whole file * * @return string */ private function fileExcerpt(string $file, int $line, int $srcContext = 3): string { if (is_file($file) && is_readable($file)) { // highlight_file could throw warnings // see https://bugs.php.net/25725 $code = @highlight_file($file, true); // remove main code/span tags $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); // split multiline spans $code = preg_replace_callback('#]++)>((?:[^<]*+
    )++[^<]*+)
    #', function ($m) { return "".str_replace('
    ', "

    ", $m[2]).''; }, $code); $content = explode('
    ', $code); $lines = []; if (0 > $srcContext) { $srcContext = \count($content); } for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) { $lines[] = ''.$this->fixCodeMarkup($content[$i - 1]).'
  • '; } return '
      '.implode("\n", $lines).'
    '; } return ''; } private function fixCodeMarkup(string $line) { // ending tag from previous line $opening = strpos($line, ''); if (false !== $closing && (false === $opening || $closing < $opening)) { $line = substr_replace($line, '', $closing, 7); } // missing tag at the end of line $opening = strrpos($line, ''); if (false !== $opening && (false === $closing || $closing < $opening)) { $line .= ''; } return trim($line); } private function formatFileFromText(string $text) { return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) { return 'in '.$this->formatFile($match[2], $match[3]); }, $text); } private function formatLogMessage(string $message, array $context) { if ($context && false !== strpos($message, '{')) { $replacements = []; foreach ($context as $key => $val) { if (is_scalar($val)) { $replacements['{'.$key.'}'] = $val; } } if ($replacements) { $message = strtr($message, $replacements); } } return $this->escape($message); } private function addElementToGhost(): string { if (!isset(self::GHOST_ADDONS[date('m-d')])) { return ''; } return ''; } private function include(string $name, array $context = []): string { extract($context, \EXTR_SKIP); ob_start(); include is_file(\dirname(__DIR__).'/Resources/'.$name) ? \dirname(__DIR__).'/Resources/'.$name : $name; return trim(ob_get_clean()); } /** * Allows overriding the default non-debug template. * * @param string $template path to the custom template file to render */ public static function setTemplate(string $template): void { self::$template = $template; } } error-handler/Internal/TentativeTypes.php000064400000163205150432043200014565 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Internal; /** * This class has been generated by extract-tentative-return-types.php. * * @internal */ class TentativeTypes { public const RETURN_TYPES = [ 'CURLFile' => [ 'getFilename' => 'string', 'getMimeType' => 'string', 'getPostFilename' => 'string', 'setMimeType' => 'void', 'setPostFilename' => 'void', ], 'DateTimeInterface' => [ 'format' => 'string', 'getTimezone' => 'DateTimeZone|false', 'getOffset' => 'int', 'getTimestamp' => 'int|false', 'diff' => 'DateInterval', '__wakeup' => 'void', ], 'DateTime' => [ '__wakeup' => 'void', '__set_state' => 'DateTime', 'createFromImmutable' => 'DateTime', 'createFromFormat' => 'DateTime|false', 'getLastErrors' => 'array|false', 'format' => 'string', 'modify' => 'DateTime|false', 'add' => 'DateTime', 'sub' => 'DateTime', 'getTimezone' => 'DateTimeZone|false', 'setTimezone' => 'DateTime', 'getOffset' => 'int', 'setTime' => 'DateTime', 'setDate' => 'DateTime', 'setISODate' => 'DateTime', 'setTimestamp' => 'DateTime', 'getTimestamp' => 'int', 'diff' => 'DateInterval', ], 'DateTimeImmutable' => [ '__wakeup' => 'void', '__set_state' => 'DateTimeImmutable', 'createFromFormat' => 'DateTimeImmutable|false', 'getLastErrors' => 'array|false', 'format' => 'string', 'getTimezone' => 'DateTimeZone|false', 'getOffset' => 'int', 'getTimestamp' => 'int', 'diff' => 'DateInterval', 'modify' => 'DateTimeImmutable|false', 'add' => 'DateTimeImmutable', 'sub' => 'DateTimeImmutable', 'setTimezone' => 'DateTimeImmutable', 'setTime' => 'DateTimeImmutable', 'setDate' => 'DateTimeImmutable', 'setISODate' => 'DateTimeImmutable', 'setTimestamp' => 'DateTimeImmutable', 'createFromMutable' => 'DateTimeImmutable', ], 'DateTimeZone' => [ 'getName' => 'string', 'getOffset' => 'int', 'getTransitions' => 'array|false', 'getLocation' => 'array|false', 'listAbbreviations' => 'array', 'listIdentifiers' => 'array', '__wakeup' => 'void', '__set_state' => 'DateTimeZone', ], 'DateInterval' => [ 'createFromDateString' => 'DateInterval|false', 'format' => 'string', '__wakeup' => 'void', '__set_state' => 'DateInterval', ], 'DatePeriod' => [ 'getStartDate' => 'DateTimeInterface', 'getEndDate' => '?DateTimeInterface', 'getDateInterval' => 'DateInterval', 'getRecurrences' => '?int', '__wakeup' => 'void', '__set_state' => 'DatePeriod', ], 'DOMNode' => [ 'C14N' => 'string|false', 'C14NFile' => 'int|false', 'getLineNo' => 'int', 'getNodePath' => '?string', 'hasAttributes' => 'bool', 'hasChildNodes' => 'bool', 'isDefaultNamespace' => 'bool', 'isSameNode' => 'bool', 'isSupported' => 'bool', 'lookupNamespaceURI' => '?string', 'lookupPrefix' => '?string', 'normalize' => 'void', ], 'DOMImplementation' => [ 'getFeature' => 'never', 'hasFeature' => 'bool', ], 'DOMDocumentFragment' => [ 'appendXML' => 'bool', ], 'DOMNodeList' => [ 'count' => 'int', ], 'DOMCharacterData' => [ 'appendData' => 'bool', 'insertData' => 'bool', 'deleteData' => 'bool', 'replaceData' => 'bool', ], 'DOMAttr' => [ 'isId' => 'bool', ], 'DOMElement' => [ 'getAttribute' => 'string', 'getAttributeNS' => 'string', 'getElementsByTagName' => 'DOMNodeList', 'getElementsByTagNameNS' => 'DOMNodeList', 'hasAttribute' => 'bool', 'hasAttributeNS' => 'bool', 'removeAttribute' => 'bool', 'removeAttributeNS' => 'void', 'setAttributeNS' => 'void', 'setIdAttribute' => 'void', 'setIdAttributeNS' => 'void', 'setIdAttributeNode' => 'void', ], 'DOMDocument' => [ 'createComment' => 'DOMComment', 'createDocumentFragment' => 'DOMDocumentFragment', 'createTextNode' => 'DOMText', 'getElementById' => '?DOMElement', 'getElementsByTagName' => 'DOMNodeList', 'getElementsByTagNameNS' => 'DOMNodeList', 'normalizeDocument' => 'void', 'registerNodeClass' => 'bool', 'save' => 'int|false', 'saveHTML' => 'string|false', 'saveHTMLFile' => 'int|false', 'saveXML' => 'string|false', 'schemaValidate' => 'bool', 'schemaValidateSource' => 'bool', 'relaxNGValidate' => 'bool', 'relaxNGValidateSource' => 'bool', 'validate' => 'bool', 'xinclude' => 'int|false', ], 'DOMText' => [ 'isWhitespaceInElementContent' => 'bool', 'isElementContentWhitespace' => 'bool', ], 'DOMNamedNodeMap' => [ 'getNamedItem' => '?DOMNode', 'getNamedItemNS' => '?DOMNode', 'item' => '?DOMNode', 'count' => 'int', ], 'DOMXPath' => [ 'evaluate' => 'mixed', 'query' => 'mixed', 'registerNamespace' => 'bool', 'registerPhpFunctions' => 'void', ], 'finfo' => [ 'file' => 'string|false', 'buffer' => 'string|false', ], 'IntlPartsIterator' => [ 'getBreakIterator' => 'IntlBreakIterator', 'getRuleStatus' => 'int', ], 'IntlBreakIterator' => [ 'createCharacterInstance' => '?IntlBreakIterator', 'createCodePointInstance' => 'IntlCodePointBreakIterator', 'createLineInstance' => '?IntlBreakIterator', 'createSentenceInstance' => '?IntlBreakIterator', 'createTitleInstance' => '?IntlBreakIterator', 'createWordInstance' => '?IntlBreakIterator', 'current' => 'int', 'first' => 'int', 'following' => 'int', 'getErrorCode' => 'int', 'getErrorMessage' => 'string', 'getLocale' => 'string|false', 'getPartsIterator' => 'IntlPartsIterator', 'getText' => '?string', 'isBoundary' => 'bool', 'last' => 'int', 'next' => 'int', 'preceding' => 'int', 'previous' => 'int', 'setText' => '?bool', ], 'IntlRuleBasedBreakIterator' => [ 'getBinaryRules' => 'string|false', 'getRules' => 'string|false', 'getRuleStatus' => 'int', 'getRuleStatusVec' => 'array|false', ], 'IntlCodePointBreakIterator' => [ 'getLastCodePoint' => 'int', ], 'IntlCalendar' => [ 'createInstance' => '?IntlCalendar', 'equals' => 'bool', 'fieldDifference' => 'int|false', 'add' => 'bool', 'after' => 'bool', 'before' => 'bool', 'fromDateTime' => '?IntlCalendar', 'get' => 'int|false', 'getActualMaximum' => 'int|false', 'getActualMinimum' => 'int|false', 'getAvailableLocales' => 'array', 'getDayOfWeekType' => 'int|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false', 'getFirstDayOfWeek' => 'int|false', 'getGreatestMinimum' => 'int|false', 'getKeywordValuesForLocale' => 'IntlIterator|false', 'getLeastMaximum' => 'int|false', 'getLocale' => 'string|false', 'getMaximum' => 'int|false', 'getMinimalDaysInFirstWeek' => 'int|false', 'getMinimum' => 'int|false', 'getNow' => 'float', 'getRepeatedWallTimeOption' => 'int', 'getSkippedWallTimeOption' => 'int', 'getTime' => 'float|false', 'getTimeZone' => 'IntlTimeZone|false', 'getType' => 'string', 'getWeekendTransition' => 'int|false', 'inDaylightTime' => 'bool', 'isEquivalentTo' => 'bool', 'isLenient' => 'bool', 'isWeekend' => 'bool', 'isSet' => 'bool', 'setTime' => 'bool', 'setTimeZone' => 'bool', 'toDateTime' => 'DateTime|false', ], 'IntlGregorianCalendar' => [ 'setGregorianChange' => 'bool', 'getGregorianChange' => 'float', 'isLeapYear' => 'bool', ], 'Collator' => [ 'create' => '?Collator', 'compare' => 'int|false', 'sort' => 'bool', 'sortWithSortKeys' => 'bool', 'asort' => 'bool', 'getAttribute' => 'int|false', 'setAttribute' => 'bool', 'getStrength' => 'int', 'getLocale' => 'string|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false', 'getSortKey' => 'string|false', ], 'IntlIterator' => [ 'current' => 'mixed', 'key' => 'mixed', 'next' => 'void', 'rewind' => 'void', 'valid' => 'bool', ], 'UConverter' => [ 'convert' => 'string|false', 'fromUCallback' => 'string|int|array|null', 'getAliases' => 'array|false|null', 'getAvailable' => 'array', 'getDestinationEncoding' => 'string|false|null', 'getDestinationType' => 'int|false|null', 'getErrorCode' => 'int', 'getErrorMessage' => '?string', 'getSourceEncoding' => 'string|false|null', 'getSourceType' => 'int|false|null', 'getStandards' => '?array', 'getSubstChars' => 'string|false|null', 'reasonText' => 'string', 'setDestinationEncoding' => 'bool', 'setSourceEncoding' => 'bool', 'setSubstChars' => 'bool', 'toUCallback' => 'string|int|array|null', 'transcode' => 'string|false', ], 'IntlDateFormatter' => [ 'create' => '?IntlDateFormatter', 'getDateType' => 'int|false', 'getTimeType' => 'int|false', 'getCalendar' => 'int|false', 'setCalendar' => 'bool', 'getTimeZoneId' => 'string|false', 'getCalendarObject' => 'IntlCalendar|false|null', 'getTimeZone' => 'IntlTimeZone|false', 'setTimeZone' => '?bool', 'setPattern' => 'bool', 'getPattern' => 'string|false', 'getLocale' => 'string|false', 'setLenient' => 'void', 'isLenient' => 'bool', 'format' => 'string|false', 'formatObject' => 'string|false', 'parse' => 'int|float|false', 'localtime' => 'array|false', 'getErrorCode' => 'int', 'getErrorMessage' => 'string', ], 'NumberFormatter' => [ 'create' => '?NumberFormatter', 'format' => 'string|false', 'parse' => 'int|float|false', 'formatCurrency' => 'string|false', 'parseCurrency' => 'float|false', 'setAttribute' => 'bool', 'getAttribute' => 'int|float|false', 'setTextAttribute' => 'bool', 'getTextAttribute' => 'string|false', 'setSymbol' => 'bool', 'getSymbol' => 'string|false', 'setPattern' => 'bool', 'getPattern' => 'string|false', 'getLocale' => 'string|false', 'getErrorCode' => 'int', 'getErrorMessage' => 'string', ], 'Locale' => [ 'getDefault' => 'string', 'getPrimaryLanguage' => '?string', 'getScript' => '?string', 'getRegion' => '?string', 'getKeywords' => 'array|false|null', 'getDisplayScript' => 'string|false', 'getDisplayRegion' => 'string|false', 'getDisplayName' => 'string|false', 'getDisplayLanguage' => 'string|false', 'getDisplayVariant' => 'string|false', 'composeLocale' => 'string|false', 'parseLocale' => '?array', 'getAllVariants' => '?array', 'filterMatches' => '?bool', 'lookup' => '?string', 'canonicalize' => '?string', 'acceptFromHttp' => 'string|false', ], 'MessageFormatter' => [ 'create' => '?MessageFormatter', 'format' => 'string|false', 'formatMessage' => 'string|false', 'parse' => 'array|false', 'parseMessage' => 'array|false', 'setPattern' => 'bool', 'getPattern' => 'string|false', 'getLocale' => 'string', 'getErrorCode' => 'int', 'getErrorMessage' => 'string', ], 'Normalizer' => [ 'normalize' => 'string|false', 'isNormalized' => 'bool', 'getRawDecomposition' => '?string', ], 'ResourceBundle' => [ 'create' => '?ResourceBundle', 'get' => 'mixed', 'count' => 'int', 'getLocales' => 'array|false', 'getErrorCode' => 'int', 'getErrorMessage' => 'string', ], 'Spoofchecker' => [ 'isSuspicious' => 'bool', 'areConfusable' => 'bool', 'setAllowedLocales' => 'void', 'setChecks' => 'void', 'setRestrictionLevel' => 'void', ], 'IntlTimeZone' => [ 'countEquivalentIDs' => 'int|false', 'createDefault' => 'IntlTimeZone', 'createEnumeration' => 'IntlIterator|false', 'createTimeZone' => '?IntlTimeZone', 'createTimeZoneIDEnumeration' => 'IntlIterator|false', 'fromDateTimeZone' => '?IntlTimeZone', 'getCanonicalID' => 'string|false', 'getDisplayName' => 'string|false', 'getDSTSavings' => 'int', 'getEquivalentID' => 'string|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false', 'getGMT' => 'IntlTimeZone', 'getID' => 'string|false', 'getOffset' => 'bool', 'getRawOffset' => 'int', 'getRegion' => 'string|false', 'getTZDataVersion' => 'string|false', 'getUnknown' => 'IntlTimeZone', 'getWindowsID' => 'string|false', 'getIDForWindowsID' => 'string|false', 'hasSameRules' => 'bool', 'toDateTimeZone' => 'DateTimeZone|false', 'useDaylightTime' => 'bool', ], 'Transliterator' => [ 'create' => '?Transliterator', 'createFromRules' => '?Transliterator', 'createInverse' => '?Transliterator', 'listIDs' => 'array|false', 'transliterate' => 'string|false', 'getErrorCode' => 'int|false', 'getErrorMessage' => 'string|false', ], 'IntlChar' => [ 'hasBinaryProperty' => '?bool', 'charAge' => '?array', 'charDigitValue' => '?int', 'charDirection' => '?int', 'charFromName' => '?int', 'charMirror' => 'int|string|null', 'charName' => '?string', 'charType' => '?int', 'chr' => '?string', 'digit' => 'int|false|null', 'enumCharNames' => '?bool', 'enumCharTypes' => 'void', 'foldCase' => 'int|string|null', 'forDigit' => 'int', 'getBidiPairedBracket' => 'int|string|null', 'getBlockCode' => '?int', 'getCombiningClass' => '?int', 'getFC_NFKC_Closure' => 'string|false|null', 'getIntPropertyMaxValue' => 'int', 'getIntPropertyMinValue' => 'int', 'getIntPropertyValue' => '?int', 'getNumericValue' => '?float', 'getPropertyEnum' => 'int', 'getPropertyName' => 'string|false', 'getPropertyValueEnum' => 'int', 'getPropertyValueName' => 'string|false', 'getUnicodeVersion' => 'array', 'isalnum' => '?bool', 'isalpha' => '?bool', 'isbase' => '?bool', 'isblank' => '?bool', 'iscntrl' => '?bool', 'isdefined' => '?bool', 'isdigit' => '?bool', 'isgraph' => '?bool', 'isIDIgnorable' => '?bool', 'isIDPart' => '?bool', 'isIDStart' => '?bool', 'isISOControl' => '?bool', 'isJavaIDPart' => '?bool', 'isJavaIDStart' => '?bool', 'isJavaSpaceChar' => '?bool', 'islower' => '?bool', 'isMirrored' => '?bool', 'isprint' => '?bool', 'ispunct' => '?bool', 'isspace' => '?bool', 'istitle' => '?bool', 'isUAlphabetic' => '?bool', 'isULowercase' => '?bool', 'isupper' => '?bool', 'isUUppercase' => '?bool', 'isUWhiteSpace' => '?bool', 'isWhitespace' => '?bool', 'isxdigit' => '?bool', 'ord' => '?int', 'tolower' => 'int|string|null', 'totitle' => 'int|string|null', 'toupper' => 'int|string|null', ], 'JsonSerializable' => [ 'jsonSerialize' => 'mixed', ], 'mysqli' => [ 'autocommit' => 'bool', 'begin_transaction' => 'bool', 'change_user' => 'bool', 'character_set_name' => 'string', 'commit' => 'bool', 'connect' => 'bool', 'dump_debug_info' => 'bool', 'get_charset' => '?object', 'get_client_info' => 'string', 'get_connection_stats' => 'array', 'get_server_info' => 'string', 'get_warnings' => 'mysqli_warning|false', 'kill' => 'bool', 'multi_query' => 'bool', 'more_results' => 'bool', 'next_result' => 'bool', 'ping' => 'bool', 'poll' => 'int|false', 'prepare' => 'mysqli_stmt|false', 'query' => 'mysqli_result|bool', 'real_connect' => 'bool', 'real_escape_string' => 'string', 'reap_async_query' => 'mysqli_result|bool', 'escape_string' => 'string', 'real_query' => 'bool', 'release_savepoint' => 'bool', 'rollback' => 'bool', 'savepoint' => 'bool', 'select_db' => 'bool', 'set_charset' => 'bool', 'options' => 'bool', 'set_opt' => 'bool', 'stat' => 'string|false', 'stmt_init' => 'mysqli_stmt|false', 'store_result' => 'mysqli_result|false', 'thread_safe' => 'bool', 'use_result' => 'mysqli_result|false', 'refresh' => 'bool', ], 'mysqli_result' => [ 'close' => 'void', 'free' => 'void', 'data_seek' => 'bool', 'fetch_field' => 'object|false', 'fetch_fields' => 'array', 'fetch_field_direct' => 'object|false', 'fetch_all' => 'array', 'fetch_array' => 'array|null|false', 'fetch_assoc' => 'array|null|false', 'fetch_object' => 'object|null|false', 'fetch_row' => 'array|null|false', 'field_seek' => 'bool', 'free_result' => 'void', ], 'mysqli_stmt' => [ 'attr_get' => 'int', 'attr_set' => 'bool', 'bind_param' => 'bool', 'bind_result' => 'bool', 'data_seek' => 'void', 'execute' => 'bool', 'fetch' => '?bool', 'get_warnings' => 'mysqli_warning|false', 'result_metadata' => 'mysqli_result|false', 'more_results' => 'bool', 'next_result' => 'bool', 'num_rows' => 'int|string', 'send_long_data' => 'bool', 'free_result' => 'void', 'reset' => 'bool', 'prepare' => 'bool', 'store_result' => 'bool', 'get_result' => 'mysqli_result|false', ], 'OCILob' => [ 'save' => 'bool', 'import' => 'bool', 'saveFile' => 'bool', 'load' => 'string|false', 'read' => 'string|false', 'eof' => 'bool', 'tell' => 'int|false', 'rewind' => 'bool', 'seek' => 'bool', 'size' => 'int|false', 'write' => 'int|false', 'append' => 'bool', 'truncate' => 'bool', 'erase' => 'int|false', 'flush' => 'bool', 'setBuffering' => 'bool', 'getBuffering' => 'bool', 'writeToFile' => 'bool', 'export' => 'bool', 'writeTemporary' => 'bool', 'close' => 'bool', 'free' => 'bool', ], 'OCICollection' => [ 'free' => 'bool', 'append' => 'bool', 'getElem' => 'string|float|null|false', 'assign' => 'bool', 'assignElem' => 'bool', 'size' => 'int|false', 'max' => 'int|false', 'trim' => 'bool', ], 'PDO' => [ 'beginTransaction' => 'bool', 'commit' => 'bool', 'errorCode' => '?string', 'errorInfo' => 'array', 'exec' => 'int|false', 'getAttribute' => 'mixed', 'getAvailableDrivers' => 'array', 'inTransaction' => 'bool', 'lastInsertId' => 'string|false', 'prepare' => 'PDOStatement|false', 'query' => 'PDOStatement|false', 'quote' => 'string|false', 'rollBack' => 'bool', 'setAttribute' => 'bool', ], 'PDOStatement' => [ 'bindColumn' => 'bool', 'bindParam' => 'bool', 'bindValue' => 'bool', 'closeCursor' => 'bool', 'columnCount' => 'int', 'debugDumpParams' => '?bool', 'errorCode' => '?string', 'errorInfo' => 'array', 'execute' => 'bool', 'fetch' => 'mixed', 'fetchAll' => 'array', 'fetchColumn' => 'mixed', 'fetchObject' => 'object|false', 'getAttribute' => 'mixed', 'getColumnMeta' => 'array|false', 'nextRowset' => 'bool', 'rowCount' => 'int', 'setAttribute' => 'bool', ], 'PDO_PGSql_Ext' => [ 'pgsqlCopyFromArray' => 'bool', 'pgsqlCopyFromFile' => 'bool', 'pgsqlCopyToArray' => 'array|false', 'pgsqlCopyToFile' => 'bool', 'pgsqlLOBCreate' => 'string|false', 'pgsqlLOBUnlink' => 'bool', 'pgsqlGetNotify' => 'array|false', 'pgsqlGetPid' => 'int', ], 'PDO_SQLite_Ext' => [ 'sqliteCreateFunction' => 'bool', 'sqliteCreateAggregate' => 'bool', 'sqliteCreateCollation' => 'bool', ], 'Phar' => [ 'addEmptyDir' => 'void', 'addFile' => 'void', 'addFromString' => 'void', 'buildFromDirectory' => 'array', 'buildFromIterator' => 'array', 'compressFiles' => 'void', 'compress' => '?Phar', 'decompress' => '?Phar', 'convertToExecutable' => '?Phar', 'convertToData' => '?PharData', 'count' => 'int', 'extractTo' => 'bool', 'getAlias' => '?string', 'getPath' => 'string', 'getMetadata' => 'mixed', 'getModified' => 'bool', 'getSignature' => 'array|false', 'getStub' => 'string', 'getVersion' => 'string', 'hasMetadata' => 'bool', 'isBuffering' => 'bool', 'isCompressed' => 'int|false', 'isFileFormat' => 'bool', 'isWritable' => 'bool', 'offsetExists' => 'bool', 'offsetGet' => 'SplFileInfo', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'setAlias' => 'bool', 'setDefaultStub' => 'bool', 'setMetadata' => 'void', 'setSignatureAlgorithm' => 'void', 'startBuffering' => 'void', 'stopBuffering' => 'void', ], 'PharData' => [ 'addEmptyDir' => 'void', 'addFile' => 'void', 'addFromString' => 'void', 'buildFromDirectory' => 'array', 'buildFromIterator' => 'array', 'compressFiles' => 'void', 'compress' => '?PharData', 'decompress' => '?PharData', 'convertToExecutable' => '?Phar', 'convertToData' => '?PharData', 'count' => 'int', 'extractTo' => 'bool', 'getAlias' => '?string', 'getPath' => 'string', 'getMetadata' => 'mixed', 'getModified' => 'bool', 'getSignature' => 'array|false', 'getStub' => 'string', 'getVersion' => 'string', 'hasMetadata' => 'bool', 'isBuffering' => 'bool', 'isCompressed' => 'int|false', 'isFileFormat' => 'bool', 'isWritable' => 'bool', 'offsetExists' => 'bool', 'offsetGet' => 'SplFileInfo', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'setAlias' => 'bool', 'setDefaultStub' => 'bool', 'setMetadata' => 'void', 'setSignatureAlgorithm' => 'void', 'startBuffering' => 'void', 'stopBuffering' => 'void', ], 'PharFileInfo' => [ 'chmod' => 'void', 'getCompressedSize' => 'int', 'getCRC32' => 'int', 'getContent' => 'string', 'getMetadata' => 'mixed', 'getPharFlags' => 'int', 'hasMetadata' => 'bool', 'isCompressed' => 'bool', 'isCRCChecked' => 'bool', 'setMetadata' => 'void', ], 'Reflection' => [ 'getModifierNames' => 'array', ], 'ReflectionFunctionAbstract' => [ 'inNamespace' => 'bool', 'isClosure' => 'bool', 'isDeprecated' => 'bool', 'isInternal' => 'bool', 'isUserDefined' => 'bool', 'isGenerator' => 'bool', 'isVariadic' => 'bool', 'isStatic' => 'bool', 'getClosureThis' => '?object', 'getClosureScopeClass' => '?ReflectionClass', 'getDocComment' => 'string|false', 'getEndLine' => 'int|false', 'getExtension' => '?ReflectionExtension', 'getExtensionName' => 'string|false', 'getFileName' => 'string|false', 'getName' => 'string', 'getNamespaceName' => 'string', 'getNumberOfParameters' => 'int', 'getNumberOfRequiredParameters' => 'int', 'getParameters' => 'array', 'getShortName' => 'string', 'getStartLine' => 'int|false', 'getStaticVariables' => 'array', 'returnsReference' => 'bool', 'hasReturnType' => 'bool', 'getReturnType' => '?ReflectionType', ], 'ReflectionFunction' => [ 'isDisabled' => 'bool', 'invoke' => 'mixed', 'invokeArgs' => 'mixed', 'getClosure' => 'Closure', 'getExecutingLine' => 'int', 'getExecutingFile' => 'string', 'getTrace' => 'array', 'getFunction' => 'ReflectionFunctionAbstract', 'getThis' => '?object', 'getExecutingGenerator' => 'Generator', ], 'ReflectionMethod' => [ 'isPublic' => 'bool', 'isPrivate' => 'bool', 'isProtected' => 'bool', 'isAbstract' => 'bool', 'isFinal' => 'bool', 'isConstructor' => 'bool', 'isDestructor' => 'bool', 'getClosure' => 'Closure', 'getModifiers' => 'int', 'invoke' => 'mixed', 'invokeArgs' => 'mixed', 'getDeclaringClass' => 'ReflectionClass', 'getPrototype' => 'ReflectionMethod', 'setAccessible' => 'void', ], 'ReflectionClass' => [ 'getName' => 'string', 'isInternal' => 'bool', 'isUserDefined' => 'bool', 'isAnonymous' => 'bool', 'isInstantiable' => 'bool', 'isCloneable' => 'bool', 'getFileName' => 'string|false', 'getStartLine' => 'int|false', 'getEndLine' => 'int|false', 'getDocComment' => 'string|false', 'getConstructor' => '?ReflectionMethod', 'hasMethod' => 'bool', 'getMethod' => 'ReflectionMethod', 'getMethods' => 'array', 'hasProperty' => 'bool', 'getProperty' => 'ReflectionProperty', 'getProperties' => 'array', 'hasConstant' => 'bool', 'getConstants' => 'array', 'getReflectionConstants' => 'array', 'getConstant' => 'mixed', 'getReflectionConstant' => 'ReflectionClassConstant|false', 'getInterfaces' => 'array', 'getInterfaceNames' => 'array', 'isInterface' => 'bool', 'getTraits' => 'array', 'getTraitNames' => 'array', 'getTraitAliases' => 'array', 'isTrait' => 'bool', 'isAbstract' => 'bool', 'isFinal' => 'bool', 'getModifiers' => 'int', 'isInstance' => 'bool', 'newInstance' => 'object', 'newInstanceWithoutConstructor' => 'object', 'newInstanceArgs' => '?object', 'getParentClass' => 'ReflectionClass|false', 'isSubclassOf' => 'bool', 'getStaticProperties' => '?array', 'getStaticPropertyValue' => 'mixed', 'setStaticPropertyValue' => 'void', 'getDefaultProperties' => 'array', 'isIterable' => 'bool', 'isIterateable' => 'bool', 'implementsInterface' => 'bool', 'getExtension' => '?ReflectionExtension', 'getExtensionName' => 'string|false', 'inNamespace' => 'bool', 'getNamespaceName' => 'string', 'getShortName' => 'string', ], 'ReflectionProperty' => [ 'getName' => 'string', 'getValue' => 'mixed', 'setValue' => 'void', 'isInitialized' => 'bool', 'isPublic' => 'bool', 'isPrivate' => 'bool', 'isProtected' => 'bool', 'isStatic' => 'bool', 'isDefault' => 'bool', 'getModifiers' => 'int', 'getDeclaringClass' => 'ReflectionClass', 'getDocComment' => 'string|false', 'setAccessible' => 'void', 'getType' => '?ReflectionType', 'hasType' => 'bool', 'getDefaultValue' => 'mixed', ], 'ReflectionClassConstant' => [ 'getName' => 'string', 'getValue' => 'mixed', 'isPublic' => 'bool', 'isPrivate' => 'bool', 'isProtected' => 'bool', 'getModifiers' => 'int', 'getDeclaringClass' => 'ReflectionClass', 'getDocComment' => 'string|false', ], 'ReflectionParameter' => [ 'getName' => 'string', 'isPassedByReference' => 'bool', 'canBePassedByValue' => 'bool', 'getDeclaringFunction' => 'ReflectionFunctionAbstract', 'getDeclaringClass' => '?ReflectionClass', 'getClass' => '?ReflectionClass', 'hasType' => 'bool', 'getType' => '?ReflectionType', 'isArray' => 'bool', 'isCallable' => 'bool', 'allowsNull' => 'bool', 'getPosition' => 'int', 'isOptional' => 'bool', 'isDefaultValueAvailable' => 'bool', 'getDefaultValue' => 'mixed', 'isDefaultValueConstant' => 'bool', 'getDefaultValueConstantName' => '?string', 'isVariadic' => 'bool', ], 'ReflectionType' => [ 'allowsNull' => 'bool', ], 'ReflectionNamedType' => [ 'getName' => 'string', 'isBuiltin' => 'bool', ], 'ReflectionExtension' => [ 'getName' => 'string', 'getVersion' => '?string', 'getFunctions' => 'array', 'getConstants' => 'array', 'getINIEntries' => 'array', 'getClasses' => 'array', 'getClassNames' => 'array', 'getDependencies' => 'array', 'info' => 'void', 'isPersistent' => 'bool', 'isTemporary' => 'bool', ], 'ReflectionZendExtension' => [ 'getName' => 'string', 'getVersion' => 'string', 'getAuthor' => 'string', 'getURL' => 'string', 'getCopyright' => 'string', ], 'SessionHandlerInterface' => [ 'open' => 'bool', 'close' => 'bool', 'read' => 'string|false', 'write' => 'bool', 'destroy' => 'bool', 'gc' => 'int|false', ], 'SessionIdInterface' => [ 'create_sid' => 'string', ], 'SessionUpdateTimestampHandlerInterface' => [ 'validateId' => 'bool', 'updateTimestamp' => 'bool', ], 'SessionHandler' => [ 'open' => 'bool', 'close' => 'bool', 'read' => 'string|false', 'write' => 'bool', 'destroy' => 'bool', 'gc' => 'int|false', 'create_sid' => 'string', ], 'SimpleXMLElement' => [ 'xpath' => 'array|null|false', 'registerXPathNamespace' => 'bool', 'asXML' => 'string|bool', 'saveXML' => 'string|bool', 'getNamespaces' => 'array', 'getDocNamespaces' => 'array|false', 'children' => '?SimpleXMLElement', 'attributes' => '?SimpleXMLElement', 'addChild' => '?SimpleXMLElement', 'addAttribute' => 'void', 'getName' => 'string', 'count' => 'int', 'rewind' => 'void', 'valid' => 'bool', 'current' => 'SimpleXMLElement', 'key' => 'string', 'next' => 'void', 'hasChildren' => 'bool', 'getChildren' => '?SimpleXMLElement', ], 'SNMP' => [ 'close' => 'bool', 'setSecurity' => 'bool', 'get' => 'mixed', 'getnext' => 'mixed', 'walk' => 'array|false', 'set' => 'bool', 'getErrno' => 'int', 'getError' => 'string', ], 'SoapServer' => [ 'fault' => 'void', 'addSoapHeader' => 'void', 'setPersistence' => 'void', 'setClass' => 'void', 'setObject' => 'void', 'getFunctions' => 'array', 'addFunction' => 'void', 'handle' => 'void', ], 'SoapClient' => [ '__call' => 'mixed', '__soapCall' => 'mixed', '__getFunctions' => '?array', '__getTypes' => '?array', '__getLastRequest' => '?string', '__getLastResponse' => '?string', '__getLastRequestHeaders' => '?string', '__getLastResponseHeaders' => '?string', '__doRequest' => '?string', '__setCookie' => 'void', '__getCookies' => 'array', '__setSoapHeaders' => 'bool', '__setLocation' => '?string', ], 'ArrayObject' => [ 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'append' => 'void', 'getArrayCopy' => 'array', 'count' => 'int', 'getFlags' => 'int', 'setFlags' => 'void', 'asort' => 'bool', 'ksort' => 'bool', 'uasort' => 'bool', 'uksort' => 'bool', 'natsort' => 'bool', 'natcasesort' => 'bool', 'unserialize' => 'void', 'serialize' => 'string', '__serialize' => 'array', '__unserialize' => 'void', 'getIterator' => 'Iterator', 'exchangeArray' => 'array', 'setIteratorClass' => 'void', 'getIteratorClass' => 'string', '__debugInfo' => 'array', ], 'ArrayIterator' => [ 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'append' => 'void', 'getArrayCopy' => 'array', 'count' => 'int', 'getFlags' => 'int', 'setFlags' => 'void', 'asort' => 'bool', 'ksort' => 'bool', 'uasort' => 'bool', 'uksort' => 'bool', 'natsort' => 'bool', 'natcasesort' => 'bool', 'unserialize' => 'void', 'serialize' => 'string', '__serialize' => 'array', '__unserialize' => 'void', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'string|int|null', 'next' => 'void', 'valid' => 'bool', 'seek' => 'void', '__debugInfo' => 'array', ], 'RecursiveArrayIterator' => [ 'hasChildren' => 'bool', 'getChildren' => '?RecursiveArrayIterator', ], 'SplFileInfo' => [ 'getPath' => 'string', 'getFilename' => 'string', 'getExtension' => 'string', 'getBasename' => 'string', 'getPathname' => 'string', 'getPerms' => 'int|false', 'getInode' => 'int|false', 'getSize' => 'int|false', 'getOwner' => 'int|false', 'getGroup' => 'int|false', 'getATime' => 'int|false', 'getMTime' => 'int|false', 'getCTime' => 'int|false', 'getType' => 'string|false', 'isWritable' => 'bool', 'isReadable' => 'bool', 'isExecutable' => 'bool', 'isFile' => 'bool', 'isDir' => 'bool', 'isLink' => 'bool', 'getLinkTarget' => 'string|false', 'getRealPath' => 'string|false', 'getFileInfo' => 'SplFileInfo', 'getPathInfo' => '?SplFileInfo', 'openFile' => 'SplFileObject', 'setFileClass' => 'void', 'setInfoClass' => 'void', '__debugInfo' => 'array', '_bad_state_ex' => 'void', ], 'DirectoryIterator' => [ 'getFilename' => 'string', 'getExtension' => 'string', 'getBasename' => 'string', 'isDot' => 'bool', 'rewind' => 'void', 'valid' => 'bool', 'next' => 'void', 'seek' => 'void', ], 'FilesystemIterator' => [ 'rewind' => 'void', 'key' => 'string', 'current' => 'string|SplFileInfo|FilesystemIterator', 'getFlags' => 'int', 'setFlags' => 'void', ], 'RecursiveDirectoryIterator' => [ 'hasChildren' => 'bool', 'getChildren' => 'RecursiveDirectoryIterator', 'getSubPath' => 'string', 'getSubPathname' => 'string', ], 'GlobIterator' => [ 'count' => 'int', ], 'SplFileObject' => [ 'rewind' => 'void', 'eof' => 'bool', 'valid' => 'bool', 'fgets' => 'string', 'fread' => 'string|false', 'fgetcsv' => 'array|false', 'fputcsv' => 'int|false', 'setCsvControl' => 'void', 'getCsvControl' => 'array', 'flock' => 'bool', 'fflush' => 'bool', 'ftell' => 'int|false', 'fseek' => 'int', 'fgetc' => 'string|false', 'fpassthru' => 'int', 'fscanf' => 'array|int|null', 'fwrite' => 'int|false', 'fstat' => 'array', 'ftruncate' => 'bool', 'current' => 'string|array|false', 'key' => 'int', 'next' => 'void', 'setFlags' => 'void', 'getFlags' => 'int', 'setMaxLineLen' => 'void', 'getMaxLineLen' => 'int', 'hasChildren' => 'bool', 'getChildren' => '?RecursiveIterator', 'seek' => 'void', 'getCurrentLine' => 'string', ], 'SplDoublyLinkedList' => [ 'add' => 'void', 'pop' => 'mixed', 'shift' => 'mixed', 'push' => 'void', 'unshift' => 'void', 'top' => 'mixed', 'bottom' => 'mixed', '__debugInfo' => 'array', 'count' => 'int', 'isEmpty' => 'bool', 'setIteratorMode' => 'int', 'getIteratorMode' => 'int', 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'int', 'prev' => 'void', 'next' => 'void', 'valid' => 'bool', 'unserialize' => 'void', 'serialize' => 'string', '__serialize' => 'array', '__unserialize' => 'void', ], 'SplQueue' => [ 'enqueue' => 'void', 'dequeue' => 'mixed', ], 'SplFixedArray' => [ '__wakeup' => 'void', 'count' => 'int', 'toArray' => 'array', 'fromArray' => 'SplFixedArray', 'getSize' => 'int', 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', ], 'SplPriorityQueue' => [ 'compare' => 'int', 'setExtractFlags' => 'int', 'top' => 'mixed', 'extract' => 'mixed', 'count' => 'int', 'isEmpty' => 'bool', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'int', 'next' => 'void', 'valid' => 'bool', 'isCorrupted' => 'bool', 'getExtractFlags' => 'int', '__debugInfo' => 'array', ], 'SplHeap' => [ 'extract' => 'mixed', 'insert' => 'bool', 'top' => 'mixed', 'count' => 'int', 'isEmpty' => 'bool', 'rewind' => 'void', 'current' => 'mixed', 'key' => 'int', 'next' => 'void', 'valid' => 'bool', 'recoverFromCorruption' => 'bool', 'compare' => 'int', 'isCorrupted' => 'bool', '__debugInfo' => 'array', ], 'SplMinHeap' => [ 'compare' => 'int', ], 'SplMaxHeap' => [ 'compare' => 'int', ], 'EmptyIterator' => [ 'current' => 'never', 'next' => 'void', 'key' => 'never', 'valid' => 'bool', 'rewind' => 'void', ], 'CallbackFilterIterator' => [ 'accept' => 'bool', ], 'RecursiveCallbackFilterIterator' => [ 'hasChildren' => 'bool', 'getChildren' => 'RecursiveCallbackFilterIterator', ], 'RecursiveIterator' => [ 'hasChildren' => 'bool', 'getChildren' => '?RecursiveIterator', ], 'RecursiveIteratorIterator' => [ 'rewind' => 'void', 'valid' => 'bool', 'key' => 'mixed', 'current' => 'mixed', 'next' => 'void', 'getDepth' => 'int', 'getSubIterator' => '?RecursiveIterator', 'getInnerIterator' => 'RecursiveIterator', 'beginIteration' => 'void', 'endIteration' => 'void', 'callHasChildren' => 'bool', 'callGetChildren' => '?RecursiveIterator', 'beginChildren' => 'void', 'endChildren' => 'void', 'nextElement' => 'void', 'setMaxDepth' => 'void', 'getMaxDepth' => 'int|false', ], 'OuterIterator' => [ 'getInnerIterator' => '?Iterator', ], 'IteratorIterator' => [ 'getInnerIterator' => '?Iterator', 'rewind' => 'void', 'valid' => 'bool', 'key' => 'mixed', 'current' => 'mixed', 'next' => 'void', ], 'FilterIterator' => [ 'accept' => 'bool', 'rewind' => 'void', 'next' => 'void', ], 'RecursiveFilterIterator' => [ 'hasChildren' => 'bool', 'getChildren' => '?RecursiveFilterIterator', ], 'ParentIterator' => [ 'accept' => 'bool', ], 'SeekableIterator' => [ 'seek' => 'void', ], 'LimitIterator' => [ 'rewind' => 'void', 'valid' => 'bool', 'next' => 'void', 'seek' => 'int', 'getPosition' => 'int', ], 'CachingIterator' => [ 'rewind' => 'void', 'valid' => 'bool', 'next' => 'void', 'hasNext' => 'bool', 'getFlags' => 'int', 'setFlags' => 'void', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'offsetExists' => 'bool', 'getCache' => 'array', 'count' => 'int', ], 'RecursiveCachingIterator' => [ 'hasChildren' => 'bool', 'getChildren' => '?RecursiveCachingIterator', ], 'NoRewindIterator' => [ 'rewind' => 'void', 'valid' => 'bool', 'key' => 'mixed', 'current' => 'mixed', 'next' => 'void', ], 'AppendIterator' => [ 'append' => 'void', 'rewind' => 'void', 'valid' => 'bool', 'current' => 'mixed', 'next' => 'void', 'getIteratorIndex' => '?int', 'getArrayIterator' => 'ArrayIterator', ], 'InfiniteIterator' => [ 'next' => 'void', ], 'RegexIterator' => [ 'accept' => 'bool', 'getMode' => 'int', 'setMode' => 'void', 'getFlags' => 'int', 'setFlags' => 'void', 'getRegex' => 'string', 'getPregFlags' => 'int', 'setPregFlags' => 'void', ], 'RecursiveRegexIterator' => [ 'accept' => 'bool', 'hasChildren' => 'bool', 'getChildren' => 'RecursiveRegexIterator', ], 'RecursiveTreeIterator' => [ 'key' => 'mixed', 'current' => 'mixed', 'getPrefix' => 'string', 'setPostfix' => 'void', 'setPrefixPart' => 'void', 'getEntry' => 'string', 'getPostfix' => 'string', ], 'SplObserver' => [ 'update' => 'void', ], 'SplSubject' => [ 'attach' => 'void', 'detach' => 'void', 'notify' => 'void', ], 'SplObjectStorage' => [ 'attach' => 'void', 'detach' => 'void', 'contains' => 'bool', 'addAll' => 'int', 'removeAll' => 'int', 'removeAllExcept' => 'int', 'getInfo' => 'mixed', 'setInfo' => 'void', 'count' => 'int', 'rewind' => 'void', 'valid' => 'bool', 'key' => 'int', 'current' => 'object', 'next' => 'void', 'unserialize' => 'void', 'serialize' => 'string', 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', 'getHash' => 'string', '__serialize' => 'array', '__unserialize' => 'void', '__debugInfo' => 'array', ], 'MultipleIterator' => [ 'getFlags' => 'int', 'setFlags' => 'void', 'attachIterator' => 'void', 'detachIterator' => 'void', 'containsIterator' => 'bool', 'countIterators' => 'int', 'rewind' => 'void', 'valid' => 'bool', 'key' => 'array', 'current' => 'array', 'next' => 'void', '__debugInfo' => 'array', ], 'SQLite3' => [ 'open' => 'void', 'version' => 'array', 'lastInsertRowID' => 'int', 'lastErrorCode' => 'int', 'lastExtendedErrorCode' => 'int', 'lastErrorMsg' => 'string', 'changes' => 'int', 'busyTimeout' => 'bool', 'loadExtension' => 'bool', 'backup' => 'bool', 'escapeString' => 'string', 'prepare' => 'SQLite3Stmt|false', 'exec' => 'bool', 'query' => 'SQLite3Result|false', 'querySingle' => 'mixed', 'createFunction' => 'bool', 'createAggregate' => 'bool', 'createCollation' => 'bool', 'enableExceptions' => 'bool', 'enableExtendedResultCodes' => 'bool', 'setAuthorizer' => 'bool', ], 'SQLite3Stmt' => [ 'bindParam' => 'bool', 'bindValue' => 'bool', 'clear' => 'bool', 'close' => 'bool', 'execute' => 'SQLite3Result|false', 'getSQL' => 'string|false', 'paramCount' => 'int', 'readOnly' => 'bool', 'reset' => 'bool', ], 'SQLite3Result' => [ 'numColumns' => 'int', 'columnName' => 'string|false', 'columnType' => 'int|false', 'fetchArray' => 'array|false', 'reset' => 'bool', ], 'Directory' => [ 'close' => 'void', 'rewind' => 'void', 'read' => 'string|false', ], 'php_user_filter' => [ 'filter' => 'int', 'onCreate' => 'bool', 'onClose' => 'void', ], 'tidy' => [ 'getOpt' => 'string|int|bool', 'cleanRepair' => 'bool', 'parseFile' => 'bool', 'parseString' => 'bool', 'repairString' => 'string|false', 'repairFile' => 'string|false', 'diagnose' => 'bool', 'getRelease' => 'string', 'getConfig' => 'array', 'getStatus' => 'int', 'getHtmlVer' => 'int', 'getOptDoc' => 'string|false', 'isXhtml' => 'bool', 'isXml' => 'bool', 'root' => '?tidyNode', 'head' => '?tidyNode', 'html' => '?tidyNode', 'body' => '?tidyNode', ], 'XMLReader' => [ 'getAttribute' => '?string', 'getAttributeNo' => '?string', 'getAttributeNs' => '?string', 'getParserProperty' => 'bool', 'isValid' => 'bool', 'lookupNamespace' => '?string', 'moveToAttribute' => 'bool', 'moveToAttributeNo' => 'bool', 'moveToAttributeNs' => 'bool', 'moveToElement' => 'bool', 'moveToFirstAttribute' => 'bool', 'moveToNextAttribute' => 'bool', 'read' => 'bool', 'next' => 'bool', 'readInnerXml' => 'string', 'readOuterXml' => 'string', 'readString' => 'string', 'setSchema' => 'bool', 'setParserProperty' => 'bool', 'setRelaxNGSchema' => 'bool', 'setRelaxNGSchemaSource' => 'bool', 'expand' => 'DOMNode|false', ], 'XMLWriter' => [ 'openUri' => 'bool', 'openMemory' => 'bool', 'setIndent' => 'bool', 'setIndentString' => 'bool', 'startComment' => 'bool', 'endComment' => 'bool', 'startAttribute' => 'bool', 'endAttribute' => 'bool', 'writeAttribute' => 'bool', 'startAttributeNs' => 'bool', 'writeAttributeNs' => 'bool', 'startElement' => 'bool', 'endElement' => 'bool', 'fullEndElement' => 'bool', 'startElementNs' => 'bool', 'writeElement' => 'bool', 'writeElementNs' => 'bool', 'startPi' => 'bool', 'endPi' => 'bool', 'writePi' => 'bool', 'startCdata' => 'bool', 'endCdata' => 'bool', 'writeCdata' => 'bool', 'text' => 'bool', 'writeRaw' => 'bool', 'startDocument' => 'bool', 'endDocument' => 'bool', 'writeComment' => 'bool', 'startDtd' => 'bool', 'endDtd' => 'bool', 'writeDtd' => 'bool', 'startDtdElement' => 'bool', 'endDtdElement' => 'bool', 'writeDtdElement' => 'bool', 'startDtdAttlist' => 'bool', 'endDtdAttlist' => 'bool', 'writeDtdAttlist' => 'bool', 'startDtdEntity' => 'bool', 'endDtdEntity' => 'bool', 'writeDtdEntity' => 'bool', 'outputMemory' => 'string', 'flush' => 'string|int', ], 'XSLTProcessor' => [ 'importStylesheet' => 'bool', 'transformToDoc' => 'DOMDocument|false', 'transformToUri' => 'int', 'transformToXml' => 'string|null|false', 'setParameter' => 'bool', 'getParameter' => 'string|false', 'removeParameter' => 'bool', 'hasExsltSupport' => 'bool', 'registerPHPFunctions' => 'void', 'setSecurityPrefs' => 'int', 'getSecurityPrefs' => 'int', ], 'ZipArchive' => [ 'open' => 'bool|int', 'setPassword' => 'bool', 'close' => 'bool', 'count' => 'int', 'getStatusString' => 'string', 'addEmptyDir' => 'bool', 'addFromString' => 'bool', 'addFile' => 'bool', 'replaceFile' => 'bool', 'addGlob' => 'array|false', 'addPattern' => 'array|false', 'renameIndex' => 'bool', 'renameName' => 'bool', 'setArchiveComment' => 'bool', 'getArchiveComment' => 'string|false', 'setCommentIndex' => 'bool', 'setCommentName' => 'bool', 'setMtimeIndex' => 'bool', 'setMtimeName' => 'bool', 'getCommentIndex' => 'string|false', 'getCommentName' => 'string|false', 'deleteIndex' => 'bool', 'deleteName' => 'bool', 'statName' => 'array|false', 'statIndex' => 'array|false', 'locateName' => 'int|false', 'getNameIndex' => 'string|false', 'unchangeArchive' => 'bool', 'unchangeAll' => 'bool', 'unchangeIndex' => 'bool', 'unchangeName' => 'bool', 'extractTo' => 'bool', 'getFromName' => 'string|false', 'getFromIndex' => 'string|false', 'setExternalAttributesName' => 'bool', 'setExternalAttributesIndex' => 'bool', 'getExternalAttributesName' => 'bool', 'getExternalAttributesIndex' => 'bool', 'setCompressionName' => 'bool', 'setCompressionIndex' => 'bool', 'setEncryptionName' => 'bool', 'setEncryptionIndex' => 'bool', 'registerProgressCallback' => 'bool', 'registerCancelCallback' => 'bool', ], 'Exception' => [ '__wakeup' => 'void', ], 'Error' => [ '__wakeup' => 'void', ], 'IteratorAggregate' => [ 'getIterator' => 'Traversable', ], 'Iterator' => [ 'current' => 'mixed', 'next' => 'void', 'key' => 'mixed', 'valid' => 'bool', 'rewind' => 'void', ], 'ArrayAccess' => [ 'offsetExists' => 'bool', 'offsetGet' => 'mixed', 'offsetSet' => 'void', 'offsetUnset' => 'void', ], 'Countable' => [ 'count' => 'int', ], ]; } error-handler/composer.json000064400000002010150432043200012014 0ustar00{ "name": "symfony/error-handler", "type": "library", "description": "Provides tools to manage errors and ease debugging PHP code", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "psr/log": "^1|^2|^3", "symfony/var-dumper": "^4.4|^5.0|^6.0" }, "require-dev": { "symfony/http-kernel": "^4.4|^5.0|^6.0", "symfony/serializer": "^4.4|^5.0|^6.0", "symfony/deprecation-contracts": "^2.1|^3" }, "autoload": { "psr-4": { "Symfony\\Component\\ErrorHandler\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "bin": [ "Resources/bin/patch-type-declarations" ], "minimum-stability": "dev" } error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php000064400000014562150432043200017757 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorEnhancer; use Composer\Autoload\ClassLoader; use Symfony\Component\ErrorHandler\DebugClassLoader; use Symfony\Component\ErrorHandler\Error\ClassNotFoundError; use Symfony\Component\ErrorHandler\Error\FatalError; /** * @author Fabien Potencier */ class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface { /** * {@inheritdoc} */ public function enhance(\Throwable $error): ?\Throwable { // Some specific versions of PHP produce a fatal error when extending a not found class. $message = !$error instanceof FatalError ? $error->getMessage() : $error->getError()['message']; if (!preg_match('/^(Class|Interface|Trait) [\'"]([^\'"]+)[\'"] not found$/', $message, $matches)) { return null; } $typeName = strtolower($matches[1]); $fullyQualifiedClassName = $matches[2]; if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix); $tail = ' for another namespace?'; } else { $className = $fullyQualifiedClassName; $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className); $tail = '?'; } if ($candidates = $this->getClassCandidates($className)) { $tail = array_pop($candidates).'"?'; if ($candidates) { $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail; } else { $tail = ' for "'.$tail; } } $message .= "\nDid you forget a \"use\" statement".$tail; return new ClassNotFoundError($message, $error); } /** * Tries to guess the full namespace for a given class name. * * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer * autoloader (that should cover all common cases). * * @param string $class A class name (without its namespace) * * Returns an array of possible fully qualified class names */ private function getClassCandidates(string $class): array { if (!\is_array($functions = spl_autoload_functions())) { return []; } // find Symfony and Composer autoloaders $classes = []; foreach ($functions as $function) { if (!\is_array($function)) { continue; } // get class loaders wrapped by DebugClassLoader if ($function[0] instanceof DebugClassLoader) { $function = $function[0]->getClassLoader(); if (!\is_array($function)) { continue; } } if ($function[0] instanceof ClassLoader) { foreach ($function[0]->getPrefixes() as $prefix => $paths) { foreach ($paths as $path) { $classes[] = $this->findClassInPath($path, $class, $prefix); } } foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) { foreach ($paths as $path) { $classes[] = $this->findClassInPath($path, $class, $prefix); } } } } return array_unique(array_merge([], ...$classes)); } private function findClassInPath(string $path, string $class, string $prefix): array { if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { return []; } $classes = []; $filename = $class.'.php'; foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { $classes[] = $class; } } return $classes; } private function convertFileToClass(string $path, string $file, string $prefix): ?string { $candidates = [ // namespaced class $namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file), // namespaced class (with target dir) $prefix.$namespacedClass, // namespaced class (with target dir and separator) $prefix.'\\'.$namespacedClass, // PEAR class str_replace('\\', '_', $namespacedClass), // PEAR class (with target dir) str_replace('\\', '_', $prefix.$namespacedClass), // PEAR class (with target dir and separator) str_replace('\\', '_', $prefix.'\\'.$namespacedClass), ]; if ($prefix) { $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); } // We cannot use the autoloader here as most of them use require; but if the class // is not found, the new autoloader call will require the file again leading to a // "cannot redeclare class" error. foreach ($candidates as $candidate) { if ($this->classExists($candidate)) { return $candidate; } } try { require_once $file; } catch (\Throwable $e) { return null; } foreach ($candidates as $candidate) { if ($this->classExists($candidate)) { return $candidate; } } return null; } private function classExists(string $class): bool { return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); } } error-handler/ErrorEnhancer/ErrorEnhancerInterface.php000064400000000772150432043200017133 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorEnhancer; interface ErrorEnhancerInterface { /** * Returns an \Throwable instance if the class is able to improve the error, null otherwise. */ public function enhance(\Throwable $error): ?\Throwable; } error-handler/ErrorEnhancer/UndefinedFunctionErrorEnhancer.php000064400000006005150432043200020635 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorEnhancer; use Symfony\Component\ErrorHandler\Error\FatalError; use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError; /** * @author Fabien Potencier */ class UndefinedFunctionErrorEnhancer implements ErrorEnhancerInterface { /** * {@inheritdoc} */ public function enhance(\Throwable $error): ?\Throwable { if ($error instanceof FatalError) { return null; } $message = $error->getMessage(); $messageLen = \strlen($message); $notFoundSuffix = '()'; $notFoundSuffixLen = \strlen($notFoundSuffix); if ($notFoundSuffixLen > $messageLen) { return null; } if (0 !== substr_compare($message, $notFoundSuffix, -$notFoundSuffixLen)) { return null; } $prefix = 'Call to undefined function '; $prefixLen = \strlen($prefix); if (0 !== strpos($message, $prefix)) { return null; } $fullyQualifiedFunctionName = substr($message, $prefixLen, -$notFoundSuffixLen); if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix); } else { $functionName = $fullyQualifiedFunctionName; $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); } $candidates = []; foreach (get_defined_functions() as $type => $definedFunctionNames) { foreach ($definedFunctionNames as $definedFunctionName) { if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1); } else { $definedFunctionNameBasename = $definedFunctionName; } if ($definedFunctionNameBasename === $functionName) { $candidates[] = '\\'.$definedFunctionName; } } } if ($candidates) { sort($candidates); $last = array_pop($candidates).'"?'; if ($candidates) { $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; } else { $candidates = '"'.$last; } $message .= "\nDid you mean to call ".$candidates; } return new UndefinedFunctionError($message, $error); } } error-handler/ErrorEnhancer/UndefinedMethodErrorEnhancer.php000064400000004211150432043200020265 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\ErrorEnhancer; use Symfony\Component\ErrorHandler\Error\FatalError; use Symfony\Component\ErrorHandler\Error\UndefinedMethodError; /** * @author Grégoire Pineau */ class UndefinedMethodErrorEnhancer implements ErrorEnhancerInterface { /** * {@inheritdoc} */ public function enhance(\Throwable $error): ?\Throwable { if ($error instanceof FatalError) { return null; } $message = $error->getMessage(); preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $message, $matches); if (!$matches) { return null; } $className = $matches[1]; $methodName = $matches[2]; $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className); if ('' === $methodName || !class_exists($className) || null === $methods = get_class_methods($className)) { // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) return new UndefinedMethodError($message, $error); } $candidates = []; foreach ($methods as $definedMethodName) { $lev = levenshtein($methodName, $definedMethodName); if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { $candidates[] = $definedMethodName; } } if ($candidates) { sort($candidates); $last = array_pop($candidates).'"?'; if ($candidates) { $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; } else { $candidates = '"'.$last; } $message .= "\nDid you mean to call ".$candidates; } return new UndefinedMethodError($message, $error); } } error-handler/LICENSE000064400000002051150432043200010304 0ustar00Copyright (c) 2019-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. error-handler/Exception/FlattenException.php000064400000024703150432043200015232 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Exception; use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; /** * FlattenException wraps a PHP Error or Exception to be able to serialize it. * * Basically, this class removes all objects from the trace. * * @author Fabien Potencier */ class FlattenException { /** @var string */ private $message; /** @var int|string */ private $code; /** @var self|null */ private $previous; /** @var array */ private $trace; /** @var string */ private $traceAsString; /** @var string */ private $class; /** @var int */ private $statusCode; /** @var string */ private $statusText; /** @var array */ private $headers; /** @var string */ private $file; /** @var int */ private $line; /** @var string|null */ private $asString; /** * @return static */ public static function create(\Exception $exception, int $statusCode = null, array $headers = []): self { return static::createFromThrowable($exception, $statusCode, $headers); } /** * @return static */ public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): self { $e = new static(); $e->setMessage($exception->getMessage()); $e->setCode($exception->getCode()); if ($exception instanceof HttpExceptionInterface) { $statusCode = $exception->getStatusCode(); $headers = array_merge($headers, $exception->getHeaders()); } elseif ($exception instanceof RequestExceptionInterface) { $statusCode = 400; } if (null === $statusCode) { $statusCode = 500; } if (class_exists(Response::class) && isset(Response::$statusTexts[$statusCode])) { $statusText = Response::$statusTexts[$statusCode]; } else { $statusText = 'Whoops, looks like something went wrong.'; } $e->setStatusText($statusText); $e->setStatusCode($statusCode); $e->setHeaders($headers); $e->setTraceFromThrowable($exception); $e->setClass(\get_class($exception)); $e->setFile($exception->getFile()); $e->setLine($exception->getLine()); $previous = $exception->getPrevious(); if ($previous instanceof \Throwable) { $e->setPrevious(static::createFromThrowable($previous)); } return $e; } public function toArray(): array { $exceptions = []; foreach (array_merge([$this], $this->getAllPrevious()) as $exception) { $exceptions[] = [ 'message' => $exception->getMessage(), 'class' => $exception->getClass(), 'trace' => $exception->getTrace(), ]; } return $exceptions; } public function getStatusCode(): int { return $this->statusCode; } /** * @return $this */ public function setStatusCode(int $code): self { $this->statusCode = $code; return $this; } public function getHeaders(): array { return $this->headers; } /** * @return $this */ public function setHeaders(array $headers): self { $this->headers = $headers; return $this; } public function getClass(): string { return $this->class; } /** * @return $this */ public function setClass(string $class): self { $this->class = false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class; return $this; } public function getFile(): string { return $this->file; } /** * @return $this */ public function setFile(string $file): self { $this->file = $file; return $this; } public function getLine(): int { return $this->line; } /** * @return $this */ public function setLine(int $line): self { $this->line = $line; return $this; } public function getStatusText(): string { return $this->statusText; } /** * @return $this */ public function setStatusText(string $statusText): self { $this->statusText = $statusText; return $this; } public function getMessage(): string { return $this->message; } /** * @return $this */ public function setMessage(string $message): self { if (false !== strpos($message, "@anonymous\0")) { $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $message); } $this->message = $message; return $this; } /** * @return int|string int most of the time (might be a string with PDOException) */ public function getCode() { return $this->code; } /** * @param int|string $code * * @return $this */ public function setCode($code): self { $this->code = $code; return $this; } public function getPrevious(): ?self { return $this->previous; } /** * @return $this */ public function setPrevious(?self $previous): self { $this->previous = $previous; return $this; } /** * @return self[] */ public function getAllPrevious(): array { $exceptions = []; $e = $this; while ($e = $e->getPrevious()) { $exceptions[] = $e; } return $exceptions; } public function getTrace(): array { return $this->trace; } /** * @return $this */ public function setTraceFromThrowable(\Throwable $throwable): self { $this->traceAsString = $throwable->getTraceAsString(); return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine()); } /** * @return $this */ public function setTrace(array $trace, ?string $file, ?int $line): self { $this->trace = []; $this->trace[] = [ 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => $file, 'line' => $line, 'args' => [], ]; foreach ($trace as $entry) { $class = ''; $namespace = ''; if (isset($entry['class'])) { $parts = explode('\\', $entry['class']); $class = array_pop($parts); $namespace = implode('\\', $parts); } $this->trace[] = [ 'namespace' => $namespace, 'short_class' => $class, 'class' => $entry['class'] ?? '', 'type' => $entry['type'] ?? '', 'function' => $entry['function'] ?? null, 'file' => $entry['file'] ?? null, 'line' => $entry['line'] ?? null, 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [], ]; } return $this; } private function flattenArgs(array $args, int $level = 0, int &$count = 0): array { $result = []; foreach ($args as $key => $value) { if (++$count > 1e4) { return ['array', '*SKIPPED over 10000 entries*']; } if ($value instanceof \__PHP_Incomplete_Class) { $result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)]; } elseif (\is_object($value)) { $result[$key] = ['object', \get_class($value)]; } elseif (\is_array($value)) { if ($level > 10) { $result[$key] = ['array', '*DEEP NESTED ARRAY*']; } else { $result[$key] = ['array', $this->flattenArgs($value, $level + 1, $count)]; } } elseif (null === $value) { $result[$key] = ['null', null]; } elseif (\is_bool($value)) { $result[$key] = ['boolean', $value]; } elseif (\is_int($value)) { $result[$key] = ['integer', $value]; } elseif (\is_float($value)) { $result[$key] = ['float', $value]; } elseif (\is_resource($value)) { $result[$key] = ['resource', get_resource_type($value)]; } else { $result[$key] = ['string', (string) $value]; } } return $result; } private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value): string { $array = new \ArrayObject($value); return $array['__PHP_Incomplete_Class_Name']; } public function getTraceAsString(): string { return $this->traceAsString; } /** * @return $this */ public function setAsString(?string $asString): self { $this->asString = $asString; return $this; } public function getAsString(): string { if (null !== $this->asString) { return $this->asString; } $message = ''; $next = false; foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) { if ($next) { $message .= 'Next '; } else { $next = true; } $message .= $exception->getClass(); if ('' != $exception->getMessage()) { $message .= ': '.$exception->getMessage(); } $message .= ' in '.$exception->getFile().':'.$exception->getLine(). "\nStack trace:\n".$exception->getTraceAsString()."\n\n"; } return rtrim($message); } } error-handler/Exception/SilencedErrorContext.php000064400000002630150432043200016056 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\ErrorHandler\Exception; /** * Data Object that represents a Silenced Error. * * @author Grégoire Pineau */ class SilencedErrorContext implements \JsonSerializable { public $count = 1; private $severity; private $file; private $line; private $trace; public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1) { $this->severity = $severity; $this->file = $file; $this->line = $line; $this->trace = $trace; $this->count = $count; } public function getSeverity(): int { return $this->severity; } public function getFile(): string { return $this->file; } public function getLine(): int { return $this->line; } public function getTrace(): array { return $this->trace; } public function jsonSerialize(): array { return [ 'severity' => $this->severity, 'file' => $this->file, 'line' => $this->line, 'trace' => $this->trace, 'count' => $this->count, ]; } } polyfill-php72/README.md000064400000001551150432043200010606 0ustar00Symfony Polyfill / Php72 ======================== This component provides functions added to PHP 7.2 core: - [`spl_object_id`](https://php.net/spl_object_id) - [`stream_isatty`](https://php.net/stream_isatty) On Windows only: - [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support) Moved to core since 7.2 (was in the optional XML extension earlier): - [`utf8_encode`](https://php.net/utf8_encode) - [`utf8_decode`](https://php.net/utf8_decode) Also, it provides constants added to PHP 7.2: - [`PHP_FLOAT_*`](https://php.net/reserved.constants#constant.php-float-dig) - [`PHP_OS_FAMILY`](https://php.net/reserved.constants#constant.php-os-family) More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= This library is released under the [MIT license](LICENSE). polyfill-php72/Php72.php000064400000015064150432043200010744 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Php72; /** * @author Nicolas Grekas * @author Dariusz Rumiński * * @internal */ final class Php72 { private static $hashMask; public static function utf8_encode($s) { $s .= $s; $len = \strlen($s); for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { switch (true) { case $s[$i] < "\x80": $s[$j] = $s[$i]; break; case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; } } return substr($s, 0, $j); } public static function utf8_decode($s) { $s = (string) $s; $len = \strlen($s); for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { switch ($s[$i] & "\xF0") { case "\xC0": case "\xD0": $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); $s[$j] = $c < 256 ? \chr($c) : '?'; break; case "\xF0": ++$i; // no break case "\xE0": $s[$j] = '?'; $i += 2; break; default: $s[$j] = $s[$i]; } } return substr($s, 0, $j); } public static function php_os_family() { if ('\\' === \DIRECTORY_SEPARATOR) { return 'Windows'; } $map = [ 'Darwin' => 'Darwin', 'DragonFly' => 'BSD', 'FreeBSD' => 'BSD', 'NetBSD' => 'BSD', 'OpenBSD' => 'BSD', 'Linux' => 'Linux', 'SunOS' => 'Solaris', ]; return isset($map[\PHP_OS]) ? $map[\PHP_OS] : 'Unknown'; } public static function spl_object_id($object) { if (null === self::$hashMask) { self::initHashMask(); } if (null === $hash = spl_object_hash($object)) { return; } // On 32-bit systems, PHP_INT_SIZE is 4, return self::$hashMask ^ hexdec(substr($hash, 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1))); } public static function sapi_windows_vt100_support($stream, $enable = null) { if (!\is_resource($stream)) { trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); return false; } $meta = stream_get_meta_data($stream); if ('STDIO' !== $meta['stream_type']) { trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', \E_USER_WARNING); return false; } // We cannot actually disable vt100 support if it is set if (false === $enable || !self::stream_isatty($stream)) { return false; } // The native function does not apply to stdin $meta = array_map('strtolower', $meta); $stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri']; return !$stdin && (false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM') || 'Hyper' === getenv('TERM_PROGRAM')); } public static function stream_isatty($stream) { if (!\is_resource($stream)) { trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', \E_USER_WARNING); return false; } if ('\\' === \DIRECTORY_SEPARATOR) { $stat = @fstat($stream); // Check if formatted mode is S_IFCHR return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; } return \function_exists('posix_isatty') && @posix_isatty($stream); } private static function initHashMask() { $obj = (object) []; self::$hashMask = -1; // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below $obFuncs = ['ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush']; foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? \DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) { $frame['line'] = 0; break; } } if (!empty($frame['line'])) { ob_start(); debug_zval_dump($obj); self::$hashMask = (int) substr(ob_get_clean(), 17); } self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - (\PHP_INT_SIZE * 2 - 1), (\PHP_INT_SIZE * 2 - 1))); } public static function mb_chr($code, $encoding = null) { if (0x80 > $code %= 0x200000) { $s = \chr($code); } elseif (0x800 > $code) { $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); } elseif (0x10000 > $code) { $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } else { $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } if ('UTF-8' !== $encoding = $encoding ?? mb_internal_encoding()) { $s = mb_convert_encoding($s, $encoding, 'UTF-8'); } return $s; } public static function mb_ord($s, $encoding = null) { if (null === $encoding) { $s = mb_convert_encoding($s, 'UTF-8'); } elseif ('UTF-8' !== $encoding) { $s = mb_convert_encoding($s, 'UTF-8', $encoding); } if (1 === \strlen($s)) { return \ord($s); } $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; if (0xF0 <= $code) { return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; } if (0xE0 <= $code) { return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; } if (0xC0 <= $code) { return (($code - 0xC0) << 6) + $s[2] - 0x80; } return $code; } } polyfill-php72/bootstrap.php000064400000003615150432043200012060 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Php72 as p; if (\PHP_VERSION_ID >= 70200) { return; } if (!defined('PHP_FLOAT_DIG')) { define('PHP_FLOAT_DIG', 15); } if (!defined('PHP_FLOAT_EPSILON')) { define('PHP_FLOAT_EPSILON', 2.2204460492503E-16); } if (!defined('PHP_FLOAT_MIN')) { define('PHP_FLOAT_MIN', 2.2250738585072E-308); } if (!defined('PHP_FLOAT_MAX')) { define('PHP_FLOAT_MAX', 1.7976931348623157E+308); } if (!defined('PHP_OS_FAMILY')) { define('PHP_OS_FAMILY', p\Php72::php_os_family()); } if ('\\' === \DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) { function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); } } if (!function_exists('stream_isatty')) { function stream_isatty($stream) { return p\Php72::stream_isatty($stream); } } if (!function_exists('utf8_encode')) { function utf8_encode($string) { return p\Php72::utf8_encode($string); } } if (!function_exists('utf8_decode')) { function utf8_decode($string) { return p\Php72::utf8_decode($string); } } if (!function_exists('spl_object_id')) { function spl_object_id($object) { return p\Php72::spl_object_id($object); } } if (!function_exists('mb_ord')) { function mb_ord($string, $encoding = null) { return p\Php72::mb_ord($string, $encoding); } } if (!function_exists('mb_chr')) { function mb_chr($codepoint, $encoding = null) { return p\Php72::mb_chr($codepoint, $encoding); } } if (!function_exists('mb_scrub')) { function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } } polyfill-php72/composer.json000064400000001661150432043200012053 0ustar00{ "name": "symfony/polyfill-php72", "type": "library", "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", "keywords": ["polyfill", "shim", "compatibility", "portable"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php72\\": "" }, "files": [ "bootstrap.php" ] }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-php72/LICENSE000064400000002051150432043200010330 0ustar00Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. polyfill-iconv/Resources/charset/from.cp950.php000064400000704014150432043200015427 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '@' => ' ', 'A' => ',', 'B' => '、', 'C' => '。', 'D' => '.', 'E' => '‧', 'F' => ';', 'G' => ':', 'H' => '?', 'I' => '!', 'J' => '︰', 'K' => '…', 'L' => '‥', 'M' => '﹐', 'N' => '﹑', 'O' => '﹒', 'P' => '·', 'Q' => '﹔', 'R' => '﹕', 'S' => '﹖', 'T' => '﹗', 'U' => '|', 'V' => '–', 'W' => '︱', 'X' => '—', 'Y' => '︳', 'Z' => '╴', '[' => '︴', '\\' => '﹏', ']' => '(', '^' => ')', '_' => '︵', '`' => '︶', 'a' => '{', 'b' => '}', 'c' => '︷', 'd' => '︸', 'e' => '〔', 'f' => '〕', 'g' => '︹', 'h' => '︺', 'i' => '【', 'j' => '】', 'k' => '︻', 'l' => '︼', 'm' => '《', 'n' => '》', 'o' => '︽', 'p' => '︾', 'q' => '〈', 'r' => '〉', 's' => '︿', 't' => '﹀', 'u' => '「', 'v' => '」', 'w' => '﹁', 'x' => '﹂', 'y' => '『', 'z' => '』', '{' => '﹃', '|' => '﹄', '}' => '﹙', '~' => '﹚', '' => '﹛', '' => '﹜', '' => '﹝', '' => '﹞', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '〝', '' => '〞', '' => '‵', '' => '′', '' => '#', '' => '&', '' => '*', '' => '※', '' => '§', '' => '〃', '' => '○', '' => '●', '' => '△', '' => '▲', '' => '◎', '' => '☆', '' => '★', '' => '◇', '' => '◆', '' => '□', '' => '■', '' => '▽', '' => '▼', '' => '㊣', '' => '℅', '' => '¯', '' => ' ̄', '' => '_', '' => 'ˍ', '' => '﹉', '' => '﹊', '' => '﹍', '' => '﹎', '' => '﹋', '' => '﹌', '' => '﹟', '' => '﹠', '' => '﹡', '' => '+', '' => '-', '' => '×', '' => '÷', '' => '±', '' => '√', '' => '<', '' => '>', '' => '=', '' => '≦', '' => '≧', '' => '≠', '' => '∞', '' => '≒', '' => '≡', '' => '﹢', '' => '﹣', '' => '﹤', '' => '﹥', '' => '﹦', '' => '~', '' => '∩', '' => '∪', '' => '⊥', '' => '∠', '' => '∟', '' => '⊿', '' => '㏒', '' => '㏑', '' => '∫', '' => '∮', '' => '∵', '' => '∴', '' => '♀', '' => '♂', '' => '⊕', '' => '⊙', '' => '↑', '' => '↓', '' => '←', '' => '→', '' => '↖', '' => '↗', '' => '↙', '' => '↘', '' => '∥', '' => '∣', '' => '/', '@' => '\', 'A' => '∕', 'B' => '﹨', 'C' => '$', 'D' => '¥', 'E' => '〒', 'F' => '¢', 'G' => '£', 'H' => '%', 'I' => '@', 'J' => '℃', 'K' => '℉', 'L' => '﹩', 'M' => '﹪', 'N' => '﹫', 'O' => '㏕', 'P' => '㎜', 'Q' => '㎝', 'R' => '㎞', 'S' => '㏎', 'T' => '㎡', 'U' => '㎎', 'V' => '㎏', 'W' => '㏄', 'X' => '°', 'Y' => '兙', 'Z' => '兛', '[' => '兞', '\\' => '兝', ']' => '兡', '^' => '兣', '_' => '嗧', '`' => '瓩', 'a' => '糎', 'b' => '▁', 'c' => '▂', 'd' => '▃', 'e' => '▄', 'f' => '▅', 'g' => '▆', 'h' => '▇', 'i' => '█', 'j' => '▏', 'k' => '▎', 'l' => '▍', 'm' => '▌', 'n' => '▋', 'o' => '▊', 'p' => '▉', 'q' => '┼', 'r' => '┴', 's' => '┬', 't' => '┤', 'u' => '├', 'v' => '▔', 'w' => '─', 'x' => '│', 'y' => '▕', 'z' => '┌', '{' => '┐', '|' => '└', '}' => '┘', '~' => '╭', '' => '╮', '' => '╰', '' => '╯', '' => '═', '' => '╞', '' => '╪', '' => '╡', '' => '◢', '' => '◣', '' => '◥', '' => '◤', '' => '╱', '' => '╲', '' => '╳', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => 'Ⅰ', '' => 'Ⅱ', '' => 'Ⅲ', '' => 'Ⅳ', '' => 'Ⅴ', '' => 'Ⅵ', '' => 'Ⅶ', '' => 'Ⅷ', '' => 'Ⅸ', '' => 'Ⅹ', '' => '〡', '' => '〢', '' => '〣', '' => '〤', '' => '〥', '' => '〦', '' => '〧', '' => '〨', '' => '〩', '' => '十', '' => '卄', '' => '卅', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 's', '' => 't', '' => 'u', '' => 'v', '@' => 'w', 'A' => 'x', 'B' => 'y', 'C' => 'z', 'D' => 'Α', 'E' => 'Β', 'F' => 'Γ', 'G' => 'Δ', 'H' => 'Ε', 'I' => 'Ζ', 'J' => 'Η', 'K' => 'Θ', 'L' => 'Ι', 'M' => 'Κ', 'N' => 'Λ', 'O' => 'Μ', 'P' => 'Ν', 'Q' => 'Ξ', 'R' => 'Ο', 'S' => 'Π', 'T' => 'Ρ', 'U' => 'Σ', 'V' => 'Τ', 'W' => 'Υ', 'X' => 'Φ', 'Y' => 'Χ', 'Z' => 'Ψ', '[' => 'Ω', '\\' => 'α', ']' => 'β', '^' => 'γ', '_' => 'δ', '`' => 'ε', 'a' => 'ζ', 'b' => 'η', 'c' => 'θ', 'd' => 'ι', 'e' => 'κ', 'f' => 'λ', 'g' => 'μ', 'h' => 'ν', 'i' => 'ξ', 'j' => 'ο', 'k' => 'π', 'l' => 'ρ', 'm' => 'σ', 'n' => 'τ', 'o' => 'υ', 'p' => 'φ', 'q' => 'χ', 'r' => 'ψ', 's' => 'ω', 't' => 'ㄅ', 'u' => 'ㄆ', 'v' => 'ㄇ', 'w' => 'ㄈ', 'x' => 'ㄉ', 'y' => 'ㄊ', 'z' => 'ㄋ', '{' => 'ㄌ', '|' => 'ㄍ', '}' => 'ㄎ', '~' => 'ㄏ', '' => 'ㄐ', '' => 'ㄑ', '' => 'ㄒ', '' => 'ㄓ', '' => 'ㄔ', '' => 'ㄕ', '' => 'ㄖ', '' => 'ㄗ', '' => 'ㄘ', '' => 'ㄙ', '' => 'ㄚ', '' => 'ㄛ', '' => 'ㄜ', '' => 'ㄝ', '' => 'ㄞ', '' => 'ㄟ', '' => 'ㄠ', '' => 'ㄡ', '' => 'ㄢ', '' => 'ㄣ', '' => 'ㄤ', '' => 'ㄥ', '' => 'ㄦ', '' => 'ㄧ', '' => 'ㄨ', '' => 'ㄩ', '' => '˙', '' => 'ˉ', '' => 'ˊ', '' => 'ˇ', '' => 'ˋ', '' => '€', '@' => '一', 'A' => '乙', 'B' => '丁', 'C' => '七', 'D' => '乃', 'E' => '九', 'F' => '了', 'G' => '二', 'H' => '人', 'I' => '儿', 'J' => '入', 'K' => '八', 'L' => '几', 'M' => '刀', 'N' => '刁', 'O' => '力', 'P' => '匕', 'Q' => '十', 'R' => '卜', 'S' => '又', 'T' => '三', 'U' => '下', 'V' => '丈', 'W' => '上', 'X' => '丫', 'Y' => '丸', 'Z' => '凡', '[' => '久', '\\' => '么', ']' => '也', '^' => '乞', '_' => '于', '`' => '亡', 'a' => '兀', 'b' => '刃', 'c' => '勺', 'd' => '千', 'e' => '叉', 'f' => '口', 'g' => '土', 'h' => '士', 'i' => '夕', 'j' => '大', 'k' => '女', 'l' => '子', 'm' => '孑', 'n' => '孓', 'o' => '寸', 'p' => '小', 'q' => '尢', 'r' => '尸', 's' => '山', 't' => '川', 'u' => '工', 'v' => '己', 'w' => '已', 'x' => '巳', 'y' => '巾', 'z' => '干', '{' => '廾', '|' => '弋', '}' => '弓', '~' => '才', '' => '丑', '' => '丐', '' => '不', '' => '中', '' => '丰', '' => '丹', '' => '之', '' => '尹', '' => '予', '' => '云', '' => '井', '' => '互', '' => '五', '' => '亢', '' => '仁', '' => '什', '' => '仃', '' => '仆', '' => '仇', '' => '仍', '' => '今', '' => '介', '' => '仄', '' => '元', '' => '允', '' => '內', '' => '六', '' => '兮', '' => '公', '' => '冗', '' => '凶', '' => '分', '' => '切', '' => '刈', '' => '勻', '' => '勾', '' => '勿', '' => '化', '' => '匹', '' => '午', '' => '升', '' => '卅', '' => '卞', '' => '厄', '' => '友', '' => '及', '' => '反', '' => '壬', '' => '天', '' => '夫', '' => '太', '' => '夭', '' => '孔', '' => '少', '' => '尤', '' => '尺', '' => '屯', '' => '巴', '' => '幻', '' => '廿', '' => '弔', '' => '引', '' => '心', '' => '戈', '' => '戶', '' => '手', '' => '扎', '' => '支', '' => '文', '' => '斗', '' => '斤', '' => '方', '' => '日', '' => '曰', '' => '月', '' => '木', '' => '欠', '' => '止', '' => '歹', '' => '毋', '' => '比', '' => '毛', '' => '氏', '' => '水', '' => '火', '' => '爪', '' => '父', '' => '爻', '' => '片', '' => '牙', '' => '牛', '' => '犬', '' => '王', '' => '丙', '@' => '世', 'A' => '丕', 'B' => '且', 'C' => '丘', 'D' => '主', 'E' => '乍', 'F' => '乏', 'G' => '乎', 'H' => '以', 'I' => '付', 'J' => '仔', 'K' => '仕', 'L' => '他', 'M' => '仗', 'N' => '代', 'O' => '令', 'P' => '仙', 'Q' => '仞', 'R' => '充', 'S' => '兄', 'T' => '冉', 'U' => '冊', 'V' => '冬', 'W' => '凹', 'X' => '出', 'Y' => '凸', 'Z' => '刊', '[' => '加', '\\' => '功', ']' => '包', '^' => '匆', '_' => '北', '`' => '匝', 'a' => '仟', 'b' => '半', 'c' => '卉', 'd' => '卡', 'e' => '占', 'f' => '卯', 'g' => '卮', 'h' => '去', 'i' => '可', 'j' => '古', 'k' => '右', 'l' => '召', 'm' => '叮', 'n' => '叩', 'o' => '叨', 'p' => '叼', 'q' => '司', 'r' => '叵', 's' => '叫', 't' => '另', 'u' => '只', 'v' => '史', 'w' => '叱', 'x' => '台', 'y' => '句', 'z' => '叭', '{' => '叻', '|' => '四', '}' => '囚', '~' => '外', '' => '央', '' => '失', '' => '奴', '' => '奶', '' => '孕', '' => '它', '' => '尼', '' => '巨', '' => '巧', '' => '左', '' => '市', '' => '布', '' => '平', '' => '幼', '' => '弁', '' => '弘', '' => '弗', '' => '必', '' => '戊', '' => '打', '' => '扔', '' => '扒', '' => '扑', '' => '斥', '' => '旦', '' => '朮', '' => '本', '' => '未', '' => '末', '' => '札', '' => '正', '' => '母', '' => '民', '' => '氐', '' => '永', '' => '汁', '' => '汀', '' => '氾', '' => '犯', '' => '玄', '' => '玉', '' => '瓜', '' => '瓦', '' => '甘', '' => '生', '' => '用', '' => '甩', '' => '田', '' => '由', '' => '甲', '' => '申', '' => '疋', '' => '白', '' => '皮', '' => '皿', '' => '目', '' => '矛', '' => '矢', '' => '石', '' => '示', '' => '禾', '' => '穴', '' => '立', '' => '丞', '' => '丟', '' => '乒', '' => '乓', '' => '乩', '' => '亙', '' => '交', '' => '亦', '' => '亥', '' => '仿', '' => '伉', '' => '伙', '' => '伊', '' => '伕', '' => '伍', '' => '伐', '' => '休', '' => '伏', '' => '仲', '' => '件', '' => '任', '' => '仰', '' => '仳', '' => '份', '' => '企', '' => '伋', '' => '光', '' => '兇', '' => '兆', '' => '先', '' => '全', '@' => '共', 'A' => '再', 'B' => '冰', 'C' => '列', 'D' => '刑', 'E' => '划', 'F' => '刎', 'G' => '刖', 'H' => '劣', 'I' => '匈', 'J' => '匡', 'K' => '匠', 'L' => '印', 'M' => '危', 'N' => '吉', 'O' => '吏', 'P' => '同', 'Q' => '吊', 'R' => '吐', 'S' => '吁', 'T' => '吋', 'U' => '各', 'V' => '向', 'W' => '名', 'X' => '合', 'Y' => '吃', 'Z' => '后', '[' => '吆', '\\' => '吒', ']' => '因', '^' => '回', '_' => '囝', '`' => '圳', 'a' => '地', 'b' => '在', 'c' => '圭', 'd' => '圬', 'e' => '圯', 'f' => '圩', 'g' => '夙', 'h' => '多', 'i' => '夷', 'j' => '夸', 'k' => '妄', 'l' => '奸', 'm' => '妃', 'n' => '好', 'o' => '她', 'p' => '如', 'q' => '妁', 'r' => '字', 's' => '存', 't' => '宇', 'u' => '守', 'v' => '宅', 'w' => '安', 'x' => '寺', 'y' => '尖', 'z' => '屹', '{' => '州', '|' => '帆', '}' => '并', '~' => '年', '' => '式', '' => '弛', '' => '忙', '' => '忖', '' => '戎', '' => '戌', '' => '戍', '' => '成', '' => '扣', '' => '扛', '' => '托', '' => '收', '' => '早', '' => '旨', '' => '旬', '' => '旭', '' => '曲', '' => '曳', '' => '有', '' => '朽', '' => '朴', '' => '朱', '' => '朵', '' => '次', '' => '此', '' => '死', '' => '氖', '' => '汝', '' => '汗', '' => '汙', '' => '江', '' => '池', '' => '汐', '' => '汕', '' => '污', '' => '汛', '' => '汍', '' => '汎', '' => '灰', '' => '牟', '' => '牝', '' => '百', '' => '竹', '' => '米', '' => '糸', '' => '缶', '' => '羊', '' => '羽', '' => '老', '' => '考', '' => '而', '' => '耒', '' => '耳', '' => '聿', '' => '肉', '' => '肋', '' => '肌', '' => '臣', '' => '自', '' => '至', '' => '臼', '' => '舌', '' => '舛', '' => '舟', '' => '艮', '' => '色', '' => '艾', '' => '虫', '' => '血', '' => '行', '' => '衣', '' => '西', '' => '阡', '' => '串', '' => '亨', '' => '位', '' => '住', '' => '佇', '' => '佗', '' => '佞', '' => '伴', '' => '佛', '' => '何', '' => '估', '' => '佐', '' => '佑', '' => '伽', '' => '伺', '' => '伸', '' => '佃', '' => '佔', '' => '似', '' => '但', '' => '佣', '@' => '作', 'A' => '你', 'B' => '伯', 'C' => '低', 'D' => '伶', 'E' => '余', 'F' => '佝', 'G' => '佈', 'H' => '佚', 'I' => '兌', 'J' => '克', 'K' => '免', 'L' => '兵', 'M' => '冶', 'N' => '冷', 'O' => '別', 'P' => '判', 'Q' => '利', 'R' => '刪', 'S' => '刨', 'T' => '劫', 'U' => '助', 'V' => '努', 'W' => '劬', 'X' => '匣', 'Y' => '即', 'Z' => '卵', '[' => '吝', '\\' => '吭', ']' => '吞', '^' => '吾', '_' => '否', '`' => '呎', 'a' => '吧', 'b' => '呆', 'c' => '呃', 'd' => '吳', 'e' => '呈', 'f' => '呂', 'g' => '君', 'h' => '吩', 'i' => '告', 'j' => '吹', 'k' => '吻', 'l' => '吸', 'm' => '吮', 'n' => '吵', 'o' => '吶', 'p' => '吠', 'q' => '吼', 'r' => '呀', 's' => '吱', 't' => '含', 'u' => '吟', 'v' => '听', 'w' => '囪', 'x' => '困', 'y' => '囤', 'z' => '囫', '{' => '坊', '|' => '坑', '}' => '址', '~' => '坍', '' => '均', '' => '坎', '' => '圾', '' => '坐', '' => '坏', '' => '圻', '' => '壯', '' => '夾', '' => '妝', '' => '妒', '' => '妨', '' => '妞', '' => '妣', '' => '妙', '' => '妖', '' => '妍', '' => '妤', '' => '妓', '' => '妊', '' => '妥', '' => '孝', '' => '孜', '' => '孚', '' => '孛', '' => '完', '' => '宋', '' => '宏', '' => '尬', '' => '局', '' => '屁', '' => '尿', '' => '尾', '' => '岐', '' => '岑', '' => '岔', '' => '岌', '' => '巫', '' => '希', '' => '序', '' => '庇', '' => '床', '' => '廷', '' => '弄', '' => '弟', '' => '彤', '' => '形', '' => '彷', '' => '役', '' => '忘', '' => '忌', '' => '志', '' => '忍', '' => '忱', '' => '快', '' => '忸', '' => '忪', '' => '戒', '' => '我', '' => '抄', '' => '抗', '' => '抖', '' => '技', '' => '扶', '' => '抉', '' => '扭', '' => '把', '' => '扼', '' => '找', '' => '批', '' => '扳', '' => '抒', '' => '扯', '' => '折', '' => '扮', '' => '投', '' => '抓', '' => '抑', '' => '抆', '' => '改', '' => '攻', '' => '攸', '' => '旱', '' => '更', '' => '束', '' => '李', '' => '杏', '' => '材', '' => '村', '' => '杜', '' => '杖', '' => '杞', '' => '杉', '' => '杆', '' => '杠', '@' => '杓', 'A' => '杗', 'B' => '步', 'C' => '每', 'D' => '求', 'E' => '汞', 'F' => '沙', 'G' => '沁', 'H' => '沈', 'I' => '沉', 'J' => '沅', 'K' => '沛', 'L' => '汪', 'M' => '決', 'N' => '沐', 'O' => '汰', 'P' => '沌', 'Q' => '汨', 'R' => '沖', 'S' => '沒', 'T' => '汽', 'U' => '沃', 'V' => '汲', 'W' => '汾', 'X' => '汴', 'Y' => '沆', 'Z' => '汶', '[' => '沍', '\\' => '沔', ']' => '沘', '^' => '沂', '_' => '灶', '`' => '灼', 'a' => '災', 'b' => '灸', 'c' => '牢', 'd' => '牡', 'e' => '牠', 'f' => '狄', 'g' => '狂', 'h' => '玖', 'i' => '甬', 'j' => '甫', 'k' => '男', 'l' => '甸', 'm' => '皂', 'n' => '盯', 'o' => '矣', 'p' => '私', 'q' => '秀', 'r' => '禿', 's' => '究', 't' => '系', 'u' => '罕', 'v' => '肖', 'w' => '肓', 'x' => '肝', 'y' => '肘', 'z' => '肛', '{' => '肚', '|' => '育', '}' => '良', '~' => '芒', '' => '芋', '' => '芍', '' => '見', '' => '角', '' => '言', '' => '谷', '' => '豆', '' => '豕', '' => '貝', '' => '赤', '' => '走', '' => '足', '' => '身', '' => '車', '' => '辛', '' => '辰', '' => '迂', '' => '迆', '' => '迅', '' => '迄', '' => '巡', '' => '邑', '' => '邢', '' => '邪', '' => '邦', '' => '那', '' => '酉', '' => '釆', '' => '里', '' => '防', '' => '阮', '' => '阱', '' => '阪', '' => '阬', '' => '並', '' => '乖', '' => '乳', '' => '事', '' => '些', '' => '亞', '' => '享', '' => '京', '' => '佯', '' => '依', '' => '侍', '' => '佳', '' => '使', '' => '佬', '' => '供', '' => '例', '' => '來', '' => '侃', '' => '佰', '' => '併', '' => '侈', '' => '佩', '' => '佻', '' => '侖', '' => '佾', '' => '侏', '' => '侑', '' => '佺', '' => '兔', '' => '兒', '' => '兕', '' => '兩', '' => '具', '' => '其', '' => '典', '' => '冽', '' => '函', '' => '刻', '' => '券', '' => '刷', '' => '刺', '' => '到', '' => '刮', '' => '制', '' => '剁', '' => '劾', '' => '劻', '' => '卒', '' => '協', '' => '卓', '' => '卑', '' => '卦', '' => '卷', '' => '卸', '' => '卹', '' => '取', '' => '叔', '' => '受', '' => '味', '' => '呵', '@' => '咖', 'A' => '呸', 'B' => '咕', 'C' => '咀', 'D' => '呻', 'E' => '呷', 'F' => '咄', 'G' => '咒', 'H' => '咆', 'I' => '呼', 'J' => '咐', 'K' => '呱', 'L' => '呶', 'M' => '和', 'N' => '咚', 'O' => '呢', 'P' => '周', 'Q' => '咋', 'R' => '命', 'S' => '咎', 'T' => '固', 'U' => '垃', 'V' => '坷', 'W' => '坪', 'X' => '坩', 'Y' => '坡', 'Z' => '坦', '[' => '坤', '\\' => '坼', ']' => '夜', '^' => '奉', '_' => '奇', '`' => '奈', 'a' => '奄', 'b' => '奔', 'c' => '妾', 'd' => '妻', 'e' => '委', 'f' => '妹', 'g' => '妮', 'h' => '姑', 'i' => '姆', 'j' => '姐', 'k' => '姍', 'l' => '始', 'm' => '姓', 'n' => '姊', 'o' => '妯', 'p' => '妳', 'q' => '姒', 'r' => '姅', 's' => '孟', 't' => '孤', 'u' => '季', 'v' => '宗', 'w' => '定', 'x' => '官', 'y' => '宜', 'z' => '宙', '{' => '宛', '|' => '尚', '}' => '屈', '~' => '居', '' => '屆', '' => '岷', '' => '岡', '' => '岸', '' => '岩', '' => '岫', '' => '岱', '' => '岳', '' => '帘', '' => '帚', '' => '帖', '' => '帕', '' => '帛', '' => '帑', '' => '幸', '' => '庚', '' => '店', '' => '府', '' => '底', '' => '庖', '' => '延', '' => '弦', '' => '弧', '' => '弩', '' => '往', '' => '征', '' => '彿', '' => '彼', '' => '忝', '' => '忠', '' => '忽', '' => '念', '' => '忿', '' => '怏', '' => '怔', '' => '怯', '' => '怵', '' => '怖', '' => '怪', '' => '怕', '' => '怡', '' => '性', '' => '怩', '' => '怫', '' => '怛', '' => '或', '' => '戕', '' => '房', '' => '戾', '' => '所', '' => '承', '' => '拉', '' => '拌', '' => '拄', '' => '抿', '' => '拂', '' => '抹', '' => '拒', '' => '招', '' => '披', '' => '拓', '' => '拔', '' => '拋', '' => '拈', '' => '抨', '' => '抽', '' => '押', '' => '拐', '' => '拙', '' => '拇', '' => '拍', '' => '抵', '' => '拚', '' => '抱', '' => '拘', '' => '拖', '' => '拗', '' => '拆', '' => '抬', '' => '拎', '' => '放', '' => '斧', '' => '於', '' => '旺', '' => '昔', '' => '易', '' => '昌', '' => '昆', '' => '昂', '' => '明', '' => '昀', '' => '昏', '' => '昕', '' => '昊', '@' => '昇', 'A' => '服', 'B' => '朋', 'C' => '杭', 'D' => '枋', 'E' => '枕', 'F' => '東', 'G' => '果', 'H' => '杳', 'I' => '杷', 'J' => '枇', 'K' => '枝', 'L' => '林', 'M' => '杯', 'N' => '杰', 'O' => '板', 'P' => '枉', 'Q' => '松', 'R' => '析', 'S' => '杵', 'T' => '枚', 'U' => '枓', 'V' => '杼', 'W' => '杪', 'X' => '杲', 'Y' => '欣', 'Z' => '武', '[' => '歧', '\\' => '歿', ']' => '氓', '^' => '氛', '_' => '泣', '`' => '注', 'a' => '泳', 'b' => '沱', 'c' => '泌', 'd' => '泥', 'e' => '河', 'f' => '沽', 'g' => '沾', 'h' => '沼', 'i' => '波', 'j' => '沫', 'k' => '法', 'l' => '泓', 'm' => '沸', 'n' => '泄', 'o' => '油', 'p' => '況', 'q' => '沮', 'r' => '泗', 's' => '泅', 't' => '泱', 'u' => '沿', 'v' => '治', 'w' => '泡', 'x' => '泛', 'y' => '泊', 'z' => '沬', '{' => '泯', '|' => '泜', '}' => '泖', '~' => '泠', '' => '炕', '' => '炎', '' => '炒', '' => '炊', '' => '炙', '' => '爬', '' => '爭', '' => '爸', '' => '版', '' => '牧', '' => '物', '' => '狀', '' => '狎', '' => '狙', '' => '狗', '' => '狐', '' => '玩', '' => '玨', '' => '玟', '' => '玫', '' => '玥', '' => '甽', '' => '疝', '' => '疙', '' => '疚', '' => '的', '' => '盂', '' => '盲', '' => '直', '' => '知', '' => '矽', '' => '社', '' => '祀', '' => '祁', '' => '秉', '' => '秈', '' => '空', '' => '穹', '' => '竺', '' => '糾', '' => '罔', '' => '羌', '' => '羋', '' => '者', '' => '肺', '' => '肥', '' => '肢', '' => '肱', '' => '股', '' => '肫', '' => '肩', '' => '肴', '' => '肪', '' => '肯', '' => '臥', '' => '臾', '' => '舍', '' => '芳', '' => '芝', '' => '芙', '' => '芭', '' => '芽', '' => '芟', '' => '芹', '' => '花', '' => '芬', '' => '芥', '' => '芯', '' => '芸', '' => '芣', '' => '芰', '' => '芾', '' => '芷', '' => '虎', '' => '虱', '' => '初', '' => '表', '' => '軋', '' => '迎', '' => '返', '' => '近', '' => '邵', '' => '邸', '' => '邱', '' => '邶', '' => '采', '' => '金', '' => '長', '' => '門', '' => '阜', '' => '陀', '' => '阿', '' => '阻', '' => '附', '@' => '陂', 'A' => '隹', 'B' => '雨', 'C' => '青', 'D' => '非', 'E' => '亟', 'F' => '亭', 'G' => '亮', 'H' => '信', 'I' => '侵', 'J' => '侯', 'K' => '便', 'L' => '俠', 'M' => '俑', 'N' => '俏', 'O' => '保', 'P' => '促', 'Q' => '侶', 'R' => '俘', 'S' => '俟', 'T' => '俊', 'U' => '俗', 'V' => '侮', 'W' => '俐', 'X' => '俄', 'Y' => '係', 'Z' => '俚', '[' => '俎', '\\' => '俞', ']' => '侷', '^' => '兗', '_' => '冒', '`' => '冑', 'a' => '冠', 'b' => '剎', 'c' => '剃', 'd' => '削', 'e' => '前', 'f' => '剌', 'g' => '剋', 'h' => '則', 'i' => '勇', 'j' => '勉', 'k' => '勃', 'l' => '勁', 'm' => '匍', 'n' => '南', 'o' => '卻', 'p' => '厚', 'q' => '叛', 'r' => '咬', 's' => '哀', 't' => '咨', 'u' => '哎', 'v' => '哉', 'w' => '咸', 'x' => '咦', 'y' => '咳', 'z' => '哇', '{' => '哂', '|' => '咽', '}' => '咪', '~' => '品', '' => '哄', '' => '哈', '' => '咯', '' => '咫', '' => '咱', '' => '咻', '' => '咩', '' => '咧', '' => '咿', '' => '囿', '' => '垂', '' => '型', '' => '垠', '' => '垣', '' => '垢', '' => '城', '' => '垮', '' => '垓', '' => '奕', '' => '契', '' => '奏', '' => '奎', '' => '奐', '' => '姜', '' => '姘', '' => '姿', '' => '姣', '' => '姨', '' => '娃', '' => '姥', '' => '姪', '' => '姚', '' => '姦', '' => '威', '' => '姻', '' => '孩', '' => '宣', '' => '宦', '' => '室', '' => '客', '' => '宥', '' => '封', '' => '屎', '' => '屏', '' => '屍', '' => '屋', '' => '峙', '' => '峒', '' => '巷', '' => '帝', '' => '帥', '' => '帟', '' => '幽', '' => '庠', '' => '度', '' => '建', '' => '弈', '' => '弭', '' => '彥', '' => '很', '' => '待', '' => '徊', '' => '律', '' => '徇', '' => '後', '' => '徉', '' => '怒', '' => '思', '' => '怠', '' => '急', '' => '怎', '' => '怨', '' => '恍', '' => '恰', '' => '恨', '' => '恢', '' => '恆', '' => '恃', '' => '恬', '' => '恫', '' => '恪', '' => '恤', '' => '扁', '' => '拜', '' => '挖', '' => '按', '' => '拼', '' => '拭', '' => '持', '' => '拮', '' => '拽', '' => '指', '' => '拱', '' => '拷', '@' => '拯', 'A' => '括', 'B' => '拾', 'C' => '拴', 'D' => '挑', 'E' => '挂', 'F' => '政', 'G' => '故', 'H' => '斫', 'I' => '施', 'J' => '既', 'K' => '春', 'L' => '昭', 'M' => '映', 'N' => '昧', 'O' => '是', 'P' => '星', 'Q' => '昨', 'R' => '昱', 'S' => '昤', 'T' => '曷', 'U' => '柿', 'V' => '染', 'W' => '柱', 'X' => '柔', 'Y' => '某', 'Z' => '柬', '[' => '架', '\\' => '枯', ']' => '柵', '^' => '柩', '_' => '柯', '`' => '柄', 'a' => '柑', 'b' => '枴', 'c' => '柚', 'd' => '查', 'e' => '枸', 'f' => '柏', 'g' => '柞', 'h' => '柳', 'i' => '枰', 'j' => '柙', 'k' => '柢', 'l' => '柝', 'm' => '柒', 'n' => '歪', 'o' => '殃', 'p' => '殆', 'q' => '段', 'r' => '毒', 's' => '毗', 't' => '氟', 'u' => '泉', 'v' => '洋', 'w' => '洲', 'x' => '洪', 'y' => '流', 'z' => '津', '{' => '洌', '|' => '洱', '}' => '洞', '~' => '洗', '' => '活', '' => '洽', '' => '派', '' => '洶', '' => '洛', '' => '泵', '' => '洹', '' => '洧', '' => '洸', '' => '洩', '' => '洮', '' => '洵', '' => '洎', '' => '洫', '' => '炫', '' => '為', '' => '炳', '' => '炬', '' => '炯', '' => '炭', '' => '炸', '' => '炮', '' => '炤', '' => '爰', '' => '牲', '' => '牯', '' => '牴', '' => '狩', '' => '狠', '' => '狡', '' => '玷', '' => '珊', '' => '玻', '' => '玲', '' => '珍', '' => '珀', '' => '玳', '' => '甚', '' => '甭', '' => '畏', '' => '界', '' => '畎', '' => '畋', '' => '疫', '' => '疤', '' => '疥', '' => '疢', '' => '疣', '' => '癸', '' => '皆', '' => '皇', '' => '皈', '' => '盈', '' => '盆', '' => '盃', '' => '盅', '' => '省', '' => '盹', '' => '相', '' => '眉', '' => '看', '' => '盾', '' => '盼', '' => '眇', '' => '矜', '' => '砂', '' => '研', '' => '砌', '' => '砍', '' => '祆', '' => '祉', '' => '祈', '' => '祇', '' => '禹', '' => '禺', '' => '科', '' => '秒', '' => '秋', '' => '穿', '' => '突', '' => '竿', '' => '竽', '' => '籽', '' => '紂', '' => '紅', '' => '紀', '' => '紉', '' => '紇', '' => '約', '' => '紆', '' => '缸', '' => '美', '' => '羿', '' => '耄', '@' => '耐', 'A' => '耍', 'B' => '耑', 'C' => '耶', 'D' => '胖', 'E' => '胥', 'F' => '胚', 'G' => '胃', 'H' => '胄', 'I' => '背', 'J' => '胡', 'K' => '胛', 'L' => '胎', 'M' => '胞', 'N' => '胤', 'O' => '胝', 'P' => '致', 'Q' => '舢', 'R' => '苧', 'S' => '范', 'T' => '茅', 'U' => '苣', 'V' => '苛', 'W' => '苦', 'X' => '茄', 'Y' => '若', 'Z' => '茂', '[' => '茉', '\\' => '苒', ']' => '苗', '^' => '英', '_' => '茁', '`' => '苜', 'a' => '苔', 'b' => '苑', 'c' => '苞', 'd' => '苓', 'e' => '苟', 'f' => '苯', 'g' => '茆', 'h' => '虐', 'i' => '虹', 'j' => '虻', 'k' => '虺', 'l' => '衍', 'm' => '衫', 'n' => '要', 'o' => '觔', 'p' => '計', 'q' => '訂', 'r' => '訃', 's' => '貞', 't' => '負', 'u' => '赴', 'v' => '赳', 'w' => '趴', 'x' => '軍', 'y' => '軌', 'z' => '述', '{' => '迦', '|' => '迢', '}' => '迪', '~' => '迥', '' => '迭', '' => '迫', '' => '迤', '' => '迨', '' => '郊', '' => '郎', '' => '郁', '' => '郃', '' => '酋', '' => '酊', '' => '重', '' => '閂', '' => '限', '' => '陋', '' => '陌', '' => '降', '' => '面', '' => '革', '' => '韋', '' => '韭', '' => '音', '' => '頁', '' => '風', '' => '飛', '' => '食', '' => '首', '' => '香', '' => '乘', '' => '亳', '' => '倌', '' => '倍', '' => '倣', '' => '俯', '' => '倦', '' => '倥', '' => '俸', '' => '倩', '' => '倖', '' => '倆', '' => '值', '' => '借', '' => '倚', '' => '倒', '' => '們', '' => '俺', '' => '倀', '' => '倔', '' => '倨', '' => '俱', '' => '倡', '' => '個', '' => '候', '' => '倘', '' => '俳', '' => '修', '' => '倭', '' => '倪', '' => '俾', '' => '倫', '' => '倉', '' => '兼', '' => '冤', '' => '冥', '' => '冢', '' => '凍', '' => '凌', '' => '准', '' => '凋', '' => '剖', '' => '剜', '' => '剔', '' => '剛', '' => '剝', '' => '匪', '' => '卿', '' => '原', '' => '厝', '' => '叟', '' => '哨', '' => '唐', '' => '唁', '' => '唷', '' => '哼', '' => '哥', '' => '哲', '' => '唆', '' => '哺', '' => '唔', '' => '哩', '' => '哭', '' => '員', '' => '唉', '' => '哮', '' => '哪', '@' => '哦', 'A' => '唧', 'B' => '唇', 'C' => '哽', 'D' => '唏', 'E' => '圃', 'F' => '圄', 'G' => '埂', 'H' => '埔', 'I' => '埋', 'J' => '埃', 'K' => '堉', 'L' => '夏', 'M' => '套', 'N' => '奘', 'O' => '奚', 'P' => '娑', 'Q' => '娘', 'R' => '娜', 'S' => '娟', 'T' => '娛', 'U' => '娓', 'V' => '姬', 'W' => '娠', 'X' => '娣', 'Y' => '娩', 'Z' => '娥', '[' => '娌', '\\' => '娉', ']' => '孫', '^' => '屘', '_' => '宰', '`' => '害', 'a' => '家', 'b' => '宴', 'c' => '宮', 'd' => '宵', 'e' => '容', 'f' => '宸', 'g' => '射', 'h' => '屑', 'i' => '展', 'j' => '屐', 'k' => '峭', 'l' => '峽', 'm' => '峻', 'n' => '峪', 'o' => '峨', 'p' => '峰', 'q' => '島', 'r' => '崁', 's' => '峴', 't' => '差', 'u' => '席', 'v' => '師', 'w' => '庫', 'x' => '庭', 'y' => '座', 'z' => '弱', '{' => '徒', '|' => '徑', '}' => '徐', '~' => '恙', '' => '恣', '' => '恥', '' => '恐', '' => '恕', '' => '恭', '' => '恩', '' => '息', '' => '悄', '' => '悟', '' => '悚', '' => '悍', '' => '悔', '' => '悌', '' => '悅', '' => '悖', '' => '扇', '' => '拳', '' => '挈', '' => '拿', '' => '捎', '' => '挾', '' => '振', '' => '捕', '' => '捂', '' => '捆', '' => '捏', '' => '捉', '' => '挺', '' => '捐', '' => '挽', '' => '挪', '' => '挫', '' => '挨', '' => '捍', '' => '捌', '' => '效', '' => '敉', '' => '料', '' => '旁', '' => '旅', '' => '時', '' => '晉', '' => '晏', '' => '晃', '' => '晒', '' => '晌', '' => '晅', '' => '晁', '' => '書', '' => '朔', '' => '朕', '' => '朗', '' => '校', '' => '核', '' => '案', '' => '框', '' => '桓', '' => '根', '' => '桂', '' => '桔', '' => '栩', '' => '梳', '' => '栗', '' => '桌', '' => '桑', '' => '栽', '' => '柴', '' => '桐', '' => '桀', '' => '格', '' => '桃', '' => '株', '' => '桅', '' => '栓', '' => '栘', '' => '桁', '' => '殊', '' => '殉', '' => '殷', '' => '氣', '' => '氧', '' => '氨', '' => '氦', '' => '氤', '' => '泰', '' => '浪', '' => '涕', '' => '消', '' => '涇', '' => '浦', '' => '浸', '' => '海', '' => '浙', '' => '涓', '@' => '浬', 'A' => '涉', 'B' => '浮', 'C' => '浚', 'D' => '浴', 'E' => '浩', 'F' => '涌', 'G' => '涊', 'H' => '浹', 'I' => '涅', 'J' => '浥', 'K' => '涔', 'L' => '烊', 'M' => '烘', 'N' => '烤', 'O' => '烙', 'P' => '烈', 'Q' => '烏', 'R' => '爹', 'S' => '特', 'T' => '狼', 'U' => '狹', 'V' => '狽', 'W' => '狸', 'X' => '狷', 'Y' => '玆', 'Z' => '班', '[' => '琉', '\\' => '珮', ']' => '珠', '^' => '珪', '_' => '珞', '`' => '畔', 'a' => '畝', 'b' => '畜', 'c' => '畚', 'd' => '留', 'e' => '疾', 'f' => '病', 'g' => '症', 'h' => '疲', 'i' => '疳', 'j' => '疽', 'k' => '疼', 'l' => '疹', 'm' => '痂', 'n' => '疸', 'o' => '皋', 'p' => '皰', 'q' => '益', 'r' => '盍', 's' => '盎', 't' => '眩', 'u' => '真', 'v' => '眠', 'w' => '眨', 'x' => '矩', 'y' => '砰', 'z' => '砧', '{' => '砸', '|' => '砝', '}' => '破', '~' => '砷', '' => '砥', '' => '砭', '' => '砠', '' => '砟', '' => '砲', '' => '祕', '' => '祐', '' => '祠', '' => '祟', '' => '祖', '' => '神', '' => '祝', '' => '祗', '' => '祚', '' => '秤', '' => '秣', '' => '秧', '' => '租', '' => '秦', '' => '秩', '' => '秘', '' => '窄', '' => '窈', '' => '站', '' => '笆', '' => '笑', '' => '粉', '' => '紡', '' => '紗', '' => '紋', '' => '紊', '' => '素', '' => '索', '' => '純', '' => '紐', '' => '紕', '' => '級', '' => '紜', '' => '納', '' => '紙', '' => '紛', '' => '缺', '' => '罟', '' => '羔', '' => '翅', '' => '翁', '' => '耆', '' => '耘', '' => '耕', '' => '耙', '' => '耗', '' => '耽', '' => '耿', '' => '胱', '' => '脂', '' => '胰', '' => '脅', '' => '胭', '' => '胴', '' => '脆', '' => '胸', '' => '胳', '' => '脈', '' => '能', '' => '脊', '' => '胼', '' => '胯', '' => '臭', '' => '臬', '' => '舀', '' => '舐', '' => '航', '' => '舫', '' => '舨', '' => '般', '' => '芻', '' => '茫', '' => '荒', '' => '荔', '' => '荊', '' => '茸', '' => '荐', '' => '草', '' => '茵', '' => '茴', '' => '荏', '' => '茲', '' => '茹', '' => '茶', '' => '茗', '' => '荀', '' => '茱', '' => '茨', '' => '荃', '@' => '虔', 'A' => '蚊', 'B' => '蚪', 'C' => '蚓', 'D' => '蚤', 'E' => '蚩', 'F' => '蚌', 'G' => '蚣', 'H' => '蚜', 'I' => '衰', 'J' => '衷', 'K' => '袁', 'L' => '袂', 'M' => '衽', 'N' => '衹', 'O' => '記', 'P' => '訐', 'Q' => '討', 'R' => '訌', 'S' => '訕', 'T' => '訊', 'U' => '託', 'V' => '訓', 'W' => '訖', 'X' => '訏', 'Y' => '訑', 'Z' => '豈', '[' => '豺', '\\' => '豹', ']' => '財', '^' => '貢', '_' => '起', '`' => '躬', 'a' => '軒', 'b' => '軔', 'c' => '軏', 'd' => '辱', 'e' => '送', 'f' => '逆', 'g' => '迷', 'h' => '退', 'i' => '迺', 'j' => '迴', 'k' => '逃', 'l' => '追', 'm' => '逅', 'n' => '迸', 'o' => '邕', 'p' => '郡', 'q' => '郝', 'r' => '郢', 's' => '酒', 't' => '配', 'u' => '酌', 'v' => '釘', 'w' => '針', 'x' => '釗', 'y' => '釜', 'z' => '釙', '{' => '閃', '|' => '院', '}' => '陣', '~' => '陡', '' => '陛', '' => '陝', '' => '除', '' => '陘', '' => '陞', '' => '隻', '' => '飢', '' => '馬', '' => '骨', '' => '高', '' => '鬥', '' => '鬲', '' => '鬼', '' => '乾', '' => '偺', '' => '偽', '' => '停', '' => '假', '' => '偃', '' => '偌', '' => '做', '' => '偉', '' => '健', '' => '偶', '' => '偎', '' => '偕', '' => '偵', '' => '側', '' => '偷', '' => '偏', '' => '倏', '' => '偯', '' => '偭', '' => '兜', '' => '冕', '' => '凰', '' => '剪', '' => '副', '' => '勒', '' => '務', '' => '勘', '' => '動', '' => '匐', '' => '匏', '' => '匙', '' => '匿', '' => '區', '' => '匾', '' => '參', '' => '曼', '' => '商', '' => '啪', '' => '啦', '' => '啄', '' => '啞', '' => '啡', '' => '啃', '' => '啊', '' => '唱', '' => '啖', '' => '問', '' => '啕', '' => '唯', '' => '啤', '' => '唸', '' => '售', '' => '啜', '' => '唬', '' => '啣', '' => '唳', '' => '啁', '' => '啗', '' => '圈', '' => '國', '' => '圉', '' => '域', '' => '堅', '' => '堊', '' => '堆', '' => '埠', '' => '埤', '' => '基', '' => '堂', '' => '堵', '' => '執', '' => '培', '' => '夠', '' => '奢', '' => '娶', '' => '婁', '' => '婉', '' => '婦', '' => '婪', '' => '婀', '@' => '娼', 'A' => '婢', 'B' => '婚', 'C' => '婆', 'D' => '婊', 'E' => '孰', 'F' => '寇', 'G' => '寅', 'H' => '寄', 'I' => '寂', 'J' => '宿', 'K' => '密', 'L' => '尉', 'M' => '專', 'N' => '將', 'O' => '屠', 'P' => '屜', 'Q' => '屝', 'R' => '崇', 'S' => '崆', 'T' => '崎', 'U' => '崛', 'V' => '崖', 'W' => '崢', 'X' => '崑', 'Y' => '崩', 'Z' => '崔', '[' => '崙', '\\' => '崤', ']' => '崧', '^' => '崗', '_' => '巢', '`' => '常', 'a' => '帶', 'b' => '帳', 'c' => '帷', 'd' => '康', 'e' => '庸', 'f' => '庶', 'g' => '庵', 'h' => '庾', 'i' => '張', 'j' => '強', 'k' => '彗', 'l' => '彬', 'm' => '彩', 'n' => '彫', 'o' => '得', 'p' => '徙', 'q' => '從', 'r' => '徘', 's' => '御', 't' => '徠', 'u' => '徜', 'v' => '恿', 'w' => '患', 'x' => '悉', 'y' => '悠', 'z' => '您', '{' => '惋', '|' => '悴', '}' => '惦', '~' => '悽', '' => '情', '' => '悻', '' => '悵', '' => '惜', '' => '悼', '' => '惘', '' => '惕', '' => '惆', '' => '惟', '' => '悸', '' => '惚', '' => '惇', '' => '戚', '' => '戛', '' => '扈', '' => '掠', '' => '控', '' => '捲', '' => '掖', '' => '探', '' => '接', '' => '捷', '' => '捧', '' => '掘', '' => '措', '' => '捱', '' => '掩', '' => '掉', '' => '掃', '' => '掛', '' => '捫', '' => '推', '' => '掄', '' => '授', '' => '掙', '' => '採', '' => '掬', '' => '排', '' => '掏', '' => '掀', '' => '捻', '' => '捩', '' => '捨', '' => '捺', '' => '敝', '' => '敖', '' => '救', '' => '教', '' => '敗', '' => '啟', '' => '敏', '' => '敘', '' => '敕', '' => '敔', '' => '斜', '' => '斛', '' => '斬', '' => '族', '' => '旋', '' => '旌', '' => '旎', '' => '晝', '' => '晚', '' => '晤', '' => '晨', '' => '晦', '' => '晞', '' => '曹', '' => '勗', '' => '望', '' => '梁', '' => '梯', '' => '梢', '' => '梓', '' => '梵', '' => '桿', '' => '桶', '' => '梱', '' => '梧', '' => '梗', '' => '械', '' => '梃', '' => '棄', '' => '梭', '' => '梆', '' => '梅', '' => '梔', '' => '條', '' => '梨', '' => '梟', '' => '梡', '' => '梂', '' => '欲', '' => '殺', '@' => '毫', 'A' => '毬', 'B' => '氫', 'C' => '涎', 'D' => '涼', 'E' => '淳', 'F' => '淙', 'G' => '液', 'H' => '淡', 'I' => '淌', 'J' => '淤', 'K' => '添', 'L' => '淺', 'M' => '清', 'N' => '淇', 'O' => '淋', 'P' => '涯', 'Q' => '淑', 'R' => '涮', 'S' => '淞', 'T' => '淹', 'U' => '涸', 'V' => '混', 'W' => '淵', 'X' => '淅', 'Y' => '淒', 'Z' => '渚', '[' => '涵', '\\' => '淚', ']' => '淫', '^' => '淘', '_' => '淪', '`' => '深', 'a' => '淮', 'b' => '淨', 'c' => '淆', 'd' => '淄', 'e' => '涪', 'f' => '淬', 'g' => '涿', 'h' => '淦', 'i' => '烹', 'j' => '焉', 'k' => '焊', 'l' => '烽', 'm' => '烯', 'n' => '爽', 'o' => '牽', 'p' => '犁', 'q' => '猜', 'r' => '猛', 's' => '猖', 't' => '猓', 'u' => '猙', 'v' => '率', 'w' => '琅', 'x' => '琊', 'y' => '球', 'z' => '理', '{' => '現', '|' => '琍', '}' => '瓠', '~' => '瓶', '' => '瓷', '' => '甜', '' => '產', '' => '略', '' => '畦', '' => '畢', '' => '異', '' => '疏', '' => '痔', '' => '痕', '' => '疵', '' => '痊', '' => '痍', '' => '皎', '' => '盔', '' => '盒', '' => '盛', '' => '眷', '' => '眾', '' => '眼', '' => '眶', '' => '眸', '' => '眺', '' => '硫', '' => '硃', '' => '硎', '' => '祥', '' => '票', '' => '祭', '' => '移', '' => '窒', '' => '窕', '' => '笠', '' => '笨', '' => '笛', '' => '第', '' => '符', '' => '笙', '' => '笞', '' => '笮', '' => '粒', '' => '粗', '' => '粕', '' => '絆', '' => '絃', '' => '統', '' => '紮', '' => '紹', '' => '紼', '' => '絀', '' => '細', '' => '紳', '' => '組', '' => '累', '' => '終', '' => '紲', '' => '紱', '' => '缽', '' => '羞', '' => '羚', '' => '翌', '' => '翎', '' => '習', '' => '耜', '' => '聊', '' => '聆', '' => '脯', '' => '脖', '' => '脣', '' => '脫', '' => '脩', '' => '脰', '' => '脤', '' => '舂', '' => '舵', '' => '舷', '' => '舶', '' => '船', '' => '莎', '' => '莞', '' => '莘', '' => '荸', '' => '莢', '' => '莖', '' => '莽', '' => '莫', '' => '莒', '' => '莊', '' => '莓', '' => '莉', '' => '莠', '' => '荷', '' => '荻', '' => '荼', '@' => '莆', 'A' => '莧', 'B' => '處', 'C' => '彪', 'D' => '蛇', 'E' => '蛀', 'F' => '蚶', 'G' => '蛄', 'H' => '蚵', 'I' => '蛆', 'J' => '蛋', 'K' => '蚱', 'L' => '蚯', 'M' => '蛉', 'N' => '術', 'O' => '袞', 'P' => '袈', 'Q' => '被', 'R' => '袒', 'S' => '袖', 'T' => '袍', 'U' => '袋', 'V' => '覓', 'W' => '規', 'X' => '訪', 'Y' => '訝', 'Z' => '訣', '[' => '訥', '\\' => '許', ']' => '設', '^' => '訟', '_' => '訛', '`' => '訢', 'a' => '豉', 'b' => '豚', 'c' => '販', 'd' => '責', 'e' => '貫', 'f' => '貨', 'g' => '貪', 'h' => '貧', 'i' => '赧', 'j' => '赦', 'k' => '趾', 'l' => '趺', 'm' => '軛', 'n' => '軟', 'o' => '這', 'p' => '逍', 'q' => '通', 'r' => '逗', 's' => '連', 't' => '速', 'u' => '逝', 'v' => '逐', 'w' => '逕', 'x' => '逞', 'y' => '造', 'z' => '透', '{' => '逢', '|' => '逖', '}' => '逛', '~' => '途', '' => '部', '' => '郭', '' => '都', '' => '酗', '' => '野', '' => '釵', '' => '釦', '' => '釣', '' => '釧', '' => '釭', '' => '釩', '' => '閉', '' => '陪', '' => '陵', '' => '陳', '' => '陸', '' => '陰', '' => '陴', '' => '陶', '' => '陷', '' => '陬', '' => '雀', '' => '雪', '' => '雩', '' => '章', '' => '竟', '' => '頂', '' => '頃', '' => '魚', '' => '鳥', '' => '鹵', '' => '鹿', '' => '麥', '' => '麻', '' => '傢', '' => '傍', '' => '傅', '' => '備', '' => '傑', '' => '傀', '' => '傖', '' => '傘', '' => '傚', '' => '最', '' => '凱', '' => '割', '' => '剴', '' => '創', '' => '剩', '' => '勞', '' => '勝', '' => '勛', '' => '博', '' => '厥', '' => '啻', '' => '喀', '' => '喧', '' => '啼', '' => '喊', '' => '喝', '' => '喘', '' => '喂', '' => '喜', '' => '喪', '' => '喔', '' => '喇', '' => '喋', '' => '喃', '' => '喳', '' => '單', '' => '喟', '' => '唾', '' => '喲', '' => '喚', '' => '喻', '' => '喬', '' => '喱', '' => '啾', '' => '喉', '' => '喫', '' => '喙', '' => '圍', '' => '堯', '' => '堪', '' => '場', '' => '堤', '' => '堰', '' => '報', '' => '堡', '' => '堝', '' => '堠', '' => '壹', '' => '壺', '' => '奠', '@' => '婷', 'A' => '媚', 'B' => '婿', 'C' => '媒', 'D' => '媛', 'E' => '媧', 'F' => '孳', 'G' => '孱', 'H' => '寒', 'I' => '富', 'J' => '寓', 'K' => '寐', 'L' => '尊', 'M' => '尋', 'N' => '就', 'O' => '嵌', 'P' => '嵐', 'Q' => '崴', 'R' => '嵇', 'S' => '巽', 'T' => '幅', 'U' => '帽', 'V' => '幀', 'W' => '幃', 'X' => '幾', 'Y' => '廊', 'Z' => '廁', '[' => '廂', '\\' => '廄', ']' => '弼', '^' => '彭', '_' => '復', '`' => '循', 'a' => '徨', 'b' => '惑', 'c' => '惡', 'd' => '悲', 'e' => '悶', 'f' => '惠', 'g' => '愜', 'h' => '愣', 'i' => '惺', 'j' => '愕', 'k' => '惰', 'l' => '惻', 'm' => '惴', 'n' => '慨', 'o' => '惱', 'p' => '愎', 'q' => '惶', 'r' => '愉', 's' => '愀', 't' => '愒', 'u' => '戟', 'v' => '扉', 'w' => '掣', 'x' => '掌', 'y' => '描', 'z' => '揀', '{' => '揩', '|' => '揉', '}' => '揆', '~' => '揍', '' => '插', '' => '揣', '' => '提', '' => '握', '' => '揖', '' => '揭', '' => '揮', '' => '捶', '' => '援', '' => '揪', '' => '換', '' => '摒', '' => '揚', '' => '揹', '' => '敞', '' => '敦', '' => '敢', '' => '散', '' => '斑', '' => '斐', '' => '斯', '' => '普', '' => '晰', '' => '晴', '' => '晶', '' => '景', '' => '暑', '' => '智', '' => '晾', '' => '晷', '' => '曾', '' => '替', '' => '期', '' => '朝', '' => '棺', '' => '棕', '' => '棠', '' => '棘', '' => '棗', '' => '椅', '' => '棟', '' => '棵', '' => '森', '' => '棧', '' => '棹', '' => '棒', '' => '棲', '' => '棣', '' => '棋', '' => '棍', '' => '植', '' => '椒', '' => '椎', '' => '棉', '' => '棚', '' => '楮', '' => '棻', '' => '款', '' => '欺', '' => '欽', '' => '殘', '' => '殖', '' => '殼', '' => '毯', '' => '氮', '' => '氯', '' => '氬', '' => '港', '' => '游', '' => '湔', '' => '渡', '' => '渲', '' => '湧', '' => '湊', '' => '渠', '' => '渥', '' => '渣', '' => '減', '' => '湛', '' => '湘', '' => '渤', '' => '湖', '' => '湮', '' => '渭', '' => '渦', '' => '湯', '' => '渴', '' => '湍', '' => '渺', '' => '測', '' => '湃', '' => '渝', '' => '渾', '' => '滋', '@' => '溉', 'A' => '渙', 'B' => '湎', 'C' => '湣', 'D' => '湄', 'E' => '湲', 'F' => '湩', 'G' => '湟', 'H' => '焙', 'I' => '焚', 'J' => '焦', 'K' => '焰', 'L' => '無', 'M' => '然', 'N' => '煮', 'O' => '焜', 'P' => '牌', 'Q' => '犄', 'R' => '犀', 'S' => '猶', 'T' => '猥', 'U' => '猴', 'V' => '猩', 'W' => '琺', 'X' => '琪', 'Y' => '琳', 'Z' => '琢', '[' => '琥', '\\' => '琵', ']' => '琶', '^' => '琴', '_' => '琯', '`' => '琛', 'a' => '琦', 'b' => '琨', 'c' => '甥', 'd' => '甦', 'e' => '畫', 'f' => '番', 'g' => '痢', 'h' => '痛', 'i' => '痣', 'j' => '痙', 'k' => '痘', 'l' => '痞', 'm' => '痠', 'n' => '登', 'o' => '發', 'p' => '皖', 'q' => '皓', 'r' => '皴', 's' => '盜', 't' => '睏', 'u' => '短', 'v' => '硝', 'w' => '硬', 'x' => '硯', 'y' => '稍', 'z' => '稈', '{' => '程', '|' => '稅', '}' => '稀', '~' => '窘', '' => '窗', '' => '窖', '' => '童', '' => '竣', '' => '等', '' => '策', '' => '筆', '' => '筐', '' => '筒', '' => '答', '' => '筍', '' => '筋', '' => '筏', '' => '筑', '' => '粟', '' => '粥', '' => '絞', '' => '結', '' => '絨', '' => '絕', '' => '紫', '' => '絮', '' => '絲', '' => '絡', '' => '給', '' => '絢', '' => '絰', '' => '絳', '' => '善', '' => '翔', '' => '翕', '' => '耋', '' => '聒', '' => '肅', '' => '腕', '' => '腔', '' => '腋', '' => '腑', '' => '腎', '' => '脹', '' => '腆', '' => '脾', '' => '腌', '' => '腓', '' => '腴', '' => '舒', '' => '舜', '' => '菩', '' => '萃', '' => '菸', '' => '萍', '' => '菠', '' => '菅', '' => '萋', '' => '菁', '' => '華', '' => '菱', '' => '菴', '' => '著', '' => '萊', '' => '菰', '' => '萌', '' => '菌', '' => '菽', '' => '菲', '' => '菊', '' => '萸', '' => '萎', '' => '萄', '' => '菜', '' => '萇', '' => '菔', '' => '菟', '' => '虛', '' => '蛟', '' => '蛙', '' => '蛭', '' => '蛔', '' => '蛛', '' => '蛤', '' => '蛐', '' => '蛞', '' => '街', '' => '裁', '' => '裂', '' => '袱', '' => '覃', '' => '視', '' => '註', '' => '詠', '' => '評', '' => '詞', '' => '証', '' => '詁', '@' => '詔', 'A' => '詛', 'B' => '詐', 'C' => '詆', 'D' => '訴', 'E' => '診', 'F' => '訶', 'G' => '詖', 'H' => '象', 'I' => '貂', 'J' => '貯', 'K' => '貼', 'L' => '貳', 'M' => '貽', 'N' => '賁', 'O' => '費', 'P' => '賀', 'Q' => '貴', 'R' => '買', 'S' => '貶', 'T' => '貿', 'U' => '貸', 'V' => '越', 'W' => '超', 'X' => '趁', 'Y' => '跎', 'Z' => '距', '[' => '跋', '\\' => '跚', ']' => '跑', '^' => '跌', '_' => '跛', '`' => '跆', 'a' => '軻', 'b' => '軸', 'c' => '軼', 'd' => '辜', 'e' => '逮', 'f' => '逵', 'g' => '週', 'h' => '逸', 'i' => '進', 'j' => '逶', 'k' => '鄂', 'l' => '郵', 'm' => '鄉', 'n' => '郾', 'o' => '酣', 'p' => '酥', 'q' => '量', 'r' => '鈔', 's' => '鈕', 't' => '鈣', 'u' => '鈉', 'v' => '鈞', 'w' => '鈍', 'x' => '鈐', 'y' => '鈇', 'z' => '鈑', '{' => '閔', '|' => '閏', '}' => '開', '~' => '閑', '' => '間', '' => '閒', '' => '閎', '' => '隊', '' => '階', '' => '隋', '' => '陽', '' => '隅', '' => '隆', '' => '隍', '' => '陲', '' => '隄', '' => '雁', '' => '雅', '' => '雄', '' => '集', '' => '雇', '' => '雯', '' => '雲', '' => '韌', '' => '項', '' => '順', '' => '須', '' => '飧', '' => '飪', '' => '飯', '' => '飩', '' => '飲', '' => '飭', '' => '馮', '' => '馭', '' => '黃', '' => '黍', '' => '黑', '' => '亂', '' => '傭', '' => '債', '' => '傲', '' => '傳', '' => '僅', '' => '傾', '' => '催', '' => '傷', '' => '傻', '' => '傯', '' => '僇', '' => '剿', '' => '剷', '' => '剽', '' => '募', '' => '勦', '' => '勤', '' => '勢', '' => '勣', '' => '匯', '' => '嗟', '' => '嗨', '' => '嗓', '' => '嗦', '' => '嗎', '' => '嗜', '' => '嗇', '' => '嗑', '' => '嗣', '' => '嗤', '' => '嗯', '' => '嗚', '' => '嗡', '' => '嗅', '' => '嗆', '' => '嗥', '' => '嗉', '' => '園', '' => '圓', '' => '塞', '' => '塑', '' => '塘', '' => '塗', '' => '塚', '' => '塔', '' => '填', '' => '塌', '' => '塭', '' => '塊', '' => '塢', '' => '塒', '' => '塋', '' => '奧', '' => '嫁', '' => '嫉', '' => '嫌', '' => '媾', '' => '媽', '' => '媼', '@' => '媳', 'A' => '嫂', 'B' => '媲', 'C' => '嵩', 'D' => '嵯', 'E' => '幌', 'F' => '幹', 'G' => '廉', 'H' => '廈', 'I' => '弒', 'J' => '彙', 'K' => '徬', 'L' => '微', 'M' => '愚', 'N' => '意', 'O' => '慈', 'P' => '感', 'Q' => '想', 'R' => '愛', 'S' => '惹', 'T' => '愁', 'U' => '愈', 'V' => '慎', 'W' => '慌', 'X' => '慄', 'Y' => '慍', 'Z' => '愾', '[' => '愴', '\\' => '愧', ']' => '愍', '^' => '愆', '_' => '愷', '`' => '戡', 'a' => '戢', 'b' => '搓', 'c' => '搾', 'd' => '搞', 'e' => '搪', 'f' => '搭', 'g' => '搽', 'h' => '搬', 'i' => '搏', 'j' => '搜', 'k' => '搔', 'l' => '損', 'm' => '搶', 'n' => '搖', 'o' => '搗', 'p' => '搆', 'q' => '敬', 'r' => '斟', 's' => '新', 't' => '暗', 'u' => '暉', 'v' => '暇', 'w' => '暈', 'x' => '暖', 'y' => '暄', 'z' => '暘', '{' => '暍', '|' => '會', '}' => '榔', '~' => '業', '' => '楚', '' => '楷', '' => '楠', '' => '楔', '' => '極', '' => '椰', '' => '概', '' => '楊', '' => '楨', '' => '楫', '' => '楞', '' => '楓', '' => '楹', '' => '榆', '' => '楝', '' => '楣', '' => '楛', '' => '歇', '' => '歲', '' => '毀', '' => '殿', '' => '毓', '' => '毽', '' => '溢', '' => '溯', '' => '滓', '' => '溶', '' => '滂', '' => '源', '' => '溝', '' => '滇', '' => '滅', '' => '溥', '' => '溘', '' => '溼', '' => '溺', '' => '溫', '' => '滑', '' => '準', '' => '溜', '' => '滄', '' => '滔', '' => '溪', '' => '溧', '' => '溴', '' => '煎', '' => '煙', '' => '煩', '' => '煤', '' => '煉', '' => '照', '' => '煜', '' => '煬', '' => '煦', '' => '煌', '' => '煥', '' => '煞', '' => '煆', '' => '煨', '' => '煖', '' => '爺', '' => '牒', '' => '猷', '' => '獅', '' => '猿', '' => '猾', '' => '瑯', '' => '瑚', '' => '瑕', '' => '瑟', '' => '瑞', '' => '瑁', '' => '琿', '' => '瑙', '' => '瑛', '' => '瑜', '' => '當', '' => '畸', '' => '瘀', '' => '痰', '' => '瘁', '' => '痲', '' => '痱', '' => '痺', '' => '痿', '' => '痴', '' => '痳', '' => '盞', '' => '盟', '' => '睛', '' => '睫', '' => '睦', '' => '睞', '' => '督', '@' => '睹', 'A' => '睪', 'B' => '睬', 'C' => '睜', 'D' => '睥', 'E' => '睨', 'F' => '睢', 'G' => '矮', 'H' => '碎', 'I' => '碰', 'J' => '碗', 'K' => '碘', 'L' => '碌', 'M' => '碉', 'N' => '硼', 'O' => '碑', 'P' => '碓', 'Q' => '硿', 'R' => '祺', 'S' => '祿', 'T' => '禁', 'U' => '萬', 'V' => '禽', 'W' => '稜', 'X' => '稚', 'Y' => '稠', 'Z' => '稔', '[' => '稟', '\\' => '稞', ']' => '窟', '^' => '窠', '_' => '筷', '`' => '節', 'a' => '筠', 'b' => '筮', 'c' => '筧', 'd' => '粱', 'e' => '粳', 'f' => '粵', 'g' => '經', 'h' => '絹', 'i' => '綑', 'j' => '綁', 'k' => '綏', 'l' => '絛', 'm' => '置', 'n' => '罩', 'o' => '罪', 'p' => '署', 'q' => '義', 'r' => '羨', 's' => '群', 't' => '聖', 'u' => '聘', 'v' => '肆', 'w' => '肄', 'x' => '腱', 'y' => '腰', 'z' => '腸', '{' => '腥', '|' => '腮', '}' => '腳', '~' => '腫', '' => '腹', '' => '腺', '' => '腦', '' => '舅', '' => '艇', '' => '蒂', '' => '葷', '' => '落', '' => '萱', '' => '葵', '' => '葦', '' => '葫', '' => '葉', '' => '葬', '' => '葛', '' => '萼', '' => '萵', '' => '葡', '' => '董', '' => '葩', '' => '葭', '' => '葆', '' => '虞', '' => '虜', '' => '號', '' => '蛹', '' => '蜓', '' => '蜈', '' => '蜇', '' => '蜀', '' => '蛾', '' => '蛻', '' => '蜂', '' => '蜃', '' => '蜆', '' => '蜊', '' => '衙', '' => '裟', '' => '裔', '' => '裙', '' => '補', '' => '裘', '' => '裝', '' => '裡', '' => '裊', '' => '裕', '' => '裒', '' => '覜', '' => '解', '' => '詫', '' => '該', '' => '詳', '' => '試', '' => '詩', '' => '詰', '' => '誇', '' => '詼', '' => '詣', '' => '誠', '' => '話', '' => '誅', '' => '詭', '' => '詢', '' => '詮', '' => '詬', '' => '詹', '' => '詻', '' => '訾', '' => '詨', '' => '豢', '' => '貊', '' => '貉', '' => '賊', '' => '資', '' => '賈', '' => '賄', '' => '貲', '' => '賃', '' => '賂', '' => '賅', '' => '跡', '' => '跟', '' => '跨', '' => '路', '' => '跳', '' => '跺', '' => '跪', '' => '跤', '' => '跦', '' => '躲', '' => '較', '' => '載', '' => '軾', '' => '輊', '@' => '辟', 'A' => '農', 'B' => '運', 'C' => '遊', 'D' => '道', 'E' => '遂', 'F' => '達', 'G' => '逼', 'H' => '違', 'I' => '遐', 'J' => '遇', 'K' => '遏', 'L' => '過', 'M' => '遍', 'N' => '遑', 'O' => '逾', 'P' => '遁', 'Q' => '鄒', 'R' => '鄗', 'S' => '酬', 'T' => '酪', 'U' => '酩', 'V' => '釉', 'W' => '鈷', 'X' => '鉗', 'Y' => '鈸', 'Z' => '鈽', '[' => '鉀', '\\' => '鈾', ']' => '鉛', '^' => '鉋', '_' => '鉤', '`' => '鉑', 'a' => '鈴', 'b' => '鉉', 'c' => '鉍', 'd' => '鉅', 'e' => '鈹', 'f' => '鈿', 'g' => '鉚', 'h' => '閘', 'i' => '隘', 'j' => '隔', 'k' => '隕', 'l' => '雍', 'm' => '雋', 'n' => '雉', 'o' => '雊', 'p' => '雷', 'q' => '電', 'r' => '雹', 's' => '零', 't' => '靖', 'u' => '靴', 'v' => '靶', 'w' => '預', 'x' => '頑', 'y' => '頓', 'z' => '頊', '{' => '頒', '|' => '頌', '}' => '飼', '~' => '飴', '' => '飽', '' => '飾', '' => '馳', '' => '馱', '' => '馴', '' => '髡', '' => '鳩', '' => '麂', '' => '鼎', '' => '鼓', '' => '鼠', '' => '僧', '' => '僮', '' => '僥', '' => '僖', '' => '僭', '' => '僚', '' => '僕', '' => '像', '' => '僑', '' => '僱', '' => '僎', '' => '僩', '' => '兢', '' => '凳', '' => '劃', '' => '劂', '' => '匱', '' => '厭', '' => '嗾', '' => '嘀', '' => '嘛', '' => '嘗', '' => '嗽', '' => '嘔', '' => '嘆', '' => '嘉', '' => '嘍', '' => '嘎', '' => '嗷', '' => '嘖', '' => '嘟', '' => '嘈', '' => '嘐', '' => '嗶', '' => '團', '' => '圖', '' => '塵', '' => '塾', '' => '境', '' => '墓', '' => '墊', '' => '塹', '' => '墅', '' => '塽', '' => '壽', '' => '夥', '' => '夢', '' => '夤', '' => '奪', '' => '奩', '' => '嫡', '' => '嫦', '' => '嫩', '' => '嫗', '' => '嫖', '' => '嫘', '' => '嫣', '' => '孵', '' => '寞', '' => '寧', '' => '寡', '' => '寥', '' => '實', '' => '寨', '' => '寢', '' => '寤', '' => '察', '' => '對', '' => '屢', '' => '嶄', '' => '嶇', '' => '幛', '' => '幣', '' => '幕', '' => '幗', '' => '幔', '' => '廓', '' => '廖', '' => '弊', '' => '彆', '' => '彰', '' => '徹', '' => '慇', '@' => '愿', 'A' => '態', 'B' => '慷', 'C' => '慢', 'D' => '慣', 'E' => '慟', 'F' => '慚', 'G' => '慘', 'H' => '慵', 'I' => '截', 'J' => '撇', 'K' => '摘', 'L' => '摔', 'M' => '撤', 'N' => '摸', 'O' => '摟', 'P' => '摺', 'Q' => '摑', 'R' => '摧', 'S' => '搴', 'T' => '摭', 'U' => '摻', 'V' => '敲', 'W' => '斡', 'X' => '旗', 'Y' => '旖', 'Z' => '暢', '[' => '暨', '\\' => '暝', ']' => '榜', '^' => '榨', '_' => '榕', '`' => '槁', 'a' => '榮', 'b' => '槓', 'c' => '構', 'd' => '榛', 'e' => '榷', 'f' => '榻', 'g' => '榫', 'h' => '榴', 'i' => '槐', 'j' => '槍', 'k' => '榭', 'l' => '槌', 'm' => '榦', 'n' => '槃', 'o' => '榣', 'p' => '歉', 'q' => '歌', 'r' => '氳', 's' => '漳', 't' => '演', 'u' => '滾', 'v' => '漓', 'w' => '滴', 'x' => '漩', 'y' => '漾', 'z' => '漠', '{' => '漬', '|' => '漏', '}' => '漂', '~' => '漢', '' => '滿', '' => '滯', '' => '漆', '' => '漱', '' => '漸', '' => '漲', '' => '漣', '' => '漕', '' => '漫', '' => '漯', '' => '澈', '' => '漪', '' => '滬', '' => '漁', '' => '滲', '' => '滌', '' => '滷', '' => '熔', '' => '熙', '' => '煽', '' => '熊', '' => '熄', '' => '熒', '' => '爾', '' => '犒', '' => '犖', '' => '獄', '' => '獐', '' => '瑤', '' => '瑣', '' => '瑪', '' => '瑰', '' => '瑭', '' => '甄', '' => '疑', '' => '瘧', '' => '瘍', '' => '瘋', '' => '瘉', '' => '瘓', '' => '盡', '' => '監', '' => '瞄', '' => '睽', '' => '睿', '' => '睡', '' => '磁', '' => '碟', '' => '碧', '' => '碳', '' => '碩', '' => '碣', '' => '禎', '' => '福', '' => '禍', '' => '種', '' => '稱', '' => '窪', '' => '窩', '' => '竭', '' => '端', '' => '管', '' => '箕', '' => '箋', '' => '筵', '' => '算', '' => '箝', '' => '箔', '' => '箏', '' => '箸', '' => '箇', '' => '箄', '' => '粹', '' => '粽', '' => '精', '' => '綻', '' => '綰', '' => '綜', '' => '綽', '' => '綾', '' => '綠', '' => '緊', '' => '綴', '' => '網', '' => '綱', '' => '綺', '' => '綢', '' => '綿', '' => '綵', '' => '綸', '' => '維', '' => '緒', '' => '緇', '' => '綬', '@' => '罰', 'A' => '翠', 'B' => '翡', 'C' => '翟', 'D' => '聞', 'E' => '聚', 'F' => '肇', 'G' => '腐', 'H' => '膀', 'I' => '膏', 'J' => '膈', 'K' => '膊', 'L' => '腿', 'M' => '膂', 'N' => '臧', 'O' => '臺', 'P' => '與', 'Q' => '舔', 'R' => '舞', 'S' => '艋', 'T' => '蓉', 'U' => '蒿', 'V' => '蓆', 'W' => '蓄', 'X' => '蒙', 'Y' => '蒞', 'Z' => '蒲', '[' => '蒜', '\\' => '蓋', ']' => '蒸', '^' => '蓀', '_' => '蓓', '`' => '蒐', 'a' => '蒼', 'b' => '蓑', 'c' => '蓊', 'd' => '蜿', 'e' => '蜜', 'f' => '蜻', 'g' => '蜢', 'h' => '蜥', 'i' => '蜴', 'j' => '蜘', 'k' => '蝕', 'l' => '蜷', 'm' => '蜩', 'n' => '裳', 'o' => '褂', 'p' => '裴', 'q' => '裹', 'r' => '裸', 's' => '製', 't' => '裨', 'u' => '褚', 'v' => '裯', 'w' => '誦', 'x' => '誌', 'y' => '語', 'z' => '誣', '{' => '認', '|' => '誡', '}' => '誓', '~' => '誤', '' => '說', '' => '誥', '' => '誨', '' => '誘', '' => '誑', '' => '誚', '' => '誧', '' => '豪', '' => '貍', '' => '貌', '' => '賓', '' => '賑', '' => '賒', '' => '赫', '' => '趙', '' => '趕', '' => '跼', '' => '輔', '' => '輒', '' => '輕', '' => '輓', '' => '辣', '' => '遠', '' => '遘', '' => '遜', '' => '遣', '' => '遙', '' => '遞', '' => '遢', '' => '遝', '' => '遛', '' => '鄙', '' => '鄘', '' => '鄞', '' => '酵', '' => '酸', '' => '酷', '' => '酴', '' => '鉸', '' => '銀', '' => '銅', '' => '銘', '' => '銖', '' => '鉻', '' => '銓', '' => '銜', '' => '銨', '' => '鉼', '' => '銑', '' => '閡', '' => '閨', '' => '閩', '' => '閣', '' => '閥', '' => '閤', '' => '隙', '' => '障', '' => '際', '' => '雌', '' => '雒', '' => '需', '' => '靼', '' => '鞅', '' => '韶', '' => '頗', '' => '領', '' => '颯', '' => '颱', '' => '餃', '' => '餅', '' => '餌', '' => '餉', '' => '駁', '' => '骯', '' => '骰', '' => '髦', '' => '魁', '' => '魂', '' => '鳴', '' => '鳶', '' => '鳳', '' => '麼', '' => '鼻', '' => '齊', '' => '億', '' => '儀', '' => '僻', '' => '僵', '' => '價', '' => '儂', '' => '儈', '' => '儉', '' => '儅', '' => '凜', '@' => '劇', 'A' => '劈', 'B' => '劉', 'C' => '劍', 'D' => '劊', 'E' => '勰', 'F' => '厲', 'G' => '嘮', 'H' => '嘻', 'I' => '嘹', 'J' => '嘲', 'K' => '嘿', 'L' => '嘴', 'M' => '嘩', 'N' => '噓', 'O' => '噎', 'P' => '噗', 'Q' => '噴', 'R' => '嘶', 'S' => '嘯', 'T' => '嘰', 'U' => '墀', 'V' => '墟', 'W' => '增', 'X' => '墳', 'Y' => '墜', 'Z' => '墮', '[' => '墩', '\\' => '墦', ']' => '奭', '^' => '嬉', '_' => '嫻', '`' => '嬋', 'a' => '嫵', 'b' => '嬌', 'c' => '嬈', 'd' => '寮', 'e' => '寬', 'f' => '審', 'g' => '寫', 'h' => '層', 'i' => '履', 'j' => '嶝', 'k' => '嶔', 'l' => '幢', 'm' => '幟', 'n' => '幡', 'o' => '廢', 'p' => '廚', 'q' => '廟', 'r' => '廝', 's' => '廣', 't' => '廠', 'u' => '彈', 'v' => '影', 'w' => '德', 'x' => '徵', 'y' => '慶', 'z' => '慧', '{' => '慮', '|' => '慝', '}' => '慕', '~' => '憂', '' => '慼', '' => '慰', '' => '慫', '' => '慾', '' => '憧', '' => '憐', '' => '憫', '' => '憎', '' => '憬', '' => '憚', '' => '憤', '' => '憔', '' => '憮', '' => '戮', '' => '摩', '' => '摯', '' => '摹', '' => '撞', '' => '撲', '' => '撈', '' => '撐', '' => '撰', '' => '撥', '' => '撓', '' => '撕', '' => '撩', '' => '撒', '' => '撮', '' => '播', '' => '撫', '' => '撚', '' => '撬', '' => '撙', '' => '撢', '' => '撳', '' => '敵', '' => '敷', '' => '數', '' => '暮', '' => '暫', '' => '暴', '' => '暱', '' => '樣', '' => '樟', '' => '槨', '' => '樁', '' => '樞', '' => '標', '' => '槽', '' => '模', '' => '樓', '' => '樊', '' => '槳', '' => '樂', '' => '樅', '' => '槭', '' => '樑', '' => '歐', '' => '歎', '' => '殤', '' => '毅', '' => '毆', '' => '漿', '' => '潼', '' => '澄', '' => '潑', '' => '潦', '' => '潔', '' => '澆', '' => '潭', '' => '潛', '' => '潸', '' => '潮', '' => '澎', '' => '潺', '' => '潰', '' => '潤', '' => '澗', '' => '潘', '' => '滕', '' => '潯', '' => '潠', '' => '潟', '' => '熟', '' => '熬', '' => '熱', '' => '熨', '' => '牖', '' => '犛', '' => '獎', '' => '獗', '' => '瑩', '' => '璋', '' => '璃', '@' => '瑾', 'A' => '璀', 'B' => '畿', 'C' => '瘠', 'D' => '瘩', 'E' => '瘟', 'F' => '瘤', 'G' => '瘦', 'H' => '瘡', 'I' => '瘢', 'J' => '皚', 'K' => '皺', 'L' => '盤', 'M' => '瞎', 'N' => '瞇', 'O' => '瞌', 'P' => '瞑', 'Q' => '瞋', 'R' => '磋', 'S' => '磅', 'T' => '確', 'U' => '磊', 'V' => '碾', 'W' => '磕', 'X' => '碼', 'Y' => '磐', 'Z' => '稿', '[' => '稼', '\\' => '穀', ']' => '稽', '^' => '稷', '_' => '稻', '`' => '窯', 'a' => '窮', 'b' => '箭', 'c' => '箱', 'd' => '範', 'e' => '箴', 'f' => '篆', 'g' => '篇', 'h' => '篁', 'i' => '箠', 'j' => '篌', 'k' => '糊', 'l' => '締', 'm' => '練', 'n' => '緯', 'o' => '緻', 'p' => '緘', 'q' => '緬', 'r' => '緝', 's' => '編', 't' => '緣', 'u' => '線', 'v' => '緞', 'w' => '緩', 'x' => '綞', 'y' => '緙', 'z' => '緲', '{' => '緹', '|' => '罵', '}' => '罷', '~' => '羯', '' => '翩', '' => '耦', '' => '膛', '' => '膜', '' => '膝', '' => '膠', '' => '膚', '' => '膘', '' => '蔗', '' => '蔽', '' => '蔚', '' => '蓮', '' => '蔬', '' => '蔭', '' => '蔓', '' => '蔑', '' => '蔣', '' => '蔡', '' => '蔔', '' => '蓬', '' => '蔥', '' => '蓿', '' => '蔆', '' => '螂', '' => '蝴', '' => '蝶', '' => '蝠', '' => '蝦', '' => '蝸', '' => '蝨', '' => '蝙', '' => '蝗', '' => '蝌', '' => '蝓', '' => '衛', '' => '衝', '' => '褐', '' => '複', '' => '褒', '' => '褓', '' => '褕', '' => '褊', '' => '誼', '' => '諒', '' => '談', '' => '諄', '' => '誕', '' => '請', '' => '諸', '' => '課', '' => '諉', '' => '諂', '' => '調', '' => '誰', '' => '論', '' => '諍', '' => '誶', '' => '誹', '' => '諛', '' => '豌', '' => '豎', '' => '豬', '' => '賠', '' => '賞', '' => '賦', '' => '賤', '' => '賬', '' => '賭', '' => '賢', '' => '賣', '' => '賜', '' => '質', '' => '賡', '' => '赭', '' => '趟', '' => '趣', '' => '踫', '' => '踐', '' => '踝', '' => '踢', '' => '踏', '' => '踩', '' => '踟', '' => '踡', '' => '踞', '' => '躺', '' => '輝', '' => '輛', '' => '輟', '' => '輩', '' => '輦', '' => '輪', '' => '輜', '' => '輞', '@' => '輥', 'A' => '適', 'B' => '遮', 'C' => '遨', 'D' => '遭', 'E' => '遷', 'F' => '鄰', 'G' => '鄭', 'H' => '鄧', 'I' => '鄱', 'J' => '醇', 'K' => '醉', 'L' => '醋', 'M' => '醃', 'N' => '鋅', 'O' => '銻', 'P' => '銷', 'Q' => '鋪', 'R' => '銬', 'S' => '鋤', 'T' => '鋁', 'U' => '銳', 'V' => '銼', 'W' => '鋒', 'X' => '鋇', 'Y' => '鋰', 'Z' => '銲', '[' => '閭', '\\' => '閱', ']' => '霄', '^' => '霆', '_' => '震', '`' => '霉', 'a' => '靠', 'b' => '鞍', 'c' => '鞋', 'd' => '鞏', 'e' => '頡', 'f' => '頫', 'g' => '頜', 'h' => '颳', 'i' => '養', 'j' => '餓', 'k' => '餒', 'l' => '餘', 'm' => '駝', 'n' => '駐', 'o' => '駟', 'p' => '駛', 'q' => '駑', 'r' => '駕', 's' => '駒', 't' => '駙', 'u' => '骷', 'v' => '髮', 'w' => '髯', 'x' => '鬧', 'y' => '魅', 'z' => '魄', '{' => '魷', '|' => '魯', '}' => '鴆', '~' => '鴉', '' => '鴃', '' => '麩', '' => '麾', '' => '黎', '' => '墨', '' => '齒', '' => '儒', '' => '儘', '' => '儔', '' => '儐', '' => '儕', '' => '冀', '' => '冪', '' => '凝', '' => '劑', '' => '劓', '' => '勳', '' => '噙', '' => '噫', '' => '噹', '' => '噩', '' => '噤', '' => '噸', '' => '噪', '' => '器', '' => '噥', '' => '噱', '' => '噯', '' => '噬', '' => '噢', '' => '噶', '' => '壁', '' => '墾', '' => '壇', '' => '壅', '' => '奮', '' => '嬝', '' => '嬴', '' => '學', '' => '寰', '' => '導', '' => '彊', '' => '憲', '' => '憑', '' => '憩', '' => '憊', '' => '懍', '' => '憶', '' => '憾', '' => '懊', '' => '懈', '' => '戰', '' => '擅', '' => '擁', '' => '擋', '' => '撻', '' => '撼', '' => '據', '' => '擄', '' => '擇', '' => '擂', '' => '操', '' => '撿', '' => '擒', '' => '擔', '' => '撾', '' => '整', '' => '曆', '' => '曉', '' => '暹', '' => '曄', '' => '曇', '' => '暸', '' => '樽', '' => '樸', '' => '樺', '' => '橙', '' => '橫', '' => '橘', '' => '樹', '' => '橄', '' => '橢', '' => '橡', '' => '橋', '' => '橇', '' => '樵', '' => '機', '' => '橈', '' => '歙', '' => '歷', '' => '氅', '' => '濂', '' => '澱', '' => '澡', '@' => '濃', 'A' => '澤', 'B' => '濁', 'C' => '澧', 'D' => '澳', 'E' => '激', 'F' => '澹', 'G' => '澶', 'H' => '澦', 'I' => '澠', 'J' => '澴', 'K' => '熾', 'L' => '燉', 'M' => '燐', 'N' => '燒', 'O' => '燈', 'P' => '燕', 'Q' => '熹', 'R' => '燎', 'S' => '燙', 'T' => '燜', 'U' => '燃', 'V' => '燄', 'W' => '獨', 'X' => '璜', 'Y' => '璣', 'Z' => '璘', '[' => '璟', '\\' => '璞', ']' => '瓢', '^' => '甌', '_' => '甍', '`' => '瘴', 'a' => '瘸', 'b' => '瘺', 'c' => '盧', 'd' => '盥', 'e' => '瞠', 'f' => '瞞', 'g' => '瞟', 'h' => '瞥', 'i' => '磨', 'j' => '磚', 'k' => '磬', 'l' => '磧', 'm' => '禦', 'n' => '積', 'o' => '穎', 'p' => '穆', 'q' => '穌', 'r' => '穋', 's' => '窺', 't' => '篙', 'u' => '簑', 'v' => '築', 'w' => '篤', 'x' => '篛', 'y' => '篡', 'z' => '篩', '{' => '篦', '|' => '糕', '}' => '糖', '~' => '縊', '' => '縑', '' => '縈', '' => '縛', '' => '縣', '' => '縞', '' => '縝', '' => '縉', '' => '縐', '' => '罹', '' => '羲', '' => '翰', '' => '翱', '' => '翮', '' => '耨', '' => '膳', '' => '膩', '' => '膨', '' => '臻', '' => '興', '' => '艘', '' => '艙', '' => '蕊', '' => '蕙', '' => '蕈', '' => '蕨', '' => '蕩', '' => '蕃', '' => '蕉', '' => '蕭', '' => '蕪', '' => '蕞', '' => '螃', '' => '螟', '' => '螞', '' => '螢', '' => '融', '' => '衡', '' => '褪', '' => '褲', '' => '褥', '' => '褫', '' => '褡', '' => '親', '' => '覦', '' => '諦', '' => '諺', '' => '諫', '' => '諱', '' => '謀', '' => '諜', '' => '諧', '' => '諮', '' => '諾', '' => '謁', '' => '謂', '' => '諷', '' => '諭', '' => '諳', '' => '諶', '' => '諼', '' => '豫', '' => '豭', '' => '貓', '' => '賴', '' => '蹄', '' => '踱', '' => '踴', '' => '蹂', '' => '踹', '' => '踵', '' => '輻', '' => '輯', '' => '輸', '' => '輳', '' => '辨', '' => '辦', '' => '遵', '' => '遴', '' => '選', '' => '遲', '' => '遼', '' => '遺', '' => '鄴', '' => '醒', '' => '錠', '' => '錶', '' => '鋸', '' => '錳', '' => '錯', '' => '錢', '' => '鋼', '' => '錫', '' => '錄', '' => '錚', '@' => '錐', 'A' => '錦', 'B' => '錡', 'C' => '錕', 'D' => '錮', 'E' => '錙', 'F' => '閻', 'G' => '隧', 'H' => '隨', 'I' => '險', 'J' => '雕', 'K' => '霎', 'L' => '霑', 'M' => '霖', 'N' => '霍', 'O' => '霓', 'P' => '霏', 'Q' => '靛', 'R' => '靜', 'S' => '靦', 'T' => '鞘', 'U' => '頰', 'V' => '頸', 'W' => '頻', 'X' => '頷', 'Y' => '頭', 'Z' => '頹', '[' => '頤', '\\' => '餐', ']' => '館', '^' => '餞', '_' => '餛', '`' => '餡', 'a' => '餚', 'b' => '駭', 'c' => '駢', 'd' => '駱', 'e' => '骸', 'f' => '骼', 'g' => '髻', 'h' => '髭', 'i' => '鬨', 'j' => '鮑', 'k' => '鴕', 'l' => '鴣', 'm' => '鴦', 'n' => '鴨', 'o' => '鴒', 'p' => '鴛', 'q' => '默', 'r' => '黔', 's' => '龍', 't' => '龜', 'u' => '優', 'v' => '償', 'w' => '儡', 'x' => '儲', 'y' => '勵', 'z' => '嚎', '{' => '嚀', '|' => '嚐', '}' => '嚅', '~' => '嚇', '' => '嚏', '' => '壕', '' => '壓', '' => '壑', '' => '壎', '' => '嬰', '' => '嬪', '' => '嬤', '' => '孺', '' => '尷', '' => '屨', '' => '嶼', '' => '嶺', '' => '嶽', '' => '嶸', '' => '幫', '' => '彌', '' => '徽', '' => '應', '' => '懂', '' => '懇', '' => '懦', '' => '懋', '' => '戲', '' => '戴', '' => '擎', '' => '擊', '' => '擘', '' => '擠', '' => '擰', '' => '擦', '' => '擬', '' => '擱', '' => '擢', '' => '擭', '' => '斂', '' => '斃', '' => '曙', '' => '曖', '' => '檀', '' => '檔', '' => '檄', '' => '檢', '' => '檜', '' => '櫛', '' => '檣', '' => '橾', '' => '檗', '' => '檐', '' => '檠', '' => '歜', '' => '殮', '' => '毚', '' => '氈', '' => '濘', '' => '濱', '' => '濟', '' => '濠', '' => '濛', '' => '濤', '' => '濫', '' => '濯', '' => '澀', '' => '濬', '' => '濡', '' => '濩', '' => '濕', '' => '濮', '' => '濰', '' => '燧', '' => '營', '' => '燮', '' => '燦', '' => '燥', '' => '燭', '' => '燬', '' => '燴', '' => '燠', '' => '爵', '' => '牆', '' => '獰', '' => '獲', '' => '璩', '' => '環', '' => '璦', '' => '璨', '' => '癆', '' => '療', '' => '癌', '' => '盪', '' => '瞳', '' => '瞪', '' => '瞰', '' => '瞬', '@' => '瞧', 'A' => '瞭', 'B' => '矯', 'C' => '磷', 'D' => '磺', 'E' => '磴', 'F' => '磯', 'G' => '礁', 'H' => '禧', 'I' => '禪', 'J' => '穗', 'K' => '窿', 'L' => '簇', 'M' => '簍', 'N' => '篾', 'O' => '篷', 'P' => '簌', 'Q' => '篠', 'R' => '糠', 'S' => '糜', 'T' => '糞', 'U' => '糢', 'V' => '糟', 'W' => '糙', 'X' => '糝', 'Y' => '縮', 'Z' => '績', '[' => '繆', '\\' => '縷', ']' => '縲', '^' => '繃', '_' => '縫', '`' => '總', 'a' => '縱', 'b' => '繅', 'c' => '繁', 'd' => '縴', 'e' => '縹', 'f' => '繈', 'g' => '縵', 'h' => '縿', 'i' => '縯', 'j' => '罄', 'k' => '翳', 'l' => '翼', 'm' => '聱', 'n' => '聲', 'o' => '聰', 'p' => '聯', 'q' => '聳', 'r' => '臆', 's' => '臃', 't' => '膺', 'u' => '臂', 'v' => '臀', 'w' => '膿', 'x' => '膽', 'y' => '臉', 'z' => '膾', '{' => '臨', '|' => '舉', '}' => '艱', '~' => '薪', '' => '薄', '' => '蕾', '' => '薜', '' => '薑', '' => '薔', '' => '薯', '' => '薛', '' => '薇', '' => '薨', '' => '薊', '' => '虧', '' => '蟀', '' => '蟑', '' => '螳', '' => '蟒', '' => '蟆', '' => '螫', '' => '螻', '' => '螺', '' => '蟈', '' => '蟋', '' => '褻', '' => '褶', '' => '襄', '' => '褸', '' => '褽', '' => '覬', '' => '謎', '' => '謗', '' => '謙', '' => '講', '' => '謊', '' => '謠', '' => '謝', '' => '謄', '' => '謐', '' => '豁', '' => '谿', '' => '豳', '' => '賺', '' => '賽', '' => '購', '' => '賸', '' => '賻', '' => '趨', '' => '蹉', '' => '蹋', '' => '蹈', '' => '蹊', '' => '轄', '' => '輾', '' => '轂', '' => '轅', '' => '輿', '' => '避', '' => '遽', '' => '還', '' => '邁', '' => '邂', '' => '邀', '' => '鄹', '' => '醣', '' => '醞', '' => '醜', '' => '鍍', '' => '鎂', '' => '錨', '' => '鍵', '' => '鍊', '' => '鍥', '' => '鍋', '' => '錘', '' => '鍾', '' => '鍬', '' => '鍛', '' => '鍰', '' => '鍚', '' => '鍔', '' => '闊', '' => '闋', '' => '闌', '' => '闈', '' => '闆', '' => '隱', '' => '隸', '' => '雖', '' => '霜', '' => '霞', '' => '鞠', '' => '韓', '' => '顆', '' => '颶', '' => '餵', '' => '騁', '@' => '駿', 'A' => '鮮', 'B' => '鮫', 'C' => '鮪', 'D' => '鮭', 'E' => '鴻', 'F' => '鴿', 'G' => '麋', 'H' => '黏', 'I' => '點', 'J' => '黜', 'K' => '黝', 'L' => '黛', 'M' => '鼾', 'N' => '齋', 'O' => '叢', 'P' => '嚕', 'Q' => '嚮', 'R' => '壙', 'S' => '壘', 'T' => '嬸', 'U' => '彝', 'V' => '懣', 'W' => '戳', 'X' => '擴', 'Y' => '擲', 'Z' => '擾', '[' => '攆', '\\' => '擺', ']' => '擻', '^' => '擷', '_' => '斷', '`' => '曜', 'a' => '朦', 'b' => '檳', 'c' => '檬', 'd' => '櫃', 'e' => '檻', 'f' => '檸', 'g' => '櫂', 'h' => '檮', 'i' => '檯', 'j' => '歟', 'k' => '歸', 'l' => '殯', 'm' => '瀉', 'n' => '瀋', 'o' => '濾', 'p' => '瀆', 'q' => '濺', 'r' => '瀑', 's' => '瀏', 't' => '燻', 'u' => '燼', 'v' => '燾', 'w' => '燸', 'x' => '獷', 'y' => '獵', 'z' => '璧', '{' => '璿', '|' => '甕', '}' => '癖', '~' => '癘', '¡' => '癒', '¢' => '瞽', '£' => '瞿', '¤' => '瞻', '¥' => '瞼', '¦' => '礎', '§' => '禮', '¨' => '穡', '©' => '穢', 'ª' => '穠', '«' => '竄', '¬' => '竅', '­' => '簫', '®' => '簧', '¯' => '簪', '°' => '簞', '±' => '簣', '²' => '簡', '³' => '糧', '´' => '織', 'µ' => '繕', '¶' => '繞', '·' => '繚', '¸' => '繡', '¹' => '繒', 'º' => '繙', '»' => '罈', '¼' => '翹', '½' => '翻', '¾' => '職', '¿' => '聶', '' => '臍', '' => '臏', '' => '舊', '' => '藏', '' => '薩', '' => '藍', '' => '藐', '' => '藉', '' => '薰', '' => '薺', '' => '薹', '' => '薦', '' => '蟯', '' => '蟬', '' => '蟲', '' => '蟠', '' => '覆', '' => '覲', '' => '觴', '' => '謨', '' => '謹', '' => '謬', '' => '謫', '' => '豐', '' => '贅', '' => '蹙', '' => '蹣', '' => '蹦', '' => '蹤', '' => '蹟', '' => '蹕', '' => '軀', '' => '轉', '' => '轍', '' => '邇', '' => '邃', '' => '邈', '' => '醫', '' => '醬', '' => '釐', '' => '鎔', '' => '鎊', '' => '鎖', '' => '鎢', '' => '鎳', '' => '鎮', '' => '鎬', '' => '鎰', '' => '鎘', '' => '鎚', '' => '鎗', '' => '闔', '' => '闖', '' => '闐', '' => '闕', '' => '離', '' => '雜', '' => '雙', '' => '雛', '' => '雞', '' => '霤', '' => '鞣', '' => '鞦', '@' => '鞭', 'A' => '韹', 'B' => '額', 'C' => '顏', 'D' => '題', 'E' => '顎', 'F' => '顓', 'G' => '颺', 'H' => '餾', 'I' => '餿', 'J' => '餽', 'K' => '餮', 'L' => '馥', 'M' => '騎', 'N' => '髁', 'O' => '鬃', 'P' => '鬆', 'Q' => '魏', 'R' => '魎', 'S' => '魍', 'T' => '鯊', 'U' => '鯉', 'V' => '鯽', 'W' => '鯈', 'X' => '鯀', 'Y' => '鵑', 'Z' => '鵝', '[' => '鵠', '\\' => '黠', ']' => '鼕', '^' => '鼬', '_' => '儳', '`' => '嚥', 'a' => '壞', 'b' => '壟', 'c' => '壢', 'd' => '寵', 'e' => '龐', 'f' => '廬', 'g' => '懲', 'h' => '懷', 'i' => '懶', 'j' => '懵', 'k' => '攀', 'l' => '攏', 'm' => '曠', 'n' => '曝', 'o' => '櫥', 'p' => '櫝', 'q' => '櫚', 'r' => '櫓', 's' => '瀛', 't' => '瀟', 'u' => '瀨', 'v' => '瀚', 'w' => '瀝', 'x' => '瀕', 'y' => '瀘', 'z' => '爆', '{' => '爍', '|' => '牘', '}' => '犢', '~' => '獸', 'á' => '獺', 'â' => '璽', 'ã' => '瓊', 'ä' => '瓣', 'å' => '疇', 'æ' => '疆', 'ç' => '癟', 'è' => '癡', 'é' => '矇', 'ê' => '礙', 'ë' => '禱', 'ì' => '穫', 'í' => '穩', 'î' => '簾', 'ï' => '簿', 'ð' => '簸', 'ñ' => '簽', 'ò' => '簷', 'ó' => '籀', 'ô' => '繫', 'õ' => '繭', 'ö' => '繹', '÷' => '繩', 'ø' => '繪', 'ù' => '羅', 'ú' => '繳', 'û' => '羶', 'ü' => '羹', 'ý' => '羸', 'þ' => '臘', 'ÿ' => '藩', '' => '藝', '' => '藪', '' => '藕', '' => '藤', '' => '藥', '' => '藷', '' => '蟻', '' => '蠅', '' => '蠍', '' => '蟹', '' => '蟾', '' => '襠', '' => '襟', '' => '襖', '' => '襞', '' => '譁', '' => '譜', '' => '識', '' => '證', '' => '譚', '' => '譎', '' => '譏', '' => '譆', '' => '譙', '' => '贈', '' => '贊', '' => '蹼', '' => '蹲', '' => '躇', '' => '蹶', '' => '蹬', '' => '蹺', '' => '蹴', '' => '轔', '' => '轎', '' => '辭', '' => '邊', '' => '邋', '' => '醱', '' => '醮', '' => '鏡', '' => '鏑', '' => '鏟', '' => '鏃', '' => '鏈', '' => '鏜', '' => '鏝', '' => '鏖', '' => '鏢', '' => '鏍', '' => '鏘', '' => '鏤', '' => '鏗', '' => '鏨', '' => '關', '' => '隴', '' => '難', '' => '霪', '' => '霧', '' => '靡', '' => '韜', '' => '韻', '' => '類', '@' => '願', 'A' => '顛', 'B' => '颼', 'C' => '饅', 'D' => '饉', 'E' => '騖', 'F' => '騙', 'G' => '鬍', 'H' => '鯨', 'I' => '鯧', 'J' => '鯖', 'K' => '鯛', 'L' => '鶉', 'M' => '鵡', 'N' => '鵲', 'O' => '鵪', 'P' => '鵬', 'Q' => '麒', 'R' => '麗', 'S' => '麓', 'T' => '麴', 'U' => '勸', 'V' => '嚨', 'W' => '嚷', 'X' => '嚶', 'Y' => '嚴', 'Z' => '嚼', '[' => '壤', '\\' => '孀', ']' => '孃', '^' => '孽', '_' => '寶', '`' => '巉', 'a' => '懸', 'b' => '懺', 'c' => '攘', 'd' => '攔', 'e' => '攙', 'f' => '曦', 'g' => '朧', 'h' => '櫬', 'i' => '瀾', 'j' => '瀰', 'k' => '瀲', 'l' => '爐', 'm' => '獻', 'n' => '瓏', 'o' => '癢', 'p' => '癥', 'q' => '礦', 'r' => '礪', 's' => '礬', 't' => '礫', 'u' => '竇', 'v' => '競', 'w' => '籌', 'x' => '籃', 'y' => '籍', 'z' => '糯', '{' => '糰', '|' => '辮', '}' => '繽', '~' => '繼', 'ġ' => '纂', 'Ģ' => '罌', 'ģ' => '耀', 'Ĥ' => '臚', 'ĥ' => '艦', 'Ħ' => '藻', 'ħ' => '藹', 'Ĩ' => '蘑', 'ĩ' => '藺', 'Ī' => '蘆', 'ī' => '蘋', 'Ĭ' => '蘇', 'ĭ' => '蘊', 'Į' => '蠔', 'į' => '蠕', 'İ' => '襤', 'ı' => '覺', 'IJ' => '觸', 'ij' => '議', 'Ĵ' => '譬', 'ĵ' => '警', 'Ķ' => '譯', 'ķ' => '譟', 'ĸ' => '譫', 'Ĺ' => '贏', 'ĺ' => '贍', 'Ļ' => '躉', 'ļ' => '躁', 'Ľ' => '躅', 'ľ' => '躂', 'Ŀ' => '醴', '' => '釋', '' => '鐘', '' => '鐃', '' => '鏽', '' => '闡', '' => '霰', '' => '飄', '' => '饒', '' => '饑', '' => '馨', '' => '騫', '' => '騰', '' => '騷', '' => '騵', '' => '鰓', '' => '鰍', '' => '鹹', '' => '麵', '' => '黨', '' => '鼯', '' => '齟', '' => '齣', '' => '齡', '' => '儷', '' => '儸', '' => '囁', '' => '囀', '' => '囂', '' => '夔', '' => '屬', '' => '巍', '' => '懼', '' => '懾', '' => '攝', '' => '攜', '' => '斕', '' => '曩', '' => '櫻', '' => '欄', '' => '櫺', '' => '殲', '' => '灌', '' => '爛', '' => '犧', '' => '瓖', '' => '瓔', '' => '癩', '' => '矓', '' => '籐', '' => '纏', '' => '續', '' => '羼', '' => '蘗', '' => '蘭', '' => '蘚', '' => '蠣', '' => '蠢', '' => '蠡', '' => '蠟', '' => '襪', '' => '襬', '' => '覽', '' => '譴', '@' => '護', 'A' => '譽', 'B' => '贓', 'C' => '躊', 'D' => '躍', 'E' => '躋', 'F' => '轟', 'G' => '辯', 'H' => '醺', 'I' => '鐮', 'J' => '鐳', 'K' => '鐵', 'L' => '鐺', 'M' => '鐸', 'N' => '鐲', 'O' => '鐫', 'P' => '闢', 'Q' => '霸', 'R' => '霹', 'S' => '露', 'T' => '響', 'U' => '顧', 'V' => '顥', 'W' => '饗', 'X' => '驅', 'Y' => '驃', 'Z' => '驀', '[' => '騾', '\\' => '髏', ']' => '魔', '^' => '魑', '_' => '鰭', '`' => '鰥', 'a' => '鶯', 'b' => '鶴', 'c' => '鷂', 'd' => '鶸', 'e' => '麝', 'f' => '黯', 'g' => '鼙', 'h' => '齜', 'i' => '齦', 'j' => '齧', 'k' => '儼', 'l' => '儻', 'm' => '囈', 'n' => '囊', 'o' => '囉', 'p' => '孿', 'q' => '巔', 'r' => '巒', 's' => '彎', 't' => '懿', 'u' => '攤', 'v' => '權', 'w' => '歡', 'x' => '灑', 'y' => '灘', 'z' => '玀', '{' => '瓤', '|' => '疊', '}' => '癮', '~' => '癬', 'š' => '禳', 'Ţ' => '籠', 'ţ' => '籟', 'Ť' => '聾', 'ť' => '聽', 'Ŧ' => '臟', 'ŧ' => '襲', 'Ũ' => '襯', 'ũ' => '觼', 'Ū' => '讀', 'ū' => '贖', 'Ŭ' => '贗', 'ŭ' => '躑', 'Ů' => '躓', 'ů' => '轡', 'Ű' => '酈', 'ű' => '鑄', 'Ų' => '鑑', 'ų' => '鑒', 'Ŵ' => '霽', 'ŵ' => '霾', 'Ŷ' => '韃', 'ŷ' => '韁', 'Ÿ' => '顫', 'Ź' => '饕', 'ź' => '驕', 'Ż' => '驍', 'ż' => '髒', 'Ž' => '鬚', 'ž' => '鱉', 'ſ' => '鰱', '' => '鰾', '' => '鰻', '' => '鷓', '' => '鷗', '' => '鼴', '' => '齬', '' => '齪', '' => '龔', '' => '囌', '' => '巖', '' => '戀', '' => '攣', '' => '攫', '' => '攪', '' => '曬', '' => '欐', '' => '瓚', '' => '竊', '' => '籤', '' => '籣', '' => '籥', '' => '纓', '' => '纖', '' => '纔', '' => '臢', '' => '蘸', '' => '蘿', '' => '蠱', '' => '變', '' => '邐', '' => '邏', '' => '鑣', '' => '鑠', '' => '鑤', '' => '靨', '' => '顯', '' => '饜', '' => '驚', '' => '驛', '' => '驗', '' => '髓', '' => '體', '' => '髑', '' => '鱔', '' => '鱗', '' => '鱖', '' => '鷥', '' => '麟', '' => '黴', '' => '囑', '' => '壩', '' => '攬', '' => '灞', '' => '癱', '' => '癲', '' => '矗', '' => '罐', '' => '羈', '' => '蠶', '' => '蠹', '' => '衢', '' => '讓', '' => '讒', '@' => '讖', 'A' => '艷', 'B' => '贛', 'C' => '釀', 'D' => '鑪', 'E' => '靂', 'F' => '靈', 'G' => '靄', 'H' => '韆', 'I' => '顰', 'J' => '驟', 'K' => '鬢', 'L' => '魘', 'M' => '鱟', 'N' => '鷹', 'O' => '鷺', 'P' => '鹼', 'Q' => '鹽', 'R' => '鼇', 'S' => '齷', 'T' => '齲', 'U' => '廳', 'V' => '欖', 'W' => '灣', 'X' => '籬', 'Y' => '籮', 'Z' => '蠻', '[' => '觀', '\\' => '躡', ']' => '釁', '^' => '鑲', '_' => '鑰', '`' => '顱', 'a' => '饞', 'b' => '髖', 'c' => '鬣', 'd' => '黌', 'e' => '灤', 'f' => '矚', 'g' => '讚', 'h' => '鑷', 'i' => '韉', 'j' => '驢', 'k' => '驥', 'l' => '纜', 'm' => '讜', 'n' => '躪', 'o' => '釅', 'p' => '鑽', 'q' => '鑾', 'r' => '鑼', 's' => '鱷', 't' => '鱸', 'u' => '黷', 'v' => '豔', 'w' => '鑿', 'x' => '鸚', 'y' => '爨', 'z' => '驪', '{' => '鬱', '|' => '鸛', '}' => '鸞', '~' => '籲', '@' => '乂', 'A' => '乜', 'B' => '凵', 'C' => '匚', 'D' => '厂', 'E' => '万', 'F' => '丌', 'G' => '乇', 'H' => '亍', 'I' => '囗', 'J' => '兀', 'K' => '屮', 'L' => '彳', 'M' => '丏', 'N' => '冇', 'O' => '与', 'P' => '丮', 'Q' => '亓', 'R' => '仂', 'S' => '仉', 'T' => '仈', 'U' => '冘', 'V' => '勼', 'W' => '卬', 'X' => '厹', 'Y' => '圠', 'Z' => '夃', '[' => '夬', '\\' => '尐', ']' => '巿', '^' => '旡', '_' => '殳', '`' => '毌', 'a' => '气', 'b' => '爿', 'c' => '丱', 'd' => '丼', 'e' => '仨', 'f' => '仜', 'g' => '仩', 'h' => '仡', 'i' => '仝', 'j' => '仚', 'k' => '刌', 'l' => '匜', 'm' => '卌', 'n' => '圢', 'o' => '圣', 'p' => '夗', 'q' => '夯', 'r' => '宁', 's' => '宄', 't' => '尒', 'u' => '尻', 'v' => '屴', 'w' => '屳', 'x' => '帄', 'y' => '庀', 'z' => '庂', '{' => '忉', '|' => '戉', '}' => '扐', '~' => '氕', 'ɡ' => '氶', 'ɢ' => '汃', 'ɣ' => '氿', 'ɤ' => '氻', 'ɥ' => '犮', 'ɦ' => '犰', 'ɧ' => '玊', 'ɨ' => '禸', 'ɩ' => '肊', 'ɪ' => '阞', 'ɫ' => '伎', 'ɬ' => '优', 'ɭ' => '伬', 'ɮ' => '仵', 'ɯ' => '伔', 'ɰ' => '仱', 'ɱ' => '伀', 'ɲ' => '价', 'ɳ' => '伈', 'ɴ' => '伝', 'ɵ' => '伂', 'ɶ' => '伅', 'ɷ' => '伢', 'ɸ' => '伓', 'ɹ' => '伄', 'ɺ' => '仴', 'ɻ' => '伒', 'ɼ' => '冱', 'ɽ' => '刓', 'ɾ' => '刉', 'ɿ' => '刐', '' => '劦', '' => '匢', '' => '匟', '' => '卍', '' => '厊', '' => '吇', '' => '囡', '' => '囟', '' => '圮', '' => '圪', '' => '圴', '' => '夼', '' => '妀', '' => '奼', '' => '妅', '' => '奻', '' => '奾', '' => '奷', '' => '奿', '' => '孖', '' => '尕', '' => '尥', '' => '屼', '' => '屺', '' => '屻', '' => '屾', '' => '巟', '' => '幵', '' => '庄', '' => '异', '' => '弚', '' => '彴', '' => '忕', '' => '忔', '' => '忏', '' => '扜', '' => '扞', '' => '扤', '' => '扡', '' => '扦', '' => '扢', '' => '扙', '' => '扠', '' => '扚', '' => '扥', '' => '旯', '' => '旮', '' => '朾', '' => '朹', '' => '朸', '' => '朻', '' => '机', '' => '朿', '' => '朼', '' => '朳', '' => '氘', '' => '汆', '' => '汒', '' => '汜', '' => '汏', '' => '汊', '' => '汔', '' => '汋', '@' => '汌', 'A' => '灱', 'B' => '牞', 'C' => '犴', 'D' => '犵', 'E' => '玎', 'F' => '甪', 'G' => '癿', 'H' => '穵', 'I' => '网', 'J' => '艸', 'K' => '艼', 'L' => '芀', 'M' => '艽', 'N' => '艿', 'O' => '虍', 'P' => '襾', 'Q' => '邙', 'R' => '邗', 'S' => '邘', 'T' => '邛', 'U' => '邔', 'V' => '阢', 'W' => '阤', 'X' => '阠', 'Y' => '阣', 'Z' => '佖', '[' => '伻', '\\' => '佢', ']' => '佉', '^' => '体', '_' => '佤', '`' => '伾', 'a' => '佧', 'b' => '佒', 'c' => '佟', 'd' => '佁', 'e' => '佘', 'f' => '伭', 'g' => '伳', 'h' => '伿', 'i' => '佡', 'j' => '冏', 'k' => '冹', 'l' => '刜', 'm' => '刞', 'n' => '刡', 'o' => '劭', 'p' => '劮', 'q' => '匉', 'r' => '卣', 's' => '卲', 't' => '厎', 'u' => '厏', 'v' => '吰', 'w' => '吷', 'x' => '吪', 'y' => '呔', 'z' => '呅', '{' => '吙', '|' => '吜', '}' => '吥', '~' => '吘', 'ʡ' => '吽', 'ʢ' => '呏', 'ʣ' => '呁', 'ʤ' => '吨', 'ʥ' => '吤', 'ʦ' => '呇', 'ʧ' => '囮', 'ʨ' => '囧', 'ʩ' => '囥', 'ʪ' => '坁', 'ʫ' => '坅', 'ʬ' => '坌', 'ʭ' => '坉', 'ʮ' => '坋', 'ʯ' => '坒', 'ʰ' => '夆', 'ʱ' => '奀', 'ʲ' => '妦', 'ʳ' => '妘', 'ʴ' => '妠', 'ʵ' => '妗', 'ʶ' => '妎', 'ʷ' => '妢', 'ʸ' => '妐', 'ʹ' => '妏', 'ʺ' => '妧', 'ʻ' => '妡', 'ʼ' => '宎', 'ʽ' => '宒', 'ʾ' => '尨', 'ʿ' => '尪', '' => '岍', '' => '岏', '' => '岈', '' => '岋', '' => '岉', '' => '岒', '' => '岊', '' => '岆', '' => '岓', '' => '岕', '' => '巠', '' => '帊', '' => '帎', '' => '庋', '' => '庉', '' => '庌', '' => '庈', '' => '庍', '' => '弅', '' => '弝', '' => '彸', '' => '彶', '' => '忒', '' => '忑', '' => '忐', '' => '忭', '' => '忨', '' => '忮', '' => '忳', '' => '忡', '' => '忤', '' => '忣', '' => '忺', '' => '忯', '' => '忷', '' => '忻', '' => '怀', '' => '忴', '' => '戺', '' => '抃', '' => '抌', '' => '抎', '' => '抏', '' => '抔', '' => '抇', '' => '扱', '' => '扻', '' => '扺', '' => '扰', '' => '抁', '' => '抈', '' => '扷', '' => '扽', '' => '扲', '' => '扴', '' => '攷', '' => '旰', '' => '旴', '' => '旳', '' => '旲', '' => '旵', '' => '杅', '' => '杇', '@' => '杙', 'A' => '杕', 'B' => '杌', 'C' => '杈', 'D' => '杝', 'E' => '杍', 'F' => '杚', 'G' => '杋', 'H' => '毐', 'I' => '氙', 'J' => '氚', 'K' => '汸', 'L' => '汧', 'M' => '汫', 'N' => '沄', 'O' => '沋', 'P' => '沏', 'Q' => '汱', 'R' => '汯', 'S' => '汩', 'T' => '沚', 'U' => '汭', 'V' => '沇', 'W' => '沕', 'X' => '沜', 'Y' => '汦', 'Z' => '汳', '[' => '汥', '\\' => '汻', ']' => '沎', '^' => '灴', '_' => '灺', '`' => '牣', 'a' => '犿', 'b' => '犽', 'c' => '狃', 'd' => '狆', 'e' => '狁', 'f' => '犺', 'g' => '狅', 'h' => '玕', 'i' => '玗', 'j' => '玓', 'k' => '玔', 'l' => '玒', 'm' => '町', 'n' => '甹', 'o' => '疔', 'p' => '疕', 'q' => '皁', 'r' => '礽', 's' => '耴', 't' => '肕', 'u' => '肙', 'v' => '肐', 'w' => '肒', 'x' => '肜', 'y' => '芐', 'z' => '芏', '{' => '芅', '|' => '芎', '}' => '芑', '~' => '芓', 'ˡ' => '芊', 'ˢ' => '芃', 'ˣ' => '芄', 'ˤ' => '豸', '˥' => '迉', '˦' => '辿', '˧' => '邟', '˨' => '邡', '˩' => '邥', '˪' => '邞', '˫' => '邧', 'ˬ' => '邠', '˭' => '阰', 'ˮ' => '阨', '˯' => '阯', '˰' => '阭', '˱' => '丳', '˲' => '侘', '˳' => '佼', '˴' => '侅', '˵' => '佽', '˶' => '侀', '˷' => '侇', '˸' => '佶', '˹' => '佴', '˺' => '侉', '˻' => '侄', '˼' => '佷', '˽' => '佌', '˾' => '侗', '˿' => '佪', '' => '侚', '' => '佹', '' => '侁', '' => '佸', '' => '侐', '' => '侜', '' => '侔', '' => '侞', '' => '侒', '' => '侂', '' => '侕', '' => '佫', '' => '佮', '' => '冞', '' => '冼', '' => '冾', '' => '刵', '' => '刲', '' => '刳', '' => '剆', '' => '刱', '' => '劼', '' => '匊', '' => '匋', '' => '匼', '' => '厒', '' => '厔', '' => '咇', '' => '呿', '' => '咁', '' => '咑', '' => '咂', '' => '咈', '' => '呫', '' => '呺', '' => '呾', '' => '呥', '' => '呬', '' => '呴', '' => '呦', '' => '咍', '' => '呯', '' => '呡', '' => '呠', '' => '咘', '' => '呣', '' => '呧', '' => '呤', '' => '囷', '' => '囹', '' => '坯', '' => '坲', '' => '坭', '' => '坫', '' => '坱', '' => '坰', '' => '坶', '' => '垀', '' => '坵', '' => '坻', '' => '坳', '' => '坴', '' => '坢', '@' => '坨', 'A' => '坽', 'B' => '夌', 'C' => '奅', 'D' => '妵', 'E' => '妺', 'F' => '姏', 'G' => '姎', 'H' => '妲', 'I' => '姌', 'J' => '姁', 'K' => '妶', 'L' => '妼', 'M' => '姃', 'N' => '姖', 'O' => '妱', 'P' => '妽', 'Q' => '姀', 'R' => '姈', 'S' => '妴', 'T' => '姇', 'U' => '孢', 'V' => '孥', 'W' => '宓', 'X' => '宕', 'Y' => '屄', 'Z' => '屇', '[' => '岮', '\\' => '岤', ']' => '岠', '^' => '岵', '_' => '岯', '`' => '岨', 'a' => '岬', 'b' => '岟', 'c' => '岣', 'd' => '岭', 'e' => '岢', 'f' => '岪', 'g' => '岧', 'h' => '岝', 'i' => '岥', 'j' => '岶', 'k' => '岰', 'l' => '岦', 'm' => '帗', 'n' => '帔', 'o' => '帙', 'p' => '弨', 'q' => '弢', 'r' => '弣', 's' => '弤', 't' => '彔', 'u' => '徂', 'v' => '彾', 'w' => '彽', 'x' => '忞', 'y' => '忥', 'z' => '怭', '{' => '怦', '|' => '怙', '}' => '怲', '~' => '怋', '̡' => '怴', '̢' => '怊', '̣' => '怗', '̤' => '怳', '̥' => '怚', '̦' => '怞', '̧' => '怬', '̨' => '怢', '̩' => '怍', '̪' => '怐', '̫' => '怮', '̬' => '怓', '̭' => '怑', '̮' => '怌', '̯' => '怉', '̰' => '怜', '̱' => '戔', '̲' => '戽', '̳' => '抭', '̴' => '抴', '̵' => '拑', '̶' => '抾', '̷' => '抪', '̸' => '抶', '̹' => '拊', '̺' => '抮', '̻' => '抳', '̼' => '抯', '̽' => '抻', '̾' => '抩', '̿' => '抰', '' => '抸', '' => '攽', '' => '斨', '' => '斻', '' => '昉', '' => '旼', '' => '昄', '' => '昒', '' => '昈', '' => '旻', '' => '昃', '' => '昋', '' => '昍', '' => '昅', '' => '旽', '' => '昑', '' => '昐', '' => '曶', '' => '朊', '' => '枅', '' => '杬', '' => '枎', '' => '枒', '' => '杶', '' => '杻', '' => '枘', '' => '枆', '' => '构', '' => '杴', '' => '枍', '' => '枌', '' => '杺', '' => '枟', '' => '枑', '' => '枙', '' => '枃', '' => '杽', '' => '极', '' => '杸', '' => '杹', '' => '枔', '' => '欥', '' => '殀', '' => '歾', '' => '毞', '' => '氝', '' => '沓', '' => '泬', '' => '泫', '' => '泮', '' => '泙', '' => '沶', '' => '泔', '' => '沭', '' => '泧', '' => '沷', '' => '泐', '' => '泂', '' => '沺', '' => '泃', '' => '泆', '' => '泭', '' => '泲', '@' => '泒', 'A' => '泝', 'B' => '沴', 'C' => '沊', 'D' => '沝', 'E' => '沀', 'F' => '泞', 'G' => '泀', 'H' => '洰', 'I' => '泍', 'J' => '泇', 'K' => '沰', 'L' => '泹', 'M' => '泏', 'N' => '泩', 'O' => '泑', 'P' => '炔', 'Q' => '炘', 'R' => '炅', 'S' => '炓', 'T' => '炆', 'U' => '炄', 'V' => '炑', 'W' => '炖', 'X' => '炂', 'Y' => '炚', 'Z' => '炃', '[' => '牪', '\\' => '狖', ']' => '狋', '^' => '狘', '_' => '狉', '`' => '狜', 'a' => '狒', 'b' => '狔', 'c' => '狚', 'd' => '狌', 'e' => '狑', 'f' => '玤', 'g' => '玡', 'h' => '玭', 'i' => '玦', 'j' => '玢', 'k' => '玠', 'l' => '玬', 'm' => '玝', 'n' => '瓝', 'o' => '瓨', 'p' => '甿', 'q' => '畀', 'r' => '甾', 's' => '疌', 't' => '疘', 'u' => '皯', 'v' => '盳', 'w' => '盱', 'x' => '盰', 'y' => '盵', 'z' => '矸', '{' => '矼', '|' => '矹', '}' => '矻', '~' => '矺', '͡' => '矷', '͢' => '祂', 'ͣ' => '礿', 'ͤ' => '秅', 'ͥ' => '穸', 'ͦ' => '穻', 'ͧ' => '竻', 'ͨ' => '籵', 'ͩ' => '糽', 'ͪ' => '耵', 'ͫ' => '肏', 'ͬ' => '肮', 'ͭ' => '肣', 'ͮ' => '肸', 'ͯ' => '肵', 'Ͱ' => '肭', 'ͱ' => '舠', 'Ͳ' => '芠', 'ͳ' => '苀', 'ʹ' => '芫', '͵' => '芚', 'Ͷ' => '芘', 'ͷ' => '芛', '͸' => '芵', '͹' => '芧', 'ͺ' => '芮', 'ͻ' => '芼', 'ͼ' => '芞', 'ͽ' => '芺', ';' => '芴', 'Ϳ' => '芨', '' => '芡', '' => '芩', '' => '苂', '' => '芤', '' => '苃', '' => '芶', '' => '芢', '' => '虰', '' => '虯', '' => '虭', '' => '虮', '' => '豖', '' => '迒', '' => '迋', '' => '迓', '' => '迍', '' => '迖', '' => '迕', '' => '迗', '' => '邲', '' => '邴', '' => '邯', '' => '邳', '' => '邰', '' => '阹', '' => '阽', '' => '阼', '' => '阺', '' => '陃', '' => '俍', '' => '俅', '' => '俓', '' => '侲', '' => '俉', '' => '俋', '' => '俁', '' => '俔', '' => '俜', '' => '俙', '' => '侻', '' => '侳', '' => '俛', '' => '俇', '' => '俖', '' => '侺', '' => '俀', '' => '侹', '' => '俬', '' => '剄', '' => '剉', '' => '勀', '' => '勂', '' => '匽', '' => '卼', '' => '厗', '' => '厖', '' => '厙', '' => '厘', '' => '咺', '' => '咡', '' => '咭', '' => '咥', '' => '哏', '@' => '哃', 'A' => '茍', 'B' => '咷', 'C' => '咮', 'D' => '哖', 'E' => '咶', 'F' => '哅', 'G' => '哆', 'H' => '咠', 'I' => '呰', 'J' => '咼', 'K' => '咢', 'L' => '咾', 'M' => '呲', 'N' => '哞', 'O' => '咰', 'P' => '垵', 'Q' => '垞', 'R' => '垟', 'S' => '垤', 'T' => '垌', 'U' => '垗', 'V' => '垝', 'W' => '垛', 'X' => '垔', 'Y' => '垘', 'Z' => '垏', '[' => '垙', '\\' => '垥', ']' => '垚', '^' => '垕', '_' => '壴', '`' => '复', 'a' => '奓', 'b' => '姡', 'c' => '姞', 'd' => '姮', 'e' => '娀', 'f' => '姱', 'g' => '姝', 'h' => '姺', 'i' => '姽', 'j' => '姼', 'k' => '姶', 'l' => '姤', 'm' => '姲', 'n' => '姷', 'o' => '姛', 'p' => '姩', 'q' => '姳', 'r' => '姵', 's' => '姠', 't' => '姾', 'u' => '姴', 'v' => '姭', 'w' => '宨', 'x' => '屌', 'y' => '峐', 'z' => '峘', '{' => '峌', '|' => '峗', '}' => '峋', '~' => '峛', 'Ρ' => '峞', '΢' => '峚', 'Σ' => '峉', 'Τ' => '峇', 'Υ' => '峊', 'Φ' => '峖', 'Χ' => '峓', 'Ψ' => '峔', 'Ω' => '峏', 'Ϊ' => '峈', 'Ϋ' => '峆', 'ά' => '峎', 'έ' => '峟', 'ή' => '峸', 'ί' => '巹', 'ΰ' => '帡', 'α' => '帢', 'β' => '帣', 'γ' => '帠', 'δ' => '帤', 'ε' => '庰', 'ζ' => '庤', 'η' => '庢', 'θ' => '庛', 'ι' => '庣', 'κ' => '庥', 'λ' => '弇', 'μ' => '弮', 'ν' => '彖', 'ξ' => '徆', 'ο' => '怷', '' => '怹', '' => '恔', '' => '恲', '' => '恞', '' => '恅', '' => '恓', '' => '恇', '' => '恉', '' => '恛', '' => '恌', '' => '恀', '' => '恂', '' => '恟', '' => '怤', '' => '恄', '' => '恘', '' => '恦', '' => '恮', '' => '扂', '' => '扃', '' => '拏', '' => '挍', '' => '挋', '' => '拵', '' => '挎', '' => '挃', '' => '拫', '' => '拹', '' => '挏', '' => '挌', '' => '拸', '' => '拶', '' => '挀', '' => '挓', '' => '挔', '' => '拺', '' => '挕', '' => '拻', '' => '拰', '' => '敁', '' => '敃', '' => '斪', '' => '斿', '' => '昶', '' => '昡', '' => '昲', '' => '昵', '' => '昜', '' => '昦', '' => '昢', '' => '昳', '' => '昫', '' => '昺', '' => '昝', '' => '昴', '' => '昹', '' => '昮', '' => '朏', '' => '朐', '' => '柁', '' => '柲', '' => '柈', '' => '枺', '@' => '柜', 'A' => '枻', 'B' => '柸', 'C' => '柘', 'D' => '柀', 'E' => '枷', 'F' => '柅', 'G' => '柫', 'H' => '柤', 'I' => '柟', 'J' => '枵', 'K' => '柍', 'L' => '枳', 'M' => '柷', 'N' => '柶', 'O' => '柮', 'P' => '柣', 'Q' => '柂', 'R' => '枹', 'S' => '柎', 'T' => '柧', 'U' => '柰', 'V' => '枲', 'W' => '柼', 'X' => '柆', 'Y' => '柭', 'Z' => '柌', '[' => '枮', '\\' => '柦', ']' => '柛', '^' => '柺', '_' => '柉', '`' => '柊', 'a' => '柃', 'b' => '柪', 'c' => '柋', 'd' => '欨', 'e' => '殂', 'f' => '殄', 'g' => '殶', 'h' => '毖', 'i' => '毘', 'j' => '毠', 'k' => '氠', 'l' => '氡', 'm' => '洨', 'n' => '洴', 'o' => '洭', 'p' => '洟', 'q' => '洼', 'r' => '洿', 's' => '洒', 't' => '洊', 'u' => '泚', 'v' => '洳', 'w' => '洄', 'x' => '洙', 'y' => '洺', 'z' => '洚', '{' => '洑', '|' => '洀', '}' => '洝', '~' => '浂', 'ϡ' => '洁', 'Ϣ' => '洘', 'ϣ' => '洷', 'Ϥ' => '洃', 'ϥ' => '洏', 'Ϧ' => '浀', 'ϧ' => '洇', 'Ϩ' => '洠', 'ϩ' => '洬', 'Ϫ' => '洈', 'ϫ' => '洢', 'Ϭ' => '洉', 'ϭ' => '洐', 'Ϯ' => '炷', 'ϯ' => '炟', 'ϰ' => '炾', 'ϱ' => '炱', 'ϲ' => '炰', 'ϳ' => '炡', 'ϴ' => '炴', 'ϵ' => '炵', '϶' => '炩', 'Ϸ' => '牁', 'ϸ' => '牉', 'Ϲ' => '牊', 'Ϻ' => '牬', 'ϻ' => '牰', 'ϼ' => '牳', 'Ͻ' => '牮', 'Ͼ' => '狊', 'Ͽ' => '狤', '' => '狨', '' => '狫', '' => '狟', '' => '狪', '' => '狦', '' => '狣', '' => '玅', '' => '珌', '' => '珂', '' => '珈', '' => '珅', '' => '玹', '' => '玶', '' => '玵', '' => '玴', '' => '珫', '' => '玿', '' => '珇', '' => '玾', '' => '珃', '' => '珆', '' => '玸', '' => '珋', '' => '瓬', '' => '瓮', '' => '甮', '' => '畇', '' => '畈', '' => '疧', '' => '疪', '' => '癹', '' => '盄', '' => '眈', '' => '眃', '' => '眄', '' => '眅', '' => '眊', '' => '盷', '' => '盻', '' => '盺', '' => '矧', '' => '矨', '' => '砆', '' => '砑', '' => '砒', '' => '砅', '' => '砐', '' => '砏', '' => '砎', '' => '砉', '' => '砃', '' => '砓', '' => '祊', '' => '祌', '' => '祋', '' => '祅', '' => '祄', '' => '秕', '' => '种', '' => '秏', '' => '秖', '' => '秎', '' => '窀', '@' => '穾', 'A' => '竑', 'B' => '笀', 'C' => '笁', 'D' => '籺', 'E' => '籸', 'F' => '籹', 'G' => '籿', 'H' => '粀', 'I' => '粁', 'J' => '紃', 'K' => '紈', 'L' => '紁', 'M' => '罘', 'N' => '羑', 'O' => '羍', 'P' => '羾', 'Q' => '耇', 'R' => '耎', 'S' => '耏', 'T' => '耔', 'U' => '耷', 'V' => '胘', 'W' => '胇', 'X' => '胠', 'Y' => '胑', 'Z' => '胈', '[' => '胂', '\\' => '胐', ']' => '胅', '^' => '胣', '_' => '胙', '`' => '胜', 'a' => '胊', 'b' => '胕', 'c' => '胉', 'd' => '胏', 'e' => '胗', 'f' => '胦', 'g' => '胍', 'h' => '臿', 'i' => '舡', 'j' => '芔', 'k' => '苙', 'l' => '苾', 'm' => '苹', 'n' => '茇', 'o' => '苨', 'p' => '茀', 'q' => '苕', 'r' => '茺', 's' => '苫', 't' => '苖', 'u' => '苴', 'v' => '苬', 'w' => '苡', 'x' => '苲', 'y' => '苵', 'z' => '茌', '{' => '苻', '|' => '苶', '}' => '苰', '~' => '苪', 'С' => '苤', 'Т' => '苠', 'У' => '苺', 'Ф' => '苳', 'Х' => '苭', 'Ц' => '虷', 'Ч' => '虴', 'Ш' => '虼', 'Щ' => '虳', 'Ъ' => '衁', 'Ы' => '衎', 'Ь' => '衧', 'Э' => '衪', 'Ю' => '衩', 'Я' => '觓', 'а' => '訄', 'б' => '訇', 'в' => '赲', 'г' => '迣', 'д' => '迡', 'е' => '迮', 'ж' => '迠', 'з' => '郱', 'и' => '邽', 'й' => '邿', 'к' => '郕', 'л' => '郅', 'м' => '邾', 'н' => '郇', 'о' => '郋', 'п' => '郈', '' => '釔', '' => '釓', '' => '陔', '' => '陏', '' => '陑', '' => '陓', '' => '陊', '' => '陎', '' => '倞', '' => '倅', '' => '倇', '' => '倓', '' => '倢', '' => '倰', '' => '倛', '' => '俵', '' => '俴', '' => '倳', '' => '倷', '' => '倬', '' => '俶', '' => '俷', '' => '倗', '' => '倜', '' => '倠', '' => '倧', '' => '倵', '' => '倯', '' => '倱', '' => '倎', '' => '党', '' => '冔', '' => '冓', '' => '凊', '' => '凄', '' => '凅', '' => '凈', '' => '凎', '' => '剡', '' => '剚', '' => '剒', '' => '剞', '' => '剟', '' => '剕', '' => '剢', '' => '勍', '' => '匎', '' => '厞', '' => '唦', '' => '哢', '' => '唗', '' => '唒', '' => '哧', '' => '哳', '' => '哤', '' => '唚', '' => '哿', '' => '唄', '' => '唈', '' => '哫', '' => '唑', '' => '唅', '' => '哱', '@' => '唊', 'A' => '哻', 'B' => '哷', 'C' => '哸', 'D' => '哠', 'E' => '唎', 'F' => '唃', 'G' => '唋', 'H' => '圁', 'I' => '圂', 'J' => '埌', 'K' => '堲', 'L' => '埕', 'M' => '埒', 'N' => '垺', 'O' => '埆', 'P' => '垽', 'Q' => '垼', 'R' => '垸', 'S' => '垶', 'T' => '垿', 'U' => '埇', 'V' => '埐', 'W' => '垹', 'X' => '埁', 'Y' => '夎', 'Z' => '奊', '[' => '娙', '\\' => '娖', ']' => '娭', '^' => '娮', '_' => '娕', '`' => '娏', 'a' => '娗', 'b' => '娊', 'c' => '娞', 'd' => '娳', 'e' => '孬', 'f' => '宧', 'g' => '宭', 'h' => '宬', 'i' => '尃', 'j' => '屖', 'k' => '屔', 'l' => '峬', 'm' => '峿', 'n' => '峮', 'o' => '峱', 'p' => '峷', 'q' => '崀', 'r' => '峹', 's' => '帩', 't' => '帨', 'u' => '庨', 'v' => '庮', 'w' => '庪', 'x' => '庬', 'y' => '弳', 'z' => '弰', '{' => '彧', '|' => '恝', '}' => '恚', '~' => '恧', 'ѡ' => '恁', 'Ѣ' => '悢', 'ѣ' => '悈', 'Ѥ' => '悀', 'ѥ' => '悒', 'Ѧ' => '悁', 'ѧ' => '悝', 'Ѩ' => '悃', 'ѩ' => '悕', 'Ѫ' => '悛', 'ѫ' => '悗', 'Ѭ' => '悇', 'ѭ' => '悜', 'Ѯ' => '悎', 'ѯ' => '戙', 'Ѱ' => '扆', 'ѱ' => '拲', 'Ѳ' => '挐', 'ѳ' => '捖', 'Ѵ' => '挬', 'ѵ' => '捄', 'Ѷ' => '捅', 'ѷ' => '挶', 'Ѹ' => '捃', 'ѹ' => '揤', 'Ѻ' => '挹', 'ѻ' => '捋', 'Ѽ' => '捊', 'ѽ' => '挼', 'Ѿ' => '挩', 'ѿ' => '捁', '' => '挴', '' => '捘', '' => '捔', '' => '捙', '' => '挭', '' => '捇', '' => '挳', '' => '捚', '' => '捑', '' => '挸', '' => '捗', '' => '捀', '' => '捈', '' => '敊', '' => '敆', '' => '旆', '' => '旃', '' => '旄', '' => '旂', '' => '晊', '' => '晟', '' => '晇', '' => '晑', '' => '朒', '' => '朓', '' => '栟', '' => '栚', '' => '桉', '' => '栲', '' => '栳', '' => '栻', '' => '桋', '' => '桏', '' => '栖', '' => '栱', '' => '栜', '' => '栵', '' => '栫', '' => '栭', '' => '栯', '' => '桎', '' => '桄', '' => '栴', '' => '栝', '' => '栒', '' => '栔', '' => '栦', '' => '栨', '' => '栮', '' => '桍', '' => '栺', '' => '栥', '' => '栠', '' => '欬', '' => '欯', '' => '欭', '' => '欱', '' => '欴', '' => '歭', '' => '肂', '' => '殈', '' => '毦', '' => '毤', '@' => '毨', 'A' => '毣', 'B' => '毢', 'C' => '毧', 'D' => '氥', 'E' => '浺', 'F' => '浣', 'G' => '浤', 'H' => '浶', 'I' => '洍', 'J' => '浡', 'K' => '涒', 'L' => '浘', 'M' => '浢', 'N' => '浭', 'O' => '浯', 'P' => '涑', 'Q' => '涍', 'R' => '淯', 'S' => '浿', 'T' => '涆', 'U' => '浞', 'V' => '浧', 'W' => '浠', 'X' => '涗', 'Y' => '浰', 'Z' => '浼', '[' => '浟', '\\' => '涂', ']' => '涘', '^' => '洯', '_' => '浨', '`' => '涋', 'a' => '浾', 'b' => '涀', 'c' => '涄', 'd' => '洖', 'e' => '涃', 'f' => '浻', 'g' => '浽', 'h' => '浵', 'i' => '涐', 'j' => '烜', 'k' => '烓', 'l' => '烑', 'm' => '烝', 'n' => '烋', 'o' => '缹', 'p' => '烢', 'q' => '烗', 'r' => '烒', 's' => '烞', 't' => '烠', 'u' => '烔', 'v' => '烍', 'w' => '烅', 'x' => '烆', 'y' => '烇', 'z' => '烚', '{' => '烎', '|' => '烡', '}' => '牂', '~' => '牸', 'ҡ' => '牷', 'Ң' => '牶', 'ң' => '猀', 'Ҥ' => '狺', 'ҥ' => '狴', 'Ҧ' => '狾', 'ҧ' => '狶', 'Ҩ' => '狳', 'ҩ' => '狻', 'Ҫ' => '猁', 'ҫ' => '珓', 'Ҭ' => '珙', 'ҭ' => '珥', 'Ү' => '珖', 'ү' => '玼', 'Ұ' => '珧', 'ұ' => '珣', 'Ҳ' => '珩', 'ҳ' => '珜', 'Ҵ' => '珒', 'ҵ' => '珛', 'Ҷ' => '珔', 'ҷ' => '珝', 'Ҹ' => '珚', 'ҹ' => '珗', 'Һ' => '珘', 'һ' => '珨', 'Ҽ' => '瓞', 'ҽ' => '瓟', 'Ҿ' => '瓴', 'ҿ' => '瓵', '' => '甡', '' => '畛', '' => '畟', '' => '疰', '' => '痁', '' => '疻', '' => '痄', '' => '痀', '' => '疿', '' => '疶', '' => '疺', '' => '皊', '' => '盉', '' => '眝', '' => '眛', '' => '眐', '' => '眓', '' => '眒', '' => '眣', '' => '眑', '' => '眕', '' => '眙', '' => '眚', '' => '眢', '' => '眧', '' => '砣', '' => '砬', '' => '砢', '' => '砵', '' => '砯', '' => '砨', '' => '砮', '' => '砫', '' => '砡', '' => '砩', '' => '砳', '' => '砪', '' => '砱', '' => '祔', '' => '祛', '' => '祏', '' => '祜', '' => '祓', '' => '祒', '' => '祑', '' => '秫', '' => '秬', '' => '秠', '' => '秮', '' => '秭', '' => '秪', '' => '秜', '' => '秞', '' => '秝', '' => '窆', '' => '窉', '' => '窅', '' => '窋', '' => '窌', '' => '窊', '' => '窇', '' => '竘', '' => '笐', '@' => '笄', 'A' => '笓', 'B' => '笅', 'C' => '笏', 'D' => '笈', 'E' => '笊', 'F' => '笎', 'G' => '笉', 'H' => '笒', 'I' => '粄', 'J' => '粑', 'K' => '粊', 'L' => '粌', 'M' => '粈', 'N' => '粍', 'O' => '粅', 'P' => '紞', 'Q' => '紝', 'R' => '紑', 'S' => '紎', 'T' => '紘', 'U' => '紖', 'V' => '紓', 'W' => '紟', 'X' => '紒', 'Y' => '紏', 'Z' => '紌', '[' => '罜', '\\' => '罡', ']' => '罞', '^' => '罠', '_' => '罝', '`' => '罛', 'a' => '羖', 'b' => '羒', 'c' => '翃', 'd' => '翂', 'e' => '翀', 'f' => '耖', 'g' => '耾', 'h' => '耹', 'i' => '胺', 'j' => '胲', 'k' => '胹', 'l' => '胵', 'm' => '脁', 'n' => '胻', 'o' => '脀', 'p' => '舁', 'q' => '舯', 'r' => '舥', 's' => '茳', 't' => '茭', 'u' => '荄', 'v' => '茙', 'w' => '荑', 'x' => '茥', 'y' => '荖', 'z' => '茿', '{' => '荁', '|' => '茦', '}' => '茜', '~' => '茢', 'ӡ' => '荂', 'Ӣ' => '荎', 'ӣ' => '茛', 'Ӥ' => '茪', 'ӥ' => '茈', 'Ӧ' => '茼', 'ӧ' => '荍', 'Ө' => '茖', 'ө' => '茤', 'Ӫ' => '茠', 'ӫ' => '茷', 'Ӭ' => '茯', 'ӭ' => '茩', 'Ӯ' => '荇', 'ӯ' => '荅', 'Ӱ' => '荌', 'ӱ' => '荓', 'Ӳ' => '茞', 'ӳ' => '茬', 'Ӵ' => '荋', 'ӵ' => '茧', 'Ӷ' => '荈', 'ӷ' => '虓', 'Ӹ' => '虒', 'ӹ' => '蚢', 'Ӻ' => '蚨', 'ӻ' => '蚖', 'Ӽ' => '蚍', 'ӽ' => '蚑', 'Ӿ' => '蚞', 'ӿ' => '蚇', '' => '蚗', '' => '蚆', '' => '蚋', '' => '蚚', '' => '蚅', '' => '蚥', '' => '蚙', '' => '蚡', '' => '蚧', '' => '蚕', '' => '蚘', '' => '蚎', '' => '蚝', '' => '蚐', '' => '蚔', '' => '衃', '' => '衄', '' => '衭', '' => '衵', '' => '衶', '' => '衲', '' => '袀', '' => '衱', '' => '衿', '' => '衯', '' => '袃', '' => '衾', '' => '衴', '' => '衼', '' => '訒', '' => '豇', '' => '豗', '' => '豻', '' => '貤', '' => '貣', '' => '赶', '' => '赸', '' => '趵', '' => '趷', '' => '趶', '' => '軑', '' => '軓', '' => '迾', '' => '迵', '' => '适', '' => '迿', '' => '迻', '' => '逄', '' => '迼', '' => '迶', '' => '郖', '' => '郠', '' => '郙', '' => '郚', '' => '郣', '' => '郟', '' => '郥', '' => '郘', '' => '郛', '' => '郗', '' => '郜', '' => '郤', '' => '酐', '@' => '酎', 'A' => '酏', 'B' => '釕', 'C' => '釢', 'D' => '釚', 'E' => '陜', 'F' => '陟', 'G' => '隼', 'H' => '飣', 'I' => '髟', 'J' => '鬯', 'K' => '乿', 'L' => '偰', 'M' => '偪', 'N' => '偡', 'O' => '偞', 'P' => '偠', 'Q' => '偓', 'R' => '偋', 'S' => '偝', 'T' => '偲', 'U' => '偈', 'V' => '偍', 'W' => '偁', 'X' => '偛', 'Y' => '偊', 'Z' => '偢', '[' => '倕', '\\' => '偅', ']' => '偟', '^' => '偩', '_' => '偫', '`' => '偣', 'a' => '偤', 'b' => '偆', 'c' => '偀', 'd' => '偮', 'e' => '偳', 'f' => '偗', 'g' => '偑', 'h' => '凐', 'i' => '剫', 'j' => '剭', 'k' => '剬', 'l' => '剮', 'm' => '勖', 'n' => '勓', 'o' => '匭', 'p' => '厜', 'q' => '啵', 'r' => '啶', 's' => '唼', 't' => '啍', 'u' => '啐', 'v' => '唴', 'w' => '唪', 'x' => '啑', 'y' => '啢', 'z' => '唶', '{' => '唵', '|' => '唰', '}' => '啒', '~' => '啅', 'ԡ' => '唌', 'Ԣ' => '唲', 'ԣ' => '啥', 'Ԥ' => '啎', 'ԥ' => '唹', 'Ԧ' => '啈', 'ԧ' => '唭', 'Ԩ' => '唻', 'ԩ' => '啀', 'Ԫ' => '啋', 'ԫ' => '圊', 'Ԭ' => '圇', 'ԭ' => '埻', 'Ԯ' => '堔', 'ԯ' => '埢', '԰' => '埶', 'Ա' => '埜', 'Բ' => '埴', 'Գ' => '堀', 'Դ' => '埭', 'Ե' => '埽', 'Զ' => '堈', 'Է' => '埸', 'Ը' => '堋', 'Թ' => '埳', 'Ժ' => '埏', 'Ի' => '堇', 'Լ' => '埮', 'Խ' => '埣', 'Ծ' => '埲', 'Կ' => '埥', '' => '埬', '' => '埡', '' => '堎', '' => '埼', '' => '堐', '' => '埧', '' => '堁', '' => '堌', '' => '埱', '' => '埩', '' => '埰', '' => '堍', '' => '堄', '' => '奜', '' => '婠', '' => '婘', '' => '婕', '' => '婧', '' => '婞', '' => '娸', '' => '娵', '' => '婭', '' => '婐', '' => '婟', '' => '婥', '' => '婬', '' => '婓', '' => '婤', '' => '婗', '' => '婃', '' => '婝', '' => '婒', '' => '婄', '' => '婛', '' => '婈', '' => '媎', '' => '娾', '' => '婍', '' => '娹', '' => '婌', '' => '婰', '' => '婩', '' => '婇', '' => '婑', '' => '婖', '' => '婂', '' => '婜', '' => '孲', '' => '孮', '' => '寁', '' => '寀', '' => '屙', '' => '崞', '' => '崋', '' => '崝', '' => '崚', '' => '崠', '' => '崌', '' => '崨', '' => '崍', '' => '崦', '' => '崥', '' => '崏', '@' => '崰', 'A' => '崒', 'B' => '崣', 'C' => '崟', 'D' => '崮', 'E' => '帾', 'F' => '帴', 'G' => '庱', 'H' => '庴', 'I' => '庹', 'J' => '庲', 'K' => '庳', 'L' => '弶', 'M' => '弸', 'N' => '徛', 'O' => '徖', 'P' => '徟', 'Q' => '悊', 'R' => '悐', 'S' => '悆', 'T' => '悾', 'U' => '悰', 'V' => '悺', 'W' => '惓', 'X' => '惔', 'Y' => '惏', 'Z' => '惤', '[' => '惙', '\\' => '惝', ']' => '惈', '^' => '悱', '_' => '惛', '`' => '悷', 'a' => '惊', 'b' => '悿', 'c' => '惃', 'd' => '惍', 'e' => '惀', 'f' => '挲', 'g' => '捥', 'h' => '掊', 'i' => '掂', 'j' => '捽', 'k' => '掽', 'l' => '掞', 'm' => '掭', 'n' => '掝', 'o' => '掗', 'p' => '掫', 'q' => '掎', 'r' => '捯', 's' => '掇', 't' => '掐', 'u' => '据', 'v' => '掯', 'w' => '捵', 'x' => '掜', 'y' => '捭', 'z' => '掮', '{' => '捼', '|' => '掤', '}' => '挻', '~' => '掟', 'ա' => '捸', 'բ' => '掅', 'գ' => '掁', 'դ' => '掑', 'ե' => '掍', 'զ' => '捰', 'է' => '敓', 'ը' => '旍', 'թ' => '晥', 'ժ' => '晡', 'ի' => '晛', 'լ' => '晙', 'խ' => '晜', 'ծ' => '晢', 'կ' => '朘', 'հ' => '桹', 'ձ' => '梇', 'ղ' => '梐', 'ճ' => '梜', 'մ' => '桭', 'յ' => '桮', 'ն' => '梮', 'շ' => '梫', 'ո' => '楖', 'չ' => '桯', 'պ' => '梣', 'ջ' => '梬', 'ռ' => '梩', 'ս' => '桵', 'վ' => '桴', 'տ' => '梲', '' => '梏', '' => '桷', '' => '梒', '' => '桼', '' => '桫', '' => '桲', '' => '梪', '' => '梀', '' => '桱', '' => '桾', '' => '梛', '' => '梖', '' => '梋', '' => '梠', '' => '梉', '' => '梤', '' => '桸', '' => '桻', '' => '梑', '' => '梌', '' => '梊', '' => '桽', '' => '欶', '' => '欳', '' => '欷', '' => '欸', '' => '殑', '' => '殏', '' => '殍', '' => '殎', '' => '殌', '' => '氪', '' => '淀', '' => '涫', '' => '涴', '' => '涳', '' => '湴', '' => '涬', '' => '淩', '' => '淢', '' => '涷', '' => '淶', '' => '淔', '' => '渀', '' => '淈', '' => '淠', '' => '淟', '' => '淖', '' => '涾', '' => '淥', '' => '淜', '' => '淝', '' => '淛', '' => '淴', '' => '淊', '' => '涽', '' => '淭', '' => '淰', '' => '涺', '' => '淕', '' => '淂', '' => '淏', '' => '淉', '@' => '淐', 'A' => '淲', 'B' => '淓', 'C' => '淽', 'D' => '淗', 'E' => '淍', 'F' => '淣', 'G' => '涻', 'H' => '烺', 'I' => '焍', 'J' => '烷', 'K' => '焗', 'L' => '烴', 'M' => '焌', 'N' => '烰', 'O' => '焄', 'P' => '烳', 'Q' => '焐', 'R' => '烼', 'S' => '烿', 'T' => '焆', 'U' => '焓', 'V' => '焀', 'W' => '烸', 'X' => '烶', 'Y' => '焋', 'Z' => '焂', '[' => '焎', '\\' => '牾', ']' => '牻', '^' => '牼', '_' => '牿', '`' => '猝', 'a' => '猗', 'b' => '猇', 'c' => '猑', 'd' => '猘', 'e' => '猊', 'f' => '猈', 'g' => '狿', 'h' => '猏', 'i' => '猞', 'j' => '玈', 'k' => '珶', 'l' => '珸', 'm' => '珵', 'n' => '琄', 'o' => '琁', 'p' => '珽', 'q' => '琇', 'r' => '琀', 's' => '珺', 't' => '珼', 'u' => '珿', 'v' => '琌', 'w' => '琋', 'x' => '珴', 'y' => '琈', 'z' => '畤', '{' => '畣', '|' => '痎', '}' => '痒', '~' => '痏', '֡' => '痋', '֢' => '痌', '֣' => '痑', '֤' => '痐', '֥' => '皏', '֦' => '皉', '֧' => '盓', '֨' => '眹', '֩' => '眯', '֪' => '眭', '֫' => '眱', '֬' => '眲', '֭' => '眴', '֮' => '眳', '֯' => '眽', 'ְ' => '眥', 'ֱ' => '眻', 'ֲ' => '眵', 'ֳ' => '硈', 'ִ' => '硒', 'ֵ' => '硉', 'ֶ' => '硍', 'ַ' => '硊', 'ָ' => '硌', 'ֹ' => '砦', 'ֺ' => '硅', 'ֻ' => '硐', 'ּ' => '祤', 'ֽ' => '祧', '־' => '祩', 'ֿ' => '祪', '' => '祣', '' => '祫', '' => '祡', '' => '离', '' => '秺', '' => '秸', '' => '秶', '' => '秷', '' => '窏', '' => '窔', '' => '窐', '' => '笵', '' => '筇', '' => '笴', '' => '笥', '' => '笰', '' => '笢', '' => '笤', '' => '笳', '' => '笘', '' => '笪', '' => '笝', '' => '笱', '' => '笫', '' => '笭', '' => '笯', '' => '笲', '' => '笸', '' => '笚', '' => '笣', '' => '粔', '' => '粘', '' => '粖', '' => '粣', '' => '紵', '' => '紽', '' => '紸', '' => '紶', '' => '紺', '' => '絅', '' => '紬', '' => '紩', '' => '絁', '' => '絇', '' => '紾', '' => '紿', '' => '絊', '' => '紻', '' => '紨', '' => '罣', '' => '羕', '' => '羜', '' => '羝', '' => '羛', '' => '翊', '' => '翋', '' => '翍', '' => '翐', '' => '翑', '' => '翇', '' => '翏', '' => '翉', '' => '耟', '@' => '耞', 'A' => '耛', 'B' => '聇', 'C' => '聃', 'D' => '聈', 'E' => '脘', 'F' => '脥', 'G' => '脙', 'H' => '脛', 'I' => '脭', 'J' => '脟', 'K' => '脬', 'L' => '脞', 'M' => '脡', 'N' => '脕', 'O' => '脧', 'P' => '脝', 'Q' => '脢', 'R' => '舑', 'S' => '舸', 'T' => '舳', 'U' => '舺', 'V' => '舴', 'W' => '舲', 'X' => '艴', 'Y' => '莐', 'Z' => '莣', '[' => '莨', '\\' => '莍', ']' => '荺', '^' => '荳', '_' => '莤', '`' => '荴', 'a' => '莏', 'b' => '莁', 'c' => '莕', 'd' => '莙', 'e' => '荵', 'f' => '莔', 'g' => '莩', 'h' => '荽', 'i' => '莃', 'j' => '莌', 'k' => '莝', 'l' => '莛', 'm' => '莪', 'n' => '莋', 'o' => '荾', 'p' => '莥', 'q' => '莯', 'r' => '莈', 's' => '莗', 't' => '莰', 'u' => '荿', 'v' => '莦', 'w' => '莇', 'x' => '莮', 'y' => '荶', 'z' => '莚', '{' => '虙', '|' => '虖', '}' => '蚿', '~' => '蚷', 'ס' => '蛂', 'ע' => '蛁', 'ף' => '蛅', 'פ' => '蚺', 'ץ' => '蚰', 'צ' => '蛈', 'ק' => '蚹', 'ר' => '蚳', 'ש' => '蚸', 'ת' => '蛌', '׫' => '蚴', '׬' => '蚻', '׭' => '蚼', '׮' => '蛃', 'ׯ' => '蚽', 'װ' => '蚾', 'ױ' => '衒', 'ײ' => '袉', '׳' => '袕', '״' => '袨', '׵' => '袢', '׶' => '袪', '׷' => '袚', '׸' => '袑', '׹' => '袡', '׺' => '袟', '׻' => '袘', '׼' => '袧', '׽' => '袙', '׾' => '袛', '׿' => '袗', '' => '袤', '' => '袬', '' => '袌', '' => '袓', '' => '袎', '' => '覂', '' => '觖', '' => '觙', '' => '觕', '' => '訰', '' => '訧', '' => '訬', '' => '訞', '' => '谹', '' => '谻', '' => '豜', '' => '豝', '' => '豽', '' => '貥', '' => '赽', '' => '赻', '' => '赹', '' => '趼', '' => '跂', '' => '趹', '' => '趿', '' => '跁', '' => '軘', '' => '軞', '' => '軝', '' => '軜', '' => '軗', '' => '軠', '' => '軡', '' => '逤', '' => '逋', '' => '逑', '' => '逜', '' => '逌', '' => '逡', '' => '郯', '' => '郪', '' => '郰', '' => '郴', '' => '郲', '' => '郳', '' => '郔', '' => '郫', '' => '郬', '' => '郩', '' => '酖', '' => '酘', '' => '酚', '' => '酓', '' => '酕', '' => '釬', '' => '釴', '' => '釱', '' => '釳', '' => '釸', '' => '釤', '' => '釹', '' => '釪', '@' => '釫', 'A' => '釷', 'B' => '釨', 'C' => '釮', 'D' => '镺', 'E' => '閆', 'F' => '閈', 'G' => '陼', 'H' => '陭', 'I' => '陫', 'J' => '陱', 'K' => '陯', 'L' => '隿', 'M' => '靪', 'N' => '頄', 'O' => '飥', 'P' => '馗', 'Q' => '傛', 'R' => '傕', 'S' => '傔', 'T' => '傞', 'U' => '傋', 'V' => '傣', 'W' => '傃', 'X' => '傌', 'Y' => '傎', 'Z' => '傝', '[' => '偨', '\\' => '傜', ']' => '傒', '^' => '傂', '_' => '傇', '`' => '兟', 'a' => '凔', 'b' => '匒', 'c' => '匑', 'd' => '厤', 'e' => '厧', 'f' => '喑', 'g' => '喨', 'h' => '喥', 'i' => '喭', 'j' => '啷', 'k' => '噅', 'l' => '喢', 'm' => '喓', 'n' => '喈', 'o' => '喏', 'p' => '喵', 'q' => '喁', 'r' => '喣', 's' => '喒', 't' => '喤', 'u' => '啽', 'v' => '喌', 'w' => '喦', 'x' => '啿', 'y' => '喕', 'z' => '喡', '{' => '喎', '|' => '圌', '}' => '堩', '~' => '堷', 'ء' => '堙', 'آ' => '堞', 'أ' => '堧', 'ؤ' => '堣', 'إ' => '堨', 'ئ' => '埵', 'ا' => '塈', 'ب' => '堥', 'ة' => '堜', 'ت' => '堛', 'ث' => '堳', 'ج' => '堿', 'ح' => '堶', 'خ' => '堮', 'د' => '堹', 'ذ' => '堸', 'ر' => '堭', 'ز' => '堬', 'س' => '堻', 'ش' => '奡', 'ص' => '媯', 'ض' => '媔', 'ط' => '媟', 'ظ' => '婺', 'ع' => '媢', 'غ' => '媞', 'ػ' => '婸', 'ؼ' => '媦', 'ؽ' => '婼', 'ؾ' => '媥', 'ؿ' => '媬', '' => '媕', '' => '媮', '' => '娷', '' => '媄', '' => '媊', '' => '媗', '' => '媃', '' => '媋', '' => '媩', '' => '婻', '' => '婽', '' => '媌', '' => '媜', '' => '媏', '' => '媓', '' => '媝', '' => '寪', '' => '寍', '' => '寋', '' => '寔', '' => '寑', '' => '寊', '' => '寎', '' => '尌', '' => '尰', '' => '崷', '' => '嵃', '' => '嵫', '' => '嵁', '' => '嵋', '' => '崿', '' => '崵', '' => '嵑', '' => '嵎', '' => '嵕', '' => '崳', '' => '崺', '' => '嵒', '' => '崽', '' => '崱', '' => '嵙', '' => '嵂', '' => '崹', '' => '嵉', '' => '崸', '' => '崼', '' => '崲', '' => '崶', '' => '嵀', '' => '嵅', '' => '幄', '' => '幁', '' => '彘', '' => '徦', '' => '徥', '' => '徫', '' => '惉', '' => '悹', '' => '惌', '' => '惢', '' => '惎', '' => '惄', '' => '愔', '@' => '惲', 'A' => '愊', 'B' => '愖', 'C' => '愅', 'D' => '惵', 'E' => '愓', 'F' => '惸', 'G' => '惼', 'H' => '惾', 'I' => '惁', 'J' => '愃', 'K' => '愘', 'L' => '愝', 'M' => '愐', 'N' => '惿', 'O' => '愄', 'P' => '愋', 'Q' => '扊', 'R' => '掔', 'S' => '掱', 'T' => '掰', 'U' => '揎', 'V' => '揥', 'W' => '揨', 'X' => '揯', 'Y' => '揃', 'Z' => '撝', '[' => '揳', '\\' => '揊', ']' => '揠', '^' => '揶', '_' => '揕', '`' => '揲', 'a' => '揵', 'b' => '摡', 'c' => '揟', 'd' => '掾', 'e' => '揝', 'f' => '揜', 'g' => '揄', 'h' => '揘', 'i' => '揓', 'j' => '揂', 'k' => '揇', 'l' => '揌', 'm' => '揋', 'n' => '揈', 'o' => '揰', 'p' => '揗', 'q' => '揙', 'r' => '攲', 's' => '敧', 't' => '敪', 'u' => '敤', 'v' => '敜', 'w' => '敨', 'x' => '敥', 'y' => '斌', 'z' => '斝', '{' => '斞', '|' => '斮', '}' => '旐', '~' => '旒', '١' => '晼', '٢' => '晬', '٣' => '晻', '٤' => '暀', '٥' => '晱', '٦' => '晹', '٧' => '晪', '٨' => '晲', '٩' => '朁', '٪' => '椌', '٫' => '棓', '٬' => '椄', '٭' => '棜', 'ٮ' => '椪', 'ٯ' => '棬', 'ٰ' => '棪', 'ٱ' => '棱', 'ٲ' => '椏', 'ٳ' => '棖', 'ٴ' => '棷', 'ٵ' => '棫', 'ٶ' => '棤', 'ٷ' => '棶', 'ٸ' => '椓', 'ٹ' => '椐', 'ٺ' => '棳', 'ٻ' => '棡', 'ټ' => '椇', 'ٽ' => '棌', 'پ' => '椈', 'ٿ' => '楰', '' => '梴', '' => '椑', '' => '棯', '' => '棆', '' => '椔', '' => '棸', '' => '棐', '' => '棽', '' => '棼', '' => '棨', '' => '椋', '' => '椊', '' => '椗', '' => '棎', '' => '棈', '' => '棝', '' => '棞', '' => '棦', '' => '棴', '' => '棑', '' => '椆', '' => '棔', '' => '棩', '' => '椕', '' => '椥', '' => '棇', '' => '欹', '' => '欻', '' => '欿', '' => '欼', '' => '殔', '' => '殗', '' => '殙', '' => '殕', '' => '殽', '' => '毰', '' => '毲', '' => '毳', '' => '氰', '' => '淼', '' => '湆', '' => '湇', '' => '渟', '' => '湉', '' => '溈', '' => '渼', '' => '渽', '' => '湅', '' => '湢', '' => '渫', '' => '渿', '' => '湁', '' => '湝', '' => '湳', '' => '渜', '' => '渳', '' => '湋', '' => '湀', '' => '湑', '' => '渻', '' => '渃', '' => '渮', '' => '湞', '@' => '湨', 'A' => '湜', 'B' => '湡', 'C' => '渱', 'D' => '渨', 'E' => '湠', 'F' => '湱', 'G' => '湫', 'H' => '渹', 'I' => '渢', 'J' => '渰', 'K' => '湓', 'L' => '湥', 'M' => '渧', 'N' => '湸', 'O' => '湤', 'P' => '湷', 'Q' => '湕', 'R' => '湹', 'S' => '湒', 'T' => '湦', 'U' => '渵', 'V' => '渶', 'W' => '湚', 'X' => '焠', 'Y' => '焞', 'Z' => '焯', '[' => '烻', '\\' => '焮', ']' => '焱', '^' => '焣', '_' => '焥', '`' => '焢', 'a' => '焲', 'b' => '焟', 'c' => '焨', 'd' => '焺', 'e' => '焛', 'f' => '牋', 'g' => '牚', 'h' => '犈', 'i' => '犉', 'j' => '犆', 'k' => '犅', 'l' => '犋', 'm' => '猒', 'n' => '猋', 'o' => '猰', 'p' => '猢', 'q' => '猱', 'r' => '猳', 's' => '猧', 't' => '猲', 'u' => '猭', 'v' => '猦', 'w' => '猣', 'x' => '猵', 'y' => '猌', 'z' => '琮', '{' => '琬', '|' => '琰', '}' => '琫', '~' => '琖', 'ڡ' => '琚', 'ڢ' => '琡', 'ڣ' => '琭', 'ڤ' => '琱', 'ڥ' => '琤', 'ڦ' => '琣', 'ڧ' => '琝', 'ڨ' => '琩', 'ک' => '琠', 'ڪ' => '琲', 'ګ' => '瓻', 'ڬ' => '甯', 'ڭ' => '畯', 'ڮ' => '畬', 'گ' => '痧', 'ڰ' => '痚', 'ڱ' => '痡', 'ڲ' => '痦', 'ڳ' => '痝', 'ڴ' => '痟', 'ڵ' => '痤', 'ڶ' => '痗', 'ڷ' => '皕', 'ڸ' => '皒', 'ڹ' => '盚', 'ں' => '睆', 'ڻ' => '睇', 'ڼ' => '睄', 'ڽ' => '睍', 'ھ' => '睅', 'ڿ' => '睊', '' => '睎', '' => '睋', '' => '睌', '' => '矞', '' => '矬', '' => '硠', '' => '硤', '' => '硥', '' => '硜', '' => '硭', '' => '硱', '' => '硪', '' => '确', '' => '硰', '' => '硩', '' => '硨', '' => '硞', '' => '硢', '' => '祴', '' => '祳', '' => '祲', '' => '祰', '' => '稂', '' => '稊', '' => '稃', '' => '稌', '' => '稄', '' => '窙', '' => '竦', '' => '竤', '' => '筊', '' => '笻', '' => '筄', '' => '筈', '' => '筌', '' => '筎', '' => '筀', '' => '筘', '' => '筅', '' => '粢', '' => '粞', '' => '粨', '' => '粡', '' => '絘', '' => '絯', '' => '絣', '' => '絓', '' => '絖', '' => '絧', '' => '絪', '' => '絏', '' => '絭', '' => '絜', '' => '絫', '' => '絒', '' => '絔', '' => '絩', '' => '絑', '' => '絟', '' => '絎', '' => '缾', '' => '缿', '' => '罥', '@' => '罦', 'A' => '羢', 'B' => '羠', 'C' => '羡', 'D' => '翗', 'E' => '聑', 'F' => '聏', 'G' => '聐', 'H' => '胾', 'I' => '胔', 'J' => '腃', 'K' => '腊', 'L' => '腒', 'M' => '腏', 'N' => '腇', 'O' => '脽', 'P' => '腍', 'Q' => '脺', 'R' => '臦', 'S' => '臮', 'T' => '臷', 'U' => '臸', 'V' => '臹', 'W' => '舄', 'X' => '舼', 'Y' => '舽', 'Z' => '舿', '[' => '艵', '\\' => '茻', ']' => '菏', '^' => '菹', '_' => '萣', '`' => '菀', 'a' => '菨', 'b' => '萒', 'c' => '菧', 'd' => '菤', 'e' => '菼', 'f' => '菶', 'g' => '萐', 'h' => '菆', 'i' => '菈', 'j' => '菫', 'k' => '菣', 'l' => '莿', 'm' => '萁', 'n' => '菝', 'o' => '菥', 'p' => '菘', 'q' => '菿', 'r' => '菡', 's' => '菋', 't' => '菎', 'u' => '菖', 'v' => '菵', 'w' => '菉', 'x' => '萉', 'y' => '萏', 'z' => '菞', '{' => '萑', '|' => '萆', '}' => '菂', '~' => '菳', 'ۡ' => '菕', 'ۢ' => '菺', 'ۣ' => '菇', 'ۤ' => '菑', 'ۥ' => '菪', 'ۦ' => '萓', 'ۧ' => '菃', 'ۨ' => '菬', '۩' => '菮', '۪' => '菄', '۫' => '菻', '۬' => '菗', 'ۭ' => '菢', 'ۮ' => '萛', 'ۯ' => '菛', '۰' => '菾', '۱' => '蛘', '۲' => '蛢', '۳' => '蛦', '۴' => '蛓', '۵' => '蛣', '۶' => '蛚', '۷' => '蛪', '۸' => '蛝', '۹' => '蛫', 'ۺ' => '蛜', 'ۻ' => '蛬', 'ۼ' => '蛩', '۽' => '蛗', '۾' => '蛨', 'ۿ' => '蛑', '' => '衈', '' => '衖', '' => '衕', '' => '袺', '' => '裗', '' => '袹', '' => '袸', '' => '裀', '' => '袾', '' => '袶', '' => '袼', '' => '袷', '' => '袽', '' => '袲', '' => '褁', '' => '裉', '' => '覕', '' => '覘', '' => '覗', '' => '觝', '' => '觚', '' => '觛', '' => '詎', '' => '詍', '' => '訹', '' => '詙', '' => '詀', '' => '詗', '' => '詘', '' => '詄', '' => '詅', '' => '詒', '' => '詈', '' => '詑', '' => '詊', '' => '詌', '' => '詏', '' => '豟', '' => '貁', '' => '貀', '' => '貺', '' => '貾', '' => '貰', '' => '貹', '' => '貵', '' => '趄', '' => '趀', '' => '趉', '' => '跘', '' => '跓', '' => '跍', '' => '跇', '' => '跖', '' => '跜', '' => '跏', '' => '跕', '' => '跙', '' => '跈', '' => '跗', '' => '跅', '' => '軯', '' => '軷', '' => '軺', '@' => '軹', 'A' => '軦', 'B' => '軮', 'C' => '軥', 'D' => '軵', 'E' => '軧', 'F' => '軨', 'G' => '軶', 'H' => '軫', 'I' => '軱', 'J' => '軬', 'K' => '軴', 'L' => '軩', 'M' => '逭', 'N' => '逴', 'O' => '逯', 'P' => '鄆', 'Q' => '鄬', 'R' => '鄄', 'S' => '郿', 'T' => '郼', 'U' => '鄈', 'V' => '郹', 'W' => '郻', 'X' => '鄁', 'Y' => '鄀', 'Z' => '鄇', '[' => '鄅', '\\' => '鄃', ']' => '酡', '^' => '酤', '_' => '酟', '`' => '酢', 'a' => '酠', 'b' => '鈁', 'c' => '鈊', 'd' => '鈥', 'e' => '鈃', 'f' => '鈚', 'g' => '鈦', 'h' => '鈏', 'i' => '鈌', 'j' => '鈀', 'k' => '鈒', 'l' => '釿', 'm' => '釽', 'n' => '鈆', 'o' => '鈄', 'p' => '鈧', 'q' => '鈂', 'r' => '鈜', 's' => '鈤', 't' => '鈙', 'u' => '鈗', 'v' => '鈅', 'w' => '鈖', 'x' => '镻', 'y' => '閍', 'z' => '閌', '{' => '閐', '|' => '隇', '}' => '陾', '~' => '隈', 'ܡ' => '隉', 'ܢ' => '隃', 'ܣ' => '隀', 'ܤ' => '雂', 'ܥ' => '雈', 'ܦ' => '雃', 'ܧ' => '雱', 'ܨ' => '雰', 'ܩ' => '靬', 'ܪ' => '靰', 'ܫ' => '靮', 'ܬ' => '頇', 'ܭ' => '颩', 'ܮ' => '飫', 'ܯ' => '鳦', 'ܰ' => '黹', 'ܱ' => '亃', 'ܲ' => '亄', 'ܳ' => '亶', 'ܴ' => '傽', 'ܵ' => '傿', 'ܶ' => '僆', 'ܷ' => '傮', 'ܸ' => '僄', 'ܹ' => '僊', 'ܺ' => '傴', 'ܻ' => '僈', 'ܼ' => '僂', 'ܽ' => '傰', 'ܾ' => '僁', 'ܿ' => '傺', '' => '傱', '' => '僋', '' => '僉', '' => '傶', '' => '傸', '' => '凗', '' => '剺', '' => '剸', '' => '剻', '' => '剼', '' => '嗃', '' => '嗛', '' => '嗌', '' => '嗐', '' => '嗋', '' => '嗊', '' => '嗝', '' => '嗀', '' => '嗔', '' => '嗄', '' => '嗩', '' => '喿', '' => '嗒', '' => '喍', '' => '嗏', '' => '嗕', '' => '嗢', '' => '嗖', '' => '嗈', '' => '嗲', '' => '嗍', '' => '嗙', '' => '嗂', '' => '圔', '' => '塓', '' => '塨', '' => '塤', '' => '塏', '' => '塍', '' => '塉', '' => '塯', '' => '塕', '' => '塎', '' => '塝', '' => '塙', '' => '塥', '' => '塛', '' => '堽', '' => '塣', '' => '塱', '' => '壼', '' => '嫇', '' => '嫄', '' => '嫋', '' => '媺', '' => '媸', '' => '媱', '' => '媵', '' => '媰', '' => '媿', '' => '嫈', '' => '媻', '' => '嫆', '@' => '媷', 'A' => '嫀', 'B' => '嫊', 'C' => '媴', 'D' => '媶', 'E' => '嫍', 'F' => '媹', 'G' => '媐', 'H' => '寖', 'I' => '寘', 'J' => '寙', 'K' => '尟', 'L' => '尳', 'M' => '嵱', 'N' => '嵣', 'O' => '嵊', 'P' => '嵥', 'Q' => '嵲', 'R' => '嵬', 'S' => '嵞', 'T' => '嵨', 'U' => '嵧', 'V' => '嵢', 'W' => '巰', 'X' => '幏', 'Y' => '幎', 'Z' => '幊', '[' => '幍', '\\' => '幋', ']' => '廅', '^' => '廌', '_' => '廆', '`' => '廋', 'a' => '廇', 'b' => '彀', 'c' => '徯', 'd' => '徭', 'e' => '惷', 'f' => '慉', 'g' => '慊', 'h' => '愫', 'i' => '慅', 'j' => '愶', 'k' => '愲', 'l' => '愮', 'm' => '慆', 'n' => '愯', 'o' => '慏', 'p' => '愩', 'q' => '慀', 'r' => '戠', 's' => '酨', 't' => '戣', 'u' => '戥', 'v' => '戤', 'w' => '揅', 'x' => '揱', 'y' => '揫', 'z' => '搐', '{' => '搒', '|' => '搉', '}' => '搠', '~' => '搤', 'ݡ' => '搳', 'ݢ' => '摃', 'ݣ' => '搟', 'ݤ' => '搕', 'ݥ' => '搘', 'ݦ' => '搹', 'ݧ' => '搷', 'ݨ' => '搢', 'ݩ' => '搣', 'ݪ' => '搌', 'ݫ' => '搦', 'ݬ' => '搰', 'ݭ' => '搨', 'ݮ' => '摁', 'ݯ' => '搵', 'ݰ' => '搯', 'ݱ' => '搊', 'ݲ' => '搚', 'ݳ' => '摀', 'ݴ' => '搥', 'ݵ' => '搧', 'ݶ' => '搋', 'ݷ' => '揧', 'ݸ' => '搛', 'ݹ' => '搮', 'ݺ' => '搡', 'ݻ' => '搎', 'ݼ' => '敯', 'ݽ' => '斒', 'ݾ' => '旓', 'ݿ' => '暆', '' => '暌', '' => '暕', '' => '暐', '' => '暋', '' => '暊', '' => '暙', '' => '暔', '' => '晸', '' => '朠', '' => '楦', '' => '楟', '' => '椸', '' => '楎', '' => '楢', '' => '楱', '' => '椿', '' => '楅', '' => '楪', '' => '椹', '' => '楂', '' => '楗', '' => '楙', '' => '楺', '' => '楈', '' => '楉', '' => '椵', '' => '楬', '' => '椳', '' => '椽', '' => '楥', '' => '棰', '' => '楸', '' => '椴', '' => '楩', '' => '楀', '' => '楯', '' => '楄', '' => '楶', '' => '楘', '' => '楁', '' => '楴', '' => '楌', '' => '椻', '' => '楋', '' => '椷', '' => '楜', '' => '楏', '' => '楑', '' => '椲', '' => '楒', '' => '椯', '' => '楻', '' => '椼', '' => '歆', '' => '歅', '' => '歃', '' => '歂', '' => '歈', '' => '歁', '' => '殛', '' => '嗀', '' => '毻', '' => '毼', '@' => '毹', 'A' => '毷', 'B' => '毸', 'C' => '溛', 'D' => '滖', 'E' => '滈', 'F' => '溏', 'G' => '滀', 'H' => '溟', 'I' => '溓', 'J' => '溔', 'K' => '溠', 'L' => '溱', 'M' => '溹', 'N' => '滆', 'O' => '滒', 'P' => '溽', 'Q' => '滁', 'R' => '溞', 'S' => '滉', 'T' => '溷', 'U' => '溰', 'V' => '滍', 'W' => '溦', 'X' => '滏', 'Y' => '溲', 'Z' => '溾', '[' => '滃', '\\' => '滜', ']' => '滘', '^' => '溙', '_' => '溒', '`' => '溎', 'a' => '溍', 'b' => '溤', 'c' => '溡', 'd' => '溿', 'e' => '溳', 'f' => '滐', 'g' => '滊', 'h' => '溗', 'i' => '溮', 'j' => '溣', 'k' => '煇', 'l' => '煔', 'm' => '煒', 'n' => '煣', 'o' => '煠', 'p' => '煁', 'q' => '煝', 'r' => '煢', 's' => '煲', 't' => '煸', 'u' => '煪', 'v' => '煡', 'w' => '煂', 'x' => '煘', 'y' => '煃', 'z' => '煋', '{' => '煰', '|' => '煟', '}' => '煐', '~' => '煓', 'ޡ' => '煄', 'ޢ' => '煍', 'ޣ' => '煚', 'ޤ' => '牏', 'ޥ' => '犍', 'ަ' => '犌', 'ާ' => '犑', 'ި' => '犐', 'ީ' => '犎', 'ު' => '猼', 'ޫ' => '獂', 'ެ' => '猻', 'ޭ' => '猺', 'ޮ' => '獀', 'ޯ' => '獊', 'ް' => '獉', 'ޱ' => '瑄', '޲' => '瑊', '޳' => '瑋', '޴' => '瑒', '޵' => '瑑', '޶' => '瑗', '޷' => '瑀', '޸' => '瑏', '޹' => '瑐', '޺' => '瑎', '޻' => '瑂', '޼' => '瑆', '޽' => '瑍', '޾' => '瑔', '޿' => '瓡', '' => '瓿', '' => '瓾', '' => '瓽', '' => '甝', '' => '畹', '' => '畷', '' => '榃', '' => '痯', '' => '瘏', '' => '瘃', '' => '痷', '' => '痾', '' => '痼', '' => '痹', '' => '痸', '' => '瘐', '' => '痻', '' => '痶', '' => '痭', '' => '痵', '' => '痽', '' => '皙', '' => '皵', '' => '盝', '' => '睕', '' => '睟', '' => '睠', '' => '睒', '' => '睖', '' => '睚', '' => '睩', '' => '睧', '' => '睔', '' => '睙', '' => '睭', '' => '矠', '' => '碇', '' => '碚', '' => '碔', '' => '碏', '' => '碄', '' => '碕', '' => '碅', '' => '碆', '' => '碡', '' => '碃', '' => '硹', '' => '碙', '' => '碀', '' => '碖', '' => '硻', '' => '祼', '' => '禂', '' => '祽', '' => '祹', '' => '稑', '' => '稘', '' => '稙', '' => '稒', '' => '稗', '' => '稕', '' => '稢', '' => '稓', '@' => '稛', 'A' => '稐', 'B' => '窣', 'C' => '窢', 'D' => '窞', 'E' => '竫', 'F' => '筦', 'G' => '筤', 'H' => '筭', 'I' => '筴', 'J' => '筩', 'K' => '筲', 'L' => '筥', 'M' => '筳', 'N' => '筱', 'O' => '筰', 'P' => '筡', 'Q' => '筸', 'R' => '筶', 'S' => '筣', 'T' => '粲', 'U' => '粴', 'V' => '粯', 'W' => '綈', 'X' => '綆', 'Y' => '綀', 'Z' => '綍', '[' => '絿', '\\' => '綅', ']' => '絺', '^' => '綎', '_' => '絻', '`' => '綃', 'a' => '絼', 'b' => '綌', 'c' => '綔', 'd' => '綄', 'e' => '絽', 'f' => '綒', 'g' => '罭', 'h' => '罫', 'i' => '罧', 'j' => '罨', 'k' => '罬', 'l' => '羦', 'm' => '羥', 'n' => '羧', 'o' => '翛', 'p' => '翜', 'q' => '耡', 'r' => '腤', 's' => '腠', 't' => '腷', 'u' => '腜', 'v' => '腩', 'w' => '腛', 'x' => '腢', 'y' => '腲', 'z' => '朡', '{' => '腞', '|' => '腶', '}' => '腧', '~' => '腯', 'ߡ' => '腄', 'ߢ' => '腡', 'ߣ' => '舝', 'ߤ' => '艉', 'ߥ' => '艄', 'ߦ' => '艀', 'ߧ' => '艂', 'ߨ' => '艅', 'ߩ' => '蓱', 'ߪ' => '萿', '߫' => '葖', '߬' => '葶', '߭' => '葹', '߮' => '蒏', '߯' => '蒍', '߰' => '葥', '߱' => '葑', '߲' => '葀', '߳' => '蒆', 'ߴ' => '葧', 'ߵ' => '萰', '߶' => '葍', '߷' => '葽', '߸' => '葚', '߹' => '葙', 'ߺ' => '葴', '߻' => '葳', '߼' => '葝', '߽' => '蔇', '߾' => '葞', '߿' => '萷', '' => '萺', '' => '萴', '' => '葺', '' => '葃', '' => '葸', '' => '萲', '' => '葅', '' => '萩', '' => '菙', '' => '葋', '' => '萯', '' => '葂', '' => '萭', '' => '葟', '' => '葰', '' => '萹', '' => '葎', '' => '葌', '' => '葒', '' => '葯', '' => '蓅', '' => '蒎', '' => '萻', '' => '葇', '' => '萶', '' => '萳', '' => '葨', '' => '葾', '' => '葄', '' => '萫', '' => '葠', '' => '葔', '' => '葮', '' => '葐', '' => '蜋', '' => '蜄', '' => '蛷', '' => '蜌', '' => '蛺', '' => '蛖', '' => '蛵', '' => '蝍', '' => '蛸', '' => '蜎', '' => '蜉', '' => '蜁', '' => '蛶', '' => '蜍', '' => '蜅', '' => '裖', '' => '裋', '' => '裍', '' => '裎', '' => '裞', '' => '裛', '' => '裚', '' => '裌', '' => '裐', '' => '覅', '' => '覛', '' => '觟', '' => '觥', '' => '觤', '@' => '觡', 'A' => '觠', 'B' => '觢', 'C' => '觜', 'D' => '触', 'E' => '詶', 'F' => '誆', 'G' => '詿', 'H' => '詡', 'I' => '訿', 'J' => '詷', 'K' => '誂', 'L' => '誄', 'M' => '詵', 'N' => '誃', 'O' => '誁', 'P' => '詴', 'Q' => '詺', 'R' => '谼', 'S' => '豋', 'T' => '豊', 'U' => '豥', 'V' => '豤', 'W' => '豦', 'X' => '貆', 'Y' => '貄', 'Z' => '貅', '[' => '賌', '\\' => '赨', ']' => '赩', '^' => '趑', '_' => '趌', '`' => '趎', 'a' => '趏', 'b' => '趍', 'c' => '趓', 'd' => '趔', 'e' => '趐', 'f' => '趒', 'g' => '跰', 'h' => '跠', 'i' => '跬', 'j' => '跱', 'k' => '跮', 'l' => '跐', 'm' => '跩', 'n' => '跣', 'o' => '跢', 'p' => '跧', 'q' => '跲', 'r' => '跫', 's' => '跴', 't' => '輆', 'u' => '軿', 'v' => '輁', 'w' => '輀', 'x' => '輅', 'y' => '輇', 'z' => '輈', '{' => '輂', '|' => '輋', '}' => '遒', '~' => '逿', '' => '遄', '' => '遉', '' => '逽', '' => '鄐', '' => '鄍', '' => '鄏', '' => '鄑', '' => '鄖', '' => '鄔', '' => '鄋', '' => '鄎', '' => '酮', '' => '酯', '' => '鉈', '' => '鉒', '' => '鈰', '' => '鈺', '' => '鉦', '' => '鈳', '' => '鉥', '' => '鉞', '' => '銃', '' => '鈮', '' => '鉊', '' => '鉆', '' => '鉭', '' => '鉬', '' => '鉏', '' => '鉠', '' => '鉧', '' => '鉯', '' => '鈶', '' => '鉡', '' => '鉰', '' => '鈱', '' => '鉔', '' => '鉣', '' => '鉐', '' => '鉲', '' => '鉎', '' => '鉓', '' => '鉌', '' => '鉖', '' => '鈲', '' => '閟', '' => '閜', '' => '閞', '' => '閛', '' => '隒', '' => '隓', '' => '隑', '' => '隗', '' => '雎', '' => '雺', '' => '雽', '' => '雸', '' => '雵', '' => '靳', '' => '靷', '' => '靸', '' => '靲', '' => '頏', '' => '頍', '' => '頎', '' => '颬', '' => '飶', '' => '飹', '' => '馯', '' => '馲', '' => '馰', '' => '馵', '' => '骭', '' => '骫', '' => '魛', '' => '鳪', '' => '鳭', '' => '鳧', '' => '麀', '' => '黽', '' => '僦', '' => '僔', '' => '僗', '' => '僨', '' => '僳', '' => '僛', '' => '僪', '' => '僝', '' => '僤', '' => '僓', '' => '僬', '' => '僰', '' => '僯', '' => '僣', '' => '僠', '@' => '凘', 'A' => '劀', 'B' => '劁', 'C' => '勩', 'D' => '勫', 'E' => '匰', 'F' => '厬', 'G' => '嘧', 'H' => '嘕', 'I' => '嘌', 'J' => '嘒', 'K' => '嗼', 'L' => '嘏', 'M' => '嘜', 'N' => '嘁', 'O' => '嘓', 'P' => '嘂', 'Q' => '嗺', 'R' => '嘝', 'S' => '嘄', 'T' => '嗿', 'U' => '嗹', 'V' => '墉', 'W' => '塼', 'X' => '墐', 'Y' => '墘', 'Z' => '墆', '[' => '墁', '\\' => '塿', ']' => '塴', '^' => '墋', '_' => '塺', '`' => '墇', 'a' => '墑', 'b' => '墎', 'c' => '塶', 'd' => '墂', 'e' => '墈', 'f' => '塻', 'g' => '墔', 'h' => '墏', 'i' => '壾', 'j' => '奫', 'k' => '嫜', 'l' => '嫮', 'm' => '嫥', 'n' => '嫕', 'o' => '嫪', 'p' => '嫚', 'q' => '嫭', 'r' => '嫫', 's' => '嫳', 't' => '嫢', 'u' => '嫠', 'v' => '嫛', 'w' => '嫬', 'x' => '嫞', 'y' => '嫝', 'z' => '嫙', '{' => '嫨', '|' => '嫟', '}' => '孷', '~' => '寠', '' => '寣', '' => '屣', '' => '嶂', '' => '嶀', '' => '嵽', '' => '嶆', '' => '嵺', '' => '嶁', '' => '嵷', '' => '嶊', '' => '嶉', '' => '嶈', '' => '嵾', '' => '嵼', '' => '嶍', '' => '嵹', '' => '嵿', '' => '幘', '' => '幙', '' => '幓', '' => '廘', '' => '廑', '' => '廗', '' => '廎', '' => '廜', '' => '廕', '' => '廙', '' => '廒', '' => '廔', '' => '彄', '' => '彃', '' => '彯', '' => '徶', '' => '愬', '' => '愨', '' => '慁', '' => '慞', '' => '慱', '' => '慳', '' => '慒', '' => '慓', '' => '慲', '' => '慬', '' => '憀', '' => '慴', '' => '慔', '' => '慺', '' => '慛', '' => '慥', '' => '愻', '' => '慪', '' => '慡', '' => '慖', '' => '戩', '' => '戧', '' => '戫', '' => '搫', '' => '摍', '' => '摛', '' => '摝', '' => '摴', '' => '摶', '' => '摲', '' => '摳', '' => '摽', '' => '摵', '' => '摦', '' => '撦', '' => '摎', '' => '撂', '' => '摞', '' => '摜', '' => '摋', '' => '摓', '' => '摠', '' => '摐', '' => '摿', '' => '搿', '' => '摬', '' => '摫', '' => '摙', '' => '摥', '' => '摷', '' => '敳', '' => '斠', '' => '暡', '' => '暠', '' => '暟', '' => '朅', '' => '朄', '' => '朢', '' => '榱', '' => '榶', '' => '槉', '@' => '榠', 'A' => '槎', 'B' => '榖', 'C' => '榰', 'D' => '榬', 'E' => '榼', 'F' => '榑', 'G' => '榙', 'H' => '榎', 'I' => '榧', 'J' => '榍', 'K' => '榩', 'L' => '榾', 'M' => '榯', 'N' => '榿', 'O' => '槄', 'P' => '榽', 'Q' => '榤', 'R' => '槔', 'S' => '榹', 'T' => '槊', 'U' => '榚', 'V' => '槏', 'W' => '榳', 'X' => '榓', 'Y' => '榪', 'Z' => '榡', '[' => '榞', '\\' => '槙', ']' => '榗', '^' => '榐', '_' => '槂', '`' => '榵', 'a' => '榥', 'b' => '槆', 'c' => '歊', 'd' => '歍', 'e' => '歋', 'f' => '殞', 'g' => '殟', 'h' => '殠', 'i' => '毃', 'j' => '毄', 'k' => '毾', 'l' => '滎', 'm' => '滵', 'n' => '滱', 'o' => '漃', 'p' => '漥', 'q' => '滸', 'r' => '漷', 's' => '滻', 't' => '漮', 'u' => '漉', 'v' => '潎', 'w' => '漙', 'x' => '漚', 'y' => '漧', 'z' => '漘', '{' => '漻', '|' => '漒', '}' => '滭', '~' => '漊', '' => '漶', '' => '潳', '' => '滹', '' => '滮', '' => '漭', '' => '潀', '' => '漰', '' => '漼', '' => '漵', '' => '滫', '' => '漇', '' => '漎', '' => '潃', '' => '漅', '' => '滽', '' => '滶', '' => '漹', '' => '漜', '' => '滼', '' => '漺', '' => '漟', '' => '漍', '' => '漞', '' => '漈', '' => '漡', '' => '熇', '' => '熐', '' => '熉', '' => '熀', '' => '熅', '' => '熂', '' => '熏', '' => '煻', '' => '熆', '' => '熁', '' => '熗', '' => '牄', '' => '牓', '' => '犗', '' => '犕', '' => '犓', '' => '獃', '' => '獍', '' => '獑', '' => '獌', '' => '瑢', '' => '瑳', '' => '瑱', '' => '瑵', '' => '瑲', '' => '瑧', '' => '瑮', '' => '甀', '' => '甂', '' => '甃', '' => '畽', '' => '疐', '' => '瘖', '' => '瘈', '' => '瘌', '' => '瘕', '' => '瘑', '' => '瘊', '' => '瘔', '' => '皸', '' => '瞁', '' => '睼', '' => '瞅', '' => '瞂', '' => '睮', '' => '瞀', '' => '睯', '' => '睾', '' => '瞃', '' => '碲', '' => '碪', '' => '碴', '' => '碭', '' => '碨', '' => '硾', '' => '碫', '' => '碞', '' => '碥', '' => '碠', '' => '碬', '' => '碢', '' => '碤', '' => '禘', '' => '禊', '' => '禋', '' => '禖', '' => '禕', '' => '禔', '' => '禓', '@' => '禗', 'A' => '禈', 'B' => '禒', 'C' => '禐', 'D' => '稫', 'E' => '穊', 'F' => '稰', 'G' => '稯', 'H' => '稨', 'I' => '稦', 'J' => '窨', 'K' => '窫', 'L' => '窬', 'M' => '竮', 'N' => '箈', 'O' => '箜', 'P' => '箊', 'Q' => '箑', 'R' => '箐', 'S' => '箖', 'T' => '箍', 'U' => '箌', 'V' => '箛', 'W' => '箎', 'X' => '箅', 'Y' => '箘', 'Z' => '劄', '[' => '箙', '\\' => '箤', ']' => '箂', '^' => '粻', '_' => '粿', '`' => '粼', 'a' => '粺', 'b' => '綧', 'c' => '綷', 'd' => '緂', 'e' => '綣', 'f' => '綪', 'g' => '緁', 'h' => '緀', 'i' => '緅', 'j' => '綝', 'k' => '緎', 'l' => '緄', 'm' => '緆', 'n' => '緋', 'o' => '緌', 'p' => '綯', 'q' => '綹', 'r' => '綖', 's' => '綼', 't' => '綟', 'u' => '綦', 'v' => '綮', 'w' => '綩', 'x' => '綡', 'y' => '緉', 'z' => '罳', '{' => '翢', '|' => '翣', '}' => '翥', '~' => '翞', '' => '耤', '' => '聝', '' => '聜', '' => '膉', '' => '膆', '' => '膃', '' => '膇', '' => '膍', '' => '膌', '' => '膋', '' => '舕', '' => '蒗', '' => '蒤', '' => '蒡', '' => '蒟', '' => '蒺', '' => '蓎', '' => '蓂', '' => '蒬', '' => '蒮', '' => '蒫', '' => '蒹', '' => '蒴', '' => '蓁', '' => '蓍', '' => '蒪', '' => '蒚', '' => '蒱', '' => '蓐', '' => '蒝', '' => '蒧', '' => '蒻', '' => '蒢', '' => '蒔', '' => '蓇', '' => '蓌', '' => '蒛', '' => '蒩', '' => '蒯', '' => '蒨', '' => '蓖', '' => '蒘', '' => '蒶', '' => '蓏', '' => '蒠', '' => '蓗', '' => '蓔', '' => '蓒', '' => '蓛', '' => '蒰', '' => '蒑', '' => '虡', '' => '蜳', '' => '蜣', '' => '蜨', '' => '蝫', '' => '蝀', '' => '蜮', '' => '蜞', '' => '蜡', '' => '蜙', '' => '蜛', '' => '蝃', '' => '蜬', '' => '蝁', '' => '蜾', '' => '蝆', '' => '蜠', '' => '蜲', '' => '蜪', '' => '蜭', '' => '蜼', '' => '蜒', '' => '蜺', '' => '蜱', '' => '蜵', '' => '蝂', '' => '蜦', '' => '蜧', '' => '蜸', '' => '蜤', '' => '蜚', '' => '蜰', '' => '蜑', '' => '裷', '' => '裧', '' => '裱', '' => '裲', '' => '裺', '' => '裾', '' => '裮', '' => '裼', '' => '裶', '' => '裻', '@' => '裰', 'A' => '裬', 'B' => '裫', 'C' => '覝', 'D' => '覡', 'E' => '覟', 'F' => '覞', 'G' => '觩', 'H' => '觫', 'I' => '觨', 'J' => '誫', 'K' => '誙', 'L' => '誋', 'M' => '誒', 'N' => '誏', 'O' => '誖', 'P' => '谽', 'Q' => '豨', 'R' => '豩', 'S' => '賕', 'T' => '賏', 'U' => '賗', 'V' => '趖', 'W' => '踉', 'X' => '踂', 'Y' => '跿', 'Z' => '踍', '[' => '跽', '\\' => '踊', ']' => '踃', '^' => '踇', '_' => '踆', '`' => '踅', 'a' => '跾', 'b' => '踀', 'c' => '踄', 'd' => '輐', 'e' => '輑', 'f' => '輎', 'g' => '輍', 'h' => '鄣', 'i' => '鄜', 'j' => '鄠', 'k' => '鄢', 'l' => '鄟', 'm' => '鄝', 'n' => '鄚', 'o' => '鄤', 'p' => '鄡', 'q' => '鄛', 'r' => '酺', 's' => '酲', 't' => '酹', 'u' => '酳', 'v' => '銥', 'w' => '銤', 'x' => '鉶', 'y' => '銛', 'z' => '鉺', '{' => '銠', '|' => '銔', '}' => '銪', '~' => '銍', '' => '銦', '' => '銚', '' => '銫', '' => '鉹', '' => '銗', '' => '鉿', '' => '銣', '' => '鋮', '' => '銎', '' => '銂', '' => '銕', '' => '銢', '' => '鉽', '' => '銈', '' => '銡', '' => '銊', '' => '銆', '' => '銌', '' => '銙', '' => '銧', '' => '鉾', '' => '銇', '' => '銩', '' => '銝', '' => '銋', '' => '鈭', '' => '隞', '' => '隡', '' => '雿', '' => '靘', '' => '靽', '' => '靺', '' => '靾', '' => '鞃', '' => '鞀', '' => '鞂', '' => '靻', '' => '鞄', '' => '鞁', '' => '靿', '' => '韎', '' => '韍', '' => '頖', '' => '颭', '' => '颮', '' => '餂', '' => '餀', '' => '餇', '' => '馝', '' => '馜', '' => '駃', '' => '馹', '' => '馻', '' => '馺', '' => '駂', '' => '馽', '' => '駇', '' => '骱', '' => '髣', '' => '髧', '' => '鬾', '' => '鬿', '' => '魠', '' => '魡', '' => '魟', '' => '鳱', '' => '鳲', '' => '鳵', '' => '麧', '' => '僿', '' => '儃', '' => '儰', '' => '僸', '' => '儆', '' => '儇', '' => '僶', '' => '僾', '' => '儋', '' => '儌', '' => '僽', '' => '儊', '' => '劋', '' => '劌', '' => '勱', '' => '勯', '' => '噈', '' => '噂', '' => '噌', '' => '嘵', '' => '噁', '' => '噊', '' => '噉', '' => '噆', '' => '噘', '@' => '噚', 'A' => '噀', 'B' => '嘳', 'C' => '嘽', 'D' => '嘬', 'E' => '嘾', 'F' => '嘸', 'G' => '嘪', 'H' => '嘺', 'I' => '圚', 'J' => '墫', 'K' => '墝', 'L' => '墱', 'M' => '墠', 'N' => '墣', 'O' => '墯', 'P' => '墬', 'Q' => '墥', 'R' => '墡', 'S' => '壿', 'T' => '嫿', 'U' => '嫴', 'V' => '嫽', 'W' => '嫷', 'X' => '嫶', 'Y' => '嬃', 'Z' => '嫸', '[' => '嬂', '\\' => '嫹', ']' => '嬁', '^' => '嬇', '_' => '嬅', '`' => '嬏', 'a' => '屧', 'b' => '嶙', 'c' => '嶗', 'd' => '嶟', 'e' => '嶒', 'f' => '嶢', 'g' => '嶓', 'h' => '嶕', 'i' => '嶠', 'j' => '嶜', 'k' => '嶡', 'l' => '嶚', 'm' => '嶞', 'n' => '幩', 'o' => '幝', 'p' => '幠', 'q' => '幜', 'r' => '緳', 's' => '廛', 't' => '廞', 'u' => '廡', 'v' => '彉', 'w' => '徲', 'x' => '憋', 'y' => '憃', 'z' => '慹', '{' => '憱', '|' => '憰', '}' => '憢', '~' => '憉', '' => '憛', '' => '憓', '' => '憯', '' => '憭', '' => '憟', '' => '憒', '' => '憪', '' => '憡', '' => '憍', '' => '慦', '' => '憳', '' => '戭', '' => '摮', '' => '摰', '' => '撖', '' => '撠', '' => '撅', '' => '撗', '' => '撜', '' => '撏', '' => '撋', '' => '撊', '' => '撌', '' => '撣', '' => '撟', '' => '摨', '' => '撱', '' => '撘', '' => '敶', '' => '敺', '' => '敹', '' => '敻', '' => '斲', '' => '斳', '' => '暵', '' => '暰', '' => '暩', '' => '暲', '' => '暷', '' => '暪', '' => '暯', '' => '樀', '' => '樆', '' => '樗', '' => '槥', '' => '槸', '' => '樕', '' => '槱', '' => '槤', '' => '樠', '' => '槿', '' => '槬', '' => '槢', '' => '樛', '' => '樝', '' => '槾', '' => '樧', '' => '槲', '' => '槮', '' => '樔', '' => '槷', '' => '槧', '' => '橀', '' => '樈', '' => '槦', '' => '槻', '' => '樍', '' => '槼', '' => '槫', '' => '樉', '' => '樄', '' => '樘', '' => '樥', '' => '樏', '' => '槶', '' => '樦', '' => '樇', '' => '槴', '' => '樖', '' => '歑', '' => '殥', '' => '殣', '' => '殢', '' => '殦', '' => '氁', '' => '氀', '' => '毿', '' => '氂', '' => '潁', '' => '漦', '' => '潾', '' => '澇', '' => '濆', '' => '澒', '@' => '澍', 'A' => '澉', 'B' => '澌', 'C' => '潢', 'D' => '潏', 'E' => '澅', 'F' => '潚', 'G' => '澖', 'H' => '潶', 'I' => '潬', 'J' => '澂', 'K' => '潕', 'L' => '潲', 'M' => '潒', 'N' => '潐', 'O' => '潗', 'P' => '澔', 'Q' => '澓', 'R' => '潝', 'S' => '漀', 'T' => '潡', 'U' => '潫', 'V' => '潽', 'W' => '潧', 'X' => '澐', 'Y' => '潓', 'Z' => '澋', '[' => '潩', '\\' => '潿', ']' => '澕', '^' => '潣', '_' => '潷', '`' => '潪', 'a' => '潻', 'b' => '熲', 'c' => '熯', 'd' => '熛', 'e' => '熰', 'f' => '熠', 'g' => '熚', 'h' => '熩', 'i' => '熵', 'j' => '熝', 'k' => '熥', 'l' => '熞', 'm' => '熤', 'n' => '熡', 'o' => '熪', 'p' => '熜', 'q' => '熧', 'r' => '熳', 's' => '犘', 't' => '犚', 'u' => '獘', 'v' => '獒', 'w' => '獞', 'x' => '獟', 'y' => '獠', 'z' => '獝', '{' => '獛', '|' => '獡', '}' => '獚', '~' => '獙', '' => '獢', '' => '璇', '' => '璉', '' => '璊', '' => '璆', '' => '璁', '' => '瑽', '' => '璅', '' => '璈', '' => '瑼', '' => '瑹', '' => '甈', '' => '甇', '' => '畾', '' => '瘥', '' => '瘞', '' => '瘙', '' => '瘝', '' => '瘜', '' => '瘣', '' => '瘚', '' => '瘨', '' => '瘛', '' => '皜', '' => '皝', '' => '皞', '' => '皛', '' => '瞍', '' => '瞏', '' => '瞉', '' => '瞈', '' => '磍', '' => '碻', '' => '磏', '' => '磌', '' => '磑', '' => '磎', '' => '磔', '' => '磈', '' => '磃', '' => '磄', '' => '磉', '' => '禚', '' => '禡', '' => '禠', '' => '禜', '' => '禢', '' => '禛', '' => '歶', '' => '稹', '' => '窲', '' => '窴', '' => '窳', '' => '箷', '' => '篋', '' => '箾', '' => '箬', '' => '篎', '' => '箯', '' => '箹', '' => '篊', '' => '箵', '' => '糅', '' => '糈', '' => '糌', '' => '糋', '' => '緷', '' => '緛', '' => '緪', '' => '緧', '' => '緗', '' => '緡', '' => '縃', '' => '緺', '' => '緦', '' => '緶', '' => '緱', '' => '緰', '' => '緮', '' => '緟', '' => '罶', '' => '羬', '' => '羰', '' => '羭', '' => '翭', '' => '翫', '' => '翪', '' => '翬', '' => '翦', '' => '翨', '' => '聤', '' => '聧', '' => '膣', '' => '膟', '@' => '膞', 'A' => '膕', 'B' => '膢', 'C' => '膙', 'D' => '膗', 'E' => '舖', 'F' => '艏', 'G' => '艓', 'H' => '艒', 'I' => '艐', 'J' => '艎', 'K' => '艑', 'L' => '蔤', 'M' => '蔻', 'N' => '蔏', 'O' => '蔀', 'P' => '蔩', 'Q' => '蔎', 'R' => '蔉', 'S' => '蔍', 'T' => '蔟', 'U' => '蔊', 'V' => '蔧', 'W' => '蔜', 'X' => '蓻', 'Y' => '蔫', 'Z' => '蓺', '[' => '蔈', '\\' => '蔌', ']' => '蓴', '^' => '蔪', '_' => '蓲', '`' => '蔕', 'a' => '蓷', 'b' => '蓫', 'c' => '蓳', 'd' => '蓼', 'e' => '蔒', 'f' => '蓪', 'g' => '蓩', 'h' => '蔖', 'i' => '蓾', 'j' => '蔨', 'k' => '蔝', 'l' => '蔮', 'm' => '蔂', 'n' => '蓽', 'o' => '蔞', 'p' => '蓶', 'q' => '蔱', 'r' => '蔦', 's' => '蓧', 't' => '蓨', 'u' => '蓰', 'v' => '蓯', 'w' => '蓹', 'x' => '蔘', 'y' => '蔠', 'z' => '蔰', '{' => '蔋', '|' => '蔙', '}' => '蔯', '~' => '虢', '' => '蝖', '' => '蝣', '' => '蝤', '' => '蝷', '' => '蟡', '' => '蝳', '' => '蝘', '' => '蝔', '' => '蝛', '' => '蝒', '' => '蝡', '' => '蝚', '' => '蝑', '' => '蝞', '' => '蝭', '' => '蝪', '' => '蝐', '' => '蝎', '' => '蝟', '' => '蝝', '' => '蝯', '' => '蝬', '' => '蝺', '' => '蝮', '' => '蝜', '' => '蝥', '' => '蝏', '' => '蝻', '' => '蝵', '' => '蝢', '' => '蝧', '' => '蝩', '' => '衚', '' => '褅', '' => '褌', '' => '褔', '' => '褋', '' => '褗', '' => '褘', '' => '褙', '' => '褆', '' => '褖', '' => '褑', '' => '褎', '' => '褉', '' => '覢', '' => '覤', '' => '覣', '' => '觭', '' => '觰', '' => '觬', '' => '諏', '' => '諆', '' => '誸', '' => '諓', '' => '諑', '' => '諔', '' => '諕', '' => '誻', '' => '諗', '' => '誾', '' => '諀', '' => '諅', '' => '諘', '' => '諃', '' => '誺', '' => '誽', '' => '諙', '' => '谾', '' => '豍', '' => '貏', '' => '賥', '' => '賟', '' => '賙', '' => '賨', '' => '賚', '' => '賝', '' => '賧', '' => '趠', '' => '趜', '' => '趡', '' => '趛', '' => '踠', '' => '踣', '' => '踥', '' => '踤', '' => '踮', '' => '踕', '' => '踛', '' => '踖', '' => '踑', '' => '踙', '' => '踦', '' => '踧', '@' => '踔', 'A' => '踒', 'B' => '踘', 'C' => '踓', 'D' => '踜', 'E' => '踗', 'F' => '踚', 'G' => '輬', 'H' => '輤', 'I' => '輘', 'J' => '輚', 'K' => '輠', 'L' => '輣', 'M' => '輖', 'N' => '輗', 'O' => '遳', 'P' => '遰', 'Q' => '遯', 'R' => '遧', 'S' => '遫', 'T' => '鄯', 'U' => '鄫', 'V' => '鄩', 'W' => '鄪', 'X' => '鄲', 'Y' => '鄦', 'Z' => '鄮', '[' => '醅', '\\' => '醆', ']' => '醊', '^' => '醁', '_' => '醂', '`' => '醄', 'a' => '醀', 'b' => '鋐', 'c' => '鋃', 'd' => '鋄', 'e' => '鋀', 'f' => '鋙', 'g' => '銶', 'h' => '鋏', 'i' => '鋱', 'j' => '鋟', 'k' => '鋘', 'l' => '鋩', 'm' => '鋗', 'n' => '鋝', 'o' => '鋌', 'p' => '鋯', 'q' => '鋂', 'r' => '鋨', 's' => '鋊', 't' => '鋈', 'u' => '鋎', 'v' => '鋦', 'w' => '鋍', 'x' => '鋕', 'y' => '鋉', 'z' => '鋠', '{' => '鋞', '|' => '鋧', '}' => '鋑', '~' => '鋓', '' => '銵', '' => '鋡', '' => '鋆', '' => '銴', '' => '镼', '' => '閬', '' => '閫', '' => '閮', '' => '閰', '' => '隤', '' => '隢', '' => '雓', '' => '霅', '' => '霈', '' => '霂', '' => '靚', '' => '鞊', '' => '鞎', '' => '鞈', '' => '韐', '' => '韏', '' => '頞', '' => '頝', '' => '頦', '' => '頩', '' => '頨', '' => '頠', '' => '頛', '' => '頧', '' => '颲', '' => '餈', '' => '飺', '' => '餑', '' => '餔', '' => '餖', '' => '餗', '' => '餕', '' => '駜', '' => '駍', '' => '駏', '' => '駓', '' => '駔', '' => '駎', '' => '駉', '' => '駖', '' => '駘', '' => '駋', '' => '駗', '' => '駌', '' => '骳', '' => '髬', '' => '髫', '' => '髳', '' => '髲', '' => '髱', '' => '魆', '' => '魃', '' => '魧', '' => '魴', '' => '魱', '' => '魦', '' => '魶', '' => '魵', '' => '魰', '' => '魨', '' => '魤', '' => '魬', '' => '鳼', '' => '鳺', '' => '鳽', '' => '鳿', '' => '鳷', '' => '鴇', '' => '鴀', '' => '鳹', '' => '鳻', '' => '鴈', '' => '鴅', '' => '鴄', '' => '麃', '' => '黓', '' => '鼏', '' => '鼐', '' => '儜', '' => '儓', '' => '儗', '' => '儚', '' => '儑', '' => '凞', '' => '匴', '' => '叡', '' => '噰', '' => '噠', '' => '噮', '@' => '噳', 'A' => '噦', 'B' => '噣', 'C' => '噭', 'D' => '噲', 'E' => '噞', 'F' => '噷', 'G' => '圜', 'H' => '圛', 'I' => '壈', 'J' => '墽', 'K' => '壉', 'L' => '墿', 'M' => '墺', 'N' => '壂', 'O' => '墼', 'P' => '壆', 'Q' => '嬗', 'R' => '嬙', 'S' => '嬛', 'T' => '嬡', 'U' => '嬔', 'V' => '嬓', 'W' => '嬐', 'X' => '嬖', 'Y' => '嬨', 'Z' => '嬚', '[' => '嬠', '\\' => '嬞', ']' => '寯', '^' => '嶬', '_' => '嶱', '`' => '嶩', 'a' => '嶧', 'b' => '嶵', 'c' => '嶰', 'd' => '嶮', 'e' => '嶪', 'f' => '嶨', 'g' => '嶲', 'h' => '嶭', 'i' => '嶯', 'j' => '嶴', 'k' => '幧', 'l' => '幨', 'm' => '幦', 'n' => '幯', 'o' => '廩', 'p' => '廧', 'q' => '廦', 'r' => '廨', 's' => '廥', 't' => '彋', 'u' => '徼', 'v' => '憝', 'w' => '憨', 'x' => '憖', 'y' => '懅', 'z' => '憴', '{' => '懆', '|' => '懁', '}' => '懌', '~' => '憺', '' => '憿', '' => '憸', '' => '憌', '' => '擗', '' => '擖', '' => '擐', '' => '擏', '' => '擉', '' => '撽', '' => '撉', '' => '擃', '' => '擛', '' => '擳', '' => '擙', '' => '攳', '' => '敿', '' => '敼', '' => '斢', '' => '曈', '' => '暾', '' => '曀', '' => '曊', '' => '曋', '' => '曏', '' => '暽', '' => '暻', '' => '暺', '' => '曌', '' => '朣', '' => '樴', '' => '橦', '' => '橉', '' => '橧', '' => '樲', '' => '橨', '' => '樾', '' => '橝', '' => '橭', '' => '橶', '' => '橛', '' => '橑', '' => '樨', '' => '橚', '' => '樻', '' => '樿', '' => '橁', '' => '橪', '' => '橤', '' => '橐', '' => '橏', '' => '橔', '' => '橯', '' => '橩', '' => '橠', '' => '樼', '' => '橞', '' => '橖', '' => '橕', '' => '橍', '' => '橎', '' => '橆', '' => '歕', '' => '歔', '' => '歖', '' => '殧', '' => '殪', '' => '殫', '' => '毈', '' => '毇', '' => '氄', '' => '氃', '' => '氆', '' => '澭', '' => '濋', '' => '澣', '' => '濇', '' => '澼', '' => '濎', '' => '濈', '' => '潞', '' => '濄', '' => '澽', '' => '澞', '' => '濊', '' => '澨', '' => '瀄', '' => '澥', '' => '澮', '' => '澺', '' => '澬', '' => '澪', '' => '濏', '' => '澿', '' => '澸', '@' => '澢', 'A' => '濉', 'B' => '澫', 'C' => '濍', 'D' => '澯', 'E' => '澲', 'F' => '澰', 'G' => '燅', 'H' => '燂', 'I' => '熿', 'J' => '熸', 'K' => '燖', 'L' => '燀', 'M' => '燁', 'N' => '燋', 'O' => '燔', 'P' => '燊', 'Q' => '燇', 'R' => '燏', 'S' => '熽', 'T' => '燘', 'U' => '熼', 'V' => '燆', 'W' => '燚', 'X' => '燛', 'Y' => '犝', 'Z' => '犞', '[' => '獩', '\\' => '獦', ']' => '獧', '^' => '獬', '_' => '獥', '`' => '獫', 'a' => '獪', 'b' => '瑿', 'c' => '璚', 'd' => '璠', 'e' => '璔', 'f' => '璒', 'g' => '璕', 'h' => '璡', 'i' => '甋', 'j' => '疀', 'k' => '瘯', 'l' => '瘭', 'm' => '瘱', 'n' => '瘽', 'o' => '瘳', 'p' => '瘼', 'q' => '瘵', 'r' => '瘲', 's' => '瘰', 't' => '皻', 'u' => '盦', 'v' => '瞚', 'w' => '瞝', 'x' => '瞡', 'y' => '瞜', 'z' => '瞛', '{' => '瞢', '|' => '瞣', '}' => '瞕', '~' => '瞙', '' => '瞗', '' => '磝', '' => '磩', '' => '磥', '' => '磪', '' => '磞', '' => '磣', '' => '磛', '' => '磡', '' => '磢', '' => '磭', '' => '磟', '' => '磠', '' => '禤', '' => '穄', '' => '穈', '' => '穇', '' => '窶', '' => '窸', '' => '窵', '' => '窱', '' => '窷', '' => '篞', '' => '篣', '' => '篧', '' => '篝', '' => '篕', '' => '篥', '' => '篚', '' => '篨', '' => '篹', '' => '篔', '' => '篪', '' => '篢', '' => '篜', '' => '篫', '' => '篘', '' => '篟', '' => '糒', '' => '糔', '' => '糗', '' => '糐', '' => '糑', '' => '縒', '' => '縡', '' => '縗', '' => '縌', '' => '縟', '' => '縠', '' => '縓', '' => '縎', '' => '縜', '' => '縕', '' => '縚', '' => '縢', '' => '縋', '' => '縏', '' => '縖', '' => '縍', '' => '縔', '' => '縥', '' => '縤', '' => '罃', '' => '罻', '' => '罼', '' => '罺', '' => '羱', '' => '翯', '' => '耪', '' => '耩', '' => '聬', '' => '膱', '' => '膦', '' => '膮', '' => '膹', '' => '膵', '' => '膫', '' => '膰', '' => '膬', '' => '膴', '' => '膲', '' => '膷', '' => '膧', '' => '臲', '' => '艕', '' => '艖', '' => '艗', '' => '蕖', '' => '蕅', '' => '蕫', '' => '蕍', '' => '蕓', '' => '蕡', '' => '蕘', '@' => '蕀', 'A' => '蕆', 'B' => '蕤', 'C' => '蕁', 'D' => '蕢', 'E' => '蕄', 'F' => '蕑', 'G' => '蕇', 'H' => '蕣', 'I' => '蔾', 'J' => '蕛', 'K' => '蕱', 'L' => '蕎', 'M' => '蕮', 'N' => '蕵', 'O' => '蕕', 'P' => '蕧', 'Q' => '蕠', 'R' => '薌', 'S' => '蕦', 'T' => '蕝', 'U' => '蕔', 'V' => '蕥', 'W' => '蕬', 'X' => '虣', 'Y' => '虥', 'Z' => '虤', '[' => '螛', '\\' => '螏', ']' => '螗', '^' => '螓', '_' => '螒', '`' => '螈', 'a' => '螁', 'b' => '螖', 'c' => '螘', 'd' => '蝹', 'e' => '螇', 'f' => '螣', 'g' => '螅', 'h' => '螐', 'i' => '螑', 'j' => '螝', 'k' => '螄', 'l' => '螔', 'm' => '螜', 'n' => '螚', 'o' => '螉', 'p' => '褞', 'q' => '褦', 'r' => '褰', 's' => '褭', 't' => '褮', 'u' => '褧', 'v' => '褱', 'w' => '褢', 'x' => '褩', 'y' => '褣', 'z' => '褯', '{' => '褬', '|' => '褟', '}' => '觱', '~' => '諠', '' => '諢', '' => '諲', '' => '諴', '' => '諵', '' => '諝', '' => '謔', '' => '諤', '' => '諟', '' => '諰', '' => '諈', '' => '諞', '' => '諡', '' => '諨', '' => '諿', '' => '諯', '' => '諻', '' => '貑', '' => '貒', '' => '貐', '' => '賵', '' => '賮', '' => '賱', '' => '賰', '' => '賳', '' => '赬', '' => '赮', '' => '趥', '' => '趧', '' => '踳', '' => '踾', '' => '踸', '' => '蹀', '' => '蹅', '' => '踶', '' => '踼', '' => '踽', '' => '蹁', '' => '踰', '' => '踿', '' => '躽', '' => '輶', '' => '輮', '' => '輵', '' => '輲', '' => '輹', '' => '輷', '' => '輴', '' => '遶', '' => '遹', '' => '遻', '' => '邆', '' => '郺', '' => '鄳', '' => '鄵', '' => '鄶', '' => '醓', '' => '醐', '' => '醑', '' => '醍', '' => '醏', '' => '錧', '' => '錞', '' => '錈', '' => '錟', '' => '錆', '' => '錏', '' => '鍺', '' => '錸', '' => '錼', '' => '錛', '' => '錣', '' => '錒', '' => '錁', '' => '鍆', '' => '錭', '' => '錎', '' => '錍', '' => '鋋', '' => '錝', '' => '鋺', '' => '錥', '' => '錓', '' => '鋹', '' => '鋷', '' => '錴', '' => '錂', '' => '錤', '' => '鋿', '' => '錩', '' => '錹', '' => '錵', '' => '錪', '' => '錔', '' => '錌', '@' => '錋', 'A' => '鋾', 'B' => '錉', 'C' => '錀', 'D' => '鋻', 'E' => '錖', 'F' => '閼', 'G' => '闍', 'H' => '閾', 'I' => '閹', 'J' => '閺', 'K' => '閶', 'L' => '閿', 'M' => '閵', 'N' => '閽', 'O' => '隩', 'P' => '雔', 'Q' => '霋', 'R' => '霒', 'S' => '霐', 'T' => '鞙', 'U' => '鞗', 'V' => '鞔', 'W' => '韰', 'X' => '韸', 'Y' => '頵', 'Z' => '頯', '[' => '頲', '\\' => '餤', ']' => '餟', '^' => '餧', '_' => '餩', '`' => '馞', 'a' => '駮', 'b' => '駬', 'c' => '駥', 'd' => '駤', 'e' => '駰', 'f' => '駣', 'g' => '駪', 'h' => '駩', 'i' => '駧', 'j' => '骹', 'k' => '骿', 'l' => '骴', 'm' => '骻', 'n' => '髶', 'o' => '髺', 'p' => '髹', 'q' => '髷', 'r' => '鬳', 's' => '鮀', 't' => '鮅', 'u' => '鮇', 'v' => '魼', 'w' => '魾', 'x' => '魻', 'y' => '鮂', 'z' => '鮓', '{' => '鮒', '|' => '鮐', '}' => '魺', '~' => '鮕', '' => '魽', '' => '鮈', '' => '鴥', '' => '鴗', '' => '鴠', '' => '鴞', '' => '鴔', '' => '鴩', '' => '鴝', '' => '鴘', '' => '鴢', '' => '鴐', '' => '鴙', '' => '鴟', '' => '麈', '' => '麆', '' => '麇', '' => '麮', '' => '麭', '' => '黕', '' => '黖', '' => '黺', '' => '鼒', '' => '鼽', '' => '儦', '' => '儥', '' => '儢', '' => '儤', '' => '儠', '' => '儩', '' => '勴', '' => '嚓', '' => '嚌', '' => '嚍', '' => '嚆', '' => '嚄', '' => '嚃', '' => '噾', '' => '嚂', '' => '噿', '' => '嚁', '' => '壖', '' => '壔', '' => '壏', '' => '壒', '' => '嬭', '' => '嬥', '' => '嬲', '' => '嬣', '' => '嬬', '' => '嬧', '' => '嬦', '' => '嬯', '' => '嬮', '' => '孻', '' => '寱', '' => '寲', '' => '嶷', '' => '幬', '' => '幪', '' => '徾', '' => '徻', '' => '懃', '' => '憵', '' => '憼', '' => '懧', '' => '懠', '' => '懥', '' => '懤', '' => '懨', '' => '懞', '' => '擯', '' => '擩', '' => '擣', '' => '擫', '' => '擤', '' => '擨', '' => '斁', '' => '斀', '' => '斶', '' => '旚', '' => '曒', '' => '檍', '' => '檖', '' => '檁', '' => '檥', '' => '檉', '' => '檟', '' => '檛', '' => '檡', '' => '檞', '' => '檇', '' => '檓', '' => '檎', '@' => '檕', 'A' => '檃', 'B' => '檨', 'C' => '檤', 'D' => '檑', 'E' => '橿', 'F' => '檦', 'G' => '檚', 'H' => '檅', 'I' => '檌', 'J' => '檒', 'K' => '歛', 'L' => '殭', 'M' => '氉', 'N' => '濌', 'O' => '澩', 'P' => '濴', 'Q' => '濔', 'R' => '濣', 'S' => '濜', 'T' => '濭', 'U' => '濧', 'V' => '濦', 'W' => '濞', 'X' => '濲', 'Y' => '濝', 'Z' => '濢', '[' => '濨', '\\' => '燡', ']' => '燱', '^' => '燨', '_' => '燲', '`' => '燤', 'a' => '燰', 'b' => '燢', 'c' => '獳', 'd' => '獮', 'e' => '獯', 'f' => '璗', 'g' => '璲', 'h' => '璫', 'i' => '璐', 'j' => '璪', 'k' => '璭', 'l' => '璱', 'm' => '璥', 'n' => '璯', 'o' => '甐', 'p' => '甑', 'q' => '甒', 'r' => '甏', 's' => '疄', 't' => '癃', 'u' => '癈', 'v' => '癉', 'w' => '癇', 'x' => '皤', 'y' => '盩', 'z' => '瞵', '{' => '瞫', '|' => '瞲', '}' => '瞷', '~' => '瞶', '' => '瞴', '' => '瞱', '' => '瞨', '' => '矰', '' => '磳', '' => '磽', '' => '礂', '' => '磻', '' => '磼', '' => '磲', '' => '礅', '' => '磹', '' => '磾', '' => '礄', '' => '禫', '' => '禨', '' => '穜', '' => '穛', '' => '穖', '' => '穘', '' => '穔', '' => '穚', '' => '窾', '' => '竀', '' => '竁', '' => '簅', '' => '簏', '' => '篲', '' => '簀', '' => '篿', '' => '篻', '' => '簎', '' => '篴', '' => '簋', '' => '篳', '' => '簂', '' => '簉', '' => '簃', '' => '簁', '' => '篸', '' => '篽', '' => '簆', '' => '篰', '' => '篱', '' => '簐', '' => '簊', '' => '糨', '' => '縭', '' => '縼', '' => '繂', '' => '縳', '' => '顈', '' => '縸', '' => '縪', '' => '繉', '' => '繀', '' => '繇', '' => '縩', '' => '繌', '' => '縰', '' => '縻', '' => '縶', '' => '繄', '' => '縺', '' => '罅', '' => '罿', '' => '罾', '' => '罽', '' => '翴', '' => '翲', '' => '耬', '' => '膻', '' => '臄', '' => '臌', '' => '臊', '' => '臅', '' => '臇', '' => '膼', '' => '臩', '' => '艛', '' => '艚', '' => '艜', '' => '薃', '' => '薀', '' => '薏', '' => '薧', '' => '薕', '' => '薠', '' => '薋', '' => '薣', '' => '蕻', '' => '薤', '' => '薚', '' => '薞', '@' => '蕷', 'A' => '蕼', 'B' => '薉', 'C' => '薡', 'D' => '蕺', 'E' => '蕸', 'F' => '蕗', 'G' => '薎', 'H' => '薖', 'I' => '薆', 'J' => '薍', 'K' => '薙', 'L' => '薝', 'M' => '薁', 'N' => '薢', 'O' => '薂', 'P' => '薈', 'Q' => '薅', 'R' => '蕹', 'S' => '蕶', 'T' => '薘', 'U' => '薐', 'V' => '薟', 'W' => '虨', 'X' => '螾', 'Y' => '螪', 'Z' => '螭', '[' => '蟅', '\\' => '螰', ']' => '螬', '^' => '螹', '_' => '螵', '`' => '螼', 'a' => '螮', 'b' => '蟉', 'c' => '蟃', 'd' => '蟂', 'e' => '蟌', 'f' => '螷', 'g' => '螯', 'h' => '蟄', 'i' => '蟊', 'j' => '螴', 'k' => '螶', 'l' => '螿', 'm' => '螸', 'n' => '螽', 'o' => '蟞', 'p' => '螲', 'q' => '褵', 'r' => '褳', 's' => '褼', 't' => '褾', 'u' => '襁', 'v' => '襒', 'w' => '褷', 'x' => '襂', 'y' => '覭', 'z' => '覯', '{' => '覮', '|' => '觲', '}' => '觳', '~' => '謞', '' => '謘', '' => '謖', '' => '謑', '' => '謅', '' => '謋', '' => '謢', '' => '謏', '' => '謒', '' => '謕', '' => '謇', '' => '謍', '' => '謈', '' => '謆', '' => '謜', '' => '謓', '' => '謚', '' => '豏', '' => '豰', '' => '豲', '' => '豱', '' => '豯', '' => '貕', '' => '貔', '' => '賹', '' => '赯', '' => '蹎', '' => '蹍', '' => '蹓', '' => '蹐', '' => '蹌', '' => '蹇', '' => '轃', '' => '轀', '' => '邅', '' => '遾', '' => '鄸', '' => '醚', '' => '醢', '' => '醛', '' => '醙', '' => '醟', '' => '醡', '' => '醝', '' => '醠', '' => '鎡', '' => '鎃', '' => '鎯', '' => '鍤', '' => '鍖', '' => '鍇', '' => '鍼', '' => '鍘', '' => '鍜', '' => '鍶', '' => '鍉', '' => '鍐', '' => '鍑', '' => '鍠', '' => '鍭', '' => '鎏', '' => '鍌', '' => '鍪', '' => '鍹', '' => '鍗', '' => '鍕', '' => '鍒', '' => '鍏', '' => '鍱', '' => '鍷', '' => '鍻', '' => '鍡', '' => '鍞', '' => '鍣', '' => '鍧', '' => '鎀', '' => '鍎', '' => '鍙', '' => '闇', '' => '闀', '' => '闉', '' => '闃', '' => '闅', '' => '閷', '' => '隮', '' => '隰', '' => '隬', '' => '霠', '' => '霟', '' => '霘', '' => '霝', '' => '霙', '' => '鞚', '' => '鞡', '' => '鞜', '@' => '鞞', 'A' => '鞝', 'B' => '韕', 'C' => '韔', 'D' => '韱', 'E' => '顁', 'F' => '顄', 'G' => '顊', 'H' => '顉', 'I' => '顅', 'J' => '顃', 'K' => '餥', 'L' => '餫', 'M' => '餬', 'N' => '餪', 'O' => '餳', 'P' => '餲', 'Q' => '餯', 'R' => '餭', 'S' => '餱', 'T' => '餰', 'U' => '馘', 'V' => '馣', 'W' => '馡', 'X' => '騂', 'Y' => '駺', 'Z' => '駴', '[' => '駷', '\\' => '駹', ']' => '駸', '^' => '駶', '_' => '駻', '`' => '駽', 'a' => '駾', 'b' => '駼', 'c' => '騃', 'd' => '骾', 'e' => '髾', 'f' => '髽', 'g' => '鬁', 'h' => '髼', 'i' => '魈', 'j' => '鮚', 'k' => '鮨', 'l' => '鮞', 'm' => '鮛', 'n' => '鮦', 'o' => '鮡', 'p' => '鮥', 'q' => '鮤', 'r' => '鮆', 's' => '鮢', 't' => '鮠', 'u' => '鮯', 'v' => '鴳', 'w' => '鵁', 'x' => '鵧', 'y' => '鴶', 'z' => '鴮', '{' => '鴯', '|' => '鴱', '}' => '鴸', '~' => '鴰', '' => '鵅', '' => '鵂', '' => '鵃', '' => '鴾', '' => '鴷', '' => '鵀', '' => '鴽', '' => '翵', '' => '鴭', '' => '麊', '' => '麉', '' => '麍', '' => '麰', '' => '黈', '' => '黚', '' => '黻', '' => '黿', '' => '鼤', '' => '鼣', '' => '鼢', '' => '齔', '' => '龠', '' => '儱', '' => '儭', '' => '儮', '' => '嚘', '' => '嚜', '' => '嚗', '' => '嚚', '' => '嚝', '' => '嚙', '' => '奰', '' => '嬼', '' => '屩', '' => '屪', '' => '巀', '' => '幭', '' => '幮', '' => '懘', '' => '懟', '' => '懭', '' => '懮', '' => '懱', '' => '懪', '' => '懰', '' => '懫', '' => '懖', '' => '懩', '' => '擿', '' => '攄', '' => '擽', '' => '擸', '' => '攁', '' => '攃', '' => '擼', '' => '斔', '' => '旛', '' => '曚', '' => '曛', '' => '曘', '' => '櫅', '' => '檹', '' => '檽', '' => '櫡', '' => '櫆', '' => '檺', '' => '檶', '' => '檷', '' => '櫇', '' => '檴', '' => '檭', '' => '歞', '' => '毉', '' => '氋', '' => '瀇', '' => '瀌', '' => '瀍', '' => '瀁', '' => '瀅', '' => '瀔', '' => '瀎', '' => '濿', '' => '瀀', '' => '濻', '' => '瀦', '' => '濼', '' => '濷', '' => '瀊', '' => '爁', '' => '燿', '' => '燹', '' => '爃', '' => '燽', '' => '獶', '@' => '璸', 'A' => '瓀', 'B' => '璵', 'C' => '瓁', 'D' => '璾', 'E' => '璶', 'F' => '璻', 'G' => '瓂', 'H' => '甔', 'I' => '甓', 'J' => '癜', 'K' => '癤', 'L' => '癙', 'M' => '癐', 'N' => '癓', 'O' => '癗', 'P' => '癚', 'Q' => '皦', 'R' => '皽', 'S' => '盬', 'T' => '矂', 'U' => '瞺', 'V' => '磿', 'W' => '礌', 'X' => '礓', 'Y' => '礔', 'Z' => '礉', '[' => '礐', '\\' => '礒', ']' => '礑', '^' => '禭', '_' => '禬', '`' => '穟', 'a' => '簜', 'b' => '簩', 'c' => '簙', 'd' => '簠', 'e' => '簟', 'f' => '簭', 'g' => '簝', 'h' => '簦', 'i' => '簨', 'j' => '簢', 'k' => '簥', 'l' => '簰', 'm' => '繜', 'n' => '繐', 'o' => '繖', 'p' => '繣', 'q' => '繘', 'r' => '繢', 's' => '繟', 't' => '繑', 'u' => '繠', 'v' => '繗', 'w' => '繓', 'x' => '羵', 'y' => '羳', 'z' => '翷', '{' => '翸', '|' => '聵', '}' => '臑', '~' => '臒', '' => '臐', '' => '艟', '' => '艞', '' => '薴', '' => '藆', '' => '藀', '' => '藃', '' => '藂', '' => '薳', '' => '薵', '' => '薽', '' => '藇', '' => '藄', '' => '薿', '' => '藋', '' => '藎', '' => '藈', '' => '藅', '' => '薱', '' => '薶', '' => '藒', '' => '蘤', '' => '薸', '' => '薷', '' => '薾', '' => '虩', '' => '蟧', '' => '蟦', '' => '蟢', '' => '蟛', '' => '蟫', '' => '蟪', '' => '蟥', '' => '蟟', '' => '蟳', '' => '蟤', '' => '蟔', '' => '蟜', '' => '蟓', '' => '蟭', '' => '蟘', '' => '蟣', '' => '螤', '' => '蟗', '' => '蟙', '' => '蠁', '' => '蟴', '' => '蟨', '' => '蟝', '' => '襓', '' => '襋', '' => '襏', '' => '襌', '' => '襆', '' => '襐', '' => '襑', '' => '襉', '' => '謪', '' => '謧', '' => '謣', '' => '謳', '' => '謰', '' => '謵', '' => '譇', '' => '謯', '' => '謼', '' => '謾', '' => '謱', '' => '謥', '' => '謷', '' => '謦', '' => '謶', '' => '謮', '' => '謤', '' => '謻', '' => '謽', '' => '謺', '' => '豂', '' => '豵', '' => '貙', '' => '貘', '' => '貗', '' => '賾', '' => '贄', '' => '贂', '' => '贀', '' => '蹜', '' => '蹢', '' => '蹠', '' => '蹗', '' => '蹖', '' => '蹞', '' => '蹥', '' => '蹧', '@' => '蹛', 'A' => '蹚', 'B' => '蹡', 'C' => '蹝', 'D' => '蹩', 'E' => '蹔', 'F' => '轆', 'G' => '轇', 'H' => '轈', 'I' => '轋', 'J' => '鄨', 'K' => '鄺', 'L' => '鄻', 'M' => '鄾', 'N' => '醨', 'O' => '醥', 'P' => '醧', 'Q' => '醯', 'R' => '醪', 'S' => '鎵', 'T' => '鎌', 'U' => '鎒', 'V' => '鎷', 'W' => '鎛', 'X' => '鎝', 'Y' => '鎉', 'Z' => '鎧', '[' => '鎎', '\\' => '鎪', ']' => '鎞', '^' => '鎦', '_' => '鎕', '`' => '鎈', 'a' => '鎙', 'b' => '鎟', 'c' => '鎍', 'd' => '鎱', 'e' => '鎑', 'f' => '鎲', 'g' => '鎤', 'h' => '鎨', 'i' => '鎴', 'j' => '鎣', 'k' => '鎥', 'l' => '闒', 'm' => '闓', 'n' => '闑', 'o' => '隳', 'p' => '雗', 'q' => '雚', 'r' => '巂', 's' => '雟', 't' => '雘', 'u' => '雝', 'v' => '霣', 'w' => '霢', 'x' => '霥', 'y' => '鞬', 'z' => '鞮', '{' => '鞨', '|' => '鞫', '}' => '鞤', '~' => '鞪', '' => '鞢', '' => '鞥', '' => '韗', '' => '韙', '' => '韖', '' => '韘', '' => '韺', '' => '顐', '' => '顑', '' => '顒', '' => '颸', '' => '饁', '' => '餼', '' => '餺', '' => '騏', '' => '騋', '' => '騉', '' => '騍', '' => '騄', '' => '騑', '' => '騊', '' => '騅', '' => '騇', '' => '騆', '' => '髀', '' => '髜', '' => '鬈', '' => '鬄', '' => '鬅', '' => '鬩', '' => '鬵', '' => '魊', '' => '魌', '' => '魋', '' => '鯇', '' => '鯆', '' => '鯃', '' => '鮿', '' => '鯁', '' => '鮵', '' => '鮸', '' => '鯓', '' => '鮶', '' => '鯄', '' => '鮹', '' => '鮽', '' => '鵜', '' => '鵓', '' => '鵏', '' => '鵊', '' => '鵛', '' => '鵋', '' => '鵙', '' => '鵖', '' => '鵌', '' => '鵗', '' => '鵒', '' => '鵔', '' => '鵟', '' => '鵘', '' => '鵚', '' => '麎', '' => '麌', '' => '黟', '' => '鼁', '' => '鼀', '' => '鼖', '' => '鼥', '' => '鼫', '' => '鼪', '' => '鼩', '' => '鼨', '' => '齌', '' => '齕', '' => '儴', '' => '儵', '' => '劖', '' => '勷', '' => '厴', '' => '嚫', '' => '嚭', '' => '嚦', '' => '嚧', '' => '嚪', '' => '嚬', '' => '壚', '' => '壝', '' => '壛', '' => '夒', '' => '嬽', '' => '嬾', '' => '嬿', '' => '巃', '' => '幰', '@' => '徿', 'A' => '懻', 'B' => '攇', 'C' => '攐', 'D' => '攍', 'E' => '攉', 'F' => '攌', 'G' => '攎', 'H' => '斄', 'I' => '旞', 'J' => '旝', 'K' => '曞', 'L' => '櫧', 'M' => '櫠', 'N' => '櫌', 'O' => '櫑', 'P' => '櫙', 'Q' => '櫋', 'R' => '櫟', 'S' => '櫜', 'T' => '櫐', 'U' => '櫫', 'V' => '櫏', 'W' => '櫍', 'X' => '櫞', 'Y' => '歠', 'Z' => '殰', '[' => '氌', '\\' => '瀙', ']' => '瀧', '^' => '瀠', '_' => '瀖', '`' => '瀫', 'a' => '瀡', 'b' => '瀢', 'c' => '瀣', 'd' => '瀩', 'e' => '瀗', 'f' => '瀤', 'g' => '瀜', 'h' => '瀪', 'i' => '爌', 'j' => '爊', 'k' => '爇', 'l' => '爂', 'm' => '爅', 'n' => '犥', 'o' => '犦', 'p' => '犤', 'q' => '犣', 'r' => '犡', 's' => '瓋', 't' => '瓅', 'u' => '璷', 'v' => '瓃', 'w' => '甖', 'x' => '癠', 'y' => '矉', 'z' => '矊', '{' => '矄', '|' => '矱', '}' => '礝', '~' => '礛', '' => '礡', '' => '礜', '' => '礗', '' => '礞', '' => '禰', '' => '穧', '' => '穨', '' => '簳', '' => '簼', '' => '簹', '' => '簬', '' => '簻', '' => '糬', '' => '糪', '' => '繶', '' => '繵', '' => '繸', '' => '繰', '' => '繷', '' => '繯', '' => '繺', '' => '繲', '' => '繴', '' => '繨', '' => '罋', '' => '罊', '' => '羃', '' => '羆', '' => '羷', '' => '翽', '' => '翾', '' => '聸', '' => '臗', '' => '臕', '' => '艤', '' => '艡', '' => '艣', '' => '藫', '' => '藱', '' => '藭', '' => '藙', '' => '藡', '' => '藨', '' => '藚', '' => '藗', '' => '藬', '' => '藲', '' => '藸', '' => '藘', '' => '藟', '' => '藣', '' => '藜', '' => '藑', '' => '藰', '' => '藦', '' => '藯', '' => '藞', '' => '藢', '' => '蠀', '' => '蟺', '' => '蠃', '' => '蟶', '' => '蟷', '' => '蠉', '' => '蠌', '' => '蠋', '' => '蠆', '' => '蟼', '' => '蠈', '' => '蟿', '' => '蠊', '' => '蠂', '' => '襢', '' => '襚', '' => '襛', '' => '襗', '' => '襡', '' => '襜', '' => '襘', '' => '襝', '' => '襙', '' => '覈', '' => '覷', '' => '覶', '' => '觶', '' => '譐', '' => '譈', '' => '譊', '' => '譀', '' => '譓', '' => '譖', '' => '譔', '' => '譋', '' => '譕', '@' => '譑', 'A' => '譂', 'B' => '譒', 'C' => '譗', 'D' => '豃', 'E' => '豷', 'F' => '豶', 'G' => '貚', 'H' => '贆', 'I' => '贇', 'J' => '贉', 'K' => '趬', 'L' => '趪', 'M' => '趭', 'N' => '趫', 'O' => '蹭', 'P' => '蹸', 'Q' => '蹳', 'R' => '蹪', 'S' => '蹯', 'T' => '蹻', 'U' => '軂', 'V' => '轒', 'W' => '轑', 'X' => '轏', 'Y' => '轐', 'Z' => '轓', '[' => '辴', '\\' => '酀', ']' => '鄿', '^' => '醰', '_' => '醭', '`' => '鏞', 'a' => '鏇', 'b' => '鏏', 'c' => '鏂', 'd' => '鏚', 'e' => '鏐', 'f' => '鏹', 'g' => '鏬', 'h' => '鏌', 'i' => '鏙', 'j' => '鎩', 'k' => '鏦', 'l' => '鏊', 'm' => '鏔', 'n' => '鏮', 'o' => '鏣', 'p' => '鏕', 'q' => '鏄', 'r' => '鏎', 's' => '鏀', 't' => '鏒', 'u' => '鏧', 'v' => '镽', 'w' => '闚', 'x' => '闛', 'y' => '雡', 'z' => '霩', '{' => '霫', '|' => '霬', '}' => '霨', '~' => '霦', '' => '鞳', '' => '鞷', '' => '鞶', '' => '韝', '' => '韞', '' => '韟', '' => '顜', '' => '顙', '' => '顝', '' => '顗', '' => '颿', '' => '颽', '' => '颻', '' => '颾', '' => '饈', '' => '饇', '' => '饃', '' => '馦', '' => '馧', '' => '騚', '' => '騕', '' => '騥', '' => '騝', '' => '騤', '' => '騛', '' => '騢', '' => '騠', '' => '騧', '' => '騣', '' => '騞', '' => '騜', '' => '騔', '' => '髂', '' => '鬋', '' => '鬊', '' => '鬎', '' => '鬌', '' => '鬷', '' => '鯪', '' => '鯫', '' => '鯠', '' => '鯞', '' => '鯤', '' => '鯦', '' => '鯢', '' => '鯰', '' => '鯔', '' => '鯗', '' => '鯬', '' => '鯜', '' => '鯙', '' => '鯥', '' => '鯕', '' => '鯡', '' => '鯚', '' => '鵷', '' => '鶁', '' => '鶊', '' => '鶄', '' => '鶈', '' => '鵱', '' => '鶀', '' => '鵸', '' => '鶆', '' => '鶋', '' => '鶌', '' => '鵽', '' => '鵫', '' => '鵴', '' => '鵵', '' => '鵰', '' => '鵩', '' => '鶅', '' => '鵳', '' => '鵻', '' => '鶂', '' => '鵯', '' => '鵹', '' => '鵿', '' => '鶇', '' => '鵨', '' => '麔', '' => '麑', '' => '黀', '' => '黼', '' => '鼭', '' => '齀', '' => '齁', '' => '齍', '' => '齖', '' => '齗', '' => '齘', '' => '匷', '' => '嚲', '@' => '嚵', 'A' => '嚳', 'B' => '壣', 'C' => '孅', 'D' => '巆', 'E' => '巇', 'F' => '廮', 'G' => '廯', 'H' => '忀', 'I' => '忁', 'J' => '懹', 'K' => '攗', 'L' => '攖', 'M' => '攕', 'N' => '攓', 'O' => '旟', 'P' => '曨', 'Q' => '曣', 'R' => '曤', 'S' => '櫳', 'T' => '櫰', 'U' => '櫪', 'V' => '櫨', 'W' => '櫹', 'X' => '櫱', 'Y' => '櫮', 'Z' => '櫯', '[' => '瀼', '\\' => '瀵', ']' => '瀯', '^' => '瀷', '_' => '瀴', '`' => '瀱', 'a' => '灂', 'b' => '瀸', 'c' => '瀿', 'd' => '瀺', 'e' => '瀹', 'f' => '灀', 'g' => '瀻', 'h' => '瀳', 'i' => '灁', 'j' => '爓', 'k' => '爔', 'l' => '犨', 'm' => '獽', 'n' => '獼', 'o' => '璺', 'p' => '皫', 'q' => '皪', 'r' => '皾', 's' => '盭', 't' => '矌', 'u' => '矎', 'v' => '矏', 'w' => '矍', 'x' => '矲', 'y' => '礥', 'z' => '礣', '{' => '礧', '|' => '礨', '}' => '礤', '~' => '礩', '' => '禲', '' => '穮', '' => '穬', '' => '穭', '' => '竷', '' => '籉', '' => '籈', '' => '籊', '' => '籇', '' => '籅', '' => '糮', '' => '繻', '' => '繾', '' => '纁', '' => '纀', '' => '羺', '' => '翿', '' => '聹', '' => '臛', '' => '臙', '' => '舋', '' => '艨', '' => '艩', '' => '蘢', '' => '藿', '' => '蘁', '' => '藾', '' => '蘛', '' => '蘀', '' => '藶', '' => '蘄', '' => '蘉', '' => '蘅', '' => '蘌', '' => '藽', '' => '蠙', '' => '蠐', '' => '蠑', '' => '蠗', '' => '蠓', '' => '蠖', '' => '襣', '' => '襦', '' => '覹', '' => '觷', '' => '譠', '' => '譪', '' => '譝', '' => '譨', '' => '譣', '' => '譥', '' => '譧', '' => '譭', '' => '趮', '' => '躆', '' => '躈', '' => '躄', '' => '轙', '' => '轖', '' => '轗', '' => '轕', '' => '轘', '' => '轚', '' => '邍', '' => '酃', '' => '酁', '' => '醷', '' => '醵', '' => '醲', '' => '醳', '' => '鐋', '' => '鐓', '' => '鏻', '' => '鐠', '' => '鐏', '' => '鐔', '' => '鏾', '' => '鐕', '' => '鐐', '' => '鐨', '' => '鐙', '' => '鐍', '' => '鏵', '' => '鐀', '' => '鏷', '' => '鐇', '' => '鐎', '' => '鐖', '' => '鐒', '' => '鏺', '' => '鐉', '' => '鏸', '' => '鐊', '' => '鏿', '@' => '鏼', 'A' => '鐌', 'B' => '鏶', 'C' => '鐑', 'D' => '鐆', 'E' => '闞', 'F' => '闠', 'G' => '闟', 'H' => '霮', 'I' => '霯', 'J' => '鞹', 'K' => '鞻', 'L' => '韽', 'M' => '韾', 'N' => '顠', 'O' => '顢', 'P' => '顣', 'Q' => '顟', 'R' => '飁', 'S' => '飂', 'T' => '饐', 'U' => '饎', 'V' => '饙', 'W' => '饌', 'X' => '饋', 'Y' => '饓', 'Z' => '騲', '[' => '騴', '\\' => '騱', ']' => '騬', '^' => '騪', '_' => '騶', '`' => '騩', 'a' => '騮', 'b' => '騸', 'c' => '騭', 'd' => '髇', 'e' => '髊', 'f' => '髆', 'g' => '鬐', 'h' => '鬒', 'i' => '鬑', 'j' => '鰋', 'k' => '鰈', 'l' => '鯷', 'm' => '鰅', 'n' => '鰒', 'o' => '鯸', 'p' => '鱀', 'q' => '鰇', 'r' => '鰎', 's' => '鰆', 't' => '鰗', 'u' => '鰔', 'v' => '鰉', 'w' => '鶟', 'x' => '鶙', 'y' => '鶤', 'z' => '鶝', '{' => '鶒', '|' => '鶘', '}' => '鶐', '~' => '鶛', '' => '鶠', '' => '鶔', '' => '鶜', '' => '鶪', '' => '鶗', '' => '鶡', '' => '鶚', '' => '鶢', '' => '鶨', '' => '鶞', '' => '鶣', '' => '鶿', '' => '鶩', '' => '鶖', '' => '鶦', '' => '鶧', '' => '麙', '' => '麛', '' => '麚', '' => '黥', '' => '黤', '' => '黧', '' => '黦', '' => '鼰', '' => '鼮', '' => '齛', '' => '齠', '' => '齞', '' => '齝', '' => '齙', '' => '龑', '' => '儺', '' => '儹', '' => '劘', '' => '劗', '' => '囃', '' => '嚽', '' => '嚾', '' => '孈', '' => '孇', '' => '巋', '' => '巏', '' => '廱', '' => '懽', '' => '攛', '' => '欂', '' => '櫼', '' => '欃', '' => '櫸', '' => '欀', '' => '灃', '' => '灄', '' => '灊', '' => '灈', '' => '灉', '' => '灅', '' => '灆', '' => '爝', '' => '爚', '' => '爙', '' => '獾', '' => '甗', '' => '癪', '' => '矐', '' => '礭', '' => '礱', '' => '礯', '' => '籔', '' => '籓', '' => '糲', '' => '纊', '' => '纇', '' => '纈', '' => '纋', '' => '纆', '' => '纍', '' => '罍', '' => '羻', '' => '耰', '' => '臝', '' => '蘘', '' => '蘪', '' => '蘦', '' => '蘟', '' => '蘣', '' => '蘜', '' => '蘙', '' => '蘧', '' => '蘮', '' => '蘡', '' => '蘠', '' => '蘩', '' => '蘞', '' => '蘥', '@' => '蠩', 'A' => '蠝', 'B' => '蠛', 'C' => '蠠', 'D' => '蠤', 'E' => '蠜', 'F' => '蠫', 'G' => '衊', 'H' => '襭', 'I' => '襩', 'J' => '襮', 'K' => '襫', 'L' => '觺', 'M' => '譹', 'N' => '譸', 'O' => '譅', 'P' => '譺', 'Q' => '譻', 'R' => '贐', 'S' => '贔', 'T' => '趯', 'U' => '躎', 'V' => '躌', 'W' => '轞', 'X' => '轛', 'Y' => '轝', 'Z' => '酆', '[' => '酄', '\\' => '酅', ']' => '醹', '^' => '鐿', '_' => '鐻', '`' => '鐶', 'a' => '鐩', 'b' => '鐽', 'c' => '鐼', 'd' => '鐰', 'e' => '鐹', 'f' => '鐪', 'g' => '鐷', 'h' => '鐬', 'i' => '鑀', 'j' => '鐱', 'k' => '闥', 'l' => '闤', 'm' => '闣', 'n' => '霵', 'o' => '霺', 'p' => '鞿', 'q' => '韡', 'r' => '顤', 's' => '飉', 't' => '飆', 'u' => '飀', 'v' => '饘', 'w' => '饖', 'x' => '騹', 'y' => '騽', 'z' => '驆', '{' => '驄', '|' => '驂', '}' => '驁', '~' => '騺', '' => '騿', '' => '髍', '' => '鬕', '' => '鬗', '' => '鬘', '' => '鬖', '' => '鬺', '' => '魒', '' => '鰫', '' => '鰝', '' => '鰜', '' => '鰬', '' => '鰣', '' => '鰨', '' => '鰩', '' => '鰤', '' => '鰡', '' => '鶷', '' => '鶶', '' => '鶼', '' => '鷁', '' => '鷇', '' => '鷊', '' => '鷏', '' => '鶾', '' => '鷅', '' => '鷃', '' => '鶻', '' => '鶵', '' => '鷎', '' => '鶹', '' => '鶺', '' => '鶬', '' => '鷈', '' => '鶱', '' => '鶭', '' => '鷌', '' => '鶳', '' => '鷍', '' => '鶲', '' => '鹺', '' => '麜', '' => '黫', '' => '黮', '' => '黭', '' => '鼛', '' => '鼘', '' => '鼚', '' => '鼱', '' => '齎', '' => '齥', '' => '齤', '' => '龒', '' => '亹', '' => '囆', '' => '囅', '' => '囋', '' => '奱', '' => '孋', '' => '孌', '' => '巕', '' => '巑', '' => '廲', '' => '攡', '' => '攠', '' => '攦', '' => '攢', '' => '欋', '' => '欈', '' => '欉', '' => '氍', '' => '灕', '' => '灖', '' => '灗', '' => '灒', '' => '爞', '' => '爟', '' => '犩', '' => '獿', '' => '瓘', '' => '瓕', '' => '瓙', '' => '瓗', '' => '癭', '' => '皭', '' => '礵', '' => '禴', '' => '穰', '' => '穱', '' => '籗', '' => '籜', '' => '籙', '' => '籛', '' => '籚', '@' => '糴', 'A' => '糱', 'B' => '纑', 'C' => '罏', 'D' => '羇', 'E' => '臞', 'F' => '艫', 'G' => '蘴', 'H' => '蘵', 'I' => '蘳', 'J' => '蘬', 'K' => '蘲', 'L' => '蘶', 'M' => '蠬', 'N' => '蠨', 'O' => '蠦', 'P' => '蠪', 'Q' => '蠥', 'R' => '襱', 'S' => '覿', 'T' => '覾', 'U' => '觻', 'V' => '譾', 'W' => '讄', 'X' => '讂', 'Y' => '讆', 'Z' => '讅', '[' => '譿', '\\' => '贕', ']' => '躕', '^' => '躔', '_' => '躚', '`' => '躒', 'a' => '躐', 'b' => '躖', 'c' => '躗', 'd' => '轠', 'e' => '轢', 'f' => '酇', 'g' => '鑌', 'h' => '鑐', 'i' => '鑊', 'j' => '鑋', 'k' => '鑏', 'l' => '鑇', 'm' => '鑅', 'n' => '鑈', 'o' => '鑉', 'p' => '鑆', 'q' => '霿', 'r' => '韣', 's' => '顪', 't' => '顩', 'u' => '飋', 'v' => '饔', 'w' => '饛', 'x' => '驎', 'y' => '驓', 'z' => '驔', '{' => '驌', '|' => '驏', '}' => '驈', '~' => '驊', '' => '驉', '' => '驒', '' => '驐', '' => '髐', '' => '鬙', '' => '鬫', '' => '鬻', '' => '魖', '' => '魕', '' => '鱆', '' => '鱈', '' => '鰿', '' => '鱄', '' => '鰹', '' => '鰳', '' => '鱁', '' => '鰼', '' => '鰷', '' => '鰴', '' => '鰲', '' => '鰽', '' => '鰶', '' => '鷛', '' => '鷒', '' => '鷞', '' => '鷚', '' => '鷋', '' => '鷐', '' => '鷜', '' => '鷑', '' => '鷟', '' => '鷩', '' => '鷙', '' => '鷘', '' => '鷖', '' => '鷵', '' => '鷕', '' => '鷝', '' => '麶', '' => '黰', '' => '鼵', '' => '鼳', '' => '鼲', '' => '齂', '' => '齫', '' => '龕', '' => '龢', '' => '儽', '' => '劙', '' => '壨', '' => '壧', '' => '奲', '' => '孍', '' => '巘', '' => '蠯', '' => '彏', '' => '戁', '' => '戃', '' => '戄', '' => '攩', '' => '攥', '' => '斖', '' => '曫', '' => '欑', '' => '欒', '' => '欏', '' => '毊', '' => '灛', '' => '灚', '' => '爢', '' => '玂', '' => '玁', '' => '玃', '' => '癰', '' => '矔', '' => '籧', '' => '籦', '' => '纕', '' => '艬', '' => '蘺', '' => '虀', '' => '蘹', '' => '蘼', '' => '蘱', '' => '蘻', '' => '蘾', '' => '蠰', '' => '蠲', '' => '蠮', '' => '蠳', '' => '襶', '' => '襴', '' => '襳', '' => '觾', '@' => '讌', 'A' => '讎', 'B' => '讋', 'C' => '讈', 'D' => '豅', 'E' => '贙', 'F' => '躘', 'G' => '轤', 'H' => '轣', 'I' => '醼', 'J' => '鑢', 'K' => '鑕', 'L' => '鑝', 'M' => '鑗', 'N' => '鑞', 'O' => '韄', 'P' => '韅', 'Q' => '頀', 'R' => '驖', 'S' => '驙', 'T' => '鬞', 'U' => '鬟', 'V' => '鬠', 'W' => '鱒', 'X' => '鱘', 'Y' => '鱐', 'Z' => '鱊', '[' => '鱍', '\\' => '鱋', ']' => '鱕', '^' => '鱙', '_' => '鱌', '`' => '鱎', 'a' => '鷻', 'b' => '鷷', 'c' => '鷯', 'd' => '鷣', 'e' => '鷫', 'f' => '鷸', 'g' => '鷤', 'h' => '鷶', 'i' => '鷡', 'j' => '鷮', 'k' => '鷦', 'l' => '鷲', 'm' => '鷰', 'n' => '鷢', 'o' => '鷬', 'p' => '鷴', 'q' => '鷳', 'r' => '鷨', 's' => '鷭', 't' => '黂', 'u' => '黐', 'v' => '黲', 'w' => '黳', 'x' => '鼆', 'y' => '鼜', 'z' => '鼸', '{' => '鼷', '|' => '鼶', '}' => '齃', '~' => '齏', '' => '齱', '' => '齰', '' => '齮', '' => '齯', '' => '囓', '' => '囍', '' => '孎', '' => '屭', '' => '攭', '' => '曭', '' => '曮', '' => '欓', '' => '灟', '' => '灡', '' => '灝', '' => '灠', '' => '爣', '' => '瓛', '' => '瓥', '' => '矕', '' => '礸', '' => '禷', '' => '禶', '' => '籪', '' => '纗', '' => '羉', '' => '艭', '' => '虃', '' => '蠸', '' => '蠷', '' => '蠵', '' => '衋', '' => '讔', '' => '讕', '' => '躞', '' => '躟', '' => '躠', '' => '躝', '' => '醾', '' => '醽', '' => '釂', '' => '鑫', '' => '鑨', '' => '鑩', '' => '雥', '' => '靆', '' => '靃', '' => '靇', '' => '韇', '' => '韥', '' => '驞', '' => '髕', '' => '魙', '' => '鱣', '' => '鱧', '' => '鱦', '' => '鱢', '' => '鱞', '' => '鱠', '' => '鸂', '' => '鷾', '' => '鸇', '' => '鸃', '' => '鸆', '' => '鸅', '' => '鸀', '' => '鸁', '' => '鸉', '' => '鷿', '' => '鷽', '' => '鸄', '' => '麠', '' => '鼞', '' => '齆', '' => '齴', '' => '齵', '' => '齶', '' => '囔', '' => '攮', '' => '斸', '' => '欘', '' => '欙', '' => '欗', '' => '欚', '' => '灢', '' => '爦', '' => '犪', '' => '矘', '' => '矙', '' => '礹', '' => '籩', '' => '籫', '' => '糶', '' => '纚', '@' => '纘', 'A' => '纛', 'B' => '纙', 'C' => '臠', 'D' => '臡', 'E' => '虆', 'F' => '虇', 'G' => '虈', 'H' => '襹', 'I' => '襺', 'J' => '襼', 'K' => '襻', 'L' => '觿', 'M' => '讘', 'N' => '讙', 'O' => '躥', 'P' => '躤', 'Q' => '躣', 'R' => '鑮', 'S' => '鑭', 'T' => '鑯', 'U' => '鑱', 'V' => '鑳', 'W' => '靉', 'X' => '顲', 'Y' => '饟', 'Z' => '鱨', '[' => '鱮', '\\' => '鱭', ']' => '鸋', '^' => '鸍', '_' => '鸐', '`' => '鸏', 'a' => '鸒', 'b' => '鸑', 'c' => '麡', 'd' => '黵', 'e' => '鼉', 'f' => '齇', 'g' => '齸', 'h' => '齻', 'i' => '齺', 'j' => '齹', 'k' => '圞', 'l' => '灦', 'm' => '籯', 'n' => '蠼', 'o' => '趲', 'p' => '躦', 'q' => '釃', 'r' => '鑴', 's' => '鑸', 't' => '鑶', 'u' => '鑵', 'v' => '驠', 'w' => '鱴', 'x' => '鱳', 'y' => '鱱', 'z' => '鱵', '{' => '鸔', '|' => '鸓', '}' => '黶', '~' => '鼊', '' => '龤', '' => '灨', '' => '灥', '' => '糷', '' => '虪', '' => '蠾', '' => '蠽', '' => '蠿', '' => '讞', '' => '貜', '' => '躩', '' => '軉', '' => '靋', '' => '顳', '' => '顴', '' => '飌', '' => '饡', '' => '馫', '' => '驤', '' => '驦', '' => '驧', '' => '鬤', '' => '鸕', '' => '鸗', '' => '齈', '' => '戇', '' => '欞', '' => '爧', '' => '虌', '' => '躨', '' => '钂', '' => '钀', '' => '钁', '' => '驩', '' => '驨', '' => '鬮', '' => '鸙', '' => '爩', '' => '虋', '' => '讟', '' => '钃', '' => '鱹', '' => '麷', '' => '癵', '' => '驫', '' => '鱺', '' => '鸝', '' => '灩', '' => '灪', '' => '麤', '' => '齾', '' => '齉', '' => '龘', '' => '碁', '' => '銹', '' => '裏', '' => '墻', '' => '恒', '' => '粧', '' => '嫺', '' => '╔', '' => '╦', '' => '╗', '' => '╠', '' => '╬', '' => '╣', '' => '╚', '' => '╩', '' => '╝', '' => '╒', '' => '╤', '' => '╕', '' => '╞', '' => '╪', '' => '╡', '' => '╘', '' => '╧', '' => '╛', '' => '╓', '' => '╥', '' => '╖', '' => '╟', '' => '╫', '' => '╢', '' => '╙', '' => '╨', '' => '╜', '' => '║', '' => '═', '' => '╭', '' => '╮', '' => '╰', '' => '╯', '' => '▓', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-7.php000064400000007154150432043200016141 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '‘', '' => '’', '' => '£', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => '«', '' => '¬', '' => '­', '' => '―', '' => '°', '' => '±', '' => '²', '' => '³', '' => '΄', '' => '΅', '' => 'Ά', '' => '·', '' => 'Έ', '' => 'Ή', '' => 'Ί', '' => '»', '' => 'Ό', '' => '½', '' => 'Ύ', '' => 'Ώ', '' => 'ΐ', '' => 'Α', '' => 'Β', '' => 'Γ', '' => 'Δ', '' => 'Ε', '' => 'Ζ', '' => 'Η', '' => 'Θ', '' => 'Ι', '' => 'Κ', '' => 'Λ', '' => 'Μ', '' => 'Ν', '' => 'Ξ', '' => 'Ο', '' => 'Π', '' => 'Ρ', '' => 'Σ', '' => 'Τ', '' => 'Υ', '' => 'Φ', '' => 'Χ', '' => 'Ψ', '' => 'Ω', '' => 'Ϊ', '' => 'Ϋ', '' => 'ά', '' => 'έ', '' => 'ή', '' => 'ί', '' => 'ΰ', '' => 'α', '' => 'β', '' => 'γ', '' => 'δ', '' => 'ε', '' => 'ζ', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'ς', '' => 'σ', '' => 'τ', '' => 'υ', '' => 'φ', '' => 'χ', '' => 'ψ', '' => 'ω', '' => 'ϊ', '' => 'ϋ', '' => 'ό', '' => 'ύ', '' => 'ώ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1258.php000064400000007116150432043200016655 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => '‹', '' => 'Œ', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => '›', '' => 'œ', '' => 'Ÿ', '' => ' ', '' => '¡', '' => '¢', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => 'ª', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => 'º', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '¿', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ă', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => '̀', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Đ', '' => 'Ñ', '' => '̉', '' => 'Ó', '' => 'Ô', '' => 'Ơ', '' => 'Ö', '' => '×', '' => 'Ø', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ư', '' => '̃', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ă', '' => 'ä', '' => 'å', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => '́', '' => 'í', '' => 'î', '' => 'ï', '' => 'đ', '' => 'ñ', '' => '̣', '' => 'ó', '' => 'ô', '' => 'ơ', '' => 'ö', '' => '÷', '' => 'ø', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ư', '' => '₫', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-9.php000064400000007303150432043200016137 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '¡', '' => '¢', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => 'ª', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => 'º', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '¿', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ğ', '' => 'Ñ', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ø', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'İ', '' => 'Ş', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'ğ', '' => 'ñ', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ø', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ı', '' => 'ş', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp861.php000064400000007401150432043200015424 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'ä', '' => 'à', '' => 'å', '' => 'ç', '' => 'ê', '' => 'ë', '' => 'è', '' => 'Ð', '' => 'ð', '' => 'Þ', '' => 'Ä', '' => 'Å', '' => 'É', '' => 'æ', '' => 'Æ', '' => 'ô', '' => 'ö', '' => 'þ', '' => 'û', '' => 'Ý', '' => 'ý', '' => 'Ö', '' => 'Ü', '' => 'ø', '' => '£', '' => 'Ø', '' => '₧', '' => 'ƒ', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'Á', '' => 'Í', '' => 'Ó', '' => 'Ú', '' => '¿', '' => '⌐', '' => '¬', '' => '½', '' => '¼', '' => '¡', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'α', '' => 'ß', '' => 'Γ', '' => 'π', '' => 'Σ', '' => 'σ', '' => 'µ', '' => 'τ', '' => 'Φ', '' => 'Θ', '' => 'Ω', '' => 'δ', '' => '∞', '' => 'φ', '' => 'ε', '' => '∩', '' => '≡', '' => '±', '' => '≥', '' => '≤', '' => '⌠', '' => '⌡', '' => '÷', '' => '≈', '' => '°', '' => '∙', '' => '·', '' => '√', '' => 'ⁿ', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp1006.php000064400000007424150432043200015501 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '۰', '' => '۱', '' => '۲', '' => '۳', '' => '۴', '' => '۵', '' => '۶', '' => '۷', '' => '۸', '' => '۹', '' => '،', '' => '؛', '' => '­', '' => '؟', '' => 'ﺁ', '' => 'ﺍ', '' => 'ﺎ', '' => 'ﺎ', '' => 'ﺏ', '' => 'ﺑ', '' => 'ﭖ', '' => 'ﭘ', '' => 'ﺓ', '' => 'ﺕ', '' => 'ﺗ', '' => 'ﭦ', '' => 'ﭨ', '' => 'ﺙ', '' => 'ﺛ', '' => 'ﺝ', '' => 'ﺟ', '' => 'ﭺ', '' => 'ﭼ', '' => 'ﺡ', '' => 'ﺣ', '' => 'ﺥ', '' => 'ﺧ', '' => 'ﺩ', '' => 'ﮄ', '' => 'ﺫ', '' => 'ﺭ', '' => 'ﮌ', '' => 'ﺯ', '' => 'ﮊ', '' => 'ﺱ', '' => 'ﺳ', '' => 'ﺵ', '' => 'ﺷ', '' => 'ﺹ', '' => 'ﺻ', '' => 'ﺽ', '' => 'ﺿ', '' => 'ﻁ', '' => 'ﻅ', '' => 'ﻉ', '' => 'ﻊ', '' => 'ﻋ', '' => 'ﻌ', '' => 'ﻍ', '' => 'ﻎ', '' => 'ﻏ', '' => 'ﻐ', '' => 'ﻑ', '' => 'ﻓ', '' => 'ﻕ', '' => 'ﻗ', '' => 'ﻙ', '' => 'ﻛ', '' => 'ﮒ', '' => 'ﮔ', '' => 'ﻝ', '' => 'ﻟ', '' => 'ﻠ', '' => 'ﻡ', '' => 'ﻣ', '' => 'ﮞ', '' => 'ﻥ', '' => 'ﻧ', '' => 'ﺅ', '' => 'ﻭ', '' => 'ﮦ', '' => 'ﮨ', '' => 'ﮩ', '' => 'ﮪ', '' => 'ﺀ', '' => 'ﺉ', '' => 'ﺊ', '' => 'ﺋ', '' => 'ﻱ', '' => 'ﻲ', '' => 'ﻳ', '' => 'ﮰ', '' => 'ﮮ', '' => 'ﹼ', '' => 'ﹽ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-4.php000064400000007303150432043200016132 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'Ą', '' => 'ĸ', '' => 'Ŗ', '' => '¤', '' => 'Ĩ', '' => 'Ļ', '' => '§', '' => '¨', '' => 'Š', '' => 'Ē', '' => 'Ģ', '' => 'Ŧ', '' => '­', '' => 'Ž', '' => '¯', '' => '°', '' => 'ą', '' => '˛', '' => 'ŗ', '' => '´', '' => 'ĩ', '' => 'ļ', '' => 'ˇ', '' => '¸', '' => 'š', '' => 'ē', '' => 'ģ', '' => 'ŧ', '' => 'Ŋ', '' => 'ž', '' => 'ŋ', '' => 'Ā', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Į', '' => 'Č', '' => 'É', '' => 'Ę', '' => 'Ë', '' => 'Ė', '' => 'Í', '' => 'Î', '' => 'Ī', '' => 'Đ', '' => 'Ņ', '' => 'Ō', '' => 'Ķ', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ø', '' => 'Ų', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ũ', '' => 'Ū', '' => 'ß', '' => 'ā', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'į', '' => 'č', '' => 'é', '' => 'ę', '' => 'ë', '' => 'ė', '' => 'í', '' => 'î', '' => 'ī', '' => 'đ', '' => 'ņ', '' => 'ō', '' => 'ķ', '' => 'ô', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ø', '' => 'ų', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ũ', '' => 'ū', '' => '˙', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp437.php000064400000007401150432043200015423 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'ä', '' => 'à', '' => 'å', '' => 'ç', '' => 'ê', '' => 'ë', '' => 'è', '' => 'ï', '' => 'î', '' => 'ì', '' => 'Ä', '' => 'Å', '' => 'É', '' => 'æ', '' => 'Æ', '' => 'ô', '' => 'ö', '' => 'ò', '' => 'û', '' => 'ù', '' => 'ÿ', '' => 'Ö', '' => 'Ü', '' => '¢', '' => '£', '' => '¥', '' => '₧', '' => 'ƒ', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'ñ', '' => 'Ñ', '' => 'ª', '' => 'º', '' => '¿', '' => '⌐', '' => '¬', '' => '½', '' => '¼', '' => '¡', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'α', '' => 'ß', '' => 'Γ', '' => 'π', '' => 'Σ', '' => 'σ', '' => 'µ', '' => 'τ', '' => 'Φ', '' => 'Θ', '' => 'Ω', '' => 'δ', '' => '∞', '' => 'φ', '' => 'ε', '' => '∩', '' => '≡', '' => '±', '' => '≥', '' => '≤', '' => '⌠', '' => '⌡', '' => '÷', '' => '≈', '' => '°', '' => '∙', '' => '·', '' => '√', '' => 'ⁿ', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.us-ascii.php000064400000003503150432043200016277 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.koi8-u.php000064400000007363150432043200015706 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '─', '' => '│', '' => '┌', '' => '┐', '' => '└', '' => '┘', '' => '├', '' => '┤', '' => '┬', '' => '┴', '' => '┼', '' => '▀', '' => '▄', '' => '█', '' => '▌', '' => '▐', '' => '░', '' => '▒', '' => '▓', '' => '⌠', '' => '■', '' => '•', '' => '√', '' => '≈', '' => '≤', '' => '≥', '' => ' ', '' => '⌡', '' => '°', '' => '²', '' => '·', '' => '÷', '' => '═', '' => '║', '' => '╒', '' => 'ё', '' => 'є', '' => '╔', '' => 'і', '' => 'ї', '' => '╗', '' => '╘', '' => '╙', '' => '╚', '' => '╛', '' => 'ґ', '' => '╝', '' => '╞', '' => '╟', '' => '╠', '' => '╡', '' => 'Ё', '' => 'Ѓ', '' => '╣', '' => 'І', '' => 'Ї', '' => '╦', '' => '╧', '' => '╨', '' => '╩', '' => '╪', '' => 'Ґ', '' => '╬', '' => '©', '' => 'ю', '' => 'а', '' => 'б', '' => 'ц', '' => 'д', '' => 'е', '' => 'ф', '' => 'г', '' => 'х', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => 'я', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ж', '' => 'в', '' => 'ь', '' => 'ы', '' => 'з', '' => 'ш', '' => 'э', '' => 'щ', '' => 'ч', '' => 'ъ', '' => 'Ю', '' => 'А', '' => 'Б', '' => 'Ц', '' => 'Д', '' => 'Е', '' => 'Ф', '' => 'Г', '' => 'Х', '' => 'И', '' => 'Й', '' => 'К', '' => 'Л', '' => 'М', '' => 'Н', '' => 'О', '' => 'П', '' => 'Я', '' => 'Р', '' => 'С', '' => 'Т', '' => 'У', '' => 'Ж', '' => 'В', '' => 'Ь', '' => 'Ы', '' => 'З', '' => 'Ш', '' => 'Э', '' => 'Щ', '' => 'Ч', '' => 'Ъ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp936.php000064400001327073150432043200015442 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '@' => '丂', 'A' => '丄', 'B' => '丅', 'C' => '丆', 'D' => '丏', 'E' => '丒', 'F' => '丗', 'G' => '丟', 'H' => '丠', 'I' => '両', 'J' => '丣', 'K' => '並', 'L' => '丩', 'M' => '丮', 'N' => '丯', 'O' => '丱', 'P' => '丳', 'Q' => '丵', 'R' => '丷', 'S' => '丼', 'T' => '乀', 'U' => '乁', 'V' => '乂', 'W' => '乄', 'X' => '乆', 'Y' => '乊', 'Z' => '乑', '[' => '乕', '\\' => '乗', ']' => '乚', '^' => '乛', '_' => '乢', '`' => '乣', 'a' => '乤', 'b' => '乥', 'c' => '乧', 'd' => '乨', 'e' => '乪', 'f' => '乫', 'g' => '乬', 'h' => '乭', 'i' => '乮', 'j' => '乯', 'k' => '乲', 'l' => '乴', 'm' => '乵', 'n' => '乶', 'o' => '乷', 'p' => '乸', 'q' => '乹', 'r' => '乺', 's' => '乻', 't' => '乼', 'u' => '乽', 'v' => '乿', 'w' => '亀', 'x' => '亁', 'y' => '亂', 'z' => '亃', '{' => '亄', '|' => '亅', '}' => '亇', '~' => '亊', '' => '亐', '' => '亖', '' => '亗', '' => '亙', '' => '亜', '' => '亝', '' => '亞', '' => '亣', '' => '亪', '' => '亯', '' => '亰', '' => '亱', '' => '亴', '' => '亶', '' => '亷', '' => '亸', '' => '亹', '' => '亼', '' => '亽', '' => '亾', '' => '仈', '' => '仌', '' => '仏', '' => '仐', '' => '仒', '' => '仚', '' => '仛', '' => '仜', '' => '仠', '' => '仢', '' => '仦', '' => '仧', '' => '仩', '' => '仭', '' => '仮', '' => '仯', '' => '仱', '' => '仴', '' => '仸', '' => '仹', '' => '仺', '' => '仼', '' => '仾', '' => '伀', '' => '伂', '' => '伃', '' => '伄', '' => '伅', '' => '伆', '' => '伇', '' => '伈', '' => '伋', '' => '伌', '' => '伒', '' => '伓', '' => '伔', '' => '伕', '' => '伖', '' => '伜', '' => '伝', '' => '伡', '' => '伣', '' => '伨', '' => '伩', '' => '伬', '' => '伭', '' => '伮', '' => '伱', '' => '伳', '' => '伵', '' => '伷', '' => '伹', '' => '伻', '' => '伾', '' => '伿', '' => '佀', '' => '佁', '' => '佂', '' => '佄', '' => '佅', '' => '佇', '' => '佈', '' => '佉', '' => '佊', '' => '佋', '' => '佌', '' => '佒', '' => '佔', '' => '佖', '' => '佡', '' => '佢', '' => '佦', '' => '佨', '' => '佪', '' => '佫', '' => '佭', '' => '佮', '' => '佱', '' => '佲', '' => '併', '' => '佷', '' => '佸', '' => '佹', '' => '佺', '' => '佽', '' => '侀', '' => '侁', '' => '侂', '' => '侅', '' => '來', '' => '侇', '' => '侊', '' => '侌', '' => '侎', '' => '侐', '' => '侒', '' => '侓', '' => '侕', '' => '侖', '' => '侘', '' => '侙', '' => '侚', '' => '侜', '' => '侞', '' => '侟', '' => '価', '' => '侢', '@' => '侤', 'A' => '侫', 'B' => '侭', 'C' => '侰', 'D' => '侱', 'E' => '侲', 'F' => '侳', 'G' => '侴', 'H' => '侶', 'I' => '侷', 'J' => '侸', 'K' => '侹', 'L' => '侺', 'M' => '侻', 'N' => '侼', 'O' => '侽', 'P' => '侾', 'Q' => '俀', 'R' => '俁', 'S' => '係', 'T' => '俆', 'U' => '俇', 'V' => '俈', 'W' => '俉', 'X' => '俋', 'Y' => '俌', 'Z' => '俍', '[' => '俒', '\\' => '俓', ']' => '俔', '^' => '俕', '_' => '俖', '`' => '俙', 'a' => '俛', 'b' => '俠', 'c' => '俢', 'd' => '俤', 'e' => '俥', 'f' => '俧', 'g' => '俫', 'h' => '俬', 'i' => '俰', 'j' => '俲', 'k' => '俴', 'l' => '俵', 'm' => '俶', 'n' => '俷', 'o' => '俹', 'p' => '俻', 'q' => '俼', 'r' => '俽', 's' => '俿', 't' => '倀', 'u' => '倁', 'v' => '倂', 'w' => '倃', 'x' => '倄', 'y' => '倅', 'z' => '倆', '{' => '倇', '|' => '倈', '}' => '倉', '~' => '倊', '' => '個', '' => '倎', '' => '倐', '' => '們', '' => '倓', '' => '倕', '' => '倖', '' => '倗', '' => '倛', '' => '倝', '' => '倞', '' => '倠', '' => '倢', '' => '倣', '' => '値', '' => '倧', '' => '倫', '' => '倯', '' => '倰', '' => '倱', '' => '倲', '' => '倳', '' => '倴', '' => '倵', '' => '倶', '' => '倷', '' => '倸', '' => '倹', '' => '倻', '' => '倽', '' => '倿', '' => '偀', '' => '偁', '' => '偂', '' => '偄', '' => '偅', '' => '偆', '' => '偉', '' => '偊', '' => '偋', '' => '偍', '' => '偐', '' => '偑', '' => '偒', '' => '偓', '' => '偔', '' => '偖', '' => '偗', '' => '偘', '' => '偙', '' => '偛', '' => '偝', '' => '偞', '' => '偟', '' => '偠', '' => '偡', '' => '偢', '' => '偣', '' => '偤', '' => '偦', '' => '偧', '' => '偨', '' => '偩', '' => '偪', '' => '偫', '' => '偭', '' => '偮', '' => '偯', '' => '偰', '' => '偱', '' => '偲', '' => '偳', '' => '側', '' => '偵', '' => '偸', '' => '偹', '' => '偺', '' => '偼', '' => '偽', '' => '傁', '' => '傂', '' => '傃', '' => '傄', '' => '傆', '' => '傇', '' => '傉', '' => '傊', '' => '傋', '' => '傌', '' => '傎', '' => '傏', '' => '傐', '' => '傑', '' => '傒', '' => '傓', '' => '傔', '' => '傕', '' => '傖', '' => '傗', '' => '傘', '' => '備', '' => '傚', '' => '傛', '' => '傜', '' => '傝', '' => '傞', '' => '傟', '' => '傠', '' => '傡', '' => '傢', '' => '傤', '' => '傦', '' => '傪', '' => '傫', '' => '傭', '' => '傮', '' => '傯', '' => '傰', '' => '傱', '' => '傳', '' => '傴', '' => '債', '' => '傶', '' => '傷', '' => '傸', '' => '傹', '' => '傼', '@' => '傽', 'A' => '傾', 'B' => '傿', 'C' => '僀', 'D' => '僁', 'E' => '僂', 'F' => '僃', 'G' => '僄', 'H' => '僅', 'I' => '僆', 'J' => '僇', 'K' => '僈', 'L' => '僉', 'M' => '僊', 'N' => '僋', 'O' => '僌', 'P' => '働', 'Q' => '僎', 'R' => '僐', 'S' => '僑', 'T' => '僒', 'U' => '僓', 'V' => '僔', 'W' => '僕', 'X' => '僗', 'Y' => '僘', 'Z' => '僙', '[' => '僛', '\\' => '僜', ']' => '僝', '^' => '僞', '_' => '僟', '`' => '僠', 'a' => '僡', 'b' => '僢', 'c' => '僣', 'd' => '僤', 'e' => '僥', 'f' => '僨', 'g' => '僩', 'h' => '僪', 'i' => '僫', 'j' => '僯', 'k' => '僰', 'l' => '僱', 'm' => '僲', 'n' => '僴', 'o' => '僶', 'p' => '僷', 'q' => '僸', 'r' => '價', 's' => '僺', 't' => '僼', 'u' => '僽', 'v' => '僾', 'w' => '僿', 'x' => '儀', 'y' => '儁', 'z' => '儂', '{' => '儃', '|' => '億', '}' => '儅', '~' => '儈', '' => '儉', '' => '儊', '' => '儌', '' => '儍', '' => '儎', '' => '儏', '' => '儐', '' => '儑', '' => '儓', '' => '儔', '' => '儕', '' => '儖', '' => '儗', '' => '儘', '' => '儙', '' => '儚', '' => '儛', '' => '儜', '' => '儝', '' => '儞', '' => '償', '' => '儠', '' => '儢', '' => '儣', '' => '儤', '' => '儥', '' => '儦', '' => '儧', '' => '儨', '' => '儩', '' => '優', '' => '儫', '' => '儬', '' => '儭', '' => '儮', '' => '儯', '' => '儰', '' => '儱', '' => '儲', '' => '儳', '' => '儴', '' => '儵', '' => '儶', '' => '儷', '' => '儸', '' => '儹', '' => '儺', '' => '儻', '' => '儼', '' => '儽', '' => '儾', '' => '兂', '' => '兇', '' => '兊', '' => '兌', '' => '兎', '' => '兏', '' => '児', '' => '兒', '' => '兓', '' => '兗', '' => '兘', '' => '兙', '' => '兛', '' => '兝', '' => '兞', '' => '兟', '' => '兠', '' => '兡', '' => '兣', '' => '兤', '' => '兦', '' => '內', '' => '兩', '' => '兪', '' => '兯', '' => '兲', '' => '兺', '' => '兾', '' => '兿', '' => '冃', '' => '冄', '' => '円', '' => '冇', '' => '冊', '' => '冋', '' => '冎', '' => '冏', '' => '冐', '' => '冑', '' => '冓', '' => '冔', '' => '冘', '' => '冚', '' => '冝', '' => '冞', '' => '冟', '' => '冡', '' => '冣', '' => '冦', '' => '冧', '' => '冨', '' => '冩', '' => '冪', '' => '冭', '' => '冮', '' => '冴', '' => '冸', '' => '冹', '' => '冺', '' => '冾', '' => '冿', '' => '凁', '' => '凂', '' => '凃', '' => '凅', '' => '凈', '' => '凊', '' => '凍', '' => '凎', '' => '凐', '' => '凒', '' => '凓', '' => '凔', '' => '凕', '' => '凖', '' => '凗', '@' => '凘', 'A' => '凙', 'B' => '凚', 'C' => '凜', 'D' => '凞', 'E' => '凟', 'F' => '凢', 'G' => '凣', 'H' => '凥', 'I' => '処', 'J' => '凧', 'K' => '凨', 'L' => '凩', 'M' => '凪', 'N' => '凬', 'O' => '凮', 'P' => '凱', 'Q' => '凲', 'R' => '凴', 'S' => '凷', 'T' => '凾', 'U' => '刄', 'V' => '刅', 'W' => '刉', 'X' => '刋', 'Y' => '刌', 'Z' => '刏', '[' => '刐', '\\' => '刓', ']' => '刔', '^' => '刕', '_' => '刜', '`' => '刞', 'a' => '刟', 'b' => '刡', 'c' => '刢', 'd' => '刣', 'e' => '別', 'f' => '刦', 'g' => '刧', 'h' => '刪', 'i' => '刬', 'j' => '刯', 'k' => '刱', 'l' => '刲', 'm' => '刴', 'n' => '刵', 'o' => '刼', 'p' => '刾', 'q' => '剄', 'r' => '剅', 's' => '剆', 't' => '則', 'u' => '剈', 'v' => '剉', 'w' => '剋', 'x' => '剎', 'y' => '剏', 'z' => '剒', '{' => '剓', '|' => '剕', '}' => '剗', '~' => '剘', '' => '剙', '' => '剚', '' => '剛', '' => '剝', '' => '剟', '' => '剠', '' => '剢', '' => '剣', '' => '剤', '' => '剦', '' => '剨', '' => '剫', '' => '剬', '' => '剭', '' => '剮', '' => '剰', '' => '剱', '' => '剳', '' => '剴', '' => '創', '' => '剶', '' => '剷', '' => '剸', '' => '剹', '' => '剺', '' => '剻', '' => '剼', '' => '剾', '' => '劀', '' => '劃', '' => '劄', '' => '劅', '' => '劆', '' => '劇', '' => '劉', '' => '劊', '' => '劋', '' => '劌', '' => '劍', '' => '劎', '' => '劏', '' => '劑', '' => '劒', '' => '劔', '' => '劕', '' => '劖', '' => '劗', '' => '劘', '' => '劙', '' => '劚', '' => '劜', '' => '劤', '' => '劥', '' => '劦', '' => '劧', '' => '劮', '' => '劯', '' => '劰', '' => '労', '' => '劵', '' => '劶', '' => '劷', '' => '劸', '' => '効', '' => '劺', '' => '劻', '' => '劼', '' => '劽', '' => '勀', '' => '勁', '' => '勂', '' => '勄', '' => '勅', '' => '勆', '' => '勈', '' => '勊', '' => '勌', '' => '勍', '' => '勎', '' => '勏', '' => '勑', '' => '勓', '' => '勔', '' => '動', '' => '勗', '' => '務', '' => '勚', '' => '勛', '' => '勜', '' => '勝', '' => '勞', '' => '勠', '' => '勡', '' => '勢', '' => '勣', '' => '勥', '' => '勦', '' => '勧', '' => '勨', '' => '勩', '' => '勪', '' => '勫', '' => '勬', '' => '勭', '' => '勮', '' => '勯', '' => '勱', '' => '勲', '' => '勳', '' => '勴', '' => '勵', '' => '勶', '' => '勷', '' => '勸', '' => '勻', '' => '勼', '' => '勽', '' => '匁', '' => '匂', '' => '匃', '' => '匄', '' => '匇', '' => '匉', '' => '匊', '' => '匋', '' => '匌', '' => '匎', '@' => '匑', 'A' => '匒', 'B' => '匓', 'C' => '匔', 'D' => '匘', 'E' => '匛', 'F' => '匜', 'G' => '匞', 'H' => '匟', 'I' => '匢', 'J' => '匤', 'K' => '匥', 'L' => '匧', 'M' => '匨', 'N' => '匩', 'O' => '匫', 'P' => '匬', 'Q' => '匭', 'R' => '匯', 'S' => '匰', 'T' => '匱', 'U' => '匲', 'V' => '匳', 'W' => '匴', 'X' => '匵', 'Y' => '匶', 'Z' => '匷', '[' => '匸', '\\' => '匼', ']' => '匽', '^' => '區', '_' => '卂', '`' => '卄', 'a' => '卆', 'b' => '卋', 'c' => '卌', 'd' => '卍', 'e' => '卐', 'f' => '協', 'g' => '単', 'h' => '卙', 'i' => '卛', 'j' => '卝', 'k' => '卥', 'l' => '卨', 'm' => '卪', 'n' => '卬', 'o' => '卭', 'p' => '卲', 'q' => '卶', 'r' => '卹', 's' => '卻', 't' => '卼', 'u' => '卽', 'v' => '卾', 'w' => '厀', 'x' => '厁', 'y' => '厃', 'z' => '厇', '{' => '厈', '|' => '厊', '}' => '厎', '~' => '厏', '' => '厐', '' => '厑', '' => '厒', '' => '厓', '' => '厔', '' => '厖', '' => '厗', '' => '厙', '' => '厛', '' => '厜', '' => '厞', '' => '厠', '' => '厡', '' => '厤', '' => '厧', '' => '厪', '' => '厫', '' => '厬', '' => '厭', '' => '厯', '' => '厰', '' => '厱', '' => '厲', '' => '厳', '' => '厴', '' => '厵', '' => '厷', '' => '厸', '' => '厹', '' => '厺', '' => '厼', '' => '厽', '' => '厾', '' => '叀', '' => '參', '' => '叄', '' => '叅', '' => '叆', '' => '叇', '' => '収', '' => '叏', '' => '叐', '' => '叒', '' => '叓', '' => '叕', '' => '叚', '' => '叜', '' => '叝', '' => '叞', '' => '叡', '' => '叢', '' => '叧', '' => '叴', '' => '叺', '' => '叾', '' => '叿', '' => '吀', '' => '吂', '' => '吅', '' => '吇', '' => '吋', '' => '吔', '' => '吘', '' => '吙', '' => '吚', '' => '吜', '' => '吢', '' => '吤', '' => '吥', '' => '吪', '' => '吰', '' => '吳', '' => '吶', '' => '吷', '' => '吺', '' => '吽', '' => '吿', '' => '呁', '' => '呂', '' => '呄', '' => '呅', '' => '呇', '' => '呉', '' => '呌', '' => '呍', '' => '呎', '' => '呏', '' => '呑', '' => '呚', '' => '呝', '' => '呞', '' => '呟', '' => '呠', '' => '呡', '' => '呣', '' => '呥', '' => '呧', '' => '呩', '' => '呪', '' => '呫', '' => '呬', '' => '呭', '' => '呮', '' => '呯', '' => '呰', '' => '呴', '' => '呹', '' => '呺', '' => '呾', '' => '呿', '' => '咁', '' => '咃', '' => '咅', '' => '咇', '' => '咈', '' => '咉', '' => '咊', '' => '咍', '' => '咑', '' => '咓', '' => '咗', '' => '咘', '' => '咜', '' => '咞', '' => '咟', '' => '咠', '' => '咡', '@' => '咢', 'A' => '咥', 'B' => '咮', 'C' => '咰', 'D' => '咲', 'E' => '咵', 'F' => '咶', 'G' => '咷', 'H' => '咹', 'I' => '咺', 'J' => '咼', 'K' => '咾', 'L' => '哃', 'M' => '哅', 'N' => '哊', 'O' => '哋', 'P' => '哖', 'Q' => '哘', 'R' => '哛', 'S' => '哠', 'T' => '員', 'U' => '哢', 'V' => '哣', 'W' => '哤', 'X' => '哫', 'Y' => '哬', 'Z' => '哯', '[' => '哰', '\\' => '哱', ']' => '哴', '^' => '哵', '_' => '哶', '`' => '哷', 'a' => '哸', 'b' => '哹', 'c' => '哻', 'd' => '哾', 'e' => '唀', 'f' => '唂', 'g' => '唃', 'h' => '唄', 'i' => '唅', 'j' => '唈', 'k' => '唊', 'l' => '唋', 'm' => '唌', 'n' => '唍', 'o' => '唎', 'p' => '唒', 'q' => '唓', 'r' => '唕', 's' => '唖', 't' => '唗', 'u' => '唘', 'v' => '唙', 'w' => '唚', 'x' => '唜', 'y' => '唝', 'z' => '唞', '{' => '唟', '|' => '唡', '}' => '唥', '~' => '唦', '' => '唨', '' => '唩', '' => '唫', '' => '唭', '' => '唲', '' => '唴', '' => '唵', '' => '唶', '' => '唸', '' => '唹', '' => '唺', '' => '唻', '' => '唽', '' => '啀', '' => '啂', '' => '啅', '' => '啇', '' => '啈', '' => '啋', '' => '啌', '' => '啍', '' => '啎', '' => '問', '' => '啑', '' => '啒', '' => '啓', '' => '啔', '' => '啗', '' => '啘', '' => '啙', '' => '啚', '' => '啛', '' => '啝', '' => '啞', '' => '啟', '' => '啠', '' => '啢', '' => '啣', '' => '啨', '' => '啩', '' => '啫', '' => '啯', '' => '啰', '' => '啱', '' => '啲', '' => '啳', '' => '啴', '' => '啹', '' => '啺', '' => '啽', '' => '啿', '' => '喅', '' => '喆', '' => '喌', '' => '喍', '' => '喎', '' => '喐', '' => '喒', '' => '喓', '' => '喕', '' => '喖', '' => '喗', '' => '喚', '' => '喛', '' => '喞', '' => '喠', '' => '喡', '' => '喢', '' => '喣', '' => '喤', '' => '喥', '' => '喦', '' => '喨', '' => '喩', '' => '喪', '' => '喫', '' => '喬', '' => '喭', '' => '單', '' => '喯', '' => '喰', '' => '喲', '' => '喴', '' => '営', '' => '喸', '' => '喺', '' => '喼', '' => '喿', '' => '嗀', '' => '嗁', '' => '嗂', '' => '嗃', '' => '嗆', '' => '嗇', '' => '嗈', '' => '嗊', '' => '嗋', '' => '嗎', '' => '嗏', '' => '嗐', '' => '嗕', '' => '嗗', '' => '嗘', '' => '嗙', '' => '嗚', '' => '嗛', '' => '嗞', '' => '嗠', '' => '嗢', '' => '嗧', '' => '嗩', '' => '嗭', '' => '嗮', '' => '嗰', '' => '嗱', '' => '嗴', '' => '嗶', '' => '嗸', '' => '嗹', '' => '嗺', '' => '嗻', '' => '嗼', '' => '嗿', '' => '嘂', '' => '嘃', '' => '嘄', '' => '嘅', '@' => '嘆', 'A' => '嘇', 'B' => '嘊', 'C' => '嘋', 'D' => '嘍', 'E' => '嘐', 'F' => '嘑', 'G' => '嘒', 'H' => '嘓', 'I' => '嘔', 'J' => '嘕', 'K' => '嘖', 'L' => '嘗', 'M' => '嘙', 'N' => '嘚', 'O' => '嘜', 'P' => '嘝', 'Q' => '嘠', 'R' => '嘡', 'S' => '嘢', 'T' => '嘥', 'U' => '嘦', 'V' => '嘨', 'W' => '嘩', 'X' => '嘪', 'Y' => '嘫', 'Z' => '嘮', '[' => '嘯', '\\' => '嘰', ']' => '嘳', '^' => '嘵', '_' => '嘷', '`' => '嘸', 'a' => '嘺', 'b' => '嘼', 'c' => '嘽', 'd' => '嘾', 'e' => '噀', 'f' => '噁', 'g' => '噂', 'h' => '噃', 'i' => '噄', 'j' => '噅', 'k' => '噆', 'l' => '噇', 'm' => '噈', 'n' => '噉', 'o' => '噊', 'p' => '噋', 'q' => '噏', 'r' => '噐', 's' => '噑', 't' => '噒', 'u' => '噓', 'v' => '噕', 'w' => '噖', 'x' => '噚', 'y' => '噛', 'z' => '噝', '{' => '噞', '|' => '噟', '}' => '噠', '~' => '噡', '' => '噣', '' => '噥', '' => '噦', '' => '噧', '' => '噭', '' => '噮', '' => '噯', '' => '噰', '' => '噲', '' => '噳', '' => '噴', '' => '噵', '' => '噷', '' => '噸', '' => '噹', '' => '噺', '' => '噽', '' => '噾', '' => '噿', '' => '嚀', '' => '嚁', '' => '嚂', '' => '嚃', '' => '嚄', '' => '嚇', '' => '嚈', '' => '嚉', '' => '嚊', '' => '嚋', '' => '嚌', '' => '嚍', '' => '嚐', '' => '嚑', '' => '嚒', '' => '嚔', '' => '嚕', '' => '嚖', '' => '嚗', '' => '嚘', '' => '嚙', '' => '嚚', '' => '嚛', '' => '嚜', '' => '嚝', '' => '嚞', '' => '嚟', '' => '嚠', '' => '嚡', '' => '嚢', '' => '嚤', '' => '嚥', '' => '嚦', '' => '嚧', '' => '嚨', '' => '嚩', '' => '嚪', '' => '嚫', '' => '嚬', '' => '嚭', '' => '嚮', '' => '嚰', '' => '嚱', '' => '嚲', '' => '嚳', '' => '嚴', '' => '嚵', '' => '嚶', '' => '嚸', '' => '嚹', '' => '嚺', '' => '嚻', '' => '嚽', '' => '嚾', '' => '嚿', '' => '囀', '' => '囁', '' => '囂', '' => '囃', '' => '囄', '' => '囅', '' => '囆', '' => '囇', '' => '囈', '' => '囉', '' => '囋', '' => '囌', '' => '囍', '' => '囎', '' => '囏', '' => '囐', '' => '囑', '' => '囒', '' => '囓', '' => '囕', '' => '囖', '' => '囘', '' => '囙', '' => '囜', '' => '団', '' => '囥', '' => '囦', '' => '囧', '' => '囨', '' => '囩', '' => '囪', '' => '囬', '' => '囮', '' => '囯', '' => '囲', '' => '図', '' => '囶', '' => '囷', '' => '囸', '' => '囻', '' => '囼', '' => '圀', '' => '圁', '' => '圂', '' => '圅', '' => '圇', '' => '國', '' => '圌', '' => '圍', '' => '圎', '' => '圏', '' => '圐', '' => '圑', '@' => '園', 'A' => '圓', 'B' => '圔', 'C' => '圕', 'D' => '圖', 'E' => '圗', 'F' => '團', 'G' => '圙', 'H' => '圚', 'I' => '圛', 'J' => '圝', 'K' => '圞', 'L' => '圠', 'M' => '圡', 'N' => '圢', 'O' => '圤', 'P' => '圥', 'Q' => '圦', 'R' => '圧', 'S' => '圫', 'T' => '圱', 'U' => '圲', 'V' => '圴', 'W' => '圵', 'X' => '圶', 'Y' => '圷', 'Z' => '圸', '[' => '圼', '\\' => '圽', ']' => '圿', '^' => '坁', '_' => '坃', '`' => '坄', 'a' => '坅', 'b' => '坆', 'c' => '坈', 'd' => '坉', 'e' => '坋', 'f' => '坒', 'g' => '坓', 'h' => '坔', 'i' => '坕', 'j' => '坖', 'k' => '坘', 'l' => '坙', 'm' => '坢', 'n' => '坣', 'o' => '坥', 'p' => '坧', 'q' => '坬', 'r' => '坮', 's' => '坰', 't' => '坱', 'u' => '坲', 'v' => '坴', 'w' => '坵', 'x' => '坸', 'y' => '坹', 'z' => '坺', '{' => '坽', '|' => '坾', '}' => '坿', '~' => '垀', '' => '垁', '' => '垇', '' => '垈', '' => '垉', '' => '垊', '' => '垍', '' => '垎', '' => '垏', '' => '垐', '' => '垑', '' => '垔', '' => '垕', '' => '垖', '' => '垗', '' => '垘', '' => '垙', '' => '垚', '' => '垜', '' => '垝', '' => '垞', '' => '垟', '' => '垥', '' => '垨', '' => '垪', '' => '垬', '' => '垯', '' => '垰', '' => '垱', '' => '垳', '' => '垵', '' => '垶', '' => '垷', '' => '垹', '' => '垺', '' => '垻', '' => '垼', '' => '垽', '' => '垾', '' => '垿', '' => '埀', '' => '埁', '' => '埄', '' => '埅', '' => '埆', '' => '埇', '' => '埈', '' => '埉', '' => '埊', '' => '埌', '' => '埍', '' => '埐', '' => '埑', '' => '埓', '' => '埖', '' => '埗', '' => '埛', '' => '埜', '' => '埞', '' => '埡', '' => '埢', '' => '埣', '' => '埥', '' => '埦', '' => '埧', '' => '埨', '' => '埩', '' => '埪', '' => '埫', '' => '埬', '' => '埮', '' => '埰', '' => '埱', '' => '埲', '' => '埳', '' => '埵', '' => '埶', '' => '執', '' => '埻', '' => '埼', '' => '埾', '' => '埿', '' => '堁', '' => '堃', '' => '堄', '' => '堅', '' => '堈', '' => '堉', '' => '堊', '' => '堌', '' => '堎', '' => '堏', '' => '堐', '' => '堒', '' => '堓', '' => '堔', '' => '堖', '' => '堗', '' => '堘', '' => '堚', '' => '堛', '' => '堜', '' => '堝', '' => '堟', '' => '堢', '' => '堣', '' => '堥', '' => '堦', '' => '堧', '' => '堨', '' => '堩', '' => '堫', '' => '堬', '' => '堭', '' => '堮', '' => '堯', '' => '報', '' => '堲', '' => '堳', '' => '場', '' => '堶', '' => '堷', '' => '堸', '' => '堹', '' => '堺', '' => '堻', '' => '堼', '' => '堽', '@' => '堾', 'A' => '堿', 'B' => '塀', 'C' => '塁', 'D' => '塂', 'E' => '塃', 'F' => '塅', 'G' => '塆', 'H' => '塇', 'I' => '塈', 'J' => '塉', 'K' => '塊', 'L' => '塋', 'M' => '塎', 'N' => '塏', 'O' => '塐', 'P' => '塒', 'Q' => '塓', 'R' => '塕', 'S' => '塖', 'T' => '塗', 'U' => '塙', 'V' => '塚', 'W' => '塛', 'X' => '塜', 'Y' => '塝', 'Z' => '塟', '[' => '塠', '\\' => '塡', ']' => '塢', '^' => '塣', '_' => '塤', '`' => '塦', 'a' => '塧', 'b' => '塨', 'c' => '塩', 'd' => '塪', 'e' => '塭', 'f' => '塮', 'g' => '塯', 'h' => '塰', 'i' => '塱', 'j' => '塲', 'k' => '塳', 'l' => '塴', 'm' => '塵', 'n' => '塶', 'o' => '塷', 'p' => '塸', 'q' => '塹', 'r' => '塺', 's' => '塻', 't' => '塼', 'u' => '塽', 'v' => '塿', 'w' => '墂', 'x' => '墄', 'y' => '墆', 'z' => '墇', '{' => '墈', '|' => '墊', '}' => '墋', '~' => '墌', '' => '墍', '' => '墎', '' => '墏', '' => '墐', '' => '墑', '' => '墔', '' => '墕', '' => '墖', '' => '増', '' => '墘', '' => '墛', '' => '墜', '' => '墝', '' => '墠', '' => '墡', '' => '墢', '' => '墣', '' => '墤', '' => '墥', '' => '墦', '' => '墧', '' => '墪', '' => '墫', '' => '墬', '' => '墭', '' => '墮', '' => '墯', '' => '墰', '' => '墱', '' => '墲', '' => '墳', '' => '墴', '' => '墵', '' => '墶', '' => '墷', '' => '墸', '' => '墹', '' => '墺', '' => '墻', '' => '墽', '' => '墾', '' => '墿', '' => '壀', '' => '壂', '' => '壃', '' => '壄', '' => '壆', '' => '壇', '' => '壈', '' => '壉', '' => '壊', '' => '壋', '' => '壌', '' => '壍', '' => '壎', '' => '壏', '' => '壐', '' => '壒', '' => '壓', '' => '壔', '' => '壖', '' => '壗', '' => '壘', '' => '壙', '' => '壚', '' => '壛', '' => '壜', '' => '壝', '' => '壞', '' => '壟', '' => '壠', '' => '壡', '' => '壢', '' => '壣', '' => '壥', '' => '壦', '' => '壧', '' => '壨', '' => '壩', '' => '壪', '' => '壭', '' => '壯', '' => '壱', '' => '売', '' => '壴', '' => '壵', '' => '壷', '' => '壸', '' => '壺', '' => '壻', '' => '壼', '' => '壽', '' => '壾', '' => '壿', '' => '夀', '' => '夁', '' => '夃', '' => '夅', '' => '夆', '' => '夈', '' => '変', '' => '夊', '' => '夋', '' => '夌', '' => '夎', '' => '夐', '' => '夑', '' => '夒', '' => '夓', '' => '夗', '' => '夘', '' => '夛', '' => '夝', '' => '夞', '' => '夠', '' => '夡', '' => '夢', '' => '夣', '' => '夦', '' => '夨', '' => '夬', '' => '夰', '' => '夲', '' => '夳', '' => '夵', '' => '夶', '' => '夻', '@' => '夽', 'A' => '夾', 'B' => '夿', 'C' => '奀', 'D' => '奃', 'E' => '奅', 'F' => '奆', 'G' => '奊', 'H' => '奌', 'I' => '奍', 'J' => '奐', 'K' => '奒', 'L' => '奓', 'M' => '奙', 'N' => '奛', 'O' => '奜', 'P' => '奝', 'Q' => '奞', 'R' => '奟', 'S' => '奡', 'T' => '奣', 'U' => '奤', 'V' => '奦', 'W' => '奧', 'X' => '奨', 'Y' => '奩', 'Z' => '奪', '[' => '奫', '\\' => '奬', ']' => '奭', '^' => '奮', '_' => '奯', '`' => '奰', 'a' => '奱', 'b' => '奲', 'c' => '奵', 'd' => '奷', 'e' => '奺', 'f' => '奻', 'g' => '奼', 'h' => '奾', 'i' => '奿', 'j' => '妀', 'k' => '妅', 'l' => '妉', 'm' => '妋', 'n' => '妌', 'o' => '妎', 'p' => '妏', 'q' => '妐', 'r' => '妑', 's' => '妔', 't' => '妕', 'u' => '妘', 'v' => '妚', 'w' => '妛', 'x' => '妜', 'y' => '妝', 'z' => '妟', '{' => '妠', '|' => '妡', '}' => '妢', '~' => '妦', '' => '妧', '' => '妬', '' => '妭', '' => '妰', '' => '妱', '' => '妳', '' => '妴', '' => '妵', '' => '妶', '' => '妷', '' => '妸', '' => '妺', '' => '妼', '' => '妽', '' => '妿', '' => '姀', '' => '姁', '' => '姂', '' => '姃', '' => '姄', '' => '姅', '' => '姇', '' => '姈', '' => '姉', '' => '姌', '' => '姍', '' => '姎', '' => '姏', '' => '姕', '' => '姖', '' => '姙', '' => '姛', '' => '姞', '' => '姟', '' => '姠', '' => '姡', '' => '姢', '' => '姤', '' => '姦', '' => '姧', '' => '姩', '' => '姪', '' => '姫', '' => '姭', '' => '姮', '' => '姯', '' => '姰', '' => '姱', '' => '姲', '' => '姳', '' => '姴', '' => '姵', '' => '姶', '' => '姷', '' => '姸', '' => '姺', '' => '姼', '' => '姽', '' => '姾', '' => '娀', '' => '娂', '' => '娊', '' => '娋', '' => '娍', '' => '娎', '' => '娏', '' => '娐', '' => '娒', '' => '娔', '' => '娕', '' => '娖', '' => '娗', '' => '娙', '' => '娚', '' => '娛', '' => '娝', '' => '娞', '' => '娡', '' => '娢', '' => '娤', '' => '娦', '' => '娧', '' => '娨', '' => '娪', '' => '娫', '' => '娬', '' => '娭', '' => '娮', '' => '娯', '' => '娰', '' => '娳', '' => '娵', '' => '娷', '' => '娸', '' => '娹', '' => '娺', '' => '娻', '' => '娽', '' => '娾', '' => '娿', '' => '婁', '' => '婂', '' => '婃', '' => '婄', '' => '婅', '' => '婇', '' => '婈', '' => '婋', '' => '婌', '' => '婍', '' => '婎', '' => '婏', '' => '婐', '' => '婑', '' => '婒', '' => '婓', '' => '婔', '' => '婖', '' => '婗', '' => '婘', '' => '婙', '' => '婛', '' => '婜', '' => '婝', '' => '婞', '' => '婟', '' => '婠', '@' => '婡', 'A' => '婣', 'B' => '婤', 'C' => '婥', 'D' => '婦', 'E' => '婨', 'F' => '婩', 'G' => '婫', 'H' => '婬', 'I' => '婭', 'J' => '婮', 'K' => '婯', 'L' => '婰', 'M' => '婱', 'N' => '婲', 'O' => '婳', 'P' => '婸', 'Q' => '婹', 'R' => '婻', 'S' => '婼', 'T' => '婽', 'U' => '婾', 'V' => '媀', 'W' => '媁', 'X' => '媂', 'Y' => '媃', 'Z' => '媄', '[' => '媅', '\\' => '媆', ']' => '媇', '^' => '媈', '_' => '媉', '`' => '媊', 'a' => '媋', 'b' => '媌', 'c' => '媍', 'd' => '媎', 'e' => '媏', 'f' => '媐', 'g' => '媑', 'h' => '媓', 'i' => '媔', 'j' => '媕', 'k' => '媖', 'l' => '媗', 'm' => '媘', 'n' => '媙', 'o' => '媜', 'p' => '媝', 'q' => '媞', 'r' => '媟', 's' => '媠', 't' => '媡', 'u' => '媢', 'v' => '媣', 'w' => '媤', 'x' => '媥', 'y' => '媦', 'z' => '媧', '{' => '媨', '|' => '媩', '}' => '媫', '~' => '媬', '' => '媭', '' => '媮', '' => '媯', '' => '媰', '' => '媱', '' => '媴', '' => '媶', '' => '媷', '' => '媹', '' => '媺', '' => '媻', '' => '媼', '' => '媽', '' => '媿', '' => '嫀', '' => '嫃', '' => '嫄', '' => '嫅', '' => '嫆', '' => '嫇', '' => '嫈', '' => '嫊', '' => '嫋', '' => '嫍', '' => '嫎', '' => '嫏', '' => '嫐', '' => '嫑', '' => '嫓', '' => '嫕', '' => '嫗', '' => '嫙', '' => '嫚', '' => '嫛', '' => '嫝', '' => '嫞', '' => '嫟', '' => '嫢', '' => '嫤', '' => '嫥', '' => '嫧', '' => '嫨', '' => '嫪', '' => '嫬', '' => '嫭', '' => '嫮', '' => '嫯', '' => '嫰', '' => '嫲', '' => '嫳', '' => '嫴', '' => '嫵', '' => '嫶', '' => '嫷', '' => '嫸', '' => '嫹', '' => '嫺', '' => '嫻', '' => '嫼', '' => '嫽', '' => '嫾', '' => '嫿', '' => '嬀', '' => '嬁', '' => '嬂', '' => '嬃', '' => '嬄', '' => '嬅', '' => '嬆', '' => '嬇', '' => '嬈', '' => '嬊', '' => '嬋', '' => '嬌', '' => '嬍', '' => '嬎', '' => '嬏', '' => '嬐', '' => '嬑', '' => '嬒', '' => '嬓', '' => '嬔', '' => '嬕', '' => '嬘', '' => '嬙', '' => '嬚', '' => '嬛', '' => '嬜', '' => '嬝', '' => '嬞', '' => '嬟', '' => '嬠', '' => '嬡', '' => '嬢', '' => '嬣', '' => '嬤', '' => '嬥', '' => '嬦', '' => '嬧', '' => '嬨', '' => '嬩', '' => '嬪', '' => '嬫', '' => '嬬', '' => '嬭', '' => '嬮', '' => '嬯', '' => '嬰', '' => '嬱', '' => '嬳', '' => '嬵', '' => '嬶', '' => '嬸', '' => '嬹', '' => '嬺', '' => '嬻', '' => '嬼', '' => '嬽', '' => '嬾', '' => '嬿', '' => '孁', '' => '孂', '' => '孃', '' => '孄', '' => '孅', '' => '孆', '' => '孇', '@' => '孈', 'A' => '孉', 'B' => '孊', 'C' => '孋', 'D' => '孌', 'E' => '孍', 'F' => '孎', 'G' => '孏', 'H' => '孒', 'I' => '孖', 'J' => '孞', 'K' => '孠', 'L' => '孡', 'M' => '孧', 'N' => '孨', 'O' => '孫', 'P' => '孭', 'Q' => '孮', 'R' => '孯', 'S' => '孲', 'T' => '孴', 'U' => '孶', 'V' => '孷', 'W' => '學', 'X' => '孹', 'Y' => '孻', 'Z' => '孼', '[' => '孾', '\\' => '孿', ']' => '宂', '^' => '宆', '_' => '宊', '`' => '宍', 'a' => '宎', 'b' => '宐', 'c' => '宑', 'd' => '宒', 'e' => '宔', 'f' => '宖', 'g' => '実', 'h' => '宧', 'i' => '宨', 'j' => '宩', 'k' => '宬', 'l' => '宭', 'm' => '宮', 'n' => '宯', 'o' => '宱', 'p' => '宲', 'q' => '宷', 'r' => '宺', 's' => '宻', 't' => '宼', 'u' => '寀', 'v' => '寁', 'w' => '寃', 'x' => '寈', 'y' => '寉', 'z' => '寊', '{' => '寋', '|' => '寍', '}' => '寎', '~' => '寏', '' => '寑', '' => '寔', '' => '寕', '' => '寖', '' => '寗', '' => '寘', '' => '寙', '' => '寚', '' => '寛', '' => '寜', '' => '寠', '' => '寢', '' => '寣', '' => '實', '' => '寧', '' => '審', '' => '寪', '' => '寫', '' => '寬', '' => '寭', '' => '寯', '' => '寱', '' => '寲', '' => '寳', '' => '寴', '' => '寵', '' => '寶', '' => '寷', '' => '寽', '' => '対', '' => '尀', '' => '専', '' => '尃', '' => '尅', '' => '將', '' => '專', '' => '尋', '' => '尌', '' => '對', '' => '導', '' => '尐', '' => '尒', '' => '尓', '' => '尗', '' => '尙', '' => '尛', '' => '尞', '' => '尟', '' => '尠', '' => '尡', '' => '尣', '' => '尦', '' => '尨', '' => '尩', '' => '尪', '' => '尫', '' => '尭', '' => '尮', '' => '尯', '' => '尰', '' => '尲', '' => '尳', '' => '尵', '' => '尶', '' => '尷', '' => '屃', '' => '屄', '' => '屆', '' => '屇', '' => '屌', '' => '屍', '' => '屒', '' => '屓', '' => '屔', '' => '屖', '' => '屗', '' => '屘', '' => '屚', '' => '屛', '' => '屜', '' => '屝', '' => '屟', '' => '屢', '' => '層', '' => '屧', '' => '屨', '' => '屩', '' => '屪', '' => '屫', '' => '屬', '' => '屭', '' => '屰', '' => '屲', '' => '屳', '' => '屴', '' => '屵', '' => '屶', '' => '屷', '' => '屸', '' => '屻', '' => '屼', '' => '屽', '' => '屾', '' => '岀', '' => '岃', '' => '岄', '' => '岅', '' => '岆', '' => '岇', '' => '岉', '' => '岊', '' => '岋', '' => '岎', '' => '岏', '' => '岒', '' => '岓', '' => '岕', '' => '岝', '' => '岞', '' => '岟', '' => '岠', '' => '岡', '' => '岤', '' => '岥', '' => '岦', '' => '岧', '' => '岨', '@' => '岪', 'A' => '岮', 'B' => '岯', 'C' => '岰', 'D' => '岲', 'E' => '岴', 'F' => '岶', 'G' => '岹', 'H' => '岺', 'I' => '岻', 'J' => '岼', 'K' => '岾', 'L' => '峀', 'M' => '峂', 'N' => '峃', 'O' => '峅', 'P' => '峆', 'Q' => '峇', 'R' => '峈', 'S' => '峉', 'T' => '峊', 'U' => '峌', 'V' => '峍', 'W' => '峎', 'X' => '峏', 'Y' => '峐', 'Z' => '峑', '[' => '峓', '\\' => '峔', ']' => '峕', '^' => '峖', '_' => '峗', '`' => '峘', 'a' => '峚', 'b' => '峛', 'c' => '峜', 'd' => '峝', 'e' => '峞', 'f' => '峟', 'g' => '峠', 'h' => '峢', 'i' => '峣', 'j' => '峧', 'k' => '峩', 'l' => '峫', 'm' => '峬', 'n' => '峮', 'o' => '峯', 'p' => '峱', 'q' => '峲', 'r' => '峳', 's' => '峴', 't' => '峵', 'u' => '島', 'v' => '峷', 'w' => '峸', 'x' => '峹', 'y' => '峺', 'z' => '峼', '{' => '峽', '|' => '峾', '}' => '峿', '~' => '崀', '' => '崁', '' => '崄', '' => '崅', '' => '崈', '' => '崉', '' => '崊', '' => '崋', '' => '崌', '' => '崍', '' => '崏', '' => '崐', '' => '崑', '' => '崒', '' => '崓', '' => '崕', '' => '崗', '' => '崘', '' => '崙', '' => '崚', '' => '崜', '' => '崝', '' => '崟', '' => '崠', '' => '崡', '' => '崢', '' => '崣', '' => '崥', '' => '崨', '' => '崪', '' => '崫', '' => '崬', '' => '崯', '' => '崰', '' => '崱', '' => '崲', '' => '崳', '' => '崵', '' => '崶', '' => '崷', '' => '崸', '' => '崹', '' => '崺', '' => '崻', '' => '崼', '' => '崿', '' => '嵀', '' => '嵁', '' => '嵂', '' => '嵃', '' => '嵄', '' => '嵅', '' => '嵆', '' => '嵈', '' => '嵉', '' => '嵍', '' => '嵎', '' => '嵏', '' => '嵐', '' => '嵑', '' => '嵒', '' => '嵓', '' => '嵔', '' => '嵕', '' => '嵖', '' => '嵗', '' => '嵙', '' => '嵚', '' => '嵜', '' => '嵞', '' => '嵟', '' => '嵠', '' => '嵡', '' => '嵢', '' => '嵣', '' => '嵤', '' => '嵥', '' => '嵦', '' => '嵧', '' => '嵨', '' => '嵪', '' => '嵭', '' => '嵮', '' => '嵰', '' => '嵱', '' => '嵲', '' => '嵳', '' => '嵵', '' => '嵶', '' => '嵷', '' => '嵸', '' => '嵹', '' => '嵺', '' => '嵻', '' => '嵼', '' => '嵽', '' => '嵾', '' => '嵿', '' => '嶀', '' => '嶁', '' => '嶃', '' => '嶄', '' => '嶅', '' => '嶆', '' => '嶇', '' => '嶈', '' => '嶉', '' => '嶊', '' => '嶋', '' => '嶌', '' => '嶍', '' => '嶎', '' => '嶏', '' => '嶐', '' => '嶑', '' => '嶒', '' => '嶓', '' => '嶔', '' => '嶕', '' => '嶖', '' => '嶗', '' => '嶘', '' => '嶚', '' => '嶛', '' => '嶜', '' => '嶞', '' => '嶟', '' => '嶠', '@' => '嶡', 'A' => '嶢', 'B' => '嶣', 'C' => '嶤', 'D' => '嶥', 'E' => '嶦', 'F' => '嶧', 'G' => '嶨', 'H' => '嶩', 'I' => '嶪', 'J' => '嶫', 'K' => '嶬', 'L' => '嶭', 'M' => '嶮', 'N' => '嶯', 'O' => '嶰', 'P' => '嶱', 'Q' => '嶲', 'R' => '嶳', 'S' => '嶴', 'T' => '嶵', 'U' => '嶶', 'V' => '嶸', 'W' => '嶹', 'X' => '嶺', 'Y' => '嶻', 'Z' => '嶼', '[' => '嶽', '\\' => '嶾', ']' => '嶿', '^' => '巀', '_' => '巁', '`' => '巂', 'a' => '巃', 'b' => '巄', 'c' => '巆', 'd' => '巇', 'e' => '巈', 'f' => '巉', 'g' => '巊', 'h' => '巋', 'i' => '巌', 'j' => '巎', 'k' => '巏', 'l' => '巐', 'm' => '巑', 'n' => '巒', 'o' => '巓', 'p' => '巔', 'q' => '巕', 'r' => '巖', 's' => '巗', 't' => '巘', 'u' => '巙', 'v' => '巚', 'w' => '巜', 'x' => '巟', 'y' => '巠', 'z' => '巣', '{' => '巤', '|' => '巪', '}' => '巬', '~' => '巭', '' => '巰', '' => '巵', '' => '巶', '' => '巸', '' => '巹', '' => '巺', '' => '巻', '' => '巼', '' => '巿', '' => '帀', '' => '帄', '' => '帇', '' => '帉', '' => '帊', '' => '帋', '' => '帍', '' => '帎', '' => '帒', '' => '帓', '' => '帗', '' => '帞', '' => '帟', '' => '帠', '' => '帡', '' => '帢', '' => '帣', '' => '帤', '' => '帥', '' => '帨', '' => '帩', '' => '帪', '' => '師', '' => '帬', '' => '帯', '' => '帰', '' => '帲', '' => '帳', '' => '帴', '' => '帵', '' => '帶', '' => '帹', '' => '帺', '' => '帾', '' => '帿', '' => '幀', '' => '幁', '' => '幃', '' => '幆', '' => '幇', '' => '幈', '' => '幉', '' => '幊', '' => '幋', '' => '幍', '' => '幎', '' => '幏', '' => '幐', '' => '幑', '' => '幒', '' => '幓', '' => '幖', '' => '幗', '' => '幘', '' => '幙', '' => '幚', '' => '幜', '' => '幝', '' => '幟', '' => '幠', '' => '幣', '' => '幤', '' => '幥', '' => '幦', '' => '幧', '' => '幨', '' => '幩', '' => '幪', '' => '幫', '' => '幬', '' => '幭', '' => '幮', '' => '幯', '' => '幰', '' => '幱', '' => '幵', '' => '幷', '' => '幹', '' => '幾', '' => '庁', '' => '庂', '' => '広', '' => '庅', '' => '庈', '' => '庉', '' => '庌', '' => '庍', '' => '庎', '' => '庒', '' => '庘', '' => '庛', '' => '庝', '' => '庡', '' => '庢', '' => '庣', '' => '庤', '' => '庨', '' => '庩', '' => '庪', '' => '庫', '' => '庬', '' => '庮', '' => '庯', '' => '庰', '' => '庱', '' => '庲', '' => '庴', '' => '庺', '' => '庻', '' => '庼', '' => '庽', '' => '庿', '' => '廀', '' => '廁', '' => '廂', '' => '廃', '' => '廄', '' => '廅', '@' => '廆', 'A' => '廇', 'B' => '廈', 'C' => '廋', 'D' => '廌', 'E' => '廍', 'F' => '廎', 'G' => '廏', 'H' => '廐', 'I' => '廔', 'J' => '廕', 'K' => '廗', 'L' => '廘', 'M' => '廙', 'N' => '廚', 'O' => '廜', 'P' => '廝', 'Q' => '廞', 'R' => '廟', 'S' => '廠', 'T' => '廡', 'U' => '廢', 'V' => '廣', 'W' => '廤', 'X' => '廥', 'Y' => '廦', 'Z' => '廧', '[' => '廩', '\\' => '廫', ']' => '廬', '^' => '廭', '_' => '廮', '`' => '廯', 'a' => '廰', 'b' => '廱', 'c' => '廲', 'd' => '廳', 'e' => '廵', 'f' => '廸', 'g' => '廹', 'h' => '廻', 'i' => '廼', 'j' => '廽', 'k' => '弅', 'l' => '弆', 'm' => '弇', 'n' => '弉', 'o' => '弌', 'p' => '弍', 'q' => '弎', 'r' => '弐', 's' => '弒', 't' => '弔', 'u' => '弖', 'v' => '弙', 'w' => '弚', 'x' => '弜', 'y' => '弝', 'z' => '弞', '{' => '弡', '|' => '弢', '}' => '弣', '~' => '弤', '' => '弨', '' => '弫', '' => '弬', '' => '弮', '' => '弰', '' => '弲', '' => '弳', '' => '弴', '' => '張', '' => '弶', '' => '強', '' => '弸', '' => '弻', '' => '弽', '' => '弾', '' => '弿', '' => '彁', '' => '彂', '' => '彃', '' => '彄', '' => '彅', '' => '彆', '' => '彇', '' => '彈', '' => '彉', '' => '彊', '' => '彋', '' => '彌', '' => '彍', '' => '彎', '' => '彏', '' => '彑', '' => '彔', '' => '彙', '' => '彚', '' => '彛', '' => '彜', '' => '彞', '' => '彟', '' => '彠', '' => '彣', '' => '彥', '' => '彧', '' => '彨', '' => '彫', '' => '彮', '' => '彯', '' => '彲', '' => '彴', '' => '彵', '' => '彶', '' => '彸', '' => '彺', '' => '彽', '' => '彾', '' => '彿', '' => '徃', '' => '徆', '' => '徍', '' => '徎', '' => '徏', '' => '徑', '' => '従', '' => '徔', '' => '徖', '' => '徚', '' => '徛', '' => '徝', '' => '從', '' => '徟', '' => '徠', '' => '徢', '' => '徣', '' => '徤', '' => '徥', '' => '徦', '' => '徧', '' => '復', '' => '徫', '' => '徬', '' => '徯', '' => '徰', '' => '徱', '' => '徲', '' => '徳', '' => '徴', '' => '徶', '' => '徸', '' => '徹', '' => '徺', '' => '徻', '' => '徾', '' => '徿', '' => '忀', '' => '忁', '' => '忂', '' => '忇', '' => '忈', '' => '忊', '' => '忋', '' => '忎', '' => '忓', '' => '忔', '' => '忕', '' => '忚', '' => '忛', '' => '応', '' => '忞', '' => '忟', '' => '忢', '' => '忣', '' => '忥', '' => '忦', '' => '忨', '' => '忩', '' => '忬', '' => '忯', '' => '忰', '' => '忲', '' => '忳', '' => '忴', '' => '忶', '' => '忷', '' => '忹', '' => '忺', '' => '忼', '' => '怇', '@' => '怈', 'A' => '怉', 'B' => '怋', 'C' => '怌', 'D' => '怐', 'E' => '怑', 'F' => '怓', 'G' => '怗', 'H' => '怘', 'I' => '怚', 'J' => '怞', 'K' => '怟', 'L' => '怢', 'M' => '怣', 'N' => '怤', 'O' => '怬', 'P' => '怭', 'Q' => '怮', 'R' => '怰', 'S' => '怱', 'T' => '怲', 'U' => '怳', 'V' => '怴', 'W' => '怶', 'X' => '怷', 'Y' => '怸', 'Z' => '怹', '[' => '怺', '\\' => '怽', ']' => '怾', '^' => '恀', '_' => '恄', '`' => '恅', 'a' => '恆', 'b' => '恇', 'c' => '恈', 'd' => '恉', 'e' => '恊', 'f' => '恌', 'g' => '恎', 'h' => '恏', 'i' => '恑', 'j' => '恓', 'k' => '恔', 'l' => '恖', 'm' => '恗', 'n' => '恘', 'o' => '恛', 'p' => '恜', 'q' => '恞', 'r' => '恟', 's' => '恠', 't' => '恡', 'u' => '恥', 'v' => '恦', 'w' => '恮', 'x' => '恱', 'y' => '恲', 'z' => '恴', '{' => '恵', '|' => '恷', '}' => '恾', '~' => '悀', '' => '悁', '' => '悂', '' => '悅', '' => '悆', '' => '悇', '' => '悈', '' => '悊', '' => '悋', '' => '悎', '' => '悏', '' => '悐', '' => '悑', '' => '悓', '' => '悕', '' => '悗', '' => '悘', '' => '悙', '' => '悜', '' => '悞', '' => '悡', '' => '悢', '' => '悤', '' => '悥', '' => '悧', '' => '悩', '' => '悪', '' => '悮', '' => '悰', '' => '悳', '' => '悵', '' => '悶', '' => '悷', '' => '悹', '' => '悺', '' => '悽', '' => '悾', '' => '悿', '' => '惀', '' => '惁', '' => '惂', '' => '惃', '' => '惄', '' => '惇', '' => '惈', '' => '惉', '' => '惌', '' => '惍', '' => '惎', '' => '惏', '' => '惐', '' => '惒', '' => '惓', '' => '惔', '' => '惖', '' => '惗', '' => '惙', '' => '惛', '' => '惞', '' => '惡', '' => '惢', '' => '惣', '' => '惤', '' => '惥', '' => '惪', '' => '惱', '' => '惲', '' => '惵', '' => '惷', '' => '惸', '' => '惻', '' => '惼', '' => '惽', '' => '惾', '' => '惿', '' => '愂', '' => '愃', '' => '愄', '' => '愅', '' => '愇', '' => '愊', '' => '愋', '' => '愌', '' => '愐', '' => '愑', '' => '愒', '' => '愓', '' => '愔', '' => '愖', '' => '愗', '' => '愘', '' => '愙', '' => '愛', '' => '愜', '' => '愝', '' => '愞', '' => '愡', '' => '愢', '' => '愥', '' => '愨', '' => '愩', '' => '愪', '' => '愬', '' => '愭', '' => '愮', '' => '愯', '' => '愰', '' => '愱', '' => '愲', '' => '愳', '' => '愴', '' => '愵', '' => '愶', '' => '愷', '' => '愸', '' => '愹', '' => '愺', '' => '愻', '' => '愼', '' => '愽', '' => '愾', '' => '慀', '' => '慁', '' => '慂', '' => '慃', '' => '慄', '' => '慅', '' => '慆', '@' => '慇', 'A' => '慉', 'B' => '態', 'C' => '慍', 'D' => '慏', 'E' => '慐', 'F' => '慒', 'G' => '慓', 'H' => '慔', 'I' => '慖', 'J' => '慗', 'K' => '慘', 'L' => '慙', 'M' => '慚', 'N' => '慛', 'O' => '慜', 'P' => '慞', 'Q' => '慟', 'R' => '慠', 'S' => '慡', 'T' => '慣', 'U' => '慤', 'V' => '慥', 'W' => '慦', 'X' => '慩', 'Y' => '慪', 'Z' => '慫', '[' => '慬', '\\' => '慭', ']' => '慮', '^' => '慯', '_' => '慱', '`' => '慲', 'a' => '慳', 'b' => '慴', 'c' => '慶', 'd' => '慸', 'e' => '慹', 'f' => '慺', 'g' => '慻', 'h' => '慼', 'i' => '慽', 'j' => '慾', 'k' => '慿', 'l' => '憀', 'm' => '憁', 'n' => '憂', 'o' => '憃', 'p' => '憄', 'q' => '憅', 'r' => '憆', 's' => '憇', 't' => '憈', 'u' => '憉', 'v' => '憊', 'w' => '憌', 'x' => '憍', 'y' => '憏', 'z' => '憐', '{' => '憑', '|' => '憒', '}' => '憓', '~' => '憕', '' => '憖', '' => '憗', '' => '憘', '' => '憙', '' => '憚', '' => '憛', '' => '憜', '' => '憞', '' => '憟', '' => '憠', '' => '憡', '' => '憢', '' => '憣', '' => '憤', '' => '憥', '' => '憦', '' => '憪', '' => '憫', '' => '憭', '' => '憮', '' => '憯', '' => '憰', '' => '憱', '' => '憲', '' => '憳', '' => '憴', '' => '憵', '' => '憶', '' => '憸', '' => '憹', '' => '憺', '' => '憻', '' => '憼', '' => '憽', '' => '憿', '' => '懀', '' => '懁', '' => '懃', '' => '懄', '' => '懅', '' => '懆', '' => '懇', '' => '應', '' => '懌', '' => '懍', '' => '懎', '' => '懏', '' => '懐', '' => '懓', '' => '懕', '' => '懖', '' => '懗', '' => '懘', '' => '懙', '' => '懚', '' => '懛', '' => '懜', '' => '懝', '' => '懞', '' => '懟', '' => '懠', '' => '懡', '' => '懢', '' => '懣', '' => '懤', '' => '懥', '' => '懧', '' => '懨', '' => '懩', '' => '懪', '' => '懫', '' => '懬', '' => '懭', '' => '懮', '' => '懯', '' => '懰', '' => '懱', '' => '懲', '' => '懳', '' => '懴', '' => '懶', '' => '懷', '' => '懸', '' => '懹', '' => '懺', '' => '懻', '' => '懼', '' => '懽', '' => '懾', '' => '戀', '' => '戁', '' => '戂', '' => '戃', '' => '戄', '' => '戅', '' => '戇', '' => '戉', '' => '戓', '' => '戔', '' => '戙', '' => '戜', '' => '戝', '' => '戞', '' => '戠', '' => '戣', '' => '戦', '' => '戧', '' => '戨', '' => '戩', '' => '戫', '' => '戭', '' => '戯', '' => '戰', '' => '戱', '' => '戲', '' => '戵', '' => '戶', '' => '戸', '' => '戹', '' => '戺', '' => '戻', '' => '戼', '' => '扂', '' => '扄', '' => '扅', '' => '扆', '' => '扊', '@' => '扏', 'A' => '扐', 'B' => '払', 'C' => '扖', 'D' => '扗', 'E' => '扙', 'F' => '扚', 'G' => '扜', 'H' => '扝', 'I' => '扞', 'J' => '扟', 'K' => '扠', 'L' => '扡', 'M' => '扢', 'N' => '扤', 'O' => '扥', 'P' => '扨', 'Q' => '扱', 'R' => '扲', 'S' => '扴', 'T' => '扵', 'U' => '扷', 'V' => '扸', 'W' => '扺', 'X' => '扻', 'Y' => '扽', 'Z' => '抁', '[' => '抂', '\\' => '抃', ']' => '抅', '^' => '抆', '_' => '抇', '`' => '抈', 'a' => '抋', 'b' => '抌', 'c' => '抍', 'd' => '抎', 'e' => '抏', 'f' => '抐', 'g' => '抔', 'h' => '抙', 'i' => '抜', 'j' => '抝', 'k' => '択', 'l' => '抣', 'm' => '抦', 'n' => '抧', 'o' => '抩', 'p' => '抪', 'q' => '抭', 'r' => '抮', 's' => '抯', 't' => '抰', 'u' => '抲', 'v' => '抳', 'w' => '抴', 'x' => '抶', 'y' => '抷', 'z' => '抸', '{' => '抺', '|' => '抾', '}' => '拀', '~' => '拁', '' => '拃', '' => '拋', '' => '拏', '' => '拑', '' => '拕', '' => '拝', '' => '拞', '' => '拠', '' => '拡', '' => '拤', '' => '拪', '' => '拫', '' => '拰', '' => '拲', '' => '拵', '' => '拸', '' => '拹', '' => '拺', '' => '拻', '' => '挀', '' => '挃', '' => '挄', '' => '挅', '' => '挆', '' => '挊', '' => '挋', '' => '挌', '' => '挍', '' => '挏', '' => '挐', '' => '挒', '' => '挓', '' => '挔', '' => '挕', '' => '挗', '' => '挘', '' => '挙', '' => '挜', '' => '挦', '' => '挧', '' => '挩', '' => '挬', '' => '挭', '' => '挮', '' => '挰', '' => '挱', '' => '挳', '' => '挴', '' => '挵', '' => '挶', '' => '挷', '' => '挸', '' => '挻', '' => '挼', '' => '挾', '' => '挿', '' => '捀', '' => '捁', '' => '捄', '' => '捇', '' => '捈', '' => '捊', '' => '捑', '' => '捒', '' => '捓', '' => '捔', '' => '捖', '' => '捗', '' => '捘', '' => '捙', '' => '捚', '' => '捛', '' => '捜', '' => '捝', '' => '捠', '' => '捤', '' => '捥', '' => '捦', '' => '捨', '' => '捪', '' => '捫', '' => '捬', '' => '捯', '' => '捰', '' => '捲', '' => '捳', '' => '捴', '' => '捵', '' => '捸', '' => '捹', '' => '捼', '' => '捽', '' => '捾', '' => '捿', '' => '掁', '' => '掃', '' => '掄', '' => '掅', '' => '掆', '' => '掋', '' => '掍', '' => '掑', '' => '掓', '' => '掔', '' => '掕', '' => '掗', '' => '掙', '' => '掚', '' => '掛', '' => '掜', '' => '掝', '' => '掞', '' => '掟', '' => '採', '' => '掤', '' => '掦', '' => '掫', '' => '掯', '' => '掱', '' => '掲', '' => '掵', '' => '掶', '' => '掹', '' => '掻', '' => '掽', '' => '掿', '' => '揀', '@' => '揁', 'A' => '揂', 'B' => '揃', 'C' => '揅', 'D' => '揇', 'E' => '揈', 'F' => '揊', 'G' => '揋', 'H' => '揌', 'I' => '揑', 'J' => '揓', 'K' => '揔', 'L' => '揕', 'M' => '揗', 'N' => '揘', 'O' => '揙', 'P' => '揚', 'Q' => '換', 'R' => '揜', 'S' => '揝', 'T' => '揟', 'U' => '揢', 'V' => '揤', 'W' => '揥', 'X' => '揦', 'Y' => '揧', 'Z' => '揨', '[' => '揫', '\\' => '揬', ']' => '揮', '^' => '揯', '_' => '揰', '`' => '揱', 'a' => '揳', 'b' => '揵', 'c' => '揷', 'd' => '揹', 'e' => '揺', 'f' => '揻', 'g' => '揼', 'h' => '揾', 'i' => '搃', 'j' => '搄', 'k' => '搆', 'l' => '搇', 'm' => '搈', 'n' => '搉', 'o' => '搊', 'p' => '損', 'q' => '搎', 'r' => '搑', 's' => '搒', 't' => '搕', 'u' => '搖', 'v' => '搗', 'w' => '搘', 'x' => '搙', 'y' => '搚', 'z' => '搝', '{' => '搟', '|' => '搢', '}' => '搣', '~' => '搤', '' => '搥', '' => '搧', '' => '搨', '' => '搩', '' => '搫', '' => '搮', '' => '搯', '' => '搰', '' => '搱', '' => '搲', '' => '搳', '' => '搵', '' => '搶', '' => '搷', '' => '搸', '' => '搹', '' => '搻', '' => '搼', '' => '搾', '' => '摀', '' => '摂', '' => '摃', '' => '摉', '' => '摋', '' => '摌', '' => '摍', '' => '摎', '' => '摏', '' => '摐', '' => '摑', '' => '摓', '' => '摕', '' => '摖', '' => '摗', '' => '摙', '' => '摚', '' => '摛', '' => '摜', '' => '摝', '' => '摟', '' => '摠', '' => '摡', '' => '摢', '' => '摣', '' => '摤', '' => '摥', '' => '摦', '' => '摨', '' => '摪', '' => '摫', '' => '摬', '' => '摮', '' => '摯', '' => '摰', '' => '摱', '' => '摲', '' => '摳', '' => '摴', '' => '摵', '' => '摶', '' => '摷', '' => '摻', '' => '摼', '' => '摽', '' => '摾', '' => '摿', '' => '撀', '' => '撁', '' => '撃', '' => '撆', '' => '撈', '' => '撉', '' => '撊', '' => '撋', '' => '撌', '' => '撍', '' => '撎', '' => '撏', '' => '撐', '' => '撓', '' => '撔', '' => '撗', '' => '撘', '' => '撚', '' => '撛', '' => '撜', '' => '撝', '' => '撟', '' => '撠', '' => '撡', '' => '撢', '' => '撣', '' => '撥', '' => '撦', '' => '撧', '' => '撨', '' => '撪', '' => '撫', '' => '撯', '' => '撱', '' => '撲', '' => '撳', '' => '撴', '' => '撶', '' => '撹', '' => '撻', '' => '撽', '' => '撾', '' => '撿', '' => '擁', '' => '擃', '' => '擄', '' => '擆', '' => '擇', '' => '擈', '' => '擉', '' => '擊', '' => '擋', '' => '擌', '' => '擏', '' => '擑', '' => '擓', '' => '擔', '' => '擕', '' => '擖', '' => '擙', '' => '據', '@' => '擛', 'A' => '擜', 'B' => '擝', 'C' => '擟', 'D' => '擠', 'E' => '擡', 'F' => '擣', 'G' => '擥', 'H' => '擧', 'I' => '擨', 'J' => '擩', 'K' => '擪', 'L' => '擫', 'M' => '擬', 'N' => '擭', 'O' => '擮', 'P' => '擯', 'Q' => '擰', 'R' => '擱', 'S' => '擲', 'T' => '擳', 'U' => '擴', 'V' => '擵', 'W' => '擶', 'X' => '擷', 'Y' => '擸', 'Z' => '擹', '[' => '擺', '\\' => '擻', ']' => '擼', '^' => '擽', '_' => '擾', '`' => '擿', 'a' => '攁', 'b' => '攂', 'c' => '攃', 'd' => '攄', 'e' => '攅', 'f' => '攆', 'g' => '攇', 'h' => '攈', 'i' => '攊', 'j' => '攋', 'k' => '攌', 'l' => '攍', 'm' => '攎', 'n' => '攏', 'o' => '攐', 'p' => '攑', 'q' => '攓', 'r' => '攔', 's' => '攕', 't' => '攖', 'u' => '攗', 'v' => '攙', 'w' => '攚', 'x' => '攛', 'y' => '攜', 'z' => '攝', '{' => '攞', '|' => '攟', '}' => '攠', '~' => '攡', '' => '攢', '' => '攣', '' => '攤', '' => '攦', '' => '攧', '' => '攨', '' => '攩', '' => '攪', '' => '攬', '' => '攭', '' => '攰', '' => '攱', '' => '攲', '' => '攳', '' => '攷', '' => '攺', '' => '攼', '' => '攽', '' => '敀', '' => '敁', '' => '敂', '' => '敃', '' => '敄', '' => '敆', '' => '敇', '' => '敊', '' => '敋', '' => '敍', '' => '敎', '' => '敐', '' => '敒', '' => '敓', '' => '敔', '' => '敗', '' => '敘', '' => '敚', '' => '敜', '' => '敟', '' => '敠', '' => '敡', '' => '敤', '' => '敥', '' => '敧', '' => '敨', '' => '敩', '' => '敪', '' => '敭', '' => '敮', '' => '敯', '' => '敱', '' => '敳', '' => '敵', '' => '敶', '' => '數', '' => '敹', '' => '敺', '' => '敻', '' => '敼', '' => '敽', '' => '敾', '' => '敿', '' => '斀', '' => '斁', '' => '斂', '' => '斃', '' => '斄', '' => '斅', '' => '斆', '' => '斈', '' => '斉', '' => '斊', '' => '斍', '' => '斎', '' => '斏', '' => '斒', '' => '斔', '' => '斕', '' => '斖', '' => '斘', '' => '斚', '' => '斝', '' => '斞', '' => '斠', '' => '斢', '' => '斣', '' => '斦', '' => '斨', '' => '斪', '' => '斬', '' => '斮', '' => '斱', '' => '斲', '' => '斳', '' => '斴', '' => '斵', '' => '斶', '' => '斷', '' => '斸', '' => '斺', '' => '斻', '' => '斾', '' => '斿', '' => '旀', '' => '旂', '' => '旇', '' => '旈', '' => '旉', '' => '旊', '' => '旍', '' => '旐', '' => '旑', '' => '旓', '' => '旔', '' => '旕', '' => '旘', '' => '旙', '' => '旚', '' => '旛', '' => '旜', '' => '旝', '' => '旞', '' => '旟', '' => '旡', '' => '旣', '' => '旤', '' => '旪', '' => '旫', '@' => '旲', 'A' => '旳', 'B' => '旴', 'C' => '旵', 'D' => '旸', 'E' => '旹', 'F' => '旻', 'G' => '旼', 'H' => '旽', 'I' => '旾', 'J' => '旿', 'K' => '昁', 'L' => '昄', 'M' => '昅', 'N' => '昇', 'O' => '昈', 'P' => '昉', 'Q' => '昋', 'R' => '昍', 'S' => '昐', 'T' => '昑', 'U' => '昒', 'V' => '昖', 'W' => '昗', 'X' => '昘', 'Y' => '昚', 'Z' => '昛', '[' => '昜', '\\' => '昞', ']' => '昡', '^' => '昢', '_' => '昣', '`' => '昤', 'a' => '昦', 'b' => '昩', 'c' => '昪', 'd' => '昫', 'e' => '昬', 'f' => '昮', 'g' => '昰', 'h' => '昲', 'i' => '昳', 'j' => '昷', 'k' => '昸', 'l' => '昹', 'm' => '昺', 'n' => '昻', 'o' => '昽', 'p' => '昿', 'q' => '晀', 'r' => '時', 's' => '晄', 't' => '晅', 'u' => '晆', 'v' => '晇', 'w' => '晈', 'x' => '晉', 'y' => '晊', 'z' => '晍', '{' => '晎', '|' => '晐', '}' => '晑', '~' => '晘', '' => '晙', '' => '晛', '' => '晜', '' => '晝', '' => '晞', '' => '晠', '' => '晢', '' => '晣', '' => '晥', '' => '晧', '' => '晩', '' => '晪', '' => '晫', '' => '晬', '' => '晭', '' => '晱', '' => '晲', '' => '晳', '' => '晵', '' => '晸', '' => '晹', '' => '晻', '' => '晼', '' => '晽', '' => '晿', '' => '暀', '' => '暁', '' => '暃', '' => '暅', '' => '暆', '' => '暈', '' => '暉', '' => '暊', '' => '暋', '' => '暍', '' => '暎', '' => '暏', '' => '暐', '' => '暒', '' => '暓', '' => '暔', '' => '暕', '' => '暘', '' => '暙', '' => '暚', '' => '暛', '' => '暜', '' => '暞', '' => '暟', '' => '暠', '' => '暡', '' => '暢', '' => '暣', '' => '暤', '' => '暥', '' => '暦', '' => '暩', '' => '暪', '' => '暫', '' => '暬', '' => '暭', '' => '暯', '' => '暰', '' => '暱', '' => '暲', '' => '暳', '' => '暵', '' => '暶', '' => '暷', '' => '暸', '' => '暺', '' => '暻', '' => '暼', '' => '暽', '' => '暿', '' => '曀', '' => '曁', '' => '曂', '' => '曃', '' => '曄', '' => '曅', '' => '曆', '' => '曇', '' => '曈', '' => '曉', '' => '曊', '' => '曋', '' => '曌', '' => '曍', '' => '曎', '' => '曏', '' => '曐', '' => '曑', '' => '曒', '' => '曓', '' => '曔', '' => '曕', '' => '曖', '' => '曗', '' => '曘', '' => '曚', '' => '曞', '' => '曟', '' => '曠', '' => '曡', '' => '曢', '' => '曣', '' => '曤', '' => '曥', '' => '曧', '' => '曨', '' => '曪', '' => '曫', '' => '曬', '' => '曭', '' => '曮', '' => '曯', '' => '曱', '' => '曵', '' => '曶', '' => '書', '' => '曺', '' => '曻', '' => '曽', '' => '朁', '' => '朂', '' => '會', '@' => '朄', 'A' => '朅', 'B' => '朆', 'C' => '朇', 'D' => '朌', 'E' => '朎', 'F' => '朏', 'G' => '朑', 'H' => '朒', 'I' => '朓', 'J' => '朖', 'K' => '朘', 'L' => '朙', 'M' => '朚', 'N' => '朜', 'O' => '朞', 'P' => '朠', 'Q' => '朡', 'R' => '朢', 'S' => '朣', 'T' => '朤', 'U' => '朥', 'V' => '朧', 'W' => '朩', 'X' => '朮', 'Y' => '朰', 'Z' => '朲', '[' => '朳', '\\' => '朶', ']' => '朷', '^' => '朸', '_' => '朹', '`' => '朻', 'a' => '朼', 'b' => '朾', 'c' => '朿', 'd' => '杁', 'e' => '杄', 'f' => '杅', 'g' => '杇', 'h' => '杊', 'i' => '杋', 'j' => '杍', 'k' => '杒', 'l' => '杔', 'm' => '杕', 'n' => '杗', 'o' => '杘', 'p' => '杙', 'q' => '杚', 'r' => '杛', 's' => '杝', 't' => '杢', 'u' => '杣', 'v' => '杤', 'w' => '杦', 'x' => '杧', 'y' => '杫', 'z' => '杬', '{' => '杮', '|' => '東', '}' => '杴', '~' => '杶', '' => '杸', '' => '杹', '' => '杺', '' => '杻', '' => '杽', '' => '枀', '' => '枂', '' => '枃', '' => '枅', '' => '枆', '' => '枈', '' => '枊', '' => '枌', '' => '枍', '' => '枎', '' => '枏', '' => '枑', '' => '枒', '' => '枓', '' => '枔', '' => '枖', '' => '枙', '' => '枛', '' => '枟', '' => '枠', '' => '枡', '' => '枤', '' => '枦', '' => '枩', '' => '枬', '' => '枮', '' => '枱', '' => '枲', '' => '枴', '' => '枹', '' => '枺', '' => '枻', '' => '枼', '' => '枽', '' => '枾', '' => '枿', '' => '柀', '' => '柂', '' => '柅', '' => '柆', '' => '柇', '' => '柈', '' => '柉', '' => '柊', '' => '柋', '' => '柌', '' => '柍', '' => '柎', '' => '柕', '' => '柖', '' => '柗', '' => '柛', '' => '柟', '' => '柡', '' => '柣', '' => '柤', '' => '柦', '' => '柧', '' => '柨', '' => '柪', '' => '柫', '' => '柭', '' => '柮', '' => '柲', '' => '柵', '' => '柶', '' => '柷', '' => '柸', '' => '柹', '' => '柺', '' => '査', '' => '柼', '' => '柾', '' => '栁', '' => '栂', '' => '栃', '' => '栄', '' => '栆', '' => '栍', '' => '栐', '' => '栒', '' => '栔', '' => '栕', '' => '栘', '' => '栙', '' => '栚', '' => '栛', '' => '栜', '' => '栞', '' => '栟', '' => '栠', '' => '栢', '' => '栣', '' => '栤', '' => '栥', '' => '栦', '' => '栧', '' => '栨', '' => '栫', '' => '栬', '' => '栭', '' => '栮', '' => '栯', '' => '栰', '' => '栱', '' => '栴', '' => '栵', '' => '栶', '' => '栺', '' => '栻', '' => '栿', '' => '桇', '' => '桋', '' => '桍', '' => '桏', '' => '桒', '' => '桖', '' => '桗', '' => '桘', '' => '桙', '' => '桚', '' => '桛', '@' => '桜', 'A' => '桝', 'B' => '桞', 'C' => '桟', 'D' => '桪', 'E' => '桬', 'F' => '桭', 'G' => '桮', 'H' => '桯', 'I' => '桰', 'J' => '桱', 'K' => '桲', 'L' => '桳', 'M' => '桵', 'N' => '桸', 'O' => '桹', 'P' => '桺', 'Q' => '桻', 'R' => '桼', 'S' => '桽', 'T' => '桾', 'U' => '桿', 'V' => '梀', 'W' => '梂', 'X' => '梄', 'Y' => '梇', 'Z' => '梈', '[' => '梉', '\\' => '梊', ']' => '梋', '^' => '梌', '_' => '梍', '`' => '梎', 'a' => '梐', 'b' => '梑', 'c' => '梒', 'd' => '梔', 'e' => '梕', 'f' => '梖', 'g' => '梘', 'h' => '梙', 'i' => '梚', 'j' => '梛', 'k' => '梜', 'l' => '條', 'm' => '梞', 'n' => '梟', 'o' => '梠', 'p' => '梡', 'q' => '梣', 'r' => '梤', 's' => '梥', 't' => '梩', 'u' => '梪', 'v' => '梫', 'w' => '梬', 'x' => '梮', 'y' => '梱', 'z' => '梲', '{' => '梴', '|' => '梶', '}' => '梷', '~' => '梸', '' => '梹', '' => '梺', '' => '梻', '' => '梼', '' => '梽', '' => '梾', '' => '梿', '' => '棁', '' => '棃', '' => '棄', '' => '棅', '' => '棆', '' => '棇', '' => '棈', '' => '棊', '' => '棌', '' => '棎', '' => '棏', '' => '棐', '' => '棑', '' => '棓', '' => '棔', '' => '棖', '' => '棗', '' => '棙', '' => '棛', '' => '棜', '' => '棝', '' => '棞', '' => '棟', '' => '棡', '' => '棢', '' => '棤', '' => '棥', '' => '棦', '' => '棧', '' => '棨', '' => '棩', '' => '棪', '' => '棫', '' => '棬', '' => '棭', '' => '棯', '' => '棲', '' => '棳', '' => '棴', '' => '棶', '' => '棷', '' => '棸', '' => '棻', '' => '棽', '' => '棾', '' => '棿', '' => '椀', '' => '椂', '' => '椃', '' => '椄', '' => '椆', '' => '椇', '' => '椈', '' => '椉', '' => '椊', '' => '椌', '' => '椏', '' => '椑', '' => '椓', '' => '椔', '' => '椕', '' => '椖', '' => '椗', '' => '椘', '' => '椙', '' => '椚', '' => '椛', '' => '検', '' => '椝', '' => '椞', '' => '椡', '' => '椢', '' => '椣', '' => '椥', '' => '椦', '' => '椧', '' => '椨', '' => '椩', '' => '椪', '' => '椫', '' => '椬', '' => '椮', '' => '椯', '' => '椱', '' => '椲', '' => '椳', '' => '椵', '' => '椶', '' => '椷', '' => '椸', '' => '椺', '' => '椻', '' => '椼', '' => '椾', '' => '楀', '' => '楁', '' => '楃', '' => '楄', '' => '楅', '' => '楆', '' => '楇', '' => '楈', '' => '楉', '' => '楊', '' => '楋', '' => '楌', '' => '楍', '' => '楎', '' => '楏', '' => '楐', '' => '楑', '' => '楒', '' => '楓', '' => '楕', '' => '楖', '' => '楘', '' => '楙', '' => '楛', '' => '楜', '' => '楟', '@' => '楡', 'A' => '楢', 'B' => '楤', 'C' => '楥', 'D' => '楧', 'E' => '楨', 'F' => '楩', 'G' => '楪', 'H' => '楬', 'I' => '業', 'J' => '楯', 'K' => '楰', 'L' => '楲', 'M' => '楳', 'N' => '楴', 'O' => '極', 'P' => '楶', 'Q' => '楺', 'R' => '楻', 'S' => '楽', 'T' => '楾', 'U' => '楿', 'V' => '榁', 'W' => '榃', 'X' => '榅', 'Y' => '榊', 'Z' => '榋', '[' => '榌', '\\' => '榎', ']' => '榏', '^' => '榐', '_' => '榑', '`' => '榒', 'a' => '榓', 'b' => '榖', 'c' => '榗', 'd' => '榙', 'e' => '榚', 'f' => '榝', 'g' => '榞', 'h' => '榟', 'i' => '榠', 'j' => '榡', 'k' => '榢', 'l' => '榣', 'm' => '榤', 'n' => '榥', 'o' => '榦', 'p' => '榩', 'q' => '榪', 'r' => '榬', 's' => '榮', 't' => '榯', 'u' => '榰', 'v' => '榲', 'w' => '榳', 'x' => '榵', 'y' => '榶', 'z' => '榸', '{' => '榹', '|' => '榺', '}' => '榼', '~' => '榽', '' => '榾', '' => '榿', '' => '槀', '' => '槂', '' => '槃', '' => '槄', '' => '槅', '' => '槆', '' => '槇', '' => '槈', '' => '槉', '' => '構', '' => '槍', '' => '槏', '' => '槑', '' => '槒', '' => '槓', '' => '槕', '' => '槖', '' => '槗', '' => '様', '' => '槙', '' => '槚', '' => '槜', '' => '槝', '' => '槞', '' => '槡', '' => '槢', '' => '槣', '' => '槤', '' => '槥', '' => '槦', '' => '槧', '' => '槨', '' => '槩', '' => '槪', '' => '槫', '' => '槬', '' => '槮', '' => '槯', '' => '槰', '' => '槱', '' => '槳', '' => '槴', '' => '槵', '' => '槶', '' => '槷', '' => '槸', '' => '槹', '' => '槺', '' => '槻', '' => '槼', '' => '槾', '' => '樀', '' => '樁', '' => '樂', '' => '樃', '' => '樄', '' => '樅', '' => '樆', '' => '樇', '' => '樈', '' => '樉', '' => '樋', '' => '樌', '' => '樍', '' => '樎', '' => '樏', '' => '樐', '' => '樑', '' => '樒', '' => '樓', '' => '樔', '' => '樕', '' => '樖', '' => '標', '' => '樚', '' => '樛', '' => '樜', '' => '樝', '' => '樞', '' => '樠', '' => '樢', '' => '樣', '' => '樤', '' => '樥', '' => '樦', '' => '樧', '' => '権', '' => '樫', '' => '樬', '' => '樭', '' => '樮', '' => '樰', '' => '樲', '' => '樳', '' => '樴', '' => '樶', '' => '樷', '' => '樸', '' => '樹', '' => '樺', '' => '樻', '' => '樼', '' => '樿', '' => '橀', '' => '橁', '' => '橂', '' => '橃', '' => '橅', '' => '橆', '' => '橈', '' => '橉', '' => '橊', '' => '橋', '' => '橌', '' => '橍', '' => '橎', '' => '橏', '' => '橑', '' => '橒', '' => '橓', '' => '橔', '' => '橕', '' => '橖', '' => '橗', '' => '橚', '@' => '橜', 'A' => '橝', 'B' => '橞', 'C' => '機', 'D' => '橠', 'E' => '橢', 'F' => '橣', 'G' => '橤', 'H' => '橦', 'I' => '橧', 'J' => '橨', 'K' => '橩', 'L' => '橪', 'M' => '橫', 'N' => '橬', 'O' => '橭', 'P' => '橮', 'Q' => '橯', 'R' => '橰', 'S' => '橲', 'T' => '橳', 'U' => '橴', 'V' => '橵', 'W' => '橶', 'X' => '橷', 'Y' => '橸', 'Z' => '橺', '[' => '橻', '\\' => '橽', ']' => '橾', '^' => '橿', '_' => '檁', '`' => '檂', 'a' => '檃', 'b' => '檅', 'c' => '檆', 'd' => '檇', 'e' => '檈', 'f' => '檉', 'g' => '檊', 'h' => '檋', 'i' => '檌', 'j' => '檍', 'k' => '檏', 'l' => '檒', 'm' => '檓', 'n' => '檔', 'o' => '檕', 'p' => '檖', 'q' => '檘', 'r' => '檙', 's' => '檚', 't' => '檛', 'u' => '檜', 'v' => '檝', 'w' => '檞', 'x' => '檟', 'y' => '檡', 'z' => '檢', '{' => '檣', '|' => '檤', '}' => '檥', '~' => '檦', '' => '檧', '' => '檨', '' => '檪', '' => '檭', '' => '檮', '' => '檯', '' => '檰', '' => '檱', '' => '檲', '' => '檳', '' => '檴', '' => '檵', '' => '檶', '' => '檷', '' => '檸', '' => '檹', '' => '檺', '' => '檻', '' => '檼', '' => '檽', '' => '檾', '' => '檿', '' => '櫀', '' => '櫁', '' => '櫂', '' => '櫃', '' => '櫄', '' => '櫅', '' => '櫆', '' => '櫇', '' => '櫈', '' => '櫉', '' => '櫊', '' => '櫋', '' => '櫌', '' => '櫍', '' => '櫎', '' => '櫏', '' => '櫐', '' => '櫑', '' => '櫒', '' => '櫓', '' => '櫔', '' => '櫕', '' => '櫖', '' => '櫗', '' => '櫘', '' => '櫙', '' => '櫚', '' => '櫛', '' => '櫜', '' => '櫝', '' => '櫞', '' => '櫟', '' => '櫠', '' => '櫡', '' => '櫢', '' => '櫣', '' => '櫤', '' => '櫥', '' => '櫦', '' => '櫧', '' => '櫨', '' => '櫩', '' => '櫪', '' => '櫫', '' => '櫬', '' => '櫭', '' => '櫮', '' => '櫯', '' => '櫰', '' => '櫱', '' => '櫲', '' => '櫳', '' => '櫴', '' => '櫵', '' => '櫶', '' => '櫷', '' => '櫸', '' => '櫹', '' => '櫺', '' => '櫻', '' => '櫼', '' => '櫽', '' => '櫾', '' => '櫿', '' => '欀', '' => '欁', '' => '欂', '' => '欃', '' => '欄', '' => '欅', '' => '欆', '' => '欇', '' => '欈', '' => '欉', '' => '權', '' => '欋', '' => '欌', '' => '欍', '' => '欎', '' => '欏', '' => '欐', '' => '欑', '' => '欒', '' => '欓', '' => '欔', '' => '欕', '' => '欖', '' => '欗', '' => '欘', '' => '欙', '' => '欚', '' => '欛', '' => '欜', '' => '欝', '' => '欞', '' => '欟', '' => '欥', '' => '欦', '' => '欨', '' => '欩', '' => '欪', '' => '欫', '' => '欬', '' => '欭', '' => '欮', '@' => '欯', 'A' => '欰', 'B' => '欱', 'C' => '欳', 'D' => '欴', 'E' => '欵', 'F' => '欶', 'G' => '欸', 'H' => '欻', 'I' => '欼', 'J' => '欽', 'K' => '欿', 'L' => '歀', 'M' => '歁', 'N' => '歂', 'O' => '歄', 'P' => '歅', 'Q' => '歈', 'R' => '歊', 'S' => '歋', 'T' => '歍', 'U' => '歎', 'V' => '歏', 'W' => '歐', 'X' => '歑', 'Y' => '歒', 'Z' => '歓', '[' => '歔', '\\' => '歕', ']' => '歖', '^' => '歗', '_' => '歘', '`' => '歚', 'a' => '歛', 'b' => '歜', 'c' => '歝', 'd' => '歞', 'e' => '歟', 'f' => '歠', 'g' => '歡', 'h' => '歨', 'i' => '歩', 'j' => '歫', 'k' => '歬', 'l' => '歭', 'm' => '歮', 'n' => '歯', 'o' => '歰', 'p' => '歱', 'q' => '歲', 'r' => '歳', 's' => '歴', 't' => '歵', 'u' => '歶', 'v' => '歷', 'w' => '歸', 'x' => '歺', 'y' => '歽', 'z' => '歾', '{' => '歿', '|' => '殀', '}' => '殅', '~' => '殈', '' => '殌', '' => '殎', '' => '殏', '' => '殐', '' => '殑', '' => '殔', '' => '殕', '' => '殗', '' => '殘', '' => '殙', '' => '殜', '' => '殝', '' => '殞', '' => '殟', '' => '殠', '' => '殢', '' => '殣', '' => '殤', '' => '殥', '' => '殦', '' => '殧', '' => '殨', '' => '殩', '' => '殫', '' => '殬', '' => '殭', '' => '殮', '' => '殯', '' => '殰', '' => '殱', '' => '殲', '' => '殶', '' => '殸', '' => '殹', '' => '殺', '' => '殻', '' => '殼', '' => '殽', '' => '殾', '' => '毀', '' => '毃', '' => '毄', '' => '毆', '' => '毇', '' => '毈', '' => '毉', '' => '毊', '' => '毌', '' => '毎', '' => '毐', '' => '毑', '' => '毘', '' => '毚', '' => '毜', '' => '毝', '' => '毞', '' => '毟', '' => '毠', '' => '毢', '' => '毣', '' => '毤', '' => '毥', '' => '毦', '' => '毧', '' => '毨', '' => '毩', '' => '毬', '' => '毭', '' => '毮', '' => '毰', '' => '毱', '' => '毲', '' => '毴', '' => '毶', '' => '毷', '' => '毸', '' => '毺', '' => '毻', '' => '毼', '' => '毾', '' => '毿', '' => '氀', '' => '氁', '' => '氂', '' => '氃', '' => '氄', '' => '氈', '' => '氉', '' => '氊', '' => '氋', '' => '氌', '' => '氎', '' => '氒', '' => '気', '' => '氜', '' => '氝', '' => '氞', '' => '氠', '' => '氣', '' => '氥', '' => '氫', '' => '氬', '' => '氭', '' => '氱', '' => '氳', '' => '氶', '' => '氷', '' => '氹', '' => '氺', '' => '氻', '' => '氼', '' => '氾', '' => '氿', '' => '汃', '' => '汄', '' => '汅', '' => '汈', '' => '汋', '' => '汌', '' => '汍', '' => '汎', '' => '汏', '' => '汑', '' => '汒', '' => '汓', '' => '汖', '' => '汘', '@' => '汙', 'A' => '汚', 'B' => '汢', 'C' => '汣', 'D' => '汥', 'E' => '汦', 'F' => '汧', 'G' => '汫', 'H' => '汬', 'I' => '汭', 'J' => '汮', 'K' => '汯', 'L' => '汱', 'M' => '汳', 'N' => '汵', 'O' => '汷', 'P' => '汸', 'Q' => '決', 'R' => '汻', 'S' => '汼', 'T' => '汿', 'U' => '沀', 'V' => '沄', 'W' => '沇', 'X' => '沊', 'Y' => '沋', 'Z' => '沍', '[' => '沎', '\\' => '沑', ']' => '沒', '^' => '沕', '_' => '沖', '`' => '沗', 'a' => '沘', 'b' => '沚', 'c' => '沜', 'd' => '沝', 'e' => '沞', 'f' => '沠', 'g' => '沢', 'h' => '沨', 'i' => '沬', 'j' => '沯', 'k' => '沰', 'l' => '沴', 'm' => '沵', 'n' => '沶', 'o' => '沷', 'p' => '沺', 'q' => '泀', 'r' => '況', 's' => '泂', 't' => '泃', 'u' => '泆', 'v' => '泇', 'w' => '泈', 'x' => '泋', 'y' => '泍', 'z' => '泎', '{' => '泏', '|' => '泑', '}' => '泒', '~' => '泘', '' => '泙', '' => '泚', '' => '泜', '' => '泝', '' => '泟', '' => '泤', '' => '泦', '' => '泧', '' => '泩', '' => '泬', '' => '泭', '' => '泲', '' => '泴', '' => '泹', '' => '泿', '' => '洀', '' => '洂', '' => '洃', '' => '洅', '' => '洆', '' => '洈', '' => '洉', '' => '洊', '' => '洍', '' => '洏', '' => '洐', '' => '洑', '' => '洓', '' => '洔', '' => '洕', '' => '洖', '' => '洘', '' => '洜', '' => '洝', '' => '洟', '' => '洠', '' => '洡', '' => '洢', '' => '洣', '' => '洤', '' => '洦', '' => '洨', '' => '洩', '' => '洬', '' => '洭', '' => '洯', '' => '洰', '' => '洴', '' => '洶', '' => '洷', '' => '洸', '' => '洺', '' => '洿', '' => '浀', '' => '浂', '' => '浄', '' => '浉', '' => '浌', '' => '浐', '' => '浕', '' => '浖', '' => '浗', '' => '浘', '' => '浛', '' => '浝', '' => '浟', '' => '浡', '' => '浢', '' => '浤', '' => '浥', '' => '浧', '' => '浨', '' => '浫', '' => '浬', '' => '浭', '' => '浰', '' => '浱', '' => '浲', '' => '浳', '' => '浵', '' => '浶', '' => '浹', '' => '浺', '' => '浻', '' => '浽', '' => '浾', '' => '浿', '' => '涀', '' => '涁', '' => '涃', '' => '涄', '' => '涆', '' => '涇', '' => '涊', '' => '涋', '' => '涍', '' => '涏', '' => '涐', '' => '涒', '' => '涖', '' => '涗', '' => '涘', '' => '涙', '' => '涚', '' => '涜', '' => '涢', '' => '涥', '' => '涬', '' => '涭', '' => '涰', '' => '涱', '' => '涳', '' => '涴', '' => '涶', '' => '涷', '' => '涹', '' => '涺', '' => '涻', '' => '涼', '' => '涽', '' => '涾', '' => '淁', '' => '淂', '' => '淃', '' => '淈', '' => '淉', '' => '淊', '@' => '淍', 'A' => '淎', 'B' => '淏', 'C' => '淐', 'D' => '淒', 'E' => '淓', 'F' => '淔', 'G' => '淕', 'H' => '淗', 'I' => '淚', 'J' => '淛', 'K' => '淜', 'L' => '淟', 'M' => '淢', 'N' => '淣', 'O' => '淥', 'P' => '淧', 'Q' => '淨', 'R' => '淩', 'S' => '淪', 'T' => '淭', 'U' => '淯', 'V' => '淰', 'W' => '淲', 'X' => '淴', 'Y' => '淵', 'Z' => '淶', '[' => '淸', '\\' => '淺', ']' => '淽', '^' => '淾', '_' => '淿', '`' => '渀', 'a' => '渁', 'b' => '渂', 'c' => '渃', 'd' => '渄', 'e' => '渆', 'f' => '渇', 'g' => '済', 'h' => '渉', 'i' => '渋', 'j' => '渏', 'k' => '渒', 'l' => '渓', 'm' => '渕', 'n' => '渘', 'o' => '渙', 'p' => '減', 'q' => '渜', 'r' => '渞', 's' => '渟', 't' => '渢', 'u' => '渦', 'v' => '渧', 'w' => '渨', 'x' => '渪', 'y' => '測', 'z' => '渮', '{' => '渰', '|' => '渱', '}' => '渳', '~' => '渵', '' => '渶', '' => '渷', '' => '渹', '' => '渻', '' => '渼', '' => '渽', '' => '渾', '' => '渿', '' => '湀', '' => '湁', '' => '湂', '' => '湅', '' => '湆', '' => '湇', '' => '湈', '' => '湉', '' => '湊', '' => '湋', '' => '湌', '' => '湏', '' => '湐', '' => '湑', '' => '湒', '' => '湕', '' => '湗', '' => '湙', '' => '湚', '' => '湜', '' => '湝', '' => '湞', '' => '湠', '' => '湡', '' => '湢', '' => '湣', '' => '湤', '' => '湥', '' => '湦', '' => '湧', '' => '湨', '' => '湩', '' => '湪', '' => '湬', '' => '湭', '' => '湯', '' => '湰', '' => '湱', '' => '湲', '' => '湳', '' => '湴', '' => '湵', '' => '湶', '' => '湷', '' => '湸', '' => '湹', '' => '湺', '' => '湻', '' => '湼', '' => '湽', '' => '満', '' => '溁', '' => '溂', '' => '溄', '' => '溇', '' => '溈', '' => '溊', '' => '溋', '' => '溌', '' => '溍', '' => '溎', '' => '溑', '' => '溒', '' => '溓', '' => '溔', '' => '溕', '' => '準', '' => '溗', '' => '溙', '' => '溚', '' => '溛', '' => '溝', '' => '溞', '' => '溠', '' => '溡', '' => '溣', '' => '溤', '' => '溦', '' => '溨', '' => '溩', '' => '溫', '' => '溬', '' => '溭', '' => '溮', '' => '溰', '' => '溳', '' => '溵', '' => '溸', '' => '溹', '' => '溼', '' => '溾', '' => '溿', '' => '滀', '' => '滃', '' => '滄', '' => '滅', '' => '滆', '' => '滈', '' => '滉', '' => '滊', '' => '滌', '' => '滍', '' => '滎', '' => '滐', '' => '滒', '' => '滖', '' => '滘', '' => '滙', '' => '滛', '' => '滜', '' => '滝', '' => '滣', '' => '滧', '' => '滪', '' => '滫', '' => '滬', '' => '滭', '' => '滮', '' => '滯', '@' => '滰', 'A' => '滱', 'B' => '滲', 'C' => '滳', 'D' => '滵', 'E' => '滶', 'F' => '滷', 'G' => '滸', 'H' => '滺', 'I' => '滻', 'J' => '滼', 'K' => '滽', 'L' => '滾', 'M' => '滿', 'N' => '漀', 'O' => '漁', 'P' => '漃', 'Q' => '漄', 'R' => '漅', 'S' => '漇', 'T' => '漈', 'U' => '漊', 'V' => '漋', 'W' => '漌', 'X' => '漍', 'Y' => '漎', 'Z' => '漐', '[' => '漑', '\\' => '漒', ']' => '漖', '^' => '漗', '_' => '漘', '`' => '漙', 'a' => '漚', 'b' => '漛', 'c' => '漜', 'd' => '漝', 'e' => '漞', 'f' => '漟', 'g' => '漡', 'h' => '漢', 'i' => '漣', 'j' => '漥', 'k' => '漦', 'l' => '漧', 'm' => '漨', 'n' => '漬', 'o' => '漮', 'p' => '漰', 'q' => '漲', 'r' => '漴', 's' => '漵', 't' => '漷', 'u' => '漸', 'v' => '漹', 'w' => '漺', 'x' => '漻', 'y' => '漼', 'z' => '漽', '{' => '漿', '|' => '潀', '}' => '潁', '~' => '潂', '' => '潃', '' => '潄', '' => '潅', '' => '潈', '' => '潉', '' => '潊', '' => '潌', '' => '潎', '' => '潏', '' => '潐', '' => '潑', '' => '潒', '' => '潓', '' => '潔', '' => '潕', '' => '潖', '' => '潗', '' => '潙', '' => '潚', '' => '潛', '' => '潝', '' => '潟', '' => '潠', '' => '潡', '' => '潣', '' => '潤', '' => '潥', '' => '潧', '' => '潨', '' => '潩', '' => '潪', '' => '潫', '' => '潬', '' => '潯', '' => '潰', '' => '潱', '' => '潳', '' => '潵', '' => '潶', '' => '潷', '' => '潹', '' => '潻', '' => '潽', '' => '潾', '' => '潿', '' => '澀', '' => '澁', '' => '澂', '' => '澃', '' => '澅', '' => '澆', '' => '澇', '' => '澊', '' => '澋', '' => '澏', '' => '澐', '' => '澑', '' => '澒', '' => '澓', '' => '澔', '' => '澕', '' => '澖', '' => '澗', '' => '澘', '' => '澙', '' => '澚', '' => '澛', '' => '澝', '' => '澞', '' => '澟', '' => '澠', '' => '澢', '' => '澣', '' => '澤', '' => '澥', '' => '澦', '' => '澨', '' => '澩', '' => '澪', '' => '澫', '' => '澬', '' => '澭', '' => '澮', '' => '澯', '' => '澰', '' => '澱', '' => '澲', '' => '澴', '' => '澵', '' => '澷', '' => '澸', '' => '澺', '' => '澻', '' => '澼', '' => '澽', '' => '澾', '' => '澿', '' => '濁', '' => '濃', '' => '濄', '' => '濅', '' => '濆', '' => '濇', '' => '濈', '' => '濊', '' => '濋', '' => '濌', '' => '濍', '' => '濎', '' => '濏', '' => '濐', '' => '濓', '' => '濔', '' => '濕', '' => '濖', '' => '濗', '' => '濘', '' => '濙', '' => '濚', '' => '濛', '' => '濜', '' => '濝', '' => '濟', '' => '濢', '' => '濣', '' => '濤', '' => '濥', '@' => '濦', 'A' => '濧', 'B' => '濨', 'C' => '濩', 'D' => '濪', 'E' => '濫', 'F' => '濬', 'G' => '濭', 'H' => '濰', 'I' => '濱', 'J' => '濲', 'K' => '濳', 'L' => '濴', 'M' => '濵', 'N' => '濶', 'O' => '濷', 'P' => '濸', 'Q' => '濹', 'R' => '濺', 'S' => '濻', 'T' => '濼', 'U' => '濽', 'V' => '濾', 'W' => '濿', 'X' => '瀀', 'Y' => '瀁', 'Z' => '瀂', '[' => '瀃', '\\' => '瀄', ']' => '瀅', '^' => '瀆', '_' => '瀇', '`' => '瀈', 'a' => '瀉', 'b' => '瀊', 'c' => '瀋', 'd' => '瀌', 'e' => '瀍', 'f' => '瀎', 'g' => '瀏', 'h' => '瀐', 'i' => '瀒', 'j' => '瀓', 'k' => '瀔', 'l' => '瀕', 'm' => '瀖', 'n' => '瀗', 'o' => '瀘', 'p' => '瀙', 'q' => '瀜', 'r' => '瀝', 's' => '瀞', 't' => '瀟', 'u' => '瀠', 'v' => '瀡', 'w' => '瀢', 'x' => '瀤', 'y' => '瀥', 'z' => '瀦', '{' => '瀧', '|' => '瀨', '}' => '瀩', '~' => '瀪', '' => '瀫', '' => '瀬', '' => '瀭', '' => '瀮', '' => '瀯', '' => '瀰', '' => '瀱', '' => '瀲', '' => '瀳', '' => '瀴', '' => '瀶', '' => '瀷', '' => '瀸', '' => '瀺', '' => '瀻', '' => '瀼', '' => '瀽', '' => '瀾', '' => '瀿', '' => '灀', '' => '灁', '' => '灂', '' => '灃', '' => '灄', '' => '灅', '' => '灆', '' => '灇', '' => '灈', '' => '灉', '' => '灊', '' => '灋', '' => '灍', '' => '灎', '' => '灐', '' => '灑', '' => '灒', '' => '灓', '' => '灔', '' => '灕', '' => '灖', '' => '灗', '' => '灘', '' => '灙', '' => '灚', '' => '灛', '' => '灜', '' => '灝', '' => '灟', '' => '灠', '' => '灡', '' => '灢', '' => '灣', '' => '灤', '' => '灥', '' => '灦', '' => '灧', '' => '灨', '' => '灩', '' => '灪', '' => '灮', '' => '灱', '' => '灲', '' => '灳', '' => '灴', '' => '灷', '' => '灹', '' => '灺', '' => '灻', '' => '災', '' => '炁', '' => '炂', '' => '炃', '' => '炄', '' => '炆', '' => '炇', '' => '炈', '' => '炋', '' => '炌', '' => '炍', '' => '炏', '' => '炐', '' => '炑', '' => '炓', '' => '炗', '' => '炘', '' => '炚', '' => '炛', '' => '炞', '' => '炟', '' => '炠', '' => '炡', '' => '炢', '' => '炣', '' => '炤', '' => '炥', '' => '炦', '' => '炧', '' => '炨', '' => '炩', '' => '炪', '' => '炰', '' => '炲', '' => '炴', '' => '炵', '' => '炶', '' => '為', '' => '炾', '' => '炿', '' => '烄', '' => '烅', '' => '烆', '' => '烇', '' => '烉', '' => '烋', '' => '烌', '' => '烍', '' => '烎', '' => '烏', '' => '烐', '' => '烑', '' => '烒', '' => '烓', '' => '烔', '' => '烕', '' => '烖', '' => '烗', '' => '烚', '@' => '烜', 'A' => '烝', 'B' => '烞', 'C' => '烠', 'D' => '烡', 'E' => '烢', 'F' => '烣', 'G' => '烥', 'H' => '烪', 'I' => '烮', 'J' => '烰', 'K' => '烱', 'L' => '烲', 'M' => '烳', 'N' => '烴', 'O' => '烵', 'P' => '烶', 'Q' => '烸', 'R' => '烺', 'S' => '烻', 'T' => '烼', 'U' => '烾', 'V' => '烿', 'W' => '焀', 'X' => '焁', 'Y' => '焂', 'Z' => '焃', '[' => '焄', '\\' => '焅', ']' => '焆', '^' => '焇', '_' => '焈', '`' => '焋', 'a' => '焌', 'b' => '焍', 'c' => '焎', 'd' => '焏', 'e' => '焑', 'f' => '焒', 'g' => '焔', 'h' => '焗', 'i' => '焛', 'j' => '焜', 'k' => '焝', 'l' => '焞', 'm' => '焟', 'n' => '焠', 'o' => '無', 'p' => '焢', 'q' => '焣', 'r' => '焤', 's' => '焥', 't' => '焧', 'u' => '焨', 'v' => '焩', 'w' => '焪', 'x' => '焫', 'y' => '焬', 'z' => '焭', '{' => '焮', '|' => '焲', '}' => '焳', '~' => '焴', '' => '焵', '' => '焷', '' => '焸', '' => '焹', '' => '焺', '' => '焻', '' => '焼', '' => '焽', '' => '焾', '' => '焿', '' => '煀', '' => '煁', '' => '煂', '' => '煃', '' => '煄', '' => '煆', '' => '煇', '' => '煈', '' => '煉', '' => '煋', '' => '煍', '' => '煏', '' => '煐', '' => '煑', '' => '煒', '' => '煓', '' => '煔', '' => '煕', '' => '煖', '' => '煗', '' => '煘', '' => '煙', '' => '煚', '' => '煛', '' => '煝', '' => '煟', '' => '煠', '' => '煡', '' => '煢', '' => '煣', '' => '煥', '' => '煩', '' => '煪', '' => '煫', '' => '煬', '' => '煭', '' => '煯', '' => '煰', '' => '煱', '' => '煴', '' => '煵', '' => '煶', '' => '煷', '' => '煹', '' => '煻', '' => '煼', '' => '煾', '' => '煿', '' => '熀', '' => '熁', '' => '熂', '' => '熃', '' => '熅', '' => '熆', '' => '熇', '' => '熈', '' => '熉', '' => '熋', '' => '熌', '' => '熍', '' => '熎', '' => '熐', '' => '熑', '' => '熒', '' => '熓', '' => '熕', '' => '熖', '' => '熗', '' => '熚', '' => '熛', '' => '熜', '' => '熝', '' => '熞', '' => '熡', '' => '熢', '' => '熣', '' => '熤', '' => '熥', '' => '熦', '' => '熧', '' => '熩', '' => '熪', '' => '熫', '' => '熭', '' => '熮', '' => '熯', '' => '熰', '' => '熱', '' => '熲', '' => '熴', '' => '熶', '' => '熷', '' => '熸', '' => '熺', '' => '熻', '' => '熼', '' => '熽', '' => '熾', '' => '熿', '' => '燀', '' => '燁', '' => '燂', '' => '燄', '' => '燅', '' => '燆', '' => '燇', '' => '燈', '' => '燉', '' => '燊', '' => '燋', '' => '燌', '' => '燍', '' => '燏', '' => '燐', '' => '燑', '' => '燒', '' => '燓', '@' => '燖', 'A' => '燗', 'B' => '燘', 'C' => '燙', 'D' => '燚', 'E' => '燛', 'F' => '燜', 'G' => '燝', 'H' => '燞', 'I' => '營', 'J' => '燡', 'K' => '燢', 'L' => '燣', 'M' => '燤', 'N' => '燦', 'O' => '燨', 'P' => '燩', 'Q' => '燪', 'R' => '燫', 'S' => '燬', 'T' => '燭', 'U' => '燯', 'V' => '燰', 'W' => '燱', 'X' => '燲', 'Y' => '燳', 'Z' => '燴', '[' => '燵', '\\' => '燶', ']' => '燷', '^' => '燸', '_' => '燺', '`' => '燻', 'a' => '燼', 'b' => '燽', 'c' => '燾', 'd' => '燿', 'e' => '爀', 'f' => '爁', 'g' => '爂', 'h' => '爃', 'i' => '爄', 'j' => '爅', 'k' => '爇', 'l' => '爈', 'm' => '爉', 'n' => '爊', 'o' => '爋', 'p' => '爌', 'q' => '爍', 'r' => '爎', 's' => '爏', 't' => '爐', 'u' => '爑', 'v' => '爒', 'w' => '爓', 'x' => '爔', 'y' => '爕', 'z' => '爖', '{' => '爗', '|' => '爘', '}' => '爙', '~' => '爚', '' => '爛', '' => '爜', '' => '爞', '' => '爟', '' => '爠', '' => '爡', '' => '爢', '' => '爣', '' => '爤', '' => '爥', '' => '爦', '' => '爧', '' => '爩', '' => '爫', '' => '爭', '' => '爮', '' => '爯', '' => '爲', '' => '爳', '' => '爴', '' => '爺', '' => '爼', '' => '爾', '' => '牀', '' => '牁', '' => '牂', '' => '牃', '' => '牄', '' => '牅', '' => '牆', '' => '牉', '' => '牊', '' => '牋', '' => '牎', '' => '牏', '' => '牐', '' => '牑', '' => '牓', '' => '牔', '' => '牕', '' => '牗', '' => '牘', '' => '牚', '' => '牜', '' => '牞', '' => '牠', '' => '牣', '' => '牤', '' => '牥', '' => '牨', '' => '牪', '' => '牫', '' => '牬', '' => '牭', '' => '牰', '' => '牱', '' => '牳', '' => '牴', '' => '牶', '' => '牷', '' => '牸', '' => '牻', '' => '牼', '' => '牽', '' => '犂', '' => '犃', '' => '犅', '' => '犆', '' => '犇', '' => '犈', '' => '犉', '' => '犌', '' => '犎', '' => '犐', '' => '犑', '' => '犓', '' => '犔', '' => '犕', '' => '犖', '' => '犗', '' => '犘', '' => '犙', '' => '犚', '' => '犛', '' => '犜', '' => '犝', '' => '犞', '' => '犠', '' => '犡', '' => '犢', '' => '犣', '' => '犤', '' => '犥', '' => '犦', '' => '犧', '' => '犨', '' => '犩', '' => '犪', '' => '犫', '' => '犮', '' => '犱', '' => '犲', '' => '犳', '' => '犵', '' => '犺', '' => '犻', '' => '犼', '' => '犽', '' => '犾', '' => '犿', '' => '狀', '' => '狅', '' => '狆', '' => '狇', '' => '狉', '' => '狊', '' => '狋', '' => '狌', '' => '狏', '' => '狑', '' => '狓', '' => '狔', '' => '狕', '' => '狖', '' => '狘', '' => '狚', '' => '狛', '' => ' ', '' => '、', '' => '。', '' => '·', '' => 'ˉ', '' => 'ˇ', '' => '¨', '' => '〃', '' => '々', '' => '—', '' => '~', '' => '‖', '' => '…', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '〔', '' => '〕', '' => '〈', '' => '〉', '' => '《', '' => '》', '' => '「', '' => '」', '' => '『', '' => '』', '' => '〖', '' => '〗', '' => '【', '' => '】', '' => '±', '' => '×', '' => '÷', '' => '∶', '' => '∧', '' => '∨', '' => '∑', '' => '∏', '' => '∪', '' => '∩', '' => '∈', '' => '∷', '' => '√', '' => '⊥', '' => '∥', '' => '∠', '' => '⌒', '' => '⊙', '' => '∫', '' => '∮', '' => '≡', '' => '≌', '' => '≈', '' => '∽', '' => '∝', '' => '≠', '' => '≮', '' => '≯', '' => '≤', '' => '≥', '' => '∞', '' => '∵', '' => '∴', '' => '♂', '' => '♀', '' => '°', '' => '′', '' => '″', '' => '℃', '' => '$', '' => '¤', '' => '¢', '' => '£', '' => '‰', '' => '§', '' => '№', '' => '☆', '' => '★', '' => '○', '' => '●', '' => '◎', '' => '◇', '' => '◆', '' => '□', '' => '■', '' => '△', '' => '▲', '' => '※', '' => '→', '' => '←', '' => '↑', '' => '↓', '' => '〓', '' => 'ⅰ', '' => 'ⅱ', '' => 'ⅲ', '' => 'ⅳ', '' => 'ⅴ', '' => 'ⅵ', '' => 'ⅶ', '' => 'ⅷ', '' => 'ⅸ', '' => 'ⅹ', '' => '⒈', '' => '⒉', '' => '⒊', '' => '⒋', '' => '⒌', '' => '⒍', '' => '⒎', '' => '⒏', '' => '⒐', '' => '⒑', '' => '⒒', '' => '⒓', '' => '⒔', '' => '⒕', '' => '⒖', '' => '⒗', '' => '⒘', '' => '⒙', '' => '⒚', '' => '⒛', '' => '⑴', '' => '⑵', '' => '⑶', '' => '⑷', '' => '⑸', '' => '⑹', '' => '⑺', '' => '⑻', '' => '⑼', '' => '⑽', '' => '⑾', '' => '⑿', '' => '⒀', '' => '⒁', '' => '⒂', '' => '⒃', '' => '⒄', '' => '⒅', '' => '⒆', '' => '⒇', '' => '①', '' => '②', '' => '③', '' => '④', '' => '⑤', '' => '⑥', '' => '⑦', '' => '⑧', '' => '⑨', '' => '⑩', '' => '㈠', '' => '㈡', '' => '㈢', '' => '㈣', '' => '㈤', '' => '㈥', '' => '㈦', '' => '㈧', '' => '㈨', '' => '㈩', '' => 'Ⅰ', '' => 'Ⅱ', '' => 'Ⅲ', '' => 'Ⅳ', '' => 'Ⅴ', '' => 'Ⅵ', '' => 'Ⅶ', '' => 'Ⅷ', '' => 'Ⅸ', '' => 'Ⅹ', '' => 'Ⅺ', '' => 'Ⅻ', '' => '!', '' => '"', '' => '#', '' => '¥', '' => '%', '' => '&', '' => ''', '' => '(', '' => ')', '' => '*', '' => '+', '' => ',', '' => '-', '' => '.', '' => '/', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => ':', '' => ';', '' => '<', '' => '=', '' => '>', '' => '?', '' => '@', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => '[', '' => '\', '' => ']', '' => '^', '' => '_', '' => '`', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => '{', '' => '|', '' => '}', '' => ' ̄', '' => 'ぁ', '' => 'あ', '' => 'ぃ', '' => 'い', '' => 'ぅ', '' => 'う', '' => 'ぇ', '' => 'え', '' => 'ぉ', '' => 'お', '' => 'か', '' => 'が', '' => 'き', '' => 'ぎ', '' => 'く', '' => 'ぐ', '' => 'け', '' => 'げ', '' => 'こ', '' => 'ご', '' => 'さ', '' => 'ざ', '' => 'し', '' => 'じ', '' => 'す', '' => 'ず', '' => 'せ', '' => 'ぜ', '' => 'そ', '' => 'ぞ', '' => 'た', '' => 'だ', '' => 'ち', '' => 'ぢ', '' => 'っ', '' => 'つ', '' => 'づ', '' => 'て', '' => 'で', '' => 'と', '' => 'ど', '' => 'な', '' => 'に', '' => 'ぬ', '' => 'ね', '' => 'の', '' => 'は', '' => 'ば', '' => 'ぱ', '' => 'ひ', '' => 'び', '' => 'ぴ', '' => 'ふ', '' => 'ぶ', '' => 'ぷ', '' => 'へ', '' => 'べ', '' => 'ぺ', '' => 'ほ', '' => 'ぼ', '' => 'ぽ', '' => 'ま', '' => 'み', '' => 'む', '' => 'め', '' => 'も', '' => 'ゃ', '' => 'や', '' => 'ゅ', '' => 'ゆ', '' => 'ょ', '' => 'よ', '' => 'ら', '' => 'り', '' => 'る', '' => 'れ', '' => 'ろ', '' => 'ゎ', '' => 'わ', '' => 'ゐ', '' => 'ゑ', '' => 'を', '' => 'ん', '' => 'ァ', '' => 'ア', '' => 'ィ', '' => 'イ', '' => 'ゥ', '' => 'ウ', '' => 'ェ', '' => 'エ', '' => 'ォ', '' => 'オ', '' => 'カ', '' => 'ガ', '' => 'キ', '' => 'ギ', '' => 'ク', '' => 'グ', '' => 'ケ', '' => 'ゲ', '' => 'コ', '' => 'ゴ', '' => 'サ', '' => 'ザ', '' => 'シ', '' => 'ジ', '' => 'ス', '' => 'ズ', '' => 'セ', '' => 'ゼ', '' => 'ソ', '' => 'ゾ', '' => 'タ', '' => 'ダ', '' => 'チ', '' => 'ヂ', '' => 'ッ', '' => 'ツ', '' => 'ヅ', '' => 'テ', '' => 'デ', '' => 'ト', '' => 'ド', '' => 'ナ', '' => 'ニ', '' => 'ヌ', '' => 'ネ', '' => 'ノ', '' => 'ハ', '' => 'バ', '' => 'パ', '' => 'ヒ', '' => 'ビ', '' => 'ピ', '' => 'フ', '' => 'ブ', '' => 'プ', '' => 'ヘ', '' => 'ベ', '' => 'ペ', '' => 'ホ', '' => 'ボ', '' => 'ポ', '' => 'マ', '' => 'ミ', '' => 'ム', '' => 'メ', '' => 'モ', '' => 'ャ', '' => 'ヤ', '' => 'ュ', '' => 'ユ', '' => 'ョ', '' => 'ヨ', '' => 'ラ', '' => 'リ', '' => 'ル', '' => 'レ', '' => 'ロ', '' => 'ヮ', '' => 'ワ', '' => 'ヰ', '' => 'ヱ', '' => 'ヲ', '' => 'ン', '' => 'ヴ', '' => 'ヵ', '' => 'ヶ', '' => 'Α', '' => 'Β', '' => 'Γ', '' => 'Δ', '' => 'Ε', '' => 'Ζ', '' => 'Η', '' => 'Θ', '' => 'Ι', '' => 'Κ', '' => 'Λ', '' => 'Μ', '' => 'Ν', '' => 'Ξ', '' => 'Ο', '' => 'Π', '' => 'Ρ', '' => 'Σ', '' => 'Τ', '' => 'Υ', '' => 'Φ', '' => 'Χ', '' => 'Ψ', '' => 'Ω', '' => 'α', '' => 'β', '' => 'γ', '' => 'δ', '' => 'ε', '' => 'ζ', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'σ', '' => 'τ', '' => 'υ', '' => 'φ', '' => 'χ', '' => 'ψ', '' => 'ω', '' => '︵', '' => '︶', '' => '︹', '' => '︺', '' => '︿', '' => '﹀', '' => '︽', '' => '︾', '' => '﹁', '' => '﹂', '' => '﹃', '' => '﹄', '' => '︻', '' => '︼', '' => '︷', '' => '︸', '' => '︱', '' => '︳', '' => '︴', '' => 'А', '' => 'Б', '' => 'В', '' => 'Г', '' => 'Д', '' => 'Е', '' => 'Ё', '' => 'Ж', '' => 'З', '' => 'И', '' => 'Й', '' => 'К', '' => 'Л', '' => 'М', '' => 'Н', '' => 'О', '' => 'П', '' => 'Р', '' => 'С', '' => 'Т', '' => 'У', '' => 'Ф', '' => 'Х', '' => 'Ц', '' => 'Ч', '' => 'Ш', '' => 'Щ', '' => 'Ъ', '' => 'Ы', '' => 'Ь', '' => 'Э', '' => 'Ю', '' => 'Я', '' => 'а', '' => 'б', '' => 'в', '' => 'г', '' => 'д', '' => 'е', '' => 'ё', '' => 'ж', '' => 'з', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ф', '' => 'х', '' => 'ц', '' => 'ч', '' => 'ш', '' => 'щ', '' => 'ъ', '' => 'ы', '' => 'ь', '' => 'э', '' => 'ю', '' => 'я', '@' => 'ˊ', 'A' => 'ˋ', 'B' => '˙', 'C' => '–', 'D' => '―', 'E' => '‥', 'F' => '‵', 'G' => '℅', 'H' => '℉', 'I' => '↖', 'J' => '↗', 'K' => '↘', 'L' => '↙', 'M' => '∕', 'N' => '∟', 'O' => '∣', 'P' => '≒', 'Q' => '≦', 'R' => '≧', 'S' => '⊿', 'T' => '═', 'U' => '║', 'V' => '╒', 'W' => '╓', 'X' => '╔', 'Y' => '╕', 'Z' => '╖', '[' => '╗', '\\' => '╘', ']' => '╙', '^' => '╚', '_' => '╛', '`' => '╜', 'a' => '╝', 'b' => '╞', 'c' => '╟', 'd' => '╠', 'e' => '╡', 'f' => '╢', 'g' => '╣', 'h' => '╤', 'i' => '╥', 'j' => '╦', 'k' => '╧', 'l' => '╨', 'm' => '╩', 'n' => '╪', 'o' => '╫', 'p' => '╬', 'q' => '╭', 'r' => '╮', 's' => '╯', 't' => '╰', 'u' => '╱', 'v' => '╲', 'w' => '╳', 'x' => '▁', 'y' => '▂', 'z' => '▃', '{' => '▄', '|' => '▅', '}' => '▆', '~' => '▇', '' => '█', '' => '▉', '' => '▊', '' => '▋', '' => '▌', '' => '▍', '' => '▎', '' => '▏', '' => '▓', '' => '▔', '' => '▕', '' => '▼', '' => '▽', '' => '◢', '' => '◣', '' => '◤', '' => '◥', '' => '☉', '' => '⊕', '' => '〒', '' => '〝', '' => '〞', '' => 'ā', '' => 'á', '' => 'ǎ', '' => 'à', '' => 'ē', '' => 'é', '' => 'ě', '' => 'è', '' => 'ī', '' => 'í', '' => 'ǐ', '' => 'ì', '' => 'ō', '' => 'ó', '' => 'ǒ', '' => 'ò', '' => 'ū', '' => 'ú', '' => 'ǔ', '' => 'ù', '' => 'ǖ', '' => 'ǘ', '' => 'ǚ', '' => 'ǜ', '' => 'ü', '' => 'ê', '' => 'ɑ', '' => 'ń', '' => 'ň', '' => 'ɡ', '' => 'ㄅ', '' => 'ㄆ', '' => 'ㄇ', '' => 'ㄈ', '' => 'ㄉ', '' => 'ㄊ', '' => 'ㄋ', '' => 'ㄌ', '' => 'ㄍ', '' => 'ㄎ', '' => 'ㄏ', '' => 'ㄐ', '' => 'ㄑ', '' => 'ㄒ', '' => 'ㄓ', '' => 'ㄔ', '' => 'ㄕ', '' => 'ㄖ', '' => 'ㄗ', '' => 'ㄘ', '' => 'ㄙ', '' => 'ㄚ', '' => 'ㄛ', '' => 'ㄜ', '' => 'ㄝ', '' => 'ㄞ', '' => 'ㄟ', '' => 'ㄠ', '' => 'ㄡ', '' => 'ㄢ', '' => 'ㄣ', '' => 'ㄤ', '' => 'ㄥ', '' => 'ㄦ', '' => 'ㄧ', '' => 'ㄨ', '' => 'ㄩ', '@' => '〡', 'A' => '〢', 'B' => '〣', 'C' => '〤', 'D' => '〥', 'E' => '〦', 'F' => '〧', 'G' => '〨', 'H' => '〩', 'I' => '㊣', 'J' => '㎎', 'K' => '㎏', 'L' => '㎜', 'M' => '㎝', 'N' => '㎞', 'O' => '㎡', 'P' => '㏄', 'Q' => '㏎', 'R' => '㏑', 'S' => '㏒', 'T' => '㏕', 'U' => '︰', 'V' => '¬', 'W' => '¦', 'Y' => '℡', 'Z' => '㈱', '\\' => '‐', '`' => 'ー', 'a' => '゛', 'b' => '゜', 'c' => 'ヽ', 'd' => 'ヾ', 'e' => '〆', 'f' => 'ゝ', 'g' => 'ゞ', 'h' => '﹉', 'i' => '﹊', 'j' => '﹋', 'k' => '﹌', 'l' => '﹍', 'm' => '﹎', 'n' => '﹏', 'o' => '﹐', 'p' => '﹑', 'q' => '﹒', 'r' => '﹔', 's' => '﹕', 't' => '﹖', 'u' => '﹗', 'v' => '﹙', 'w' => '﹚', 'x' => '﹛', 'y' => '﹜', 'z' => '﹝', '{' => '﹞', '|' => '﹟', '}' => '﹠', '~' => '﹡', '' => '﹢', '' => '﹣', '' => '﹤', '' => '﹥', '' => '﹦', '' => '﹨', '' => '﹩', '' => '﹪', '' => '﹫', '' => '〇', '' => '─', '' => '━', '' => '│', '' => '┃', '' => '┄', '' => '┅', '' => '┆', '' => '┇', '' => '┈', '' => '┉', '' => '┊', '' => '┋', '' => '┌', '' => '┍', '' => '┎', '' => '┏', '' => '┐', '' => '┑', '' => '┒', '' => '┓', '' => '└', '' => '┕', '' => '┖', '' => '┗', '' => '┘', '' => '┙', '' => '┚', '' => '┛', '' => '├', '' => '┝', '' => '┞', '' => '┟', '' => '┠', '' => '┡', '' => '┢', '' => '┣', '' => '┤', '' => '┥', '' => '┦', '' => '┧', '' => '┨', '' => '┩', '' => '┪', '' => '┫', '' => '┬', '' => '┭', '' => '┮', '' => '┯', '' => '┰', '' => '┱', '' => '┲', '' => '┳', '' => '┴', '' => '┵', '' => '┶', '' => '┷', '' => '┸', '' => '┹', '' => '┺', '' => '┻', '' => '┼', '' => '┽', '' => '┾', '' => '┿', '' => '╀', '' => '╁', '' => '╂', '' => '╃', '' => '╄', '' => '╅', '' => '╆', '' => '╇', '' => '╈', '' => '╉', '' => '╊', '' => '╋', '@' => '狜', 'A' => '狝', 'B' => '狟', 'C' => '狢', 'D' => '狣', 'E' => '狤', 'F' => '狥', 'G' => '狦', 'H' => '狧', 'I' => '狪', 'J' => '狫', 'K' => '狵', 'L' => '狶', 'M' => '狹', 'N' => '狽', 'O' => '狾', 'P' => '狿', 'Q' => '猀', 'R' => '猂', 'S' => '猄', 'T' => '猅', 'U' => '猆', 'V' => '猇', 'W' => '猈', 'X' => '猉', 'Y' => '猋', 'Z' => '猌', '[' => '猍', '\\' => '猏', ']' => '猐', '^' => '猑', '_' => '猒', '`' => '猔', 'a' => '猘', 'b' => '猙', 'c' => '猚', 'd' => '猟', 'e' => '猠', 'f' => '猣', 'g' => '猤', 'h' => '猦', 'i' => '猧', 'j' => '猨', 'k' => '猭', 'l' => '猯', 'm' => '猰', 'n' => '猲', 'o' => '猳', 'p' => '猵', 'q' => '猶', 'r' => '猺', 's' => '猻', 't' => '猼', 'u' => '猽', 'v' => '獀', 'w' => '獁', 'x' => '獂', 'y' => '獃', 'z' => '獄', '{' => '獅', '|' => '獆', '}' => '獇', '~' => '獈', '' => '獉', '' => '獊', '' => '獋', '' => '獌', '' => '獎', '' => '獏', '' => '獑', '' => '獓', '' => '獔', '' => '獕', '' => '獖', '' => '獘', '' => '獙', '' => '獚', '' => '獛', '' => '獜', '' => '獝', '' => '獞', '' => '獟', '' => '獡', '' => '獢', '' => '獣', '' => '獤', '' => '獥', '' => '獦', '' => '獧', '' => '獨', '' => '獩', '' => '獪', '' => '獫', '' => '獮', '' => '獰', '' => '獱', '@' => '獲', 'A' => '獳', 'B' => '獴', 'C' => '獵', 'D' => '獶', 'E' => '獷', 'F' => '獸', 'G' => '獹', 'H' => '獺', 'I' => '獻', 'J' => '獼', 'K' => '獽', 'L' => '獿', 'M' => '玀', 'N' => '玁', 'O' => '玂', 'P' => '玃', 'Q' => '玅', 'R' => '玆', 'S' => '玈', 'T' => '玊', 'U' => '玌', 'V' => '玍', 'W' => '玏', 'X' => '玐', 'Y' => '玒', 'Z' => '玓', '[' => '玔', '\\' => '玕', ']' => '玗', '^' => '玘', '_' => '玙', '`' => '玚', 'a' => '玜', 'b' => '玝', 'c' => '玞', 'd' => '玠', 'e' => '玡', 'f' => '玣', 'g' => '玤', 'h' => '玥', 'i' => '玦', 'j' => '玧', 'k' => '玨', 'l' => '玪', 'm' => '玬', 'n' => '玭', 'o' => '玱', 'p' => '玴', 'q' => '玵', 'r' => '玶', 's' => '玸', 't' => '玹', 'u' => '玼', 'v' => '玽', 'w' => '玾', 'x' => '玿', 'y' => '珁', 'z' => '珃', '{' => '珄', '|' => '珅', '}' => '珆', '~' => '珇', '' => '珋', '' => '珌', '' => '珎', '' => '珒', '' => '珓', '' => '珔', '' => '珕', '' => '珖', '' => '珗', '' => '珘', '' => '珚', '' => '珛', '' => '珜', '' => '珝', '' => '珟', '' => '珡', '' => '珢', '' => '珣', '' => '珤', '' => '珦', '' => '珨', '' => '珪', '' => '珫', '' => '珬', '' => '珮', '' => '珯', '' => '珰', '' => '珱', '' => '珳', '' => '珴', '' => '珵', '' => '珶', '' => '珷', '@' => '珸', 'A' => '珹', 'B' => '珺', 'C' => '珻', 'D' => '珼', 'E' => '珽', 'F' => '現', 'G' => '珿', 'H' => '琀', 'I' => '琁', 'J' => '琂', 'K' => '琄', 'L' => '琇', 'M' => '琈', 'N' => '琋', 'O' => '琌', 'P' => '琍', 'Q' => '琎', 'R' => '琑', 'S' => '琒', 'T' => '琓', 'U' => '琔', 'V' => '琕', 'W' => '琖', 'X' => '琗', 'Y' => '琘', 'Z' => '琙', '[' => '琜', '\\' => '琝', ']' => '琞', '^' => '琟', '_' => '琠', '`' => '琡', 'a' => '琣', 'b' => '琤', 'c' => '琧', 'd' => '琩', 'e' => '琫', 'f' => '琭', 'g' => '琯', 'h' => '琱', 'i' => '琲', 'j' => '琷', 'k' => '琸', 'l' => '琹', 'm' => '琺', 'n' => '琻', 'o' => '琽', 'p' => '琾', 'q' => '琿', 'r' => '瑀', 's' => '瑂', 't' => '瑃', 'u' => '瑄', 'v' => '瑅', 'w' => '瑆', 'x' => '瑇', 'y' => '瑈', 'z' => '瑉', '{' => '瑊', '|' => '瑋', '}' => '瑌', '~' => '瑍', '' => '瑎', '' => '瑏', '' => '瑐', '' => '瑑', '' => '瑒', '' => '瑓', '' => '瑔', '' => '瑖', '' => '瑘', '' => '瑝', '' => '瑠', '' => '瑡', '' => '瑢', '' => '瑣', '' => '瑤', '' => '瑥', '' => '瑦', '' => '瑧', '' => '瑨', '' => '瑩', '' => '瑪', '' => '瑫', '' => '瑬', '' => '瑮', '' => '瑯', '' => '瑱', '' => '瑲', '' => '瑳', '' => '瑴', '' => '瑵', '' => '瑸', '' => '瑹', '' => '瑺', '@' => '瑻', 'A' => '瑼', 'B' => '瑽', 'C' => '瑿', 'D' => '璂', 'E' => '璄', 'F' => '璅', 'G' => '璆', 'H' => '璈', 'I' => '璉', 'J' => '璊', 'K' => '璌', 'L' => '璍', 'M' => '璏', 'N' => '璑', 'O' => '璒', 'P' => '璓', 'Q' => '璔', 'R' => '璕', 'S' => '璖', 'T' => '璗', 'U' => '璘', 'V' => '璙', 'W' => '璚', 'X' => '璛', 'Y' => '璝', 'Z' => '璟', '[' => '璠', '\\' => '璡', ']' => '璢', '^' => '璣', '_' => '璤', '`' => '璥', 'a' => '璦', 'b' => '璪', 'c' => '璫', 'd' => '璬', 'e' => '璭', 'f' => '璮', 'g' => '璯', 'h' => '環', 'i' => '璱', 'j' => '璲', 'k' => '璳', 'l' => '璴', 'm' => '璵', 'n' => '璶', 'o' => '璷', 'p' => '璸', 'q' => '璹', 'r' => '璻', 's' => '璼', 't' => '璽', 'u' => '璾', 'v' => '璿', 'w' => '瓀', 'x' => '瓁', 'y' => '瓂', 'z' => '瓃', '{' => '瓄', '|' => '瓅', '}' => '瓆', '~' => '瓇', '' => '瓈', '' => '瓉', '' => '瓊', '' => '瓋', '' => '瓌', '' => '瓍', '' => '瓎', '' => '瓏', '' => '瓐', '' => '瓑', '' => '瓓', '' => '瓔', '' => '瓕', '' => '瓖', '' => '瓗', '' => '瓘', '' => '瓙', '' => '瓚', '' => '瓛', '' => '瓝', '' => '瓟', '' => '瓡', '' => '瓥', '' => '瓧', '' => '瓨', '' => '瓩', '' => '瓪', '' => '瓫', '' => '瓬', '' => '瓭', '' => '瓰', '' => '瓱', '' => '瓲', '@' => '瓳', 'A' => '瓵', 'B' => '瓸', 'C' => '瓹', 'D' => '瓺', 'E' => '瓻', 'F' => '瓼', 'G' => '瓽', 'H' => '瓾', 'I' => '甀', 'J' => '甁', 'K' => '甂', 'L' => '甃', 'M' => '甅', 'N' => '甆', 'O' => '甇', 'P' => '甈', 'Q' => '甉', 'R' => '甊', 'S' => '甋', 'T' => '甌', 'U' => '甎', 'V' => '甐', 'W' => '甒', 'X' => '甔', 'Y' => '甕', 'Z' => '甖', '[' => '甗', '\\' => '甛', ']' => '甝', '^' => '甞', '_' => '甠', '`' => '甡', 'a' => '產', 'b' => '産', 'c' => '甤', 'd' => '甦', 'e' => '甧', 'f' => '甪', 'g' => '甮', 'h' => '甴', 'i' => '甶', 'j' => '甹', 'k' => '甼', 'l' => '甽', 'm' => '甿', 'n' => '畁', 'o' => '畂', 'p' => '畃', 'q' => '畄', 'r' => '畆', 's' => '畇', 't' => '畉', 'u' => '畊', 'v' => '畍', 'w' => '畐', 'x' => '畑', 'y' => '畒', 'z' => '畓', '{' => '畕', '|' => '畖', '}' => '畗', '~' => '畘', '' => '畝', '' => '畞', '' => '畟', '' => '畠', '' => '畡', '' => '畢', '' => '畣', '' => '畤', '' => '畧', '' => '畨', '' => '畩', '' => '畫', '' => '畬', '' => '畭', '' => '畮', '' => '畯', '' => '異', '' => '畱', '' => '畳', '' => '畵', '' => '當', '' => '畷', '' => '畺', '' => '畻', '' => '畼', '' => '畽', '' => '畾', '' => '疀', '' => '疁', '' => '疂', '' => '疄', '' => '疅', '' => '疇', '@' => '疈', 'A' => '疉', 'B' => '疊', 'C' => '疌', 'D' => '疍', 'E' => '疎', 'F' => '疐', 'G' => '疓', 'H' => '疕', 'I' => '疘', 'J' => '疛', 'K' => '疜', 'L' => '疞', 'M' => '疢', 'N' => '疦', 'O' => '疧', 'P' => '疨', 'Q' => '疩', 'R' => '疪', 'S' => '疭', 'T' => '疶', 'U' => '疷', 'V' => '疺', 'W' => '疻', 'X' => '疿', 'Y' => '痀', 'Z' => '痁', '[' => '痆', '\\' => '痋', ']' => '痌', '^' => '痎', '_' => '痏', '`' => '痐', 'a' => '痑', 'b' => '痓', 'c' => '痗', 'd' => '痙', 'e' => '痚', 'f' => '痜', 'g' => '痝', 'h' => '痟', 'i' => '痠', 'j' => '痡', 'k' => '痥', 'l' => '痩', 'm' => '痬', 'n' => '痭', 'o' => '痮', 'p' => '痯', 'q' => '痲', 'r' => '痳', 's' => '痵', 't' => '痶', 'u' => '痷', 'v' => '痸', 'w' => '痺', 'x' => '痻', 'y' => '痽', 'z' => '痾', '{' => '瘂', '|' => '瘄', '}' => '瘆', '~' => '瘇', '' => '瘈', '' => '瘉', '' => '瘋', '' => '瘍', '' => '瘎', '' => '瘏', '' => '瘑', '' => '瘒', '' => '瘓', '' => '瘔', '' => '瘖', '' => '瘚', '' => '瘜', '' => '瘝', '' => '瘞', '' => '瘡', '' => '瘣', '' => '瘧', '' => '瘨', '' => '瘬', '' => '瘮', '' => '瘯', '' => '瘱', '' => '瘲', '' => '瘶', '' => '瘷', '' => '瘹', '' => '瘺', '' => '瘻', '' => '瘽', '' => '癁', '' => '療', '' => '癄', '@' => '癅', 'A' => '癆', 'B' => '癇', 'C' => '癈', 'D' => '癉', 'E' => '癊', 'F' => '癋', 'G' => '癎', 'H' => '癏', 'I' => '癐', 'J' => '癑', 'K' => '癒', 'L' => '癓', 'M' => '癕', 'N' => '癗', 'O' => '癘', 'P' => '癙', 'Q' => '癚', 'R' => '癛', 'S' => '癝', 'T' => '癟', 'U' => '癠', 'V' => '癡', 'W' => '癢', 'X' => '癤', 'Y' => '癥', 'Z' => '癦', '[' => '癧', '\\' => '癨', ']' => '癩', '^' => '癪', '_' => '癬', '`' => '癭', 'a' => '癮', 'b' => '癰', 'c' => '癱', 'd' => '癲', 'e' => '癳', 'f' => '癴', 'g' => '癵', 'h' => '癶', 'i' => '癷', 'j' => '癹', 'k' => '発', 'l' => '發', 'm' => '癿', 'n' => '皀', 'o' => '皁', 'p' => '皃', 'q' => '皅', 'r' => '皉', 's' => '皊', 't' => '皌', 'u' => '皍', 'v' => '皏', 'w' => '皐', 'x' => '皒', 'y' => '皔', 'z' => '皕', '{' => '皗', '|' => '皘', '}' => '皚', '~' => '皛', '' => '皜', '' => '皝', '' => '皞', '' => '皟', '' => '皠', '' => '皡', '' => '皢', '' => '皣', '' => '皥', '' => '皦', '' => '皧', '' => '皨', '' => '皩', '' => '皪', '' => '皫', '' => '皬', '' => '皭', '' => '皯', '' => '皰', '' => '皳', '' => '皵', '' => '皶', '' => '皷', '' => '皸', '' => '皹', '' => '皺', '' => '皻', '' => '皼', '' => '皽', '' => '皾', '' => '盀', '' => '盁', '' => '盃', '' => '啊', '' => '阿', '' => '埃', '' => '挨', '' => '哎', '' => '唉', '' => '哀', '' => '皑', '' => '癌', '' => '蔼', '' => '矮', '' => '艾', '' => '碍', '' => '爱', '' => '隘', '' => '鞍', '' => '氨', '' => '安', '' => '俺', '' => '按', '' => '暗', '' => '岸', '' => '胺', '' => '案', '' => '肮', '' => '昂', '' => '盎', '' => '凹', '' => '敖', '' => '熬', '' => '翱', '' => '袄', '' => '傲', '' => '奥', '' => '懊', '' => '澳', '' => '芭', '' => '捌', '' => '扒', '' => '叭', '' => '吧', '' => '笆', '' => '八', '' => '疤', '' => '巴', '' => '拔', '' => '跋', '' => '靶', '' => '把', '' => '耙', '' => '坝', '' => '霸', '' => '罢', '' => '爸', '' => '白', '' => '柏', '' => '百', '' => '摆', '' => '佰', '' => '败', '' => '拜', '' => '稗', '' => '斑', '' => '班', '' => '搬', '' => '扳', '' => '般', '' => '颁', '' => '板', '' => '版', '' => '扮', '' => '拌', '' => '伴', '' => '瓣', '' => '半', '' => '办', '' => '绊', '' => '邦', '' => '帮', '' => '梆', '' => '榜', '' => '膀', '' => '绑', '' => '棒', '' => '磅', '' => '蚌', '' => '镑', '' => '傍', '' => '谤', '' => '苞', '' => '胞', '' => '包', '' => '褒', '' => '剥', '@' => '盄', 'A' => '盇', 'B' => '盉', 'C' => '盋', 'D' => '盌', 'E' => '盓', 'F' => '盕', 'G' => '盙', 'H' => '盚', 'I' => '盜', 'J' => '盝', 'K' => '盞', 'L' => '盠', 'M' => '盡', 'N' => '盢', 'O' => '監', 'P' => '盤', 'Q' => '盦', 'R' => '盧', 'S' => '盨', 'T' => '盩', 'U' => '盪', 'V' => '盫', 'W' => '盬', 'X' => '盭', 'Y' => '盰', 'Z' => '盳', '[' => '盵', '\\' => '盶', ']' => '盷', '^' => '盺', '_' => '盻', '`' => '盽', 'a' => '盿', 'b' => '眀', 'c' => '眂', 'd' => '眃', 'e' => '眅', 'f' => '眆', 'g' => '眊', 'h' => '県', 'i' => '眎', 'j' => '眏', 'k' => '眐', 'l' => '眑', 'm' => '眒', 'n' => '眓', 'o' => '眔', 'p' => '眕', 'q' => '眖', 'r' => '眗', 's' => '眘', 't' => '眛', 'u' => '眜', 'v' => '眝', 'w' => '眞', 'x' => '眡', 'y' => '眣', 'z' => '眤', '{' => '眥', '|' => '眧', '}' => '眪', '~' => '眫', '' => '眬', '' => '眮', '' => '眰', '' => '眱', '' => '眲', '' => '眳', '' => '眴', '' => '眹', '' => '眻', '' => '眽', '' => '眾', '' => '眿', '' => '睂', '' => '睄', '' => '睅', '' => '睆', '' => '睈', '' => '睉', '' => '睊', '' => '睋', '' => '睌', '' => '睍', '' => '睎', '' => '睏', '' => '睒', '' => '睓', '' => '睔', '' => '睕', '' => '睖', '' => '睗', '' => '睘', '' => '睙', '' => '睜', '' => '薄', '' => '雹', '' => '保', '' => '堡', '' => '饱', '' => '宝', '' => '抱', '' => '报', '' => '暴', '' => '豹', '' => '鲍', '' => '爆', '' => '杯', '' => '碑', '' => '悲', '' => '卑', '' => '北', '' => '辈', '' => '背', '' => '贝', '' => '钡', '' => '倍', '' => '狈', '' => '备', '' => '惫', '' => '焙', '' => '被', '' => '奔', '' => '苯', '' => '本', '' => '笨', '' => '崩', '' => '绷', '' => '甭', '' => '泵', '' => '蹦', '' => '迸', '' => '逼', '' => '鼻', '' => '比', '' => '鄙', '' => '笔', '' => '彼', '' => '碧', '' => '蓖', '' => '蔽', '' => '毕', '' => '毙', '' => '毖', '' => '币', '' => '庇', '' => '痹', '' => '闭', '' => '敝', '' => '弊', '' => '必', '' => '辟', '' => '壁', '' => '臂', '' => '避', '' => '陛', '' => '鞭', '' => '边', '' => '编', '' => '贬', '' => '扁', '' => '便', '' => '变', '' => '卞', '' => '辨', '' => '辩', '' => '辫', '' => '遍', '' => '标', '' => '彪', '' => '膘', '' => '表', '' => '鳖', '' => '憋', '' => '别', '' => '瘪', '' => '彬', '' => '斌', '' => '濒', '' => '滨', '' => '宾', '' => '摈', '' => '兵', '' => '冰', '' => '柄', '' => '丙', '' => '秉', '' => '饼', '' => '炳', '@' => '睝', 'A' => '睞', 'B' => '睟', 'C' => '睠', 'D' => '睤', 'E' => '睧', 'F' => '睩', 'G' => '睪', 'H' => '睭', 'I' => '睮', 'J' => '睯', 'K' => '睰', 'L' => '睱', 'M' => '睲', 'N' => '睳', 'O' => '睴', 'P' => '睵', 'Q' => '睶', 'R' => '睷', 'S' => '睸', 'T' => '睺', 'U' => '睻', 'V' => '睼', 'W' => '瞁', 'X' => '瞂', 'Y' => '瞃', 'Z' => '瞆', '[' => '瞇', '\\' => '瞈', ']' => '瞉', '^' => '瞊', '_' => '瞋', '`' => '瞏', 'a' => '瞐', 'b' => '瞓', 'c' => '瞔', 'd' => '瞕', 'e' => '瞖', 'f' => '瞗', 'g' => '瞘', 'h' => '瞙', 'i' => '瞚', 'j' => '瞛', 'k' => '瞜', 'l' => '瞝', 'm' => '瞞', 'n' => '瞡', 'o' => '瞣', 'p' => '瞤', 'q' => '瞦', 'r' => '瞨', 's' => '瞫', 't' => '瞭', 'u' => '瞮', 'v' => '瞯', 'w' => '瞱', 'x' => '瞲', 'y' => '瞴', 'z' => '瞶', '{' => '瞷', '|' => '瞸', '}' => '瞹', '~' => '瞺', '' => '瞼', '' => '瞾', '' => '矀', '' => '矁', '' => '矂', '' => '矃', '' => '矄', '' => '矅', '' => '矆', '' => '矇', '' => '矈', '' => '矉', '' => '矊', '' => '矋', '' => '矌', '' => '矎', '' => '矏', '' => '矐', '' => '矑', '' => '矒', '' => '矓', '' => '矔', '' => '矕', '' => '矖', '' => '矘', '' => '矙', '' => '矚', '' => '矝', '' => '矞', '' => '矟', '' => '矠', '' => '矡', '' => '矤', '' => '病', '' => '并', '' => '玻', '' => '菠', '' => '播', '' => '拨', '' => '钵', '' => '波', '' => '博', '' => '勃', '' => '搏', '' => '铂', '' => '箔', '' => '伯', '' => '帛', '' => '舶', '' => '脖', '' => '膊', '' => '渤', '' => '泊', '' => '驳', '' => '捕', '' => '卜', '' => '哺', '' => '补', '' => '埠', '' => '不', '' => '布', '' => '步', '' => '簿', '' => '部', '' => '怖', '' => '擦', '' => '猜', '' => '裁', '' => '材', '' => '才', '' => '财', '' => '睬', '' => '踩', '' => '采', '' => '彩', '' => '菜', '' => '蔡', '' => '餐', '' => '参', '' => '蚕', '' => '残', '' => '惭', '' => '惨', '' => '灿', '' => '苍', '' => '舱', '' => '仓', '' => '沧', '' => '藏', '' => '操', '' => '糙', '' => '槽', '' => '曹', '' => '草', '' => '厕', '' => '策', '' => '侧', '' => '册', '' => '测', '' => '层', '' => '蹭', '' => '插', '' => '叉', '' => '茬', '' => '茶', '' => '查', '' => '碴', '' => '搽', '' => '察', '' => '岔', '' => '差', '' => '诧', '' => '拆', '' => '柴', '' => '豺', '' => '搀', '' => '掺', '' => '蝉', '' => '馋', '' => '谗', '' => '缠', '' => '铲', '' => '产', '' => '阐', '' => '颤', '' => '昌', '' => '猖', '@' => '矦', 'A' => '矨', 'B' => '矪', 'C' => '矯', 'D' => '矰', 'E' => '矱', 'F' => '矲', 'G' => '矴', 'H' => '矵', 'I' => '矷', 'J' => '矹', 'K' => '矺', 'L' => '矻', 'M' => '矼', 'N' => '砃', 'O' => '砄', 'P' => '砅', 'Q' => '砆', 'R' => '砇', 'S' => '砈', 'T' => '砊', 'U' => '砋', 'V' => '砎', 'W' => '砏', 'X' => '砐', 'Y' => '砓', 'Z' => '砕', '[' => '砙', '\\' => '砛', ']' => '砞', '^' => '砠', '_' => '砡', '`' => '砢', 'a' => '砤', 'b' => '砨', 'c' => '砪', 'd' => '砫', 'e' => '砮', 'f' => '砯', 'g' => '砱', 'h' => '砲', 'i' => '砳', 'j' => '砵', 'k' => '砶', 'l' => '砽', 'm' => '砿', 'n' => '硁', 'o' => '硂', 'p' => '硃', 'q' => '硄', 'r' => '硆', 's' => '硈', 't' => '硉', 'u' => '硊', 'v' => '硋', 'w' => '硍', 'x' => '硏', 'y' => '硑', 'z' => '硓', '{' => '硔', '|' => '硘', '}' => '硙', '~' => '硚', '' => '硛', '' => '硜', '' => '硞', '' => '硟', '' => '硠', '' => '硡', '' => '硢', '' => '硣', '' => '硤', '' => '硥', '' => '硦', '' => '硧', '' => '硨', '' => '硩', '' => '硯', '' => '硰', '' => '硱', '' => '硲', '' => '硳', '' => '硴', '' => '硵', '' => '硶', '' => '硸', '' => '硹', '' => '硺', '' => '硻', '' => '硽', '' => '硾', '' => '硿', '' => '碀', '' => '碁', '' => '碂', '' => '碃', '' => '场', '' => '尝', '' => '常', '' => '长', '' => '偿', '' => '肠', '' => '厂', '' => '敞', '' => '畅', '' => '唱', '' => '倡', '' => '超', '' => '抄', '' => '钞', '' => '朝', '' => '嘲', '' => '潮', '' => '巢', '' => '吵', '' => '炒', '' => '车', '' => '扯', '' => '撤', '' => '掣', '' => '彻', '' => '澈', '' => '郴', '' => '臣', '' => '辰', '' => '尘', '' => '晨', '' => '忱', '' => '沉', '' => '陈', '' => '趁', '' => '衬', '' => '撑', '' => '称', '' => '城', '' => '橙', '' => '成', '' => '呈', '' => '乘', '' => '程', '' => '惩', '' => '澄', '' => '诚', '' => '承', '' => '逞', '' => '骋', '' => '秤', '' => '吃', '' => '痴', '' => '持', '' => '匙', '' => '池', '' => '迟', '' => '弛', '' => '驰', '' => '耻', '' => '齿', '' => '侈', '' => '尺', '' => '赤', '' => '翅', '' => '斥', '' => '炽', '' => '充', '' => '冲', '' => '虫', '' => '崇', '' => '宠', '' => '抽', '' => '酬', '' => '畴', '' => '踌', '' => '稠', '' => '愁', '' => '筹', '' => '仇', '' => '绸', '' => '瞅', '' => '丑', '' => '臭', '' => '初', '' => '出', '' => '橱', '' => '厨', '' => '躇', '' => '锄', '' => '雏', '' => '滁', '' => '除', '' => '楚', '@' => '碄', 'A' => '碅', 'B' => '碆', 'C' => '碈', 'D' => '碊', 'E' => '碋', 'F' => '碏', 'G' => '碐', 'H' => '碒', 'I' => '碔', 'J' => '碕', 'K' => '碖', 'L' => '碙', 'M' => '碝', 'N' => '碞', 'O' => '碠', 'P' => '碢', 'Q' => '碤', 'R' => '碦', 'S' => '碨', 'T' => '碩', 'U' => '碪', 'V' => '碫', 'W' => '碬', 'X' => '碭', 'Y' => '碮', 'Z' => '碯', '[' => '碵', '\\' => '碶', ']' => '碷', '^' => '碸', '_' => '確', '`' => '碻', 'a' => '碼', 'b' => '碽', 'c' => '碿', 'd' => '磀', 'e' => '磂', 'f' => '磃', 'g' => '磄', 'h' => '磆', 'i' => '磇', 'j' => '磈', 'k' => '磌', 'l' => '磍', 'm' => '磎', 'n' => '磏', 'o' => '磑', 'p' => '磒', 'q' => '磓', 'r' => '磖', 's' => '磗', 't' => '磘', 'u' => '磚', 'v' => '磛', 'w' => '磜', 'x' => '磝', 'y' => '磞', 'z' => '磟', '{' => '磠', '|' => '磡', '}' => '磢', '~' => '磣', '' => '磤', '' => '磥', '' => '磦', '' => '磧', '' => '磩', '' => '磪', '' => '磫', '' => '磭', '' => '磮', '' => '磯', '' => '磰', '' => '磱', '' => '磳', '' => '磵', '' => '磶', '' => '磸', '' => '磹', '' => '磻', '' => '磼', '' => '磽', '' => '磾', '' => '磿', '' => '礀', '' => '礂', '' => '礃', '' => '礄', '' => '礆', '' => '礇', '' => '礈', '' => '礉', '' => '礊', '' => '礋', '' => '礌', '' => '础', '' => '储', '' => '矗', '' => '搐', '' => '触', '' => '处', '' => '揣', '' => '川', '' => '穿', '' => '椽', '' => '传', '' => '船', '' => '喘', '' => '串', '' => '疮', '' => '窗', '' => '幢', '' => '床', '' => '闯', '' => '创', '' => '吹', '' => '炊', '' => '捶', '' => '锤', '' => '垂', '' => '春', '' => '椿', '' => '醇', '' => '唇', '' => '淳', '' => '纯', '' => '蠢', '' => '戳', '' => '绰', '' => '疵', '' => '茨', '' => '磁', '' => '雌', '' => '辞', '' => '慈', '' => '瓷', '' => '词', '' => '此', '' => '刺', '' => '赐', '' => '次', '' => '聪', '' => '葱', '' => '囱', '' => '匆', '' => '从', '' => '丛', '' => '凑', '' => '粗', '' => '醋', '' => '簇', '' => '促', '' => '蹿', '' => '篡', '' => '窜', '' => '摧', '' => '崔', '' => '催', '' => '脆', '' => '瘁', '' => '粹', '' => '淬', '' => '翠', '' => '村', '' => '存', '' => '寸', '' => '磋', '' => '撮', '' => '搓', '' => '措', '' => '挫', '' => '错', '' => '搭', '' => '达', '' => '答', '' => '瘩', '' => '打', '' => '大', '' => '呆', '' => '歹', '' => '傣', '' => '戴', '' => '带', '' => '殆', '' => '代', '' => '贷', '' => '袋', '' => '待', '' => '逮', '@' => '礍', 'A' => '礎', 'B' => '礏', 'C' => '礐', 'D' => '礑', 'E' => '礒', 'F' => '礔', 'G' => '礕', 'H' => '礖', 'I' => '礗', 'J' => '礘', 'K' => '礙', 'L' => '礚', 'M' => '礛', 'N' => '礜', 'O' => '礝', 'P' => '礟', 'Q' => '礠', 'R' => '礡', 'S' => '礢', 'T' => '礣', 'U' => '礥', 'V' => '礦', 'W' => '礧', 'X' => '礨', 'Y' => '礩', 'Z' => '礪', '[' => '礫', '\\' => '礬', ']' => '礭', '^' => '礮', '_' => '礯', '`' => '礰', 'a' => '礱', 'b' => '礲', 'c' => '礳', 'd' => '礵', 'e' => '礶', 'f' => '礷', 'g' => '礸', 'h' => '礹', 'i' => '礽', 'j' => '礿', 'k' => '祂', 'l' => '祃', 'm' => '祄', 'n' => '祅', 'o' => '祇', 'p' => '祊', 'q' => '祋', 'r' => '祌', 's' => '祍', 't' => '祎', 'u' => '祏', 'v' => '祐', 'w' => '祑', 'x' => '祒', 'y' => '祔', 'z' => '祕', '{' => '祘', '|' => '祙', '}' => '祡', '~' => '祣', '' => '祤', '' => '祦', '' => '祩', '' => '祪', '' => '祫', '' => '祬', '' => '祮', '' => '祰', '' => '祱', '' => '祲', '' => '祳', '' => '祴', '' => '祵', '' => '祶', '' => '祹', '' => '祻', '' => '祼', '' => '祽', '' => '祾', '' => '祿', '' => '禂', '' => '禃', '' => '禆', '' => '禇', '' => '禈', '' => '禉', '' => '禋', '' => '禌', '' => '禍', '' => '禎', '' => '禐', '' => '禑', '' => '禒', '' => '怠', '' => '耽', '' => '担', '' => '丹', '' => '单', '' => '郸', '' => '掸', '' => '胆', '' => '旦', '' => '氮', '' => '但', '' => '惮', '' => '淡', '' => '诞', '' => '弹', '' => '蛋', '' => '当', '' => '挡', '' => '党', '' => '荡', '' => '档', '' => '刀', '' => '捣', '' => '蹈', '' => '倒', '' => '岛', '' => '祷', '' => '导', '' => '到', '' => '稻', '' => '悼', '' => '道', '' => '盗', '' => '德', '' => '得', '' => '的', '' => '蹬', '' => '灯', '' => '登', '' => '等', '' => '瞪', '' => '凳', '' => '邓', '' => '堤', '' => '低', '' => '滴', '' => '迪', '' => '敌', '' => '笛', '' => '狄', '' => '涤', '' => '翟', '' => '嫡', '' => '抵', '' => '底', '' => '地', '' => '蒂', '' => '第', '' => '帝', '' => '弟', '' => '递', '' => '缔', '' => '颠', '' => '掂', '' => '滇', '' => '碘', '' => '点', '' => '典', '' => '靛', '' => '垫', '' => '电', '' => '佃', '' => '甸', '' => '店', '' => '惦', '' => '奠', '' => '淀', '' => '殿', '' => '碉', '' => '叼', '' => '雕', '' => '凋', '' => '刁', '' => '掉', '' => '吊', '' => '钓', '' => '调', '' => '跌', '' => '爹', '' => '碟', '' => '蝶', '' => '迭', '' => '谍', '' => '叠', '@' => '禓', 'A' => '禔', 'B' => '禕', 'C' => '禖', 'D' => '禗', 'E' => '禘', 'F' => '禙', 'G' => '禛', 'H' => '禜', 'I' => '禝', 'J' => '禞', 'K' => '禟', 'L' => '禠', 'M' => '禡', 'N' => '禢', 'O' => '禣', 'P' => '禤', 'Q' => '禥', 'R' => '禦', 'S' => '禨', 'T' => '禩', 'U' => '禪', 'V' => '禫', 'W' => '禬', 'X' => '禭', 'Y' => '禮', 'Z' => '禯', '[' => '禰', '\\' => '禱', ']' => '禲', '^' => '禴', '_' => '禵', '`' => '禶', 'a' => '禷', 'b' => '禸', 'c' => '禼', 'd' => '禿', 'e' => '秂', 'f' => '秄', 'g' => '秅', 'h' => '秇', 'i' => '秈', 'j' => '秊', 'k' => '秌', 'l' => '秎', 'm' => '秏', 'n' => '秐', 'o' => '秓', 'p' => '秔', 'q' => '秖', 'r' => '秗', 's' => '秙', 't' => '秚', 'u' => '秛', 'v' => '秜', 'w' => '秝', 'x' => '秞', 'y' => '秠', 'z' => '秡', '{' => '秢', '|' => '秥', '}' => '秨', '~' => '秪', '' => '秬', '' => '秮', '' => '秱', '' => '秲', '' => '秳', '' => '秴', '' => '秵', '' => '秶', '' => '秷', '' => '秹', '' => '秺', '' => '秼', '' => '秾', '' => '秿', '' => '稁', '' => '稄', '' => '稅', '' => '稇', '' => '稈', '' => '稉', '' => '稊', '' => '稌', '' => '稏', '' => '稐', '' => '稑', '' => '稒', '' => '稓', '' => '稕', '' => '稖', '' => '稘', '' => '稙', '' => '稛', '' => '稜', '' => '丁', '' => '盯', '' => '叮', '' => '钉', '' => '顶', '' => '鼎', '' => '锭', '' => '定', '' => '订', '' => '丢', '' => '东', '' => '冬', '' => '董', '' => '懂', '' => '动', '' => '栋', '' => '侗', '' => '恫', '' => '冻', '' => '洞', '' => '兜', '' => '抖', '' => '斗', '' => '陡', '' => '豆', '' => '逗', '' => '痘', '' => '都', '' => '督', '' => '毒', '' => '犊', '' => '独', '' => '读', '' => '堵', '' => '睹', '' => '赌', '' => '杜', '' => '镀', '' => '肚', '' => '度', '' => '渡', '' => '妒', '' => '端', '' => '短', '' => '锻', '' => '段', '' => '断', '' => '缎', '' => '堆', '' => '兑', '' => '队', '' => '对', '' => '墩', '' => '吨', '' => '蹲', '' => '敦', '' => '顿', '' => '囤', '' => '钝', '' => '盾', '' => '遁', '' => '掇', '' => '哆', '' => '多', '' => '夺', '' => '垛', '' => '躲', '' => '朵', '' => '跺', '' => '舵', '' => '剁', '' => '惰', '' => '堕', '' => '蛾', '' => '峨', '' => '鹅', '' => '俄', '' => '额', '' => '讹', '' => '娥', '' => '恶', '' => '厄', '' => '扼', '' => '遏', '' => '鄂', '' => '饿', '' => '恩', '' => '而', '' => '儿', '' => '耳', '' => '尔', '' => '饵', '' => '洱', '' => '二', '@' => '稝', 'A' => '稟', 'B' => '稡', 'C' => '稢', 'D' => '稤', 'E' => '稥', 'F' => '稦', 'G' => '稧', 'H' => '稨', 'I' => '稩', 'J' => '稪', 'K' => '稫', 'L' => '稬', 'M' => '稭', 'N' => '種', 'O' => '稯', 'P' => '稰', 'Q' => '稱', 'R' => '稲', 'S' => '稴', 'T' => '稵', 'U' => '稶', 'V' => '稸', 'W' => '稺', 'X' => '稾', 'Y' => '穀', 'Z' => '穁', '[' => '穂', '\\' => '穃', ']' => '穄', '^' => '穅', '_' => '穇', '`' => '穈', 'a' => '穉', 'b' => '穊', 'c' => '穋', 'd' => '穌', 'e' => '積', 'f' => '穎', 'g' => '穏', 'h' => '穐', 'i' => '穒', 'j' => '穓', 'k' => '穔', 'l' => '穕', 'm' => '穖', 'n' => '穘', 'o' => '穙', 'p' => '穚', 'q' => '穛', 'r' => '穜', 's' => '穝', 't' => '穞', 'u' => '穟', 'v' => '穠', 'w' => '穡', 'x' => '穢', 'y' => '穣', 'z' => '穤', '{' => '穥', '|' => '穦', '}' => '穧', '~' => '穨', '' => '穩', '' => '穪', '' => '穫', '' => '穬', '' => '穭', '' => '穮', '' => '穯', '' => '穱', '' => '穲', '' => '穳', '' => '穵', '' => '穻', '' => '穼', '' => '穽', '' => '穾', '' => '窂', '' => '窅', '' => '窇', '' => '窉', '' => '窊', '' => '窋', '' => '窌', '' => '窎', '' => '窏', '' => '窐', '' => '窓', '' => '窔', '' => '窙', '' => '窚', '' => '窛', '' => '窞', '' => '窡', '' => '窢', '' => '贰', '' => '发', '' => '罚', '' => '筏', '' => '伐', '' => '乏', '' => '阀', '' => '法', '' => '珐', '' => '藩', '' => '帆', '' => '番', '' => '翻', '' => '樊', '' => '矾', '' => '钒', '' => '繁', '' => '凡', '' => '烦', '' => '反', '' => '返', '' => '范', '' => '贩', '' => '犯', '' => '饭', '' => '泛', '' => '坊', '' => '芳', '' => '方', '' => '肪', '' => '房', '' => '防', '' => '妨', '' => '仿', '' => '访', '' => '纺', '' => '放', '' => '菲', '' => '非', '' => '啡', '' => '飞', '' => '肥', '' => '匪', '' => '诽', '' => '吠', '' => '肺', '' => '废', '' => '沸', '' => '费', '' => '芬', '' => '酚', '' => '吩', '' => '氛', '' => '分', '' => '纷', '' => '坟', '' => '焚', '' => '汾', '' => '粉', '' => '奋', '' => '份', '' => '忿', '' => '愤', '' => '粪', '' => '丰', '' => '封', '' => '枫', '' => '蜂', '' => '峰', '' => '锋', '' => '风', '' => '疯', '' => '烽', '' => '逢', '' => '冯', '' => '缝', '' => '讽', '' => '奉', '' => '凤', '' => '佛', '' => '否', '' => '夫', '' => '敷', '' => '肤', '' => '孵', '' => '扶', '' => '拂', '' => '辐', '' => '幅', '' => '氟', '' => '符', '' => '伏', '' => '俘', '' => '服', '@' => '窣', 'A' => '窤', 'B' => '窧', 'C' => '窩', 'D' => '窪', 'E' => '窫', 'F' => '窮', 'G' => '窯', 'H' => '窰', 'I' => '窱', 'J' => '窲', 'K' => '窴', 'L' => '窵', 'M' => '窶', 'N' => '窷', 'O' => '窸', 'P' => '窹', 'Q' => '窺', 'R' => '窻', 'S' => '窼', 'T' => '窽', 'U' => '窾', 'V' => '竀', 'W' => '竁', 'X' => '竂', 'Y' => '竃', 'Z' => '竄', '[' => '竅', '\\' => '竆', ']' => '竇', '^' => '竈', '_' => '竉', '`' => '竊', 'a' => '竌', 'b' => '竍', 'c' => '竎', 'd' => '竏', 'e' => '竐', 'f' => '竑', 'g' => '竒', 'h' => '竓', 'i' => '竔', 'j' => '竕', 'k' => '竗', 'l' => '竘', 'm' => '竚', 'n' => '竛', 'o' => '竜', 'p' => '竝', 'q' => '竡', 'r' => '竢', 's' => '竤', 't' => '竧', 'u' => '竨', 'v' => '竩', 'w' => '竪', 'x' => '竫', 'y' => '竬', 'z' => '竮', '{' => '竰', '|' => '竱', '}' => '竲', '~' => '竳', '' => '竴', '' => '竵', '' => '競', '' => '竷', '' => '竸', '' => '竻', '' => '竼', '' => '竾', '' => '笀', '' => '笁', '' => '笂', '' => '笅', '' => '笇', '' => '笉', '' => '笌', '' => '笍', '' => '笎', '' => '笐', '' => '笒', '' => '笓', '' => '笖', '' => '笗', '' => '笘', '' => '笚', '' => '笜', '' => '笝', '' => '笟', '' => '笡', '' => '笢', '' => '笣', '' => '笧', '' => '笩', '' => '笭', '' => '浮', '' => '涪', '' => '福', '' => '袱', '' => '弗', '' => '甫', '' => '抚', '' => '辅', '' => '俯', '' => '釜', '' => '斧', '' => '脯', '' => '腑', '' => '府', '' => '腐', '' => '赴', '' => '副', '' => '覆', '' => '赋', '' => '复', '' => '傅', '' => '付', '' => '阜', '' => '父', '' => '腹', '' => '负', '' => '富', '' => '讣', '' => '附', '' => '妇', '' => '缚', '' => '咐', '' => '噶', '' => '嘎', '' => '该', '' => '改', '' => '概', '' => '钙', '' => '盖', '' => '溉', '' => '干', '' => '甘', '' => '杆', '' => '柑', '' => '竿', '' => '肝', '' => '赶', '' => '感', '' => '秆', '' => '敢', '' => '赣', '' => '冈', '' => '刚', '' => '钢', '' => '缸', '' => '肛', '' => '纲', '' => '岗', '' => '港', '' => '杠', '' => '篙', '' => '皋', '' => '高', '' => '膏', '' => '羔', '' => '糕', '' => '搞', '' => '镐', '' => '稿', '' => '告', '' => '哥', '' => '歌', '' => '搁', '' => '戈', '' => '鸽', '' => '胳', '' => '疙', '' => '割', '' => '革', '' => '葛', '' => '格', '' => '蛤', '' => '阁', '' => '隔', '' => '铬', '' => '个', '' => '各', '' => '给', '' => '根', '' => '跟', '' => '耕', '' => '更', '' => '庚', '' => '羹', '@' => '笯', 'A' => '笰', 'B' => '笲', 'C' => '笴', 'D' => '笵', 'E' => '笶', 'F' => '笷', 'G' => '笹', 'H' => '笻', 'I' => '笽', 'J' => '笿', 'K' => '筀', 'L' => '筁', 'M' => '筂', 'N' => '筃', 'O' => '筄', 'P' => '筆', 'Q' => '筈', 'R' => '筊', 'S' => '筍', 'T' => '筎', 'U' => '筓', 'V' => '筕', 'W' => '筗', 'X' => '筙', 'Y' => '筜', 'Z' => '筞', '[' => '筟', '\\' => '筡', ']' => '筣', '^' => '筤', '_' => '筥', '`' => '筦', 'a' => '筧', 'b' => '筨', 'c' => '筩', 'd' => '筪', 'e' => '筫', 'f' => '筬', 'g' => '筭', 'h' => '筯', 'i' => '筰', 'j' => '筳', 'k' => '筴', 'l' => '筶', 'm' => '筸', 'n' => '筺', 'o' => '筼', 'p' => '筽', 'q' => '筿', 'r' => '箁', 's' => '箂', 't' => '箃', 'u' => '箄', 'v' => '箆', 'w' => '箇', 'x' => '箈', 'y' => '箉', 'z' => '箊', '{' => '箋', '|' => '箌', '}' => '箎', '~' => '箏', '' => '箑', '' => '箒', '' => '箓', '' => '箖', '' => '箘', '' => '箙', '' => '箚', '' => '箛', '' => '箞', '' => '箟', '' => '箠', '' => '箣', '' => '箤', '' => '箥', '' => '箮', '' => '箯', '' => '箰', '' => '箲', '' => '箳', '' => '箵', '' => '箶', '' => '箷', '' => '箹', '' => '箺', '' => '箻', '' => '箼', '' => '箽', '' => '箾', '' => '箿', '' => '節', '' => '篂', '' => '篃', '' => '範', '' => '埂', '' => '耿', '' => '梗', '' => '工', '' => '攻', '' => '功', '' => '恭', '' => '龚', '' => '供', '' => '躬', '' => '公', '' => '宫', '' => '弓', '' => '巩', '' => '汞', '' => '拱', '' => '贡', '' => '共', '' => '钩', '' => '勾', '' => '沟', '' => '苟', '' => '狗', '' => '垢', '' => '构', '' => '购', '' => '够', '' => '辜', '' => '菇', '' => '咕', '' => '箍', '' => '估', '' => '沽', '' => '孤', '' => '姑', '' => '鼓', '' => '古', '' => '蛊', '' => '骨', '' => '谷', '' => '股', '' => '故', '' => '顾', '' => '固', '' => '雇', '' => '刮', '' => '瓜', '' => '剐', '' => '寡', '' => '挂', '' => '褂', '' => '乖', '' => '拐', '' => '怪', '' => '棺', '' => '关', '' => '官', '' => '冠', '' => '观', '' => '管', '' => '馆', '' => '罐', '' => '惯', '' => '灌', '' => '贯', '' => '光', '' => '广', '' => '逛', '' => '瑰', '' => '规', '' => '圭', '' => '硅', '' => '归', '' => '龟', '' => '闺', '' => '轨', '' => '鬼', '' => '诡', '' => '癸', '' => '桂', '' => '柜', '' => '跪', '' => '贵', '' => '刽', '' => '辊', '' => '滚', '' => '棍', '' => '锅', '' => '郭', '' => '国', '' => '果', '' => '裹', '' => '过', '' => '哈', '@' => '篅', 'A' => '篈', 'B' => '築', 'C' => '篊', 'D' => '篋', 'E' => '篍', 'F' => '篎', 'G' => '篏', 'H' => '篐', 'I' => '篒', 'J' => '篔', 'K' => '篕', 'L' => '篖', 'M' => '篗', 'N' => '篘', 'O' => '篛', 'P' => '篜', 'Q' => '篞', 'R' => '篟', 'S' => '篠', 'T' => '篢', 'U' => '篣', 'V' => '篤', 'W' => '篧', 'X' => '篨', 'Y' => '篩', 'Z' => '篫', '[' => '篬', '\\' => '篭', ']' => '篯', '^' => '篰', '_' => '篲', '`' => '篳', 'a' => '篴', 'b' => '篵', 'c' => '篶', 'd' => '篸', 'e' => '篹', 'f' => '篺', 'g' => '篻', 'h' => '篽', 'i' => '篿', 'j' => '簀', 'k' => '簁', 'l' => '簂', 'm' => '簃', 'n' => '簄', 'o' => '簅', 'p' => '簆', 'q' => '簈', 'r' => '簉', 's' => '簊', 't' => '簍', 'u' => '簎', 'v' => '簐', 'w' => '簑', 'x' => '簒', 'y' => '簓', 'z' => '簔', '{' => '簕', '|' => '簗', '}' => '簘', '~' => '簙', '' => '簚', '' => '簛', '' => '簜', '' => '簝', '' => '簞', '' => '簠', '' => '簡', '' => '簢', '' => '簣', '' => '簤', '' => '簥', '' => '簨', '' => '簩', '' => '簫', '' => '簬', '' => '簭', '' => '簮', '' => '簯', '' => '簰', '' => '簱', '' => '簲', '' => '簳', '' => '簴', '' => '簵', '' => '簶', '' => '簷', '' => '簹', '' => '簺', '' => '簻', '' => '簼', '' => '簽', '' => '簾', '' => '籂', '' => '骸', '' => '孩', '' => '海', '' => '氦', '' => '亥', '' => '害', '' => '骇', '' => '酣', '' => '憨', '' => '邯', '' => '韩', '' => '含', '' => '涵', '' => '寒', '' => '函', '' => '喊', '' => '罕', '' => '翰', '' => '撼', '' => '捍', '' => '旱', '' => '憾', '' => '悍', '' => '焊', '' => '汗', '' => '汉', '' => '夯', '' => '杭', '' => '航', '' => '壕', '' => '嚎', '' => '豪', '' => '毫', '' => '郝', '' => '好', '' => '耗', '' => '号', '' => '浩', '' => '呵', '' => '喝', '' => '荷', '' => '菏', '' => '核', '' => '禾', '' => '和', '' => '何', '' => '合', '' => '盒', '' => '貉', '' => '阂', '' => '河', '' => '涸', '' => '赫', '' => '褐', '' => '鹤', '' => '贺', '' => '嘿', '' => '黑', '' => '痕', '' => '很', '' => '狠', '' => '恨', '' => '哼', '' => '亨', '' => '横', '' => '衡', '' => '恒', '' => '轰', '' => '哄', '' => '烘', '' => '虹', '' => '鸿', '' => '洪', '' => '宏', '' => '弘', '' => '红', '' => '喉', '' => '侯', '' => '猴', '' => '吼', '' => '厚', '' => '候', '' => '后', '' => '呼', '' => '乎', '' => '忽', '' => '瑚', '' => '壶', '' => '葫', '' => '胡', '' => '蝴', '' => '狐', '' => '糊', '' => '湖', '@' => '籃', 'A' => '籄', 'B' => '籅', 'C' => '籆', 'D' => '籇', 'E' => '籈', 'F' => '籉', 'G' => '籊', 'H' => '籋', 'I' => '籌', 'J' => '籎', 'K' => '籏', 'L' => '籐', 'M' => '籑', 'N' => '籒', 'O' => '籓', 'P' => '籔', 'Q' => '籕', 'R' => '籖', 'S' => '籗', 'T' => '籘', 'U' => '籙', 'V' => '籚', 'W' => '籛', 'X' => '籜', 'Y' => '籝', 'Z' => '籞', '[' => '籟', '\\' => '籠', ']' => '籡', '^' => '籢', '_' => '籣', '`' => '籤', 'a' => '籥', 'b' => '籦', 'c' => '籧', 'd' => '籨', 'e' => '籩', 'f' => '籪', 'g' => '籫', 'h' => '籬', 'i' => '籭', 'j' => '籮', 'k' => '籯', 'l' => '籰', 'm' => '籱', 'n' => '籲', 'o' => '籵', 'p' => '籶', 'q' => '籷', 'r' => '籸', 's' => '籹', 't' => '籺', 'u' => '籾', 'v' => '籿', 'w' => '粀', 'x' => '粁', 'y' => '粂', 'z' => '粃', '{' => '粄', '|' => '粅', '}' => '粆', '~' => '粇', '' => '粈', '' => '粊', '' => '粋', '' => '粌', '' => '粍', '' => '粎', '' => '粏', '' => '粐', '' => '粓', '' => '粔', '' => '粖', '' => '粙', '' => '粚', '' => '粛', '' => '粠', '' => '粡', '' => '粣', '' => '粦', '' => '粧', '' => '粨', '' => '粩', '' => '粫', '' => '粬', '' => '粭', '' => '粯', '' => '粰', '' => '粴', '' => '粵', '' => '粶', '' => '粷', '' => '粸', '' => '粺', '' => '粻', '' => '弧', '' => '虎', '' => '唬', '' => '护', '' => '互', '' => '沪', '' => '户', '' => '花', '' => '哗', '' => '华', '' => '猾', '' => '滑', '' => '画', '' => '划', '' => '化', '' => '话', '' => '槐', '' => '徊', '' => '怀', '' => '淮', '' => '坏', '' => '欢', '' => '环', '' => '桓', '' => '还', '' => '缓', '' => '换', '' => '患', '' => '唤', '' => '痪', '' => '豢', '' => '焕', '' => '涣', '' => '宦', '' => '幻', '' => '荒', '' => '慌', '' => '黄', '' => '磺', '' => '蝗', '' => '簧', '' => '皇', '' => '凰', '' => '惶', '' => '煌', '' => '晃', '' => '幌', '' => '恍', '' => '谎', '' => '灰', '' => '挥', '' => '辉', '' => '徽', '' => '恢', '' => '蛔', '' => '回', '' => '毁', '' => '悔', '' => '慧', '' => '卉', '' => '惠', '' => '晦', '' => '贿', '' => '秽', '' => '会', '' => '烩', '' => '汇', '' => '讳', '' => '诲', '' => '绘', '' => '荤', '' => '昏', '' => '婚', '' => '魂', '' => '浑', '' => '混', '' => '豁', '' => '活', '' => '伙', '' => '火', '' => '获', '' => '或', '' => '惑', '' => '霍', '' => '货', '' => '祸', '' => '击', '' => '圾', '' => '基', '' => '机', '' => '畸', '' => '稽', '' => '积', '' => '箕', '@' => '粿', 'A' => '糀', 'B' => '糂', 'C' => '糃', 'D' => '糄', 'E' => '糆', 'F' => '糉', 'G' => '糋', 'H' => '糎', 'I' => '糏', 'J' => '糐', 'K' => '糑', 'L' => '糒', 'M' => '糓', 'N' => '糔', 'O' => '糘', 'P' => '糚', 'Q' => '糛', 'R' => '糝', 'S' => '糞', 'T' => '糡', 'U' => '糢', 'V' => '糣', 'W' => '糤', 'X' => '糥', 'Y' => '糦', 'Z' => '糧', '[' => '糩', '\\' => '糪', ']' => '糫', '^' => '糬', '_' => '糭', '`' => '糮', 'a' => '糰', 'b' => '糱', 'c' => '糲', 'd' => '糳', 'e' => '糴', 'f' => '糵', 'g' => '糶', 'h' => '糷', 'i' => '糹', 'j' => '糺', 'k' => '糼', 'l' => '糽', 'm' => '糾', 'n' => '糿', 'o' => '紀', 'p' => '紁', 'q' => '紂', 'r' => '紃', 's' => '約', 't' => '紅', 'u' => '紆', 'v' => '紇', 'w' => '紈', 'x' => '紉', 'y' => '紋', 'z' => '紌', '{' => '納', '|' => '紎', '}' => '紏', '~' => '紐', '' => '紑', '' => '紒', '' => '紓', '' => '純', '' => '紕', '' => '紖', '' => '紗', '' => '紘', '' => '紙', '' => '級', '' => '紛', '' => '紜', '' => '紝', '' => '紞', '' => '紟', '' => '紡', '' => '紣', '' => '紤', '' => '紥', '' => '紦', '' => '紨', '' => '紩', '' => '紪', '' => '紬', '' => '紭', '' => '紮', '' => '細', '' => '紱', '' => '紲', '' => '紳', '' => '紴', '' => '紵', '' => '紶', '' => '肌', '' => '饥', '' => '迹', '' => '激', '' => '讥', '' => '鸡', '' => '姬', '' => '绩', '' => '缉', '' => '吉', '' => '极', '' => '棘', '' => '辑', '' => '籍', '' => '集', '' => '及', '' => '急', '' => '疾', '' => '汲', '' => '即', '' => '嫉', '' => '级', '' => '挤', '' => '几', '' => '脊', '' => '己', '' => '蓟', '' => '技', '' => '冀', '' => '季', '' => '伎', '' => '祭', '' => '剂', '' => '悸', '' => '济', '' => '寄', '' => '寂', '' => '计', '' => '记', '' => '既', '' => '忌', '' => '际', '' => '妓', '' => '继', '' => '纪', '' => '嘉', '' => '枷', '' => '夹', '' => '佳', '' => '家', '' => '加', '' => '荚', '' => '颊', '' => '贾', '' => '甲', '' => '钾', '' => '假', '' => '稼', '' => '价', '' => '架', '' => '驾', '' => '嫁', '' => '歼', '' => '监', '' => '坚', '' => '尖', '' => '笺', '' => '间', '' => '煎', '' => '兼', '' => '肩', '' => '艰', '' => '奸', '' => '缄', '' => '茧', '' => '检', '' => '柬', '' => '碱', '' => '硷', '' => '拣', '' => '捡', '' => '简', '' => '俭', '' => '剪', '' => '减', '' => '荐', '' => '槛', '' => '鉴', '' => '践', '' => '贱', '' => '见', '' => '键', '' => '箭', '' => '件', '@' => '紷', 'A' => '紸', 'B' => '紹', 'C' => '紺', 'D' => '紻', 'E' => '紼', 'F' => '紽', 'G' => '紾', 'H' => '紿', 'I' => '絀', 'J' => '絁', 'K' => '終', 'L' => '絃', 'M' => '組', 'N' => '絅', 'O' => '絆', 'P' => '絇', 'Q' => '絈', 'R' => '絉', 'S' => '絊', 'T' => '絋', 'U' => '経', 'V' => '絍', 'W' => '絎', 'X' => '絏', 'Y' => '結', 'Z' => '絑', '[' => '絒', '\\' => '絓', ']' => '絔', '^' => '絕', '_' => '絖', '`' => '絗', 'a' => '絘', 'b' => '絙', 'c' => '絚', 'd' => '絛', 'e' => '絜', 'f' => '絝', 'g' => '絞', 'h' => '絟', 'i' => '絠', 'j' => '絡', 'k' => '絢', 'l' => '絣', 'm' => '絤', 'n' => '絥', 'o' => '給', 'p' => '絧', 'q' => '絨', 'r' => '絩', 's' => '絪', 't' => '絫', 'u' => '絬', 'v' => '絭', 'w' => '絯', 'x' => '絰', 'y' => '統', 'z' => '絲', '{' => '絳', '|' => '絴', '}' => '絵', '~' => '絶', '' => '絸', '' => '絹', '' => '絺', '' => '絻', '' => '絼', '' => '絽', '' => '絾', '' => '絿', '' => '綀', '' => '綁', '' => '綂', '' => '綃', '' => '綄', '' => '綅', '' => '綆', '' => '綇', '' => '綈', '' => '綉', '' => '綊', '' => '綋', '' => '綌', '' => '綍', '' => '綎', '' => '綏', '' => '綐', '' => '綑', '' => '綒', '' => '經', '' => '綔', '' => '綕', '' => '綖', '' => '綗', '' => '綘', '' => '健', '' => '舰', '' => '剑', '' => '饯', '' => '渐', '' => '溅', '' => '涧', '' => '建', '' => '僵', '' => '姜', '' => '将', '' => '浆', '' => '江', '' => '疆', '' => '蒋', '' => '桨', '' => '奖', '' => '讲', '' => '匠', '' => '酱', '' => '降', '' => '蕉', '' => '椒', '' => '礁', '' => '焦', '' => '胶', '' => '交', '' => '郊', '' => '浇', '' => '骄', '' => '娇', '' => '嚼', '' => '搅', '' => '铰', '' => '矫', '' => '侥', '' => '脚', '' => '狡', '' => '角', '' => '饺', '' => '缴', '' => '绞', '' => '剿', '' => '教', '' => '酵', '' => '轿', '' => '较', '' => '叫', '' => '窖', '' => '揭', '' => '接', '' => '皆', '' => '秸', '' => '街', '' => '阶', '' => '截', '' => '劫', '' => '节', '' => '桔', '' => '杰', '' => '捷', '' => '睫', '' => '竭', '' => '洁', '' => '结', '' => '解', '' => '姐', '' => '戒', '' => '藉', '' => '芥', '' => '界', '' => '借', '' => '介', '' => '疥', '' => '诫', '' => '届', '' => '巾', '' => '筋', '' => '斤', '' => '金', '' => '今', '' => '津', '' => '襟', '' => '紧', '' => '锦', '' => '仅', '' => '谨', '' => '进', '' => '靳', '' => '晋', '' => '禁', '' => '近', '' => '烬', '' => '浸', '@' => '継', 'A' => '続', 'B' => '綛', 'C' => '綜', 'D' => '綝', 'E' => '綞', 'F' => '綟', 'G' => '綠', 'H' => '綡', 'I' => '綢', 'J' => '綣', 'K' => '綤', 'L' => '綥', 'M' => '綧', 'N' => '綨', 'O' => '綩', 'P' => '綪', 'Q' => '綫', 'R' => '綬', 'S' => '維', 'T' => '綯', 'U' => '綰', 'V' => '綱', 'W' => '網', 'X' => '綳', 'Y' => '綴', 'Z' => '綵', '[' => '綶', '\\' => '綷', ']' => '綸', '^' => '綹', '_' => '綺', '`' => '綻', 'a' => '綼', 'b' => '綽', 'c' => '綾', 'd' => '綿', 'e' => '緀', 'f' => '緁', 'g' => '緂', 'h' => '緃', 'i' => '緄', 'j' => '緅', 'k' => '緆', 'l' => '緇', 'm' => '緈', 'n' => '緉', 'o' => '緊', 'p' => '緋', 'q' => '緌', 'r' => '緍', 's' => '緎', 't' => '総', 'u' => '緐', 'v' => '緑', 'w' => '緒', 'x' => '緓', 'y' => '緔', 'z' => '緕', '{' => '緖', '|' => '緗', '}' => '緘', '~' => '緙', '' => '線', '' => '緛', '' => '緜', '' => '緝', '' => '緞', '' => '緟', '' => '締', '' => '緡', '' => '緢', '' => '緣', '' => '緤', '' => '緥', '' => '緦', '' => '緧', '' => '編', '' => '緩', '' => '緪', '' => '緫', '' => '緬', '' => '緭', '' => '緮', '' => '緯', '' => '緰', '' => '緱', '' => '緲', '' => '緳', '' => '練', '' => '緵', '' => '緶', '' => '緷', '' => '緸', '' => '緹', '' => '緺', '' => '尽', '' => '劲', '' => '荆', '' => '兢', '' => '茎', '' => '睛', '' => '晶', '' => '鲸', '' => '京', '' => '惊', '' => '精', '' => '粳', '' => '经', '' => '井', '' => '警', '' => '景', '' => '颈', '' => '静', '' => '境', '' => '敬', '' => '镜', '' => '径', '' => '痉', '' => '靖', '' => '竟', '' => '竞', '' => '净', '' => '炯', '' => '窘', '' => '揪', '' => '究', '' => '纠', '' => '玖', '' => '韭', '' => '久', '' => '灸', '' => '九', '' => '酒', '' => '厩', '' => '救', '' => '旧', '' => '臼', '' => '舅', '' => '咎', '' => '就', '' => '疚', '' => '鞠', '' => '拘', '' => '狙', '' => '疽', '' => '居', '' => '驹', '' => '菊', '' => '局', '' => '咀', '' => '矩', '' => '举', '' => '沮', '' => '聚', '' => '拒', '' => '据', '' => '巨', '' => '具', '' => '距', '' => '踞', '' => '锯', '' => '俱', '' => '句', '' => '惧', '' => '炬', '' => '剧', '' => '捐', '' => '鹃', '' => '娟', '' => '倦', '' => '眷', '' => '卷', '' => '绢', '' => '撅', '' => '攫', '' => '抉', '' => '掘', '' => '倔', '' => '爵', '' => '觉', '' => '决', '' => '诀', '' => '绝', '' => '均', '' => '菌', '' => '钧', '' => '军', '' => '君', '' => '峻', '@' => '緻', 'A' => '緼', 'B' => '緽', 'C' => '緾', 'D' => '緿', 'E' => '縀', 'F' => '縁', 'G' => '縂', 'H' => '縃', 'I' => '縄', 'J' => '縅', 'K' => '縆', 'L' => '縇', 'M' => '縈', 'N' => '縉', 'O' => '縊', 'P' => '縋', 'Q' => '縌', 'R' => '縍', 'S' => '縎', 'T' => '縏', 'U' => '縐', 'V' => '縑', 'W' => '縒', 'X' => '縓', 'Y' => '縔', 'Z' => '縕', '[' => '縖', '\\' => '縗', ']' => '縘', '^' => '縙', '_' => '縚', '`' => '縛', 'a' => '縜', 'b' => '縝', 'c' => '縞', 'd' => '縟', 'e' => '縠', 'f' => '縡', 'g' => '縢', 'h' => '縣', 'i' => '縤', 'j' => '縥', 'k' => '縦', 'l' => '縧', 'm' => '縨', 'n' => '縩', 'o' => '縪', 'p' => '縫', 'q' => '縬', 'r' => '縭', 's' => '縮', 't' => '縯', 'u' => '縰', 'v' => '縱', 'w' => '縲', 'x' => '縳', 'y' => '縴', 'z' => '縵', '{' => '縶', '|' => '縷', '}' => '縸', '~' => '縹', '' => '縺', '' => '縼', '' => '總', '' => '績', '' => '縿', '' => '繀', '' => '繂', '' => '繃', '' => '繄', '' => '繅', '' => '繆', '' => '繈', '' => '繉', '' => '繊', '' => '繋', '' => '繌', '' => '繍', '' => '繎', '' => '繏', '' => '繐', '' => '繑', '' => '繒', '' => '繓', '' => '織', '' => '繕', '' => '繖', '' => '繗', '' => '繘', '' => '繙', '' => '繚', '' => '繛', '' => '繜', '' => '繝', '' => '俊', '' => '竣', '' => '浚', '' => '郡', '' => '骏', '' => '喀', '' => '咖', '' => '卡', '' => '咯', '' => '开', '' => '揩', '' => '楷', '' => '凯', '' => '慨', '' => '刊', '' => '堪', '' => '勘', '' => '坎', '' => '砍', '' => '看', '' => '康', '' => '慷', '' => '糠', '' => '扛', '' => '抗', '' => '亢', '' => '炕', '' => '考', '' => '拷', '' => '烤', '' => '靠', '' => '坷', '' => '苛', '' => '柯', '' => '棵', '' => '磕', '' => '颗', '' => '科', '' => '壳', '' => '咳', '' => '可', '' => '渴', '' => '克', '' => '刻', '' => '客', '' => '课', '' => '肯', '' => '啃', '' => '垦', '' => '恳', '' => '坑', '' => '吭', '' => '空', '' => '恐', '' => '孔', '' => '控', '' => '抠', '' => '口', '' => '扣', '' => '寇', '' => '枯', '' => '哭', '' => '窟', '' => '苦', '' => '酷', '' => '库', '' => '裤', '' => '夸', '' => '垮', '' => '挎', '' => '跨', '' => '胯', '' => '块', '' => '筷', '' => '侩', '' => '快', '' => '宽', '' => '款', '' => '匡', '' => '筐', '' => '狂', '' => '框', '' => '矿', '' => '眶', '' => '旷', '' => '况', '' => '亏', '' => '盔', '' => '岿', '' => '窥', '' => '葵', '' => '奎', '' => '魁', '' => '傀', '@' => '繞', 'A' => '繟', 'B' => '繠', 'C' => '繡', 'D' => '繢', 'E' => '繣', 'F' => '繤', 'G' => '繥', 'H' => '繦', 'I' => '繧', 'J' => '繨', 'K' => '繩', 'L' => '繪', 'M' => '繫', 'N' => '繬', 'O' => '繭', 'P' => '繮', 'Q' => '繯', 'R' => '繰', 'S' => '繱', 'T' => '繲', 'U' => '繳', 'V' => '繴', 'W' => '繵', 'X' => '繶', 'Y' => '繷', 'Z' => '繸', '[' => '繹', '\\' => '繺', ']' => '繻', '^' => '繼', '_' => '繽', '`' => '繾', 'a' => '繿', 'b' => '纀', 'c' => '纁', 'd' => '纃', 'e' => '纄', 'f' => '纅', 'g' => '纆', 'h' => '纇', 'i' => '纈', 'j' => '纉', 'k' => '纊', 'l' => '纋', 'm' => '續', 'n' => '纍', 'o' => '纎', 'p' => '纏', 'q' => '纐', 'r' => '纑', 's' => '纒', 't' => '纓', 'u' => '纔', 'v' => '纕', 'w' => '纖', 'x' => '纗', 'y' => '纘', 'z' => '纙', '{' => '纚', '|' => '纜', '}' => '纝', '~' => '纞', '' => '纮', '' => '纴', '' => '纻', '' => '纼', '' => '绖', '' => '绤', '' => '绬', '' => '绹', '' => '缊', '' => '缐', '' => '缞', '' => '缷', '' => '缹', '' => '缻', '' => '缼', '' => '缽', '' => '缾', '' => '缿', '' => '罀', '' => '罁', '' => '罃', '' => '罆', '' => '罇', '' => '罈', '' => '罉', '' => '罊', '' => '罋', '' => '罌', '' => '罍', '' => '罎', '' => '罏', '' => '罒', '' => '罓', '' => '馈', '' => '愧', '' => '溃', '' => '坤', '' => '昆', '' => '捆', '' => '困', '' => '括', '' => '扩', '' => '廓', '' => '阔', '' => '垃', '' => '拉', '' => '喇', '' => '蜡', '' => '腊', '' => '辣', '' => '啦', '' => '莱', '' => '来', '' => '赖', '' => '蓝', '' => '婪', '' => '栏', '' => '拦', '' => '篮', '' => '阑', '' => '兰', '' => '澜', '' => '谰', '' => '揽', '' => '览', '' => '懒', '' => '缆', '' => '烂', '' => '滥', '' => '琅', '' => '榔', '' => '狼', '' => '廊', '' => '郎', '' => '朗', '' => '浪', '' => '捞', '' => '劳', '' => '牢', '' => '老', '' => '佬', '' => '姥', '' => '酪', '' => '烙', '' => '涝', '' => '勒', '' => '乐', '' => '雷', '' => '镭', '' => '蕾', '' => '磊', '' => '累', '' => '儡', '' => '垒', '' => '擂', '' => '肋', '' => '类', '' => '泪', '' => '棱', '' => '楞', '' => '冷', '' => '厘', '' => '梨', '' => '犁', '' => '黎', '' => '篱', '' => '狸', '' => '离', '' => '漓', '' => '理', '' => '李', '' => '里', '' => '鲤', '' => '礼', '' => '莉', '' => '荔', '' => '吏', '' => '栗', '' => '丽', '' => '厉', '' => '励', '' => '砾', '' => '历', '' => '利', '' => '傈', '' => '例', '' => '俐', '@' => '罖', 'A' => '罙', 'B' => '罛', 'C' => '罜', 'D' => '罝', 'E' => '罞', 'F' => '罠', 'G' => '罣', 'H' => '罤', 'I' => '罥', 'J' => '罦', 'K' => '罧', 'L' => '罫', 'M' => '罬', 'N' => '罭', 'O' => '罯', 'P' => '罰', 'Q' => '罳', 'R' => '罵', 'S' => '罶', 'T' => '罷', 'U' => '罸', 'V' => '罺', 'W' => '罻', 'X' => '罼', 'Y' => '罽', 'Z' => '罿', '[' => '羀', '\\' => '羂', ']' => '羃', '^' => '羄', '_' => '羅', '`' => '羆', 'a' => '羇', 'b' => '羈', 'c' => '羉', 'd' => '羋', 'e' => '羍', 'f' => '羏', 'g' => '羐', 'h' => '羑', 'i' => '羒', 'j' => '羓', 'k' => '羕', 'l' => '羖', 'm' => '羗', 'n' => '羘', 'o' => '羙', 'p' => '羛', 'q' => '羜', 'r' => '羠', 's' => '羢', 't' => '羣', 'u' => '羥', 'v' => '羦', 'w' => '羨', 'x' => '義', 'y' => '羪', 'z' => '羫', '{' => '羬', '|' => '羭', '}' => '羮', '~' => '羱', '' => '羳', '' => '羴', '' => '羵', '' => '羶', '' => '羷', '' => '羺', '' => '羻', '' => '羾', '' => '翀', '' => '翂', '' => '翃', '' => '翄', '' => '翆', '' => '翇', '' => '翈', '' => '翉', '' => '翋', '' => '翍', '' => '翏', '' => '翐', '' => '翑', '' => '習', '' => '翓', '' => '翖', '' => '翗', '' => '翙', '' => '翚', '' => '翛', '' => '翜', '' => '翝', '' => '翞', '' => '翢', '' => '翣', '' => '痢', '' => '立', '' => '粒', '' => '沥', '' => '隶', '' => '力', '' => '璃', '' => '哩', '' => '俩', '' => '联', '' => '莲', '' => '连', '' => '镰', '' => '廉', '' => '怜', '' => '涟', '' => '帘', '' => '敛', '' => '脸', '' => '链', '' => '恋', '' => '炼', '' => '练', '' => '粮', '' => '凉', '' => '梁', '' => '粱', '' => '良', '' => '两', '' => '辆', '' => '量', '' => '晾', '' => '亮', '' => '谅', '' => '撩', '' => '聊', '' => '僚', '' => '疗', '' => '燎', '' => '寥', '' => '辽', '' => '潦', '' => '了', '' => '撂', '' => '镣', '' => '廖', '' => '料', '' => '列', '' => '裂', '' => '烈', '' => '劣', '' => '猎', '' => '琳', '' => '林', '' => '磷', '' => '霖', '' => '临', '' => '邻', '' => '鳞', '' => '淋', '' => '凛', '' => '赁', '' => '吝', '' => '拎', '' => '玲', '' => '菱', '' => '零', '' => '龄', '' => '铃', '' => '伶', '' => '羚', '' => '凌', '' => '灵', '' => '陵', '' => '岭', '' => '领', '' => '另', '' => '令', '' => '溜', '' => '琉', '' => '榴', '' => '硫', '' => '馏', '' => '留', '' => '刘', '' => '瘤', '' => '流', '' => '柳', '' => '六', '' => '龙', '' => '聋', '' => '咙', '' => '笼', '' => '窿', '@' => '翤', 'A' => '翧', 'B' => '翨', 'C' => '翪', 'D' => '翫', 'E' => '翬', 'F' => '翭', 'G' => '翯', 'H' => '翲', 'I' => '翴', 'J' => '翵', 'K' => '翶', 'L' => '翷', 'M' => '翸', 'N' => '翹', 'O' => '翺', 'P' => '翽', 'Q' => '翾', 'R' => '翿', 'S' => '耂', 'T' => '耇', 'U' => '耈', 'V' => '耉', 'W' => '耊', 'X' => '耎', 'Y' => '耏', 'Z' => '耑', '[' => '耓', '\\' => '耚', ']' => '耛', '^' => '耝', '_' => '耞', '`' => '耟', 'a' => '耡', 'b' => '耣', 'c' => '耤', 'd' => '耫', 'e' => '耬', 'f' => '耭', 'g' => '耮', 'h' => '耯', 'i' => '耰', 'j' => '耲', 'k' => '耴', 'l' => '耹', 'm' => '耺', 'n' => '耼', 'o' => '耾', 'p' => '聀', 'q' => '聁', 'r' => '聄', 's' => '聅', 't' => '聇', 'u' => '聈', 'v' => '聉', 'w' => '聎', 'x' => '聏', 'y' => '聐', 'z' => '聑', '{' => '聓', '|' => '聕', '}' => '聖', '~' => '聗', '€' => '聙', '' => '聛', '‚' => '聜', 'ƒ' => '聝', '„' => '聞', '…' => '聟', '†' => '聠', '‡' => '聡', 'ˆ' => '聢', '‰' => '聣', 'Š' => '聤', '‹' => '聥', 'Œ' => '聦', '' => '聧', 'Ž' => '聨', '' => '聫', '' => '聬', '‘' => '聭', '’' => '聮', '“' => '聯', '”' => '聰', '•' => '聲', '–' => '聳', '—' => '聴', '˜' => '聵', '™' => '聶', 'š' => '職', '›' => '聸', 'œ' => '聹', '' => '聺', 'ž' => '聻', 'Ÿ' => '聼', ' ' => '聽', '¡' => '隆', '¢' => '垄', '£' => '拢', '¤' => '陇', '¥' => '楼', '¦' => '娄', '§' => '搂', '¨' => '篓', '©' => '漏', 'ª' => '陋', '«' => '芦', '¬' => '卢', '­' => '颅', '®' => '庐', '¯' => '炉', '°' => '掳', '±' => '卤', '²' => '虏', '³' => '鲁', '´' => '麓', 'µ' => '碌', '¶' => '露', '·' => '路', '¸' => '赂', '¹' => '鹿', 'º' => '潞', '»' => '禄', '¼' => '录', '½' => '陆', '¾' => '戮', '¿' => '驴', '' => '吕', '' => '铝', '' => '侣', '' => '旅', '' => '履', '' => '屡', '' => '缕', '' => '虑', '' => '氯', '' => '律', '' => '率', '' => '滤', '' => '绿', '' => '峦', '' => '挛', '' => '孪', '' => '滦', '' => '卵', '' => '乱', '' => '掠', '' => '略', '' => '抡', '' => '轮', '' => '伦', '' => '仑', '' => '沦', '' => '纶', '' => '论', '' => '萝', '' => '螺', '' => '罗', '' => '逻', '' => '锣', '' => '箩', '' => '骡', '' => '裸', '' => '落', '' => '洛', '' => '骆', '' => '络', '' => '妈', '' => '麻', '' => '玛', '' => '码', '' => '蚂', '' => '马', '' => '骂', '' => '嘛', '' => '吗', '' => '埋', '' => '买', '' => '麦', '' => '卖', '' => '迈', '' => '脉', '' => '瞒', '' => '馒', '' => '蛮', '' => '满', '' => '蔓', '' => '曼', '' => '慢', '' => '漫', '@' => '聾', 'A' => '肁', 'B' => '肂', 'C' => '肅', 'D' => '肈', 'E' => '肊', 'F' => '肍', 'G' => '肎', 'H' => '肏', 'I' => '肐', 'J' => '肑', 'K' => '肒', 'L' => '肔', 'M' => '肕', 'N' => '肗', 'O' => '肙', 'P' => '肞', 'Q' => '肣', 'R' => '肦', 'S' => '肧', 'T' => '肨', 'U' => '肬', 'V' => '肰', 'W' => '肳', 'X' => '肵', 'Y' => '肶', 'Z' => '肸', '[' => '肹', '\\' => '肻', ']' => '胅', '^' => '胇', '_' => '胈', '`' => '胉', 'a' => '胊', 'b' => '胋', 'c' => '胏', 'd' => '胐', 'e' => '胑', 'f' => '胒', 'g' => '胓', 'h' => '胔', 'i' => '胕', 'j' => '胘', 'k' => '胟', 'l' => '胠', 'm' => '胢', 'n' => '胣', 'o' => '胦', 'p' => '胮', 'q' => '胵', 'r' => '胷', 's' => '胹', 't' => '胻', 'u' => '胾', 'v' => '胿', 'w' => '脀', 'x' => '脁', 'y' => '脃', 'z' => '脄', '{' => '脅', '|' => '脇', '}' => '脈', '~' => '脋', 'À' => '脌', 'Á' => '脕', 'Â' => '脗', 'Ã' => '脙', 'Ä' => '脛', 'Å' => '脜', 'Æ' => '脝', 'Ç' => '脟', 'È' => '脠', 'É' => '脡', 'Ê' => '脢', 'Ë' => '脣', 'Ì' => '脤', 'Í' => '脥', 'Î' => '脦', 'Ï' => '脧', 'Ð' => '脨', 'Ñ' => '脩', 'Ò' => '脪', 'Ó' => '脫', 'Ô' => '脭', 'Õ' => '脮', 'Ö' => '脰', '×' => '脳', 'Ø' => '脴', 'Ù' => '脵', 'Ú' => '脷', 'Û' => '脹', 'Ü' => '脺', 'Ý' => '脻', 'Þ' => '脼', 'ß' => '脽', 'à' => '脿', 'á' => '谩', 'â' => '芒', 'ã' => '茫', 'ä' => '盲', 'å' => '氓', 'æ' => '忙', 'ç' => '莽', 'è' => '猫', 'é' => '茅', 'ê' => '锚', 'ë' => '毛', 'ì' => '矛', 'í' => '铆', 'î' => '卯', 'ï' => '茂', 'ð' => '冒', 'ñ' => '帽', 'ò' => '貌', 'ó' => '贸', 'ô' => '么', 'õ' => '玫', 'ö' => '枚', '÷' => '梅', 'ø' => '酶', 'ù' => '霉', 'ú' => '煤', 'û' => '没', 'ü' => '眉', 'ý' => '媒', 'þ' => '镁', 'ÿ' => '每', '' => '美', '' => '昧', '' => '寐', '' => '妹', '' => '媚', '' => '门', '' => '闷', '' => '们', '' => '萌', '' => '蒙', '' => '檬', '' => '盟', '' => '锰', '' => '猛', '' => '梦', '' => '孟', '' => '眯', '' => '醚', '' => '靡', '' => '糜', '' => '迷', '' => '谜', '' => '弥', '' => '米', '' => '秘', '' => '觅', '' => '泌', '' => '蜜', '' => '密', '' => '幂', '' => '棉', '' => '眠', '' => '绵', '' => '冕', '' => '免', '' => '勉', '' => '娩', '' => '缅', '' => '面', '' => '苗', '' => '描', '' => '瞄', '' => '藐', '' => '秒', '' => '渺', '' => '庙', '' => '妙', '' => '蔑', '' => '灭', '' => '民', '' => '抿', '' => '皿', '' => '敏', '' => '悯', '' => '闽', '' => '明', '' => '螟', '' => '鸣', '' => '铭', '' => '名', '' => '命', '' => '谬', '' => '摸', '@' => '腀', 'A' => '腁', 'B' => '腂', 'C' => '腃', 'D' => '腄', 'E' => '腅', 'F' => '腇', 'G' => '腉', 'H' => '腍', 'I' => '腎', 'J' => '腏', 'K' => '腒', 'L' => '腖', 'M' => '腗', 'N' => '腘', 'O' => '腛', 'P' => '腜', 'Q' => '腝', 'R' => '腞', 'S' => '腟', 'T' => '腡', 'U' => '腢', 'V' => '腣', 'W' => '腤', 'X' => '腦', 'Y' => '腨', 'Z' => '腪', '[' => '腫', '\\' => '腬', ']' => '腯', '^' => '腲', '_' => '腳', '`' => '腵', 'a' => '腶', 'b' => '腷', 'c' => '腸', 'd' => '膁', 'e' => '膃', 'f' => '膄', 'g' => '膅', 'h' => '膆', 'i' => '膇', 'j' => '膉', 'k' => '膋', 'l' => '膌', 'm' => '膍', 'n' => '膎', 'o' => '膐', 'p' => '膒', 'q' => '膓', 'r' => '膔', 's' => '膕', 't' => '膖', 'u' => '膗', 'v' => '膙', 'w' => '膚', 'x' => '膞', 'y' => '膟', 'z' => '膠', '{' => '膡', '|' => '膢', '}' => '膤', '~' => '膥', 'Ā' => '膧', 'ā' => '膩', 'Ă' => '膫', 'ă' => '膬', 'Ą' => '膭', 'ą' => '膮', 'Ć' => '膯', 'ć' => '膰', 'Ĉ' => '膱', 'ĉ' => '膲', 'Ċ' => '膴', 'ċ' => '膵', 'Č' => '膶', 'č' => '膷', 'Ď' => '膸', 'ď' => '膹', 'Đ' => '膼', 'đ' => '膽', 'Ē' => '膾', 'ē' => '膿', 'Ĕ' => '臄', 'ĕ' => '臅', 'Ė' => '臇', 'ė' => '臈', 'Ę' => '臉', 'ę' => '臋', 'Ě' => '臍', 'ě' => '臎', 'Ĝ' => '臏', 'ĝ' => '臐', 'Ğ' => '臑', 'ğ' => '臒', 'Ġ' => '臓', 'ġ' => '摹', 'Ģ' => '蘑', 'ģ' => '模', 'Ĥ' => '膜', 'ĥ' => '磨', 'Ħ' => '摩', 'ħ' => '魔', 'Ĩ' => '抹', 'ĩ' => '末', 'Ī' => '莫', 'ī' => '墨', 'Ĭ' => '默', 'ĭ' => '沫', 'Į' => '漠', 'į' => '寞', 'İ' => '陌', 'ı' => '谋', 'IJ' => '牟', 'ij' => '某', 'Ĵ' => '拇', 'ĵ' => '牡', 'Ķ' => '亩', 'ķ' => '姆', 'ĸ' => '母', 'Ĺ' => '墓', 'ĺ' => '暮', 'Ļ' => '幕', 'ļ' => '募', 'Ľ' => '慕', 'ľ' => '木', 'Ŀ' => '目', '' => '睦', '' => '牧', '' => '穆', '' => '拿', '' => '哪', '' => '呐', '' => '钠', '' => '那', '' => '娜', '' => '纳', '' => '氖', '' => '乃', '' => '奶', '' => '耐', '' => '奈', '' => '南', '' => '男', '' => '难', '' => '囊', '' => '挠', '' => '脑', '' => '恼', '' => '闹', '' => '淖', '' => '呢', '' => '馁', '' => '内', '' => '嫩', '' => '能', '' => '妮', '' => '霓', '' => '倪', '' => '泥', '' => '尼', '' => '拟', '' => '你', '' => '匿', '' => '腻', '' => '逆', '' => '溺', '' => '蔫', '' => '拈', '' => '年', '' => '碾', '' => '撵', '' => '捻', '' => '念', '' => '娘', '' => '酿', '' => '鸟', '' => '尿', '' => '捏', '' => '聂', '' => '孽', '' => '啮', '' => '镊', '' => '镍', '' => '涅', '' => '您', '' => '柠', '' => '狞', '' => '凝', '' => '宁', '@' => '臔', 'A' => '臕', 'B' => '臖', 'C' => '臗', 'D' => '臘', 'E' => '臙', 'F' => '臚', 'G' => '臛', 'H' => '臜', 'I' => '臝', 'J' => '臞', 'K' => '臟', 'L' => '臠', 'M' => '臡', 'N' => '臢', 'O' => '臤', 'P' => '臥', 'Q' => '臦', 'R' => '臨', 'S' => '臩', 'T' => '臫', 'U' => '臮', 'V' => '臯', 'W' => '臰', 'X' => '臱', 'Y' => '臲', 'Z' => '臵', '[' => '臶', '\\' => '臷', ']' => '臸', '^' => '臹', '_' => '臺', '`' => '臽', 'a' => '臿', 'b' => '舃', 'c' => '與', 'd' => '興', 'e' => '舉', 'f' => '舊', 'g' => '舋', 'h' => '舎', 'i' => '舏', 'j' => '舑', 'k' => '舓', 'l' => '舕', 'm' => '舖', 'n' => '舗', 'o' => '舘', 'p' => '舙', 'q' => '舚', 'r' => '舝', 's' => '舠', 't' => '舤', 'u' => '舥', 'v' => '舦', 'w' => '舧', 'x' => '舩', 'y' => '舮', 'z' => '舲', '{' => '舺', '|' => '舼', '}' => '舽', '~' => '舿', 'ŀ' => '艀', 'Ł' => '艁', 'ł' => '艂', 'Ń' => '艃', 'ń' => '艅', 'Ņ' => '艆', 'ņ' => '艈', 'Ň' => '艊', 'ň' => '艌', 'ʼn' => '艍', 'Ŋ' => '艎', 'ŋ' => '艐', 'Ō' => '艑', 'ō' => '艒', 'Ŏ' => '艓', 'ŏ' => '艔', 'Ő' => '艕', 'ő' => '艖', 'Œ' => '艗', 'œ' => '艙', 'Ŕ' => '艛', 'ŕ' => '艜', 'Ŗ' => '艝', 'ŗ' => '艞', 'Ř' => '艠', 'ř' => '艡', 'Ś' => '艢', 'ś' => '艣', 'Ŝ' => '艤', 'ŝ' => '艥', 'Ş' => '艦', 'ş' => '艧', 'Š' => '艩', 'š' => '拧', 'Ţ' => '泞', 'ţ' => '牛', 'Ť' => '扭', 'ť' => '钮', 'Ŧ' => '纽', 'ŧ' => '脓', 'Ũ' => '浓', 'ũ' => '农', 'Ū' => '弄', 'ū' => '奴', 'Ŭ' => '努', 'ŭ' => '怒', 'Ů' => '女', 'ů' => '暖', 'Ű' => '虐', 'ű' => '疟', 'Ų' => '挪', 'ų' => '懦', 'Ŵ' => '糯', 'ŵ' => '诺', 'Ŷ' => '哦', 'ŷ' => '欧', 'Ÿ' => '鸥', 'Ź' => '殴', 'ź' => '藕', 'Ż' => '呕', 'ż' => '偶', 'Ž' => '沤', 'ž' => '啪', 'ſ' => '趴', '' => '爬', '' => '帕', '' => '怕', '' => '琶', '' => '拍', '' => '排', '' => '牌', '' => '徘', '' => '湃', '' => '派', '' => '攀', '' => '潘', '' => '盘', '' => '磐', '' => '盼', '' => '畔', '' => '判', '' => '叛', '' => '乓', '' => '庞', '' => '旁', '' => '耪', '' => '胖', '' => '抛', '' => '咆', '' => '刨', '' => '炮', '' => '袍', '' => '跑', '' => '泡', '' => '呸', '' => '胚', '' => '培', '' => '裴', '' => '赔', '' => '陪', '' => '配', '' => '佩', '' => '沛', '' => '喷', '' => '盆', '' => '砰', '' => '抨', '' => '烹', '' => '澎', '' => '彭', '' => '蓬', '' => '棚', '' => '硼', '' => '篷', '' => '膨', '' => '朋', '' => '鹏', '' => '捧', '' => '碰', '' => '坯', '' => '砒', '' => '霹', '' => '批', '' => '披', '' => '劈', '' => '琵', '' => '毗', '@' => '艪', 'A' => '艫', 'B' => '艬', 'C' => '艭', 'D' => '艱', 'E' => '艵', 'F' => '艶', 'G' => '艷', 'H' => '艸', 'I' => '艻', 'J' => '艼', 'K' => '芀', 'L' => '芁', 'M' => '芃', 'N' => '芅', 'O' => '芆', 'P' => '芇', 'Q' => '芉', 'R' => '芌', 'S' => '芐', 'T' => '芓', 'U' => '芔', 'V' => '芕', 'W' => '芖', 'X' => '芚', 'Y' => '芛', 'Z' => '芞', '[' => '芠', '\\' => '芢', ']' => '芣', '^' => '芧', '_' => '芲', '`' => '芵', 'a' => '芶', 'b' => '芺', 'c' => '芻', 'd' => '芼', 'e' => '芿', 'f' => '苀', 'g' => '苂', 'h' => '苃', 'i' => '苅', 'j' => '苆', 'k' => '苉', 'l' => '苐', 'm' => '苖', 'n' => '苙', 'o' => '苚', 'p' => '苝', 'q' => '苢', 'r' => '苧', 's' => '苨', 't' => '苩', 'u' => '苪', 'v' => '苬', 'w' => '苭', 'x' => '苮', 'y' => '苰', 'z' => '苲', '{' => '苳', '|' => '苵', '}' => '苶', '~' => '苸', 'ƀ' => '苺', 'Ɓ' => '苼', 'Ƃ' => '苽', 'ƃ' => '苾', 'Ƅ' => '苿', 'ƅ' => '茀', 'Ɔ' => '茊', 'Ƈ' => '茋', 'ƈ' => '茍', 'Ɖ' => '茐', 'Ɗ' => '茒', 'Ƌ' => '茓', 'ƌ' => '茖', 'ƍ' => '茘', 'Ǝ' => '茙', 'Ə' => '茝', 'Ɛ' => '茞', 'Ƒ' => '茟', 'ƒ' => '茠', 'Ɠ' => '茡', 'Ɣ' => '茢', 'ƕ' => '茣', 'Ɩ' => '茤', 'Ɨ' => '茥', 'Ƙ' => '茦', 'ƙ' => '茩', 'ƚ' => '茪', 'ƛ' => '茮', 'Ɯ' => '茰', 'Ɲ' => '茲', 'ƞ' => '茷', 'Ɵ' => '茻', 'Ơ' => '茽', 'ơ' => '啤', 'Ƣ' => '脾', 'ƣ' => '疲', 'Ƥ' => '皮', 'ƥ' => '匹', 'Ʀ' => '痞', 'Ƨ' => '僻', 'ƨ' => '屁', 'Ʃ' => '譬', 'ƪ' => '篇', 'ƫ' => '偏', 'Ƭ' => '片', 'ƭ' => '骗', 'Ʈ' => '飘', 'Ư' => '漂', 'ư' => '瓢', 'Ʊ' => '票', 'Ʋ' => '撇', 'Ƴ' => '瞥', 'ƴ' => '拼', 'Ƶ' => '频', 'ƶ' => '贫', 'Ʒ' => '品', 'Ƹ' => '聘', 'ƹ' => '乒', 'ƺ' => '坪', 'ƻ' => '苹', 'Ƽ' => '萍', 'ƽ' => '平', 'ƾ' => '凭', 'ƿ' => '瓶', '' => '评', '' => '屏', '' => '坡', '' => '泼', '' => '颇', '' => '婆', '' => '破', '' => '魄', '' => '迫', '' => '粕', '' => '剖', '' => '扑', '' => '铺', '' => '仆', '' => '莆', '' => '葡', '' => '菩', '' => '蒲', '' => '埔', '' => '朴', '' => '圃', '' => '普', '' => '浦', '' => '谱', '' => '曝', '' => '瀑', '' => '期', '' => '欺', '' => '栖', '' => '戚', '' => '妻', '' => '七', '' => '凄', '' => '漆', '' => '柒', '' => '沏', '' => '其', '' => '棋', '' => '奇', '' => '歧', '' => '畦', '' => '崎', '' => '脐', '' => '齐', '' => '旗', '' => '祈', '' => '祁', '' => '骑', '' => '起', '' => '岂', '' => '乞', '' => '企', '' => '启', '' => '契', '' => '砌', '' => '器', '' => '气', '' => '迄', '' => '弃', '' => '汽', '' => '泣', '' => '讫', '' => '掐', '@' => '茾', 'A' => '茿', 'B' => '荁', 'C' => '荂', 'D' => '荄', 'E' => '荅', 'F' => '荈', 'G' => '荊', 'H' => '荋', 'I' => '荌', 'J' => '荍', 'K' => '荎', 'L' => '荓', 'M' => '荕', 'N' => '荖', 'O' => '荗', 'P' => '荘', 'Q' => '荙', 'R' => '荝', 'S' => '荢', 'T' => '荰', 'U' => '荱', 'V' => '荲', 'W' => '荳', 'X' => '荴', 'Y' => '荵', 'Z' => '荶', '[' => '荹', '\\' => '荺', ']' => '荾', '^' => '荿', '_' => '莀', '`' => '莁', 'a' => '莂', 'b' => '莃', 'c' => '莄', 'd' => '莇', 'e' => '莈', 'f' => '莊', 'g' => '莋', 'h' => '莌', 'i' => '莍', 'j' => '莏', 'k' => '莐', 'l' => '莑', 'm' => '莔', 'n' => '莕', 'o' => '莖', 'p' => '莗', 'q' => '莙', 'r' => '莚', 's' => '莝', 't' => '莟', 'u' => '莡', 'v' => '莢', 'w' => '莣', 'x' => '莤', 'y' => '莥', 'z' => '莦', '{' => '莧', '|' => '莬', '}' => '莭', '~' => '莮', 'ǀ' => '莯', 'ǁ' => '莵', 'ǂ' => '莻', 'ǃ' => '莾', 'DŽ' => '莿', 'Dž' => '菂', 'dž' => '菃', 'LJ' => '菄', 'Lj' => '菆', 'lj' => '菈', 'NJ' => '菉', 'Nj' => '菋', 'nj' => '菍', 'Ǎ' => '菎', 'ǎ' => '菐', 'Ǐ' => '菑', 'ǐ' => '菒', 'Ǒ' => '菓', 'ǒ' => '菕', 'Ǔ' => '菗', 'ǔ' => '菙', 'Ǖ' => '菚', 'ǖ' => '菛', 'Ǘ' => '菞', 'ǘ' => '菢', 'Ǚ' => '菣', 'ǚ' => '菤', 'Ǜ' => '菦', 'ǜ' => '菧', 'ǝ' => '菨', 'Ǟ' => '菫', 'ǟ' => '菬', 'Ǡ' => '菭', 'ǡ' => '恰', 'Ǣ' => '洽', 'ǣ' => '牵', 'Ǥ' => '扦', 'ǥ' => '钎', 'Ǧ' => '铅', 'ǧ' => '千', 'Ǩ' => '迁', 'ǩ' => '签', 'Ǫ' => '仟', 'ǫ' => '谦', 'Ǭ' => '乾', 'ǭ' => '黔', 'Ǯ' => '钱', 'ǯ' => '钳', 'ǰ' => '前', 'DZ' => '潜', 'Dz' => '遣', 'dz' => '浅', 'Ǵ' => '谴', 'ǵ' => '堑', 'Ƕ' => '嵌', 'Ƿ' => '欠', 'Ǹ' => '歉', 'ǹ' => '枪', 'Ǻ' => '呛', 'ǻ' => '腔', 'Ǽ' => '羌', 'ǽ' => '墙', 'Ǿ' => '蔷', 'ǿ' => '强', '' => '抢', '' => '橇', '' => '锹', '' => '敲', '' => '悄', '' => '桥', '' => '瞧', '' => '乔', '' => '侨', '' => '巧', '' => '鞘', '' => '撬', '' => '翘', '' => '峭', '' => '俏', '' => '窍', '' => '切', '' => '茄', '' => '且', '' => '怯', '' => '窃', '' => '钦', '' => '侵', '' => '亲', '' => '秦', '' => '琴', '' => '勤', '' => '芹', '' => '擒', '' => '禽', '' => '寝', '' => '沁', '' => '青', '' => '轻', '' => '氢', '' => '倾', '' => '卿', '' => '清', '' => '擎', '' => '晴', '' => '氰', '' => '情', '' => '顷', '' => '请', '' => '庆', '' => '琼', '' => '穷', '' => '秋', '' => '丘', '' => '邱', '' => '球', '' => '求', '' => '囚', '' => '酋', '' => '泅', '' => '趋', '' => '区', '' => '蛆', '' => '曲', '' => '躯', '' => '屈', '' => '驱', '' => '渠', '@' => '菮', 'A' => '華', 'B' => '菳', 'C' => '菴', 'D' => '菵', 'E' => '菶', 'F' => '菷', 'G' => '菺', 'H' => '菻', 'I' => '菼', 'J' => '菾', 'K' => '菿', 'L' => '萀', 'M' => '萂', 'N' => '萅', 'O' => '萇', 'P' => '萈', 'Q' => '萉', 'R' => '萊', 'S' => '萐', 'T' => '萒', 'U' => '萓', 'V' => '萔', 'W' => '萕', 'X' => '萖', 'Y' => '萗', 'Z' => '萙', '[' => '萚', '\\' => '萛', ']' => '萞', '^' => '萟', '_' => '萠', '`' => '萡', 'a' => '萢', 'b' => '萣', 'c' => '萩', 'd' => '萪', 'e' => '萫', 'f' => '萬', 'g' => '萭', 'h' => '萮', 'i' => '萯', 'j' => '萰', 'k' => '萲', 'l' => '萳', 'm' => '萴', 'n' => '萵', 'o' => '萶', 'p' => '萷', 'q' => '萹', 'r' => '萺', 's' => '萻', 't' => '萾', 'u' => '萿', 'v' => '葀', 'w' => '葁', 'x' => '葂', 'y' => '葃', 'z' => '葄', '{' => '葅', '|' => '葇', '}' => '葈', '~' => '葉', 'Ȁ' => '葊', 'ȁ' => '葋', 'Ȃ' => '葌', 'ȃ' => '葍', 'Ȅ' => '葎', 'ȅ' => '葏', 'Ȇ' => '葐', 'ȇ' => '葒', 'Ȉ' => '葓', 'ȉ' => '葔', 'Ȋ' => '葕', 'ȋ' => '葖', 'Ȍ' => '葘', 'ȍ' => '葝', 'Ȏ' => '葞', 'ȏ' => '葟', 'Ȑ' => '葠', 'ȑ' => '葢', 'Ȓ' => '葤', 'ȓ' => '葥', 'Ȕ' => '葦', 'ȕ' => '葧', 'Ȗ' => '葨', 'ȗ' => '葪', 'Ș' => '葮', 'ș' => '葯', 'Ț' => '葰', 'ț' => '葲', 'Ȝ' => '葴', 'ȝ' => '葷', 'Ȟ' => '葹', 'ȟ' => '葻', 'Ƞ' => '葼', 'ȡ' => '取', 'Ȣ' => '娶', 'ȣ' => '龋', 'Ȥ' => '趣', 'ȥ' => '去', 'Ȧ' => '圈', 'ȧ' => '颧', 'Ȩ' => '权', 'ȩ' => '醛', 'Ȫ' => '泉', 'ȫ' => '全', 'Ȭ' => '痊', 'ȭ' => '拳', 'Ȯ' => '犬', 'ȯ' => '券', 'Ȱ' => '劝', 'ȱ' => '缺', 'Ȳ' => '炔', 'ȳ' => '瘸', 'ȴ' => '却', 'ȵ' => '鹊', 'ȶ' => '榷', 'ȷ' => '确', 'ȸ' => '雀', 'ȹ' => '裙', 'Ⱥ' => '群', 'Ȼ' => '然', 'ȼ' => '燃', 'Ƚ' => '冉', 'Ⱦ' => '染', 'ȿ' => '瓤', '' => '壤', '' => '攘', '' => '嚷', '' => '让', '' => '饶', '' => '扰', '' => '绕', '' => '惹', '' => '热', '' => '壬', '' => '仁', '' => '人', '' => '忍', '' => '韧', '' => '任', '' => '认', '' => '刃', '' => '妊', '' => '纫', '' => '扔', '' => '仍', '' => '日', '' => '戎', '' => '茸', '' => '蓉', '' => '荣', '' => '融', '' => '熔', '' => '溶', '' => '容', '' => '绒', '' => '冗', '' => '揉', '' => '柔', '' => '肉', '' => '茹', '' => '蠕', '' => '儒', '' => '孺', '' => '如', '' => '辱', '' => '乳', '' => '汝', '' => '入', '' => '褥', '' => '软', '' => '阮', '' => '蕊', '' => '瑞', '' => '锐', '' => '闰', '' => '润', '' => '若', '' => '弱', '' => '撒', '' => '洒', '' => '萨', '' => '腮', '' => '鳃', '' => '塞', '' => '赛', '' => '三', '' => '叁', '@' => '葽', 'A' => '葾', 'B' => '葿', 'C' => '蒀', 'D' => '蒁', 'E' => '蒃', 'F' => '蒄', 'G' => '蒅', 'H' => '蒆', 'I' => '蒊', 'J' => '蒍', 'K' => '蒏', 'L' => '蒐', 'M' => '蒑', 'N' => '蒒', 'O' => '蒓', 'P' => '蒔', 'Q' => '蒕', 'R' => '蒖', 'S' => '蒘', 'T' => '蒚', 'U' => '蒛', 'V' => '蒝', 'W' => '蒞', 'X' => '蒟', 'Y' => '蒠', 'Z' => '蒢', '[' => '蒣', '\\' => '蒤', ']' => '蒥', '^' => '蒦', '_' => '蒧', '`' => '蒨', 'a' => '蒩', 'b' => '蒪', 'c' => '蒫', 'd' => '蒬', 'e' => '蒭', 'f' => '蒮', 'g' => '蒰', 'h' => '蒱', 'i' => '蒳', 'j' => '蒵', 'k' => '蒶', 'l' => '蒷', 'm' => '蒻', 'n' => '蒼', 'o' => '蒾', 'p' => '蓀', 'q' => '蓂', 'r' => '蓃', 's' => '蓅', 't' => '蓆', 'u' => '蓇', 'v' => '蓈', 'w' => '蓋', 'x' => '蓌', 'y' => '蓎', 'z' => '蓏', '{' => '蓒', '|' => '蓔', '}' => '蓕', '~' => '蓗', 'ɀ' => '蓘', 'Ɂ' => '蓙', 'ɂ' => '蓚', 'Ƀ' => '蓛', 'Ʉ' => '蓜', 'Ʌ' => '蓞', 'Ɇ' => '蓡', 'ɇ' => '蓢', 'Ɉ' => '蓤', 'ɉ' => '蓧', 'Ɋ' => '蓨', 'ɋ' => '蓩', 'Ɍ' => '蓪', 'ɍ' => '蓫', 'Ɏ' => '蓭', 'ɏ' => '蓮', 'ɐ' => '蓯', 'ɑ' => '蓱', 'ɒ' => '蓲', 'ɓ' => '蓳', 'ɔ' => '蓴', 'ɕ' => '蓵', 'ɖ' => '蓶', 'ɗ' => '蓷', 'ɘ' => '蓸', 'ə' => '蓹', 'ɚ' => '蓺', 'ɛ' => '蓻', 'ɜ' => '蓽', 'ɝ' => '蓾', 'ɞ' => '蔀', 'ɟ' => '蔁', 'ɠ' => '蔂', 'ɡ' => '伞', 'ɢ' => '散', 'ɣ' => '桑', 'ɤ' => '嗓', 'ɥ' => '丧', 'ɦ' => '搔', 'ɧ' => '骚', 'ɨ' => '扫', 'ɩ' => '嫂', 'ɪ' => '瑟', 'ɫ' => '色', 'ɬ' => '涩', 'ɭ' => '森', 'ɮ' => '僧', 'ɯ' => '莎', 'ɰ' => '砂', 'ɱ' => '杀', 'ɲ' => '刹', 'ɳ' => '沙', 'ɴ' => '纱', 'ɵ' => '傻', 'ɶ' => '啥', 'ɷ' => '煞', 'ɸ' => '筛', 'ɹ' => '晒', 'ɺ' => '珊', 'ɻ' => '苫', 'ɼ' => '杉', 'ɽ' => '山', 'ɾ' => '删', 'ɿ' => '煽', '' => '衫', '' => '闪', '' => '陕', '' => '擅', '' => '赡', '' => '膳', '' => '善', '' => '汕', '' => '扇', '' => '缮', '' => '墒', '' => '伤', '' => '商', '' => '赏', '' => '晌', '' => '上', '' => '尚', '' => '裳', '' => '梢', '' => '捎', '' => '稍', '' => '烧', '' => '芍', '' => '勺', '' => '韶', '' => '少', '' => '哨', '' => '邵', '' => '绍', '' => '奢', '' => '赊', '' => '蛇', '' => '舌', '' => '舍', '' => '赦', '' => '摄', '' => '射', '' => '慑', '' => '涉', '' => '社', '' => '设', '' => '砷', '' => '申', '' => '呻', '' => '伸', '' => '身', '' => '深', '' => '娠', '' => '绅', '' => '神', '' => '沈', '' => '审', '' => '婶', '' => '甚', '' => '肾', '' => '慎', '' => '渗', '' => '声', '' => '生', '' => '甥', '' => '牲', '' => '升', '' => '绳', '@' => '蔃', 'A' => '蔄', 'B' => '蔅', 'C' => '蔆', 'D' => '蔇', 'E' => '蔈', 'F' => '蔉', 'G' => '蔊', 'H' => '蔋', 'I' => '蔍', 'J' => '蔎', 'K' => '蔏', 'L' => '蔐', 'M' => '蔒', 'N' => '蔔', 'O' => '蔕', 'P' => '蔖', 'Q' => '蔘', 'R' => '蔙', 'S' => '蔛', 'T' => '蔜', 'U' => '蔝', 'V' => '蔞', 'W' => '蔠', 'X' => '蔢', 'Y' => '蔣', 'Z' => '蔤', '[' => '蔥', '\\' => '蔦', ']' => '蔧', '^' => '蔨', '_' => '蔩', '`' => '蔪', 'a' => '蔭', 'b' => '蔮', 'c' => '蔯', 'd' => '蔰', 'e' => '蔱', 'f' => '蔲', 'g' => '蔳', 'h' => '蔴', 'i' => '蔵', 'j' => '蔶', 'k' => '蔾', 'l' => '蔿', 'm' => '蕀', 'n' => '蕁', 'o' => '蕂', 'p' => '蕄', 'q' => '蕅', 'r' => '蕆', 's' => '蕇', 't' => '蕋', 'u' => '蕌', 'v' => '蕍', 'w' => '蕎', 'x' => '蕏', 'y' => '蕐', 'z' => '蕑', '{' => '蕒', '|' => '蕓', '}' => '蕔', '~' => '蕕', 'ʀ' => '蕗', 'ʁ' => '蕘', 'ʂ' => '蕚', 'ʃ' => '蕛', 'ʄ' => '蕜', 'ʅ' => '蕝', 'ʆ' => '蕟', 'ʇ' => '蕠', 'ʈ' => '蕡', 'ʉ' => '蕢', 'ʊ' => '蕣', 'ʋ' => '蕥', 'ʌ' => '蕦', 'ʍ' => '蕧', 'ʎ' => '蕩', 'ʏ' => '蕪', 'ʐ' => '蕫', 'ʑ' => '蕬', 'ʒ' => '蕭', 'ʓ' => '蕮', 'ʔ' => '蕯', 'ʕ' => '蕰', 'ʖ' => '蕱', 'ʗ' => '蕳', 'ʘ' => '蕵', 'ʙ' => '蕶', 'ʚ' => '蕷', 'ʛ' => '蕸', 'ʜ' => '蕼', 'ʝ' => '蕽', 'ʞ' => '蕿', 'ʟ' => '薀', 'ʠ' => '薁', 'ʡ' => '省', 'ʢ' => '盛', 'ʣ' => '剩', 'ʤ' => '胜', 'ʥ' => '圣', 'ʦ' => '师', 'ʧ' => '失', 'ʨ' => '狮', 'ʩ' => '施', 'ʪ' => '湿', 'ʫ' => '诗', 'ʬ' => '尸', 'ʭ' => '虱', 'ʮ' => '十', 'ʯ' => '石', 'ʰ' => '拾', 'ʱ' => '时', 'ʲ' => '什', 'ʳ' => '食', 'ʴ' => '蚀', 'ʵ' => '实', 'ʶ' => '识', 'ʷ' => '史', 'ʸ' => '矢', 'ʹ' => '使', 'ʺ' => '屎', 'ʻ' => '驶', 'ʼ' => '始', 'ʽ' => '式', 'ʾ' => '示', 'ʿ' => '士', '' => '世', '' => '柿', '' => '事', '' => '拭', '' => '誓', '' => '逝', '' => '势', '' => '是', '' => '嗜', '' => '噬', '' => '适', '' => '仕', '' => '侍', '' => '释', '' => '饰', '' => '氏', '' => '市', '' => '恃', '' => '室', '' => '视', '' => '试', '' => '收', '' => '手', '' => '首', '' => '守', '' => '寿', '' => '授', '' => '售', '' => '受', '' => '瘦', '' => '兽', '' => '蔬', '' => '枢', '' => '梳', '' => '殊', '' => '抒', '' => '输', '' => '叔', '' => '舒', '' => '淑', '' => '疏', '' => '书', '' => '赎', '' => '孰', '' => '熟', '' => '薯', '' => '暑', '' => '曙', '' => '署', '' => '蜀', '' => '黍', '' => '鼠', '' => '属', '' => '术', '' => '述', '' => '树', '' => '束', '' => '戍', '' => '竖', '' => '墅', '' => '庶', '' => '数', '' => '漱', '@' => '薂', 'A' => '薃', 'B' => '薆', 'C' => '薈', 'D' => '薉', 'E' => '薊', 'F' => '薋', 'G' => '薌', 'H' => '薍', 'I' => '薎', 'J' => '薐', 'K' => '薑', 'L' => '薒', 'M' => '薓', 'N' => '薔', 'O' => '薕', 'P' => '薖', 'Q' => '薗', 'R' => '薘', 'S' => '薙', 'T' => '薚', 'U' => '薝', 'V' => '薞', 'W' => '薟', 'X' => '薠', 'Y' => '薡', 'Z' => '薢', '[' => '薣', '\\' => '薥', ']' => '薦', '^' => '薧', '_' => '薩', '`' => '薫', 'a' => '薬', 'b' => '薭', 'c' => '薱', 'd' => '薲', 'e' => '薳', 'f' => '薴', 'g' => '薵', 'h' => '薶', 'i' => '薸', 'j' => '薺', 'k' => '薻', 'l' => '薼', 'm' => '薽', 'n' => '薾', 'o' => '薿', 'p' => '藀', 'q' => '藂', 'r' => '藃', 's' => '藄', 't' => '藅', 'u' => '藆', 'v' => '藇', 'w' => '藈', 'x' => '藊', 'y' => '藋', 'z' => '藌', '{' => '藍', '|' => '藎', '}' => '藑', '~' => '藒', 'ˀ' => '藔', 'ˁ' => '藖', '˂' => '藗', '˃' => '藘', '˄' => '藙', '˅' => '藚', 'ˆ' => '藛', 'ˇ' => '藝', 'ˈ' => '藞', 'ˉ' => '藟', 'ˊ' => '藠', 'ˋ' => '藡', 'ˌ' => '藢', 'ˍ' => '藣', 'ˎ' => '藥', 'ˏ' => '藦', 'ː' => '藧', 'ˑ' => '藨', '˒' => '藪', '˓' => '藫', '˔' => '藬', '˕' => '藭', '˖' => '藮', '˗' => '藯', '˘' => '藰', '˙' => '藱', '˚' => '藲', '˛' => '藳', '˜' => '藴', '˝' => '藵', '˞' => '藶', '˟' => '藷', 'ˠ' => '藸', 'ˡ' => '恕', 'ˢ' => '刷', 'ˣ' => '耍', 'ˤ' => '摔', '˥' => '衰', '˦' => '甩', '˧' => '帅', '˨' => '栓', '˩' => '拴', '˪' => '霜', '˫' => '双', 'ˬ' => '爽', '˭' => '谁', 'ˮ' => '水', '˯' => '睡', '˰' => '税', '˱' => '吮', '˲' => '瞬', '˳' => '顺', '˴' => '舜', '˵' => '说', '˶' => '硕', '˷' => '朔', '˸' => '烁', '˹' => '斯', '˺' => '撕', '˻' => '嘶', '˼' => '思', '˽' => '私', '˾' => '司', '˿' => '丝', '' => '死', '' => '肆', '' => '寺', '' => '嗣', '' => '四', '' => '伺', '' => '似', '' => '饲', '' => '巳', '' => '松', '' => '耸', '' => '怂', '' => '颂', '' => '送', '' => '宋', '' => '讼', '' => '诵', '' => '搜', '' => '艘', '' => '擞', '' => '嗽', '' => '苏', '' => '酥', '' => '俗', '' => '素', '' => '速', '' => '粟', '' => '僳', '' => '塑', '' => '溯', '' => '宿', '' => '诉', '' => '肃', '' => '酸', '' => '蒜', '' => '算', '' => '虽', '' => '隋', '' => '随', '' => '绥', '' => '髓', '' => '碎', '' => '岁', '' => '穗', '' => '遂', '' => '隧', '' => '祟', '' => '孙', '' => '损', '' => '笋', '' => '蓑', '' => '梭', '' => '唆', '' => '缩', '' => '琐', '' => '索', '' => '锁', '' => '所', '' => '塌', '' => '他', '' => '它', '' => '她', '' => '塔', '@' => '藹', 'A' => '藺', 'B' => '藼', 'C' => '藽', 'D' => '藾', 'E' => '蘀', 'F' => '蘁', 'G' => '蘂', 'H' => '蘃', 'I' => '蘄', 'J' => '蘆', 'K' => '蘇', 'L' => '蘈', 'M' => '蘉', 'N' => '蘊', 'O' => '蘋', 'P' => '蘌', 'Q' => '蘍', 'R' => '蘎', 'S' => '蘏', 'T' => '蘐', 'U' => '蘒', 'V' => '蘓', 'W' => '蘔', 'X' => '蘕', 'Y' => '蘗', 'Z' => '蘘', '[' => '蘙', '\\' => '蘚', ']' => '蘛', '^' => '蘜', '_' => '蘝', '`' => '蘞', 'a' => '蘟', 'b' => '蘠', 'c' => '蘡', 'd' => '蘢', 'e' => '蘣', 'f' => '蘤', 'g' => '蘥', 'h' => '蘦', 'i' => '蘨', 'j' => '蘪', 'k' => '蘫', 'l' => '蘬', 'm' => '蘭', 'n' => '蘮', 'o' => '蘯', 'p' => '蘰', 'q' => '蘱', 'r' => '蘲', 's' => '蘳', 't' => '蘴', 'u' => '蘵', 'v' => '蘶', 'w' => '蘷', 'x' => '蘹', 'y' => '蘺', 'z' => '蘻', '{' => '蘽', '|' => '蘾', '}' => '蘿', '~' => '虀', '̀' => '虁', '́' => '虂', '̂' => '虃', '̃' => '虄', '̄' => '虅', '̅' => '虆', '̆' => '虇', '̇' => '虈', '̈' => '虉', '̉' => '虊', '̊' => '虋', '̋' => '虌', '̌' => '虒', '̍' => '虓', '̎' => '處', '̏' => '虖', '̐' => '虗', '̑' => '虘', '̒' => '虙', '̓' => '虛', '̔' => '虜', '̕' => '虝', '̖' => '號', '̗' => '虠', '̘' => '虡', '̙' => '虣', '̚' => '虤', '̛' => '虥', '̜' => '虦', '̝' => '虧', '̞' => '虨', '̟' => '虩', '̠' => '虪', '̡' => '獭', '̢' => '挞', '̣' => '蹋', '̤' => '踏', '̥' => '胎', '̦' => '苔', '̧' => '抬', '̨' => '台', '̩' => '泰', '̪' => '酞', '̫' => '太', '̬' => '态', '̭' => '汰', '̮' => '坍', '̯' => '摊', '̰' => '贪', '̱' => '瘫', '̲' => '滩', '̳' => '坛', '̴' => '檀', '̵' => '痰', '̶' => '潭', '̷' => '谭', '̸' => '谈', '̹' => '坦', '̺' => '毯', '̻' => '袒', '̼' => '碳', '̽' => '探', '̾' => '叹', '̿' => '炭', '' => '汤', '' => '塘', '' => '搪', '' => '堂', '' => '棠', '' => '膛', '' => '唐', '' => '糖', '' => '倘', '' => '躺', '' => '淌', '' => '趟', '' => '烫', '' => '掏', '' => '涛', '' => '滔', '' => '绦', '' => '萄', '' => '桃', '' => '逃', '' => '淘', '' => '陶', '' => '讨', '' => '套', '' => '特', '' => '藤', '' => '腾', '' => '疼', '' => '誊', '' => '梯', '' => '剔', '' => '踢', '' => '锑', '' => '提', '' => '题', '' => '蹄', '' => '啼', '' => '体', '' => '替', '' => '嚏', '' => '惕', '' => '涕', '' => '剃', '' => '屉', '' => '天', '' => '添', '' => '填', '' => '田', '' => '甜', '' => '恬', '' => '舔', '' => '腆', '' => '挑', '' => '条', '' => '迢', '' => '眺', '' => '跳', '' => '贴', '' => '铁', '' => '帖', '' => '厅', '' => '听', '' => '烃', '@' => '虭', 'A' => '虯', 'B' => '虰', 'C' => '虲', 'D' => '虳', 'E' => '虴', 'F' => '虵', 'G' => '虶', 'H' => '虷', 'I' => '虸', 'J' => '蚃', 'K' => '蚄', 'L' => '蚅', 'M' => '蚆', 'N' => '蚇', 'O' => '蚈', 'P' => '蚉', 'Q' => '蚎', 'R' => '蚏', 'S' => '蚐', 'T' => '蚑', 'U' => '蚒', 'V' => '蚔', 'W' => '蚖', 'X' => '蚗', 'Y' => '蚘', 'Z' => '蚙', '[' => '蚚', '\\' => '蚛', ']' => '蚞', '^' => '蚟', '_' => '蚠', '`' => '蚡', 'a' => '蚢', 'b' => '蚥', 'c' => '蚦', 'd' => '蚫', 'e' => '蚭', 'f' => '蚮', 'g' => '蚲', 'h' => '蚳', 'i' => '蚷', 'j' => '蚸', 'k' => '蚹', 'l' => '蚻', 'm' => '蚼', 'n' => '蚽', 'o' => '蚾', 'p' => '蚿', 'q' => '蛁', 'r' => '蛂', 's' => '蛃', 't' => '蛅', 'u' => '蛈', 'v' => '蛌', 'w' => '蛍', 'x' => '蛒', 'y' => '蛓', 'z' => '蛕', '{' => '蛖', '|' => '蛗', '}' => '蛚', '~' => '蛜', '̀' => '蛝', '́' => '蛠', '͂' => '蛡', '̓' => '蛢', '̈́' => '蛣', 'ͅ' => '蛥', '͆' => '蛦', '͇' => '蛧', '͈' => '蛨', '͉' => '蛪', '͊' => '蛫', '͋' => '蛬', '͌' => '蛯', '͍' => '蛵', '͎' => '蛶', '͏' => '蛷', '͐' => '蛺', '͑' => '蛻', '͒' => '蛼', '͓' => '蛽', '͔' => '蛿', '͕' => '蜁', '͖' => '蜄', '͗' => '蜅', '͘' => '蜆', '͙' => '蜋', '͚' => '蜌', '͛' => '蜎', '͜' => '蜏', '͝' => '蜐', '͞' => '蜑', '͟' => '蜔', '͠' => '蜖', '͡' => '汀', '͢' => '廷', 'ͣ' => '停', 'ͤ' => '亭', 'ͥ' => '庭', 'ͦ' => '挺', 'ͧ' => '艇', 'ͨ' => '通', 'ͩ' => '桐', 'ͪ' => '酮', 'ͫ' => '瞳', 'ͬ' => '同', 'ͭ' => '铜', 'ͮ' => '彤', 'ͯ' => '童', 'Ͱ' => '桶', 'ͱ' => '捅', 'Ͳ' => '筒', 'ͳ' => '统', 'ʹ' => '痛', '͵' => '偷', 'Ͷ' => '投', 'ͷ' => '头', '͸' => '透', '͹' => '凸', 'ͺ' => '秃', 'ͻ' => '突', 'ͼ' => '图', 'ͽ' => '徒', ';' => '途', 'Ϳ' => '涂', '' => '屠', '' => '土', '' => '吐', '' => '兔', '' => '湍', '' => '团', '' => '推', '' => '颓', '' => '腿', '' => '蜕', '' => '褪', '' => '退', '' => '吞', '' => '屯', '' => '臀', '' => '拖', '' => '托', '' => '脱', '' => '鸵', '' => '陀', '' => '驮', '' => '驼', '' => '椭', '' => '妥', '' => '拓', '' => '唾', '' => '挖', '' => '哇', '' => '蛙', '' => '洼', '' => '娃', '' => '瓦', '' => '袜', '' => '歪', '' => '外', '' => '豌', '' => '弯', '' => '湾', '' => '玩', '' => '顽', '' => '丸', '' => '烷', '' => '完', '' => '碗', '' => '挽', '' => '晚', '' => '皖', '' => '惋', '' => '宛', '' => '婉', '' => '万', '' => '腕', '' => '汪', '' => '王', '' => '亡', '' => '枉', '' => '网', '' => '往', '' => '旺', '' => '望', '' => '忘', '' => '妄', '' => '威', '@' => '蜙', 'A' => '蜛', 'B' => '蜝', 'C' => '蜟', 'D' => '蜠', 'E' => '蜤', 'F' => '蜦', 'G' => '蜧', 'H' => '蜨', 'I' => '蜪', 'J' => '蜫', 'K' => '蜬', 'L' => '蜭', 'M' => '蜯', 'N' => '蜰', 'O' => '蜲', 'P' => '蜳', 'Q' => '蜵', 'R' => '蜶', 'S' => '蜸', 'T' => '蜹', 'U' => '蜺', 'V' => '蜼', 'W' => '蜽', 'X' => '蝀', 'Y' => '蝁', 'Z' => '蝂', '[' => '蝃', '\\' => '蝄', ']' => '蝅', '^' => '蝆', '_' => '蝊', '`' => '蝋', 'a' => '蝍', 'b' => '蝏', 'c' => '蝐', 'd' => '蝑', 'e' => '蝒', 'f' => '蝔', 'g' => '蝕', 'h' => '蝖', 'i' => '蝘', 'j' => '蝚', 'k' => '蝛', 'l' => '蝜', 'm' => '蝝', 'n' => '蝞', 'o' => '蝟', 'p' => '蝡', 'q' => '蝢', 'r' => '蝦', 's' => '蝧', 't' => '蝨', 'u' => '蝩', 'v' => '蝪', 'w' => '蝫', 'x' => '蝬', 'y' => '蝭', 'z' => '蝯', '{' => '蝱', '|' => '蝲', '}' => '蝳', '~' => '蝵', '΀' => '蝷', '΁' => '蝸', '΂' => '蝹', '΃' => '蝺', '΄' => '蝿', '΅' => '螀', 'Ά' => '螁', '·' => '螄', 'Έ' => '螆', 'Ή' => '螇', 'Ί' => '螉', '΋' => '螊', 'Ό' => '螌', '΍' => '螎', 'Ύ' => '螏', 'Ώ' => '螐', 'ΐ' => '螑', 'Α' => '螒', 'Β' => '螔', 'Γ' => '螕', 'Δ' => '螖', 'Ε' => '螘', 'Ζ' => '螙', 'Η' => '螚', 'Θ' => '螛', 'Ι' => '螜', 'Κ' => '螝', 'Λ' => '螞', 'Μ' => '螠', 'Ν' => '螡', 'Ξ' => '螢', 'Ο' => '螣', 'Π' => '螤', 'Ρ' => '巍', '΢' => '微', 'Σ' => '危', 'Τ' => '韦', 'Υ' => '违', 'Φ' => '桅', 'Χ' => '围', 'Ψ' => '唯', 'Ω' => '惟', 'Ϊ' => '为', 'Ϋ' => '潍', 'ά' => '维', 'έ' => '苇', 'ή' => '萎', 'ί' => '委', 'ΰ' => '伟', 'α' => '伪', 'β' => '尾', 'γ' => '纬', 'δ' => '未', 'ε' => '蔚', 'ζ' => '味', 'η' => '畏', 'θ' => '胃', 'ι' => '喂', 'κ' => '魏', 'λ' => '位', 'μ' => '渭', 'ν' => '谓', 'ξ' => '尉', 'ο' => '慰', '' => '卫', '' => '瘟', '' => '温', '' => '蚊', '' => '文', '' => '闻', '' => '纹', '' => '吻', '' => '稳', '' => '紊', '' => '问', '' => '嗡', '' => '翁', '' => '瓮', '' => '挝', '' => '蜗', '' => '涡', '' => '窝', '' => '我', '' => '斡', '' => '卧', '' => '握', '' => '沃', '' => '巫', '' => '呜', '' => '钨', '' => '乌', '' => '污', '' => '诬', '' => '屋', '' => '无', '' => '芜', '' => '梧', '' => '吾', '' => '吴', '' => '毋', '' => '武', '' => '五', '' => '捂', '' => '午', '' => '舞', '' => '伍', '' => '侮', '' => '坞', '' => '戊', '' => '雾', '' => '晤', '' => '物', '' => '勿', '' => '务', '' => '悟', '' => '误', '' => '昔', '' => '熙', '' => '析', '' => '西', '' => '硒', '' => '矽', '' => '晰', '' => '嘻', '' => '吸', '' => '锡', '' => '牺', '@' => '螥', 'A' => '螦', 'B' => '螧', 'C' => '螩', 'D' => '螪', 'E' => '螮', 'F' => '螰', 'G' => '螱', 'H' => '螲', 'I' => '螴', 'J' => '螶', 'K' => '螷', 'L' => '螸', 'M' => '螹', 'N' => '螻', 'O' => '螼', 'P' => '螾', 'Q' => '螿', 'R' => '蟁', 'S' => '蟂', 'T' => '蟃', 'U' => '蟄', 'V' => '蟅', 'W' => '蟇', 'X' => '蟈', 'Y' => '蟉', 'Z' => '蟌', '[' => '蟍', '\\' => '蟎', ']' => '蟏', '^' => '蟐', '_' => '蟔', '`' => '蟕', 'a' => '蟖', 'b' => '蟗', 'c' => '蟘', 'd' => '蟙', 'e' => '蟚', 'f' => '蟜', 'g' => '蟝', 'h' => '蟞', 'i' => '蟟', 'j' => '蟡', 'k' => '蟢', 'l' => '蟣', 'm' => '蟤', 'n' => '蟦', 'o' => '蟧', 'p' => '蟨', 'q' => '蟩', 'r' => '蟫', 's' => '蟬', 't' => '蟭', 'u' => '蟯', 'v' => '蟰', 'w' => '蟱', 'x' => '蟲', 'y' => '蟳', 'z' => '蟴', '{' => '蟵', '|' => '蟶', '}' => '蟷', '~' => '蟸', 'π' => '蟺', 'ρ' => '蟻', 'ς' => '蟼', 'σ' => '蟽', 'τ' => '蟿', 'υ' => '蠀', 'φ' => '蠁', 'χ' => '蠂', 'ψ' => '蠄', 'ω' => '蠅', 'ϊ' => '蠆', 'ϋ' => '蠇', 'ό' => '蠈', 'ύ' => '蠉', 'ώ' => '蠋', 'Ϗ' => '蠌', 'ϐ' => '蠍', 'ϑ' => '蠎', 'ϒ' => '蠏', 'ϓ' => '蠐', 'ϔ' => '蠑', 'ϕ' => '蠒', 'ϖ' => '蠔', 'ϗ' => '蠗', 'Ϙ' => '蠘', 'ϙ' => '蠙', 'Ϛ' => '蠚', 'ϛ' => '蠜', 'Ϝ' => '蠝', 'ϝ' => '蠞', 'Ϟ' => '蠟', 'ϟ' => '蠠', 'Ϡ' => '蠣', 'ϡ' => '稀', 'Ϣ' => '息', 'ϣ' => '希', 'Ϥ' => '悉', 'ϥ' => '膝', 'Ϧ' => '夕', 'ϧ' => '惜', 'Ϩ' => '熄', 'ϩ' => '烯', 'Ϫ' => '溪', 'ϫ' => '汐', 'Ϭ' => '犀', 'ϭ' => '檄', 'Ϯ' => '袭', 'ϯ' => '席', 'ϰ' => '习', 'ϱ' => '媳', 'ϲ' => '喜', 'ϳ' => '铣', 'ϴ' => '洗', 'ϵ' => '系', '϶' => '隙', 'Ϸ' => '戏', 'ϸ' => '细', 'Ϲ' => '瞎', 'Ϻ' => '虾', 'ϻ' => '匣', 'ϼ' => '霞', 'Ͻ' => '辖', 'Ͼ' => '暇', 'Ͽ' => '峡', '' => '侠', '' => '狭', '' => '下', '' => '厦', '' => '夏', '' => '吓', '' => '掀', '' => '锨', '' => '先', '' => '仙', '' => '鲜', '' => '纤', '' => '咸', '' => '贤', '' => '衔', '' => '舷', '' => '闲', '' => '涎', '' => '弦', '' => '嫌', '' => '显', '' => '险', '' => '现', '' => '献', '' => '县', '' => '腺', '' => '馅', '' => '羡', '' => '宪', '' => '陷', '' => '限', '' => '线', '' => '相', '' => '厢', '' => '镶', '' => '香', '' => '箱', '' => '襄', '' => '湘', '' => '乡', '' => '翔', '' => '祥', '' => '详', '' => '想', '' => '响', '' => '享', '' => '项', '' => '巷', '' => '橡', '' => '像', '' => '向', '' => '象', '' => '萧', '' => '硝', '' => '霄', '' => '削', '' => '哮', '' => '嚣', '' => '销', '' => '消', '' => '宵', '' => '淆', '' => '晓', '@' => '蠤', 'A' => '蠥', 'B' => '蠦', 'C' => '蠧', 'D' => '蠨', 'E' => '蠩', 'F' => '蠪', 'G' => '蠫', 'H' => '蠬', 'I' => '蠭', 'J' => '蠮', 'K' => '蠯', 'L' => '蠰', 'M' => '蠱', 'N' => '蠳', 'O' => '蠴', 'P' => '蠵', 'Q' => '蠶', 'R' => '蠷', 'S' => '蠸', 'T' => '蠺', 'U' => '蠻', 'V' => '蠽', 'W' => '蠾', 'X' => '蠿', 'Y' => '衁', 'Z' => '衂', '[' => '衃', '\\' => '衆', ']' => '衇', '^' => '衈', '_' => '衉', '`' => '衊', 'a' => '衋', 'b' => '衎', 'c' => '衏', 'd' => '衐', 'e' => '衑', 'f' => '衒', 'g' => '術', 'h' => '衕', 'i' => '衖', 'j' => '衘', 'k' => '衚', 'l' => '衛', 'm' => '衜', 'n' => '衝', 'o' => '衞', 'p' => '衟', 'q' => '衠', 'r' => '衦', 's' => '衧', 't' => '衪', 'u' => '衭', 'v' => '衯', 'w' => '衱', 'x' => '衳', 'y' => '衴', 'z' => '衵', '{' => '衶', '|' => '衸', '}' => '衹', '~' => '衺', 'Ѐ' => '衻', 'Ё' => '衼', 'Ђ' => '袀', 'Ѓ' => '袃', 'Є' => '袆', 'Ѕ' => '袇', 'І' => '袉', 'Ї' => '袊', 'Ј' => '袌', 'Љ' => '袎', 'Њ' => '袏', 'Ћ' => '袐', 'Ќ' => '袑', 'Ѝ' => '袓', 'Ў' => '袔', 'Џ' => '袕', 'А' => '袗', 'Б' => '袘', 'В' => '袙', 'Г' => '袚', 'Д' => '袛', 'Е' => '袝', 'Ж' => '袞', 'З' => '袟', 'И' => '袠', 'Й' => '袡', 'К' => '袣', 'Л' => '袥', 'М' => '袦', 'Н' => '袧', 'О' => '袨', 'П' => '袩', 'Р' => '袪', 'С' => '小', 'Т' => '孝', 'У' => '校', 'Ф' => '肖', 'Х' => '啸', 'Ц' => '笑', 'Ч' => '效', 'Ш' => '楔', 'Щ' => '些', 'Ъ' => '歇', 'Ы' => '蝎', 'Ь' => '鞋', 'Э' => '协', 'Ю' => '挟', 'Я' => '携', 'а' => '邪', 'б' => '斜', 'в' => '胁', 'г' => '谐', 'д' => '写', 'е' => '械', 'ж' => '卸', 'з' => '蟹', 'и' => '懈', 'й' => '泄', 'к' => '泻', 'л' => '谢', 'м' => '屑', 'н' => '薪', 'о' => '芯', 'п' => '锌', '' => '欣', '' => '辛', '' => '新', '' => '忻', '' => '心', '' => '信', '' => '衅', '' => '星', '' => '腥', '' => '猩', '' => '惺', '' => '兴', '' => '刑', '' => '型', '' => '形', '' => '邢', '' => '行', '' => '醒', '' => '幸', '' => '杏', '' => '性', '' => '姓', '' => '兄', '' => '凶', '' => '胸', '' => '匈', '' => '汹', '' => '雄', '' => '熊', '' => '休', '' => '修', '' => '羞', '' => '朽', '' => '嗅', '' => '锈', '' => '秀', '' => '袖', '' => '绣', '' => '墟', '' => '戌', '' => '需', '' => '虚', '' => '嘘', '' => '须', '' => '徐', '' => '许', '' => '蓄', '' => '酗', '' => '叙', '' => '旭', '' => '序', '' => '畜', '' => '恤', '' => '絮', '' => '婿', '' => '绪', '' => '续', '' => '轩', '' => '喧', '' => '宣', '' => '悬', '' => '旋', '' => '玄', '@' => '袬', 'A' => '袮', 'B' => '袯', 'C' => '袰', 'D' => '袲', 'E' => '袳', 'F' => '袴', 'G' => '袵', 'H' => '袶', 'I' => '袸', 'J' => '袹', 'K' => '袺', 'L' => '袻', 'M' => '袽', 'N' => '袾', 'O' => '袿', 'P' => '裀', 'Q' => '裃', 'R' => '裄', 'S' => '裇', 'T' => '裈', 'U' => '裊', 'V' => '裋', 'W' => '裌', 'X' => '裍', 'Y' => '裏', 'Z' => '裐', '[' => '裑', '\\' => '裓', ']' => '裖', '^' => '裗', '_' => '裚', '`' => '裛', 'a' => '補', 'b' => '裝', 'c' => '裞', 'd' => '裠', 'e' => '裡', 'f' => '裦', 'g' => '裧', 'h' => '裩', 'i' => '裪', 'j' => '裫', 'k' => '裬', 'l' => '裭', 'm' => '裮', 'n' => '裯', 'o' => '裲', 'p' => '裵', 'q' => '裶', 'r' => '裷', 's' => '裺', 't' => '裻', 'u' => '製', 'v' => '裿', 'w' => '褀', 'x' => '褁', 'y' => '褃', 'z' => '褄', '{' => '褅', '|' => '褆', '}' => '複', '~' => '褈', 'р' => '褉', 'с' => '褋', 'т' => '褌', 'у' => '褍', 'ф' => '褎', 'х' => '褏', 'ц' => '褑', 'ч' => '褔', 'ш' => '褕', 'щ' => '褖', 'ъ' => '褗', 'ы' => '褘', 'ь' => '褜', 'э' => '褝', 'ю' => '褞', 'я' => '褟', 'ѐ' => '褠', 'ё' => '褢', 'ђ' => '褣', 'ѓ' => '褤', 'є' => '褦', 'ѕ' => '褧', 'і' => '褨', 'ї' => '褩', 'ј' => '褬', 'љ' => '褭', 'њ' => '褮', 'ћ' => '褯', 'ќ' => '褱', 'ѝ' => '褲', 'ў' => '褳', 'џ' => '褵', 'Ѡ' => '褷', 'ѡ' => '选', 'Ѣ' => '癣', 'ѣ' => '眩', 'Ѥ' => '绚', 'ѥ' => '靴', 'Ѧ' => '薛', 'ѧ' => '学', 'Ѩ' => '穴', 'ѩ' => '雪', 'Ѫ' => '血', 'ѫ' => '勋', 'Ѭ' => '熏', 'ѭ' => '循', 'Ѯ' => '旬', 'ѯ' => '询', 'Ѱ' => '寻', 'ѱ' => '驯', 'Ѳ' => '巡', 'ѳ' => '殉', 'Ѵ' => '汛', 'ѵ' => '训', 'Ѷ' => '讯', 'ѷ' => '逊', 'Ѹ' => '迅', 'ѹ' => '压', 'Ѻ' => '押', 'ѻ' => '鸦', 'Ѽ' => '鸭', 'ѽ' => '呀', 'Ѿ' => '丫', 'ѿ' => '芽', '' => '牙', '' => '蚜', '' => '崖', '' => '衙', '' => '涯', '' => '雅', '' => '哑', '' => '亚', '' => '讶', '' => '焉', '' => '咽', '' => '阉', '' => '烟', '' => '淹', '' => '盐', '' => '严', '' => '研', '' => '蜒', '' => '岩', '' => '延', '' => '言', '' => '颜', '' => '阎', '' => '炎', '' => '沿', '' => '奄', '' => '掩', '' => '眼', '' => '衍', '' => '演', '' => '艳', '' => '堰', '' => '燕', '' => '厌', '' => '砚', '' => '雁', '' => '唁', '' => '彦', '' => '焰', '' => '宴', '' => '谚', '' => '验', '' => '殃', '' => '央', '' => '鸯', '' => '秧', '' => '杨', '' => '扬', '' => '佯', '' => '疡', '' => '羊', '' => '洋', '' => '阳', '' => '氧', '' => '仰', '' => '痒', '' => '养', '' => '样', '' => '漾', '' => '邀', '' => '腰', '' => '妖', '' => '瑶', '@' => '褸', 'A' => '褹', 'B' => '褺', 'C' => '褻', 'D' => '褼', 'E' => '褽', 'F' => '褾', 'G' => '褿', 'H' => '襀', 'I' => '襂', 'J' => '襃', 'K' => '襅', 'L' => '襆', 'M' => '襇', 'N' => '襈', 'O' => '襉', 'P' => '襊', 'Q' => '襋', 'R' => '襌', 'S' => '襍', 'T' => '襎', 'U' => '襏', 'V' => '襐', 'W' => '襑', 'X' => '襒', 'Y' => '襓', 'Z' => '襔', '[' => '襕', '\\' => '襖', ']' => '襗', '^' => '襘', '_' => '襙', '`' => '襚', 'a' => '襛', 'b' => '襜', 'c' => '襝', 'd' => '襠', 'e' => '襡', 'f' => '襢', 'g' => '襣', 'h' => '襤', 'i' => '襥', 'j' => '襧', 'k' => '襨', 'l' => '襩', 'm' => '襪', 'n' => '襫', 'o' => '襬', 'p' => '襭', 'q' => '襮', 'r' => '襯', 's' => '襰', 't' => '襱', 'u' => '襲', 'v' => '襳', 'w' => '襴', 'x' => '襵', 'y' => '襶', 'z' => '襷', '{' => '襸', '|' => '襹', '}' => '襺', '~' => '襼', 'Ҁ' => '襽', 'ҁ' => '襾', '҂' => '覀', '҃' => '覂', '҄' => '覄', '҅' => '覅', '҆' => '覇', '҇' => '覈', '҈' => '覉', '҉' => '覊', 'Ҋ' => '見', 'ҋ' => '覌', 'Ҍ' => '覍', 'ҍ' => '覎', 'Ҏ' => '規', 'ҏ' => '覐', 'Ґ' => '覑', 'ґ' => '覒', 'Ғ' => '覓', 'ғ' => '覔', 'Ҕ' => '覕', 'ҕ' => '視', 'Җ' => '覗', 'җ' => '覘', 'Ҙ' => '覙', 'ҙ' => '覚', 'Қ' => '覛', 'қ' => '覜', 'Ҝ' => '覝', 'ҝ' => '覞', 'Ҟ' => '覟', 'ҟ' => '覠', 'Ҡ' => '覡', 'ҡ' => '摇', 'Ң' => '尧', 'ң' => '遥', 'Ҥ' => '窑', 'ҥ' => '谣', 'Ҧ' => '姚', 'ҧ' => '咬', 'Ҩ' => '舀', 'ҩ' => '药', 'Ҫ' => '要', 'ҫ' => '耀', 'Ҭ' => '椰', 'ҭ' => '噎', 'Ү' => '耶', 'ү' => '爷', 'Ұ' => '野', 'ұ' => '冶', 'Ҳ' => '也', 'ҳ' => '页', 'Ҵ' => '掖', 'ҵ' => '业', 'Ҷ' => '叶', 'ҷ' => '曳', 'Ҹ' => '腋', 'ҹ' => '夜', 'Һ' => '液', 'һ' => '一', 'Ҽ' => '壹', 'ҽ' => '医', 'Ҿ' => '揖', 'ҿ' => '铱', '' => '依', '' => '伊', '' => '衣', '' => '颐', '' => '夷', '' => '遗', '' => '移', '' => '仪', '' => '胰', '' => '疑', '' => '沂', '' => '宜', '' => '姨', '' => '彝', '' => '椅', '' => '蚁', '' => '倚', '' => '已', '' => '乙', '' => '矣', '' => '以', '' => '艺', '' => '抑', '' => '易', '' => '邑', '' => '屹', '' => '亿', '' => '役', '' => '臆', '' => '逸', '' => '肄', '' => '疫', '' => '亦', '' => '裔', '' => '意', '' => '毅', '' => '忆', '' => '义', '' => '益', '' => '溢', '' => '诣', '' => '议', '' => '谊', '' => '译', '' => '异', '' => '翼', '' => '翌', '' => '绎', '' => '茵', '' => '荫', '' => '因', '' => '殷', '' => '音', '' => '阴', '' => '姻', '' => '吟', '' => '银', '' => '淫', '' => '寅', '' => '饮', '' => '尹', '' => '引', '' => '隐', '@' => '覢', 'A' => '覣', 'B' => '覤', 'C' => '覥', 'D' => '覦', 'E' => '覧', 'F' => '覨', 'G' => '覩', 'H' => '親', 'I' => '覫', 'J' => '覬', 'K' => '覭', 'L' => '覮', 'M' => '覯', 'N' => '覰', 'O' => '覱', 'P' => '覲', 'Q' => '観', 'R' => '覴', 'S' => '覵', 'T' => '覶', 'U' => '覷', 'V' => '覸', 'W' => '覹', 'X' => '覺', 'Y' => '覻', 'Z' => '覼', '[' => '覽', '\\' => '覾', ']' => '覿', '^' => '觀', '_' => '觃', '`' => '觍', 'a' => '觓', 'b' => '觔', 'c' => '觕', 'd' => '觗', 'e' => '觘', 'f' => '觙', 'g' => '觛', 'h' => '觝', 'i' => '觟', 'j' => '觠', 'k' => '觡', 'l' => '觢', 'm' => '觤', 'n' => '觧', 'o' => '觨', 'p' => '觩', 'q' => '觪', 'r' => '觬', 's' => '觭', 't' => '觮', 'u' => '觰', 'v' => '觱', 'w' => '觲', 'x' => '觴', 'y' => '觵', 'z' => '觶', '{' => '觷', '|' => '觸', '}' => '觹', '~' => '觺', 'Ӏ' => '觻', 'Ӂ' => '觼', 'ӂ' => '觽', 'Ӄ' => '觾', 'ӄ' => '觿', 'Ӆ' => '訁', 'ӆ' => '訂', 'Ӈ' => '訃', 'ӈ' => '訄', 'Ӊ' => '訅', 'ӊ' => '訆', 'Ӌ' => '計', 'ӌ' => '訉', 'Ӎ' => '訊', 'ӎ' => '訋', 'ӏ' => '訌', 'Ӑ' => '訍', 'ӑ' => '討', 'Ӓ' => '訏', 'ӓ' => '訐', 'Ӕ' => '訑', 'ӕ' => '訒', 'Ӗ' => '訓', 'ӗ' => '訔', 'Ә' => '訕', 'ә' => '訖', 'Ӛ' => '託', 'ӛ' => '記', 'Ӝ' => '訙', 'ӝ' => '訚', 'Ӟ' => '訛', 'ӟ' => '訜', 'Ӡ' => '訝', 'ӡ' => '印', 'Ӣ' => '英', 'ӣ' => '樱', 'Ӥ' => '婴', 'ӥ' => '鹰', 'Ӧ' => '应', 'ӧ' => '缨', 'Ө' => '莹', 'ө' => '萤', 'Ӫ' => '营', 'ӫ' => '荧', 'Ӭ' => '蝇', 'ӭ' => '迎', 'Ӯ' => '赢', 'ӯ' => '盈', 'Ӱ' => '影', 'ӱ' => '颖', 'Ӳ' => '硬', 'ӳ' => '映', 'Ӵ' => '哟', 'ӵ' => '拥', 'Ӷ' => '佣', 'ӷ' => '臃', 'Ӹ' => '痈', 'ӹ' => '庸', 'Ӻ' => '雍', 'ӻ' => '踊', 'Ӽ' => '蛹', 'ӽ' => '咏', 'Ӿ' => '泳', 'ӿ' => '涌', '' => '永', '' => '恿', '' => '勇', '' => '用', '' => '幽', '' => '优', '' => '悠', '' => '忧', '' => '尤', '' => '由', '' => '邮', '' => '铀', '' => '犹', '' => '油', '' => '游', '' => '酉', '' => '有', '' => '友', '' => '右', '' => '佑', '' => '釉', '' => '诱', '' => '又', '' => '幼', '' => '迂', '' => '淤', '' => '于', '' => '盂', '' => '榆', '' => '虞', '' => '愚', '' => '舆', '' => '余', '' => '俞', '' => '逾', '' => '鱼', '' => '愉', '' => '渝', '' => '渔', '' => '隅', '' => '予', '' => '娱', '' => '雨', '' => '与', '' => '屿', '' => '禹', '' => '宇', '' => '语', '' => '羽', '' => '玉', '' => '域', '' => '芋', '' => '郁', '' => '吁', '' => '遇', '' => '喻', '' => '峪', '' => '御', '' => '愈', '' => '欲', '' => '狱', '' => '育', '' => '誉', '@' => '訞', 'A' => '訟', 'B' => '訠', 'C' => '訡', 'D' => '訢', 'E' => '訣', 'F' => '訤', 'G' => '訥', 'H' => '訦', 'I' => '訧', 'J' => '訨', 'K' => '訩', 'L' => '訪', 'M' => '訫', 'N' => '訬', 'O' => '設', 'P' => '訮', 'Q' => '訯', 'R' => '訰', 'S' => '許', 'T' => '訲', 'U' => '訳', 'V' => '訴', 'W' => '訵', 'X' => '訶', 'Y' => '訷', 'Z' => '訸', '[' => '訹', '\\' => '診', ']' => '註', '^' => '証', '_' => '訽', '`' => '訿', 'a' => '詀', 'b' => '詁', 'c' => '詂', 'd' => '詃', 'e' => '詄', 'f' => '詅', 'g' => '詆', 'h' => '詇', 'i' => '詉', 'j' => '詊', 'k' => '詋', 'l' => '詌', 'm' => '詍', 'n' => '詎', 'o' => '詏', 'p' => '詐', 'q' => '詑', 'r' => '詒', 's' => '詓', 't' => '詔', 'u' => '評', 'v' => '詖', 'w' => '詗', 'x' => '詘', 'y' => '詙', 'z' => '詚', '{' => '詛', '|' => '詜', '}' => '詝', '~' => '詞', 'Ԁ' => '詟', 'ԁ' => '詠', 'Ԃ' => '詡', 'ԃ' => '詢', 'Ԅ' => '詣', 'ԅ' => '詤', 'Ԇ' => '詥', 'ԇ' => '試', 'Ԉ' => '詧', 'ԉ' => '詨', 'Ԋ' => '詩', 'ԋ' => '詪', 'Ԍ' => '詫', 'ԍ' => '詬', 'Ԏ' => '詭', 'ԏ' => '詮', 'Ԑ' => '詯', 'ԑ' => '詰', 'Ԓ' => '話', 'ԓ' => '該', 'Ԕ' => '詳', 'ԕ' => '詴', 'Ԗ' => '詵', 'ԗ' => '詶', 'Ԙ' => '詷', 'ԙ' => '詸', 'Ԛ' => '詺', 'ԛ' => '詻', 'Ԝ' => '詼', 'ԝ' => '詽', 'Ԟ' => '詾', 'ԟ' => '詿', 'Ԡ' => '誀', 'ԡ' => '浴', 'Ԣ' => '寓', 'ԣ' => '裕', 'Ԥ' => '预', 'ԥ' => '豫', 'Ԧ' => '驭', 'ԧ' => '鸳', 'Ԩ' => '渊', 'ԩ' => '冤', 'Ԫ' => '元', 'ԫ' => '垣', 'Ԭ' => '袁', 'ԭ' => '原', 'Ԯ' => '援', 'ԯ' => '辕', '԰' => '园', 'Ա' => '员', 'Բ' => '圆', 'Գ' => '猿', 'Դ' => '源', 'Ե' => '缘', 'Զ' => '远', 'Է' => '苑', 'Ը' => '愿', 'Թ' => '怨', 'Ժ' => '院', 'Ի' => '曰', 'Լ' => '约', 'Խ' => '越', 'Ծ' => '跃', 'Կ' => '钥', '' => '岳', '' => '粤', '' => '月', '' => '悦', '' => '阅', '' => '耘', '' => '云', '' => '郧', '' => '匀', '' => '陨', '' => '允', '' => '运', '' => '蕴', '' => '酝', '' => '晕', '' => '韵', '' => '孕', '' => '匝', '' => '砸', '' => '杂', '' => '栽', '' => '哉', '' => '灾', '' => '宰', '' => '载', '' => '再', '' => '在', '' => '咱', '' => '攒', '' => '暂', '' => '赞', '' => '赃', '' => '脏', '' => '葬', '' => '遭', '' => '糟', '' => '凿', '' => '藻', '' => '枣', '' => '早', '' => '澡', '' => '蚤', '' => '躁', '' => '噪', '' => '造', '' => '皂', '' => '灶', '' => '燥', '' => '责', '' => '择', '' => '则', '' => '泽', '' => '贼', '' => '怎', '' => '增', '' => '憎', '' => '曾', '' => '赠', '' => '扎', '' => '喳', '' => '渣', '' => '札', '' => '轧', '@' => '誁', 'A' => '誂', 'B' => '誃', 'C' => '誄', 'D' => '誅', 'E' => '誆', 'F' => '誇', 'G' => '誈', 'H' => '誋', 'I' => '誌', 'J' => '認', 'K' => '誎', 'L' => '誏', 'M' => '誐', 'N' => '誑', 'O' => '誒', 'P' => '誔', 'Q' => '誕', 'R' => '誖', 'S' => '誗', 'T' => '誘', 'U' => '誙', 'V' => '誚', 'W' => '誛', 'X' => '誜', 'Y' => '誝', 'Z' => '語', '[' => '誟', '\\' => '誠', ']' => '誡', '^' => '誢', '_' => '誣', '`' => '誤', 'a' => '誥', 'b' => '誦', 'c' => '誧', 'd' => '誨', 'e' => '誩', 'f' => '說', 'g' => '誫', 'h' => '説', 'i' => '読', 'j' => '誮', 'k' => '誯', 'l' => '誰', 'm' => '誱', 'n' => '課', 'o' => '誳', 'p' => '誴', 'q' => '誵', 'r' => '誶', 's' => '誷', 't' => '誸', 'u' => '誹', 'v' => '誺', 'w' => '誻', 'x' => '誼', 'y' => '誽', 'z' => '誾', '{' => '調', '|' => '諀', '}' => '諁', '~' => '諂', 'Հ' => '諃', 'Ձ' => '諄', 'Ղ' => '諅', 'Ճ' => '諆', 'Մ' => '談', 'Յ' => '諈', 'Ն' => '諉', 'Շ' => '諊', 'Ո' => '請', 'Չ' => '諌', 'Պ' => '諍', 'Ջ' => '諎', 'Ռ' => '諏', 'Ս' => '諐', 'Վ' => '諑', 'Տ' => '諒', 'Ր' => '諓', 'Ց' => '諔', 'Ւ' => '諕', 'Փ' => '論', 'Ք' => '諗', 'Օ' => '諘', 'Ֆ' => '諙', '՗' => '諚', '՘' => '諛', 'ՙ' => '諜', '՚' => '諝', '՛' => '諞', '՜' => '諟', '՝' => '諠', '՞' => '諡', '՟' => '諢', 'ՠ' => '諣', 'ա' => '铡', 'բ' => '闸', 'գ' => '眨', 'դ' => '栅', 'ե' => '榨', 'զ' => '咋', 'է' => '乍', 'ը' => '炸', 'թ' => '诈', 'ժ' => '摘', 'ի' => '斋', 'լ' => '宅', 'խ' => '窄', 'ծ' => '债', 'կ' => '寨', 'հ' => '瞻', 'ձ' => '毡', 'ղ' => '詹', 'ճ' => '粘', 'մ' => '沾', 'յ' => '盏', 'ն' => '斩', 'շ' => '辗', 'ո' => '崭', 'չ' => '展', 'պ' => '蘸', 'ջ' => '栈', 'ռ' => '占', 'ս' => '战', 'վ' => '站', 'տ' => '湛', '' => '绽', '' => '樟', '' => '章', '' => '彰', '' => '漳', '' => '张', '' => '掌', '' => '涨', '' => '杖', '' => '丈', '' => '帐', '' => '账', '' => '仗', '' => '胀', '' => '瘴', '' => '障', '' => '招', '' => '昭', '' => '找', '' => '沼', '' => '赵', '' => '照', '' => '罩', '' => '兆', '' => '肇', '' => '召', '' => '遮', '' => '折', '' => '哲', '' => '蛰', '' => '辙', '' => '者', '' => '锗', '' => '蔗', '' => '这', '' => '浙', '' => '珍', '' => '斟', '' => '真', '' => '甄', '' => '砧', '' => '臻', '' => '贞', '' => '针', '' => '侦', '' => '枕', '' => '疹', '' => '诊', '' => '震', '' => '振', '' => '镇', '' => '阵', '' => '蒸', '' => '挣', '' => '睁', '' => '征', '' => '狰', '' => '争', '' => '怔', '' => '整', '' => '拯', '' => '正', '' => '政', '@' => '諤', 'A' => '諥', 'B' => '諦', 'C' => '諧', 'D' => '諨', 'E' => '諩', 'F' => '諪', 'G' => '諫', 'H' => '諬', 'I' => '諭', 'J' => '諮', 'K' => '諯', 'L' => '諰', 'M' => '諱', 'N' => '諲', 'O' => '諳', 'P' => '諴', 'Q' => '諵', 'R' => '諶', 'S' => '諷', 'T' => '諸', 'U' => '諹', 'V' => '諺', 'W' => '諻', 'X' => '諼', 'Y' => '諽', 'Z' => '諾', '[' => '諿', '\\' => '謀', ']' => '謁', '^' => '謂', '_' => '謃', '`' => '謄', 'a' => '謅', 'b' => '謆', 'c' => '謈', 'd' => '謉', 'e' => '謊', 'f' => '謋', 'g' => '謌', 'h' => '謍', 'i' => '謎', 'j' => '謏', 'k' => '謐', 'l' => '謑', 'm' => '謒', 'n' => '謓', 'o' => '謔', 'p' => '謕', 'q' => '謖', 'r' => '謗', 's' => '謘', 't' => '謙', 'u' => '謚', 'v' => '講', 'w' => '謜', 'x' => '謝', 'y' => '謞', 'z' => '謟', '{' => '謠', '|' => '謡', '}' => '謢', '~' => '謣', 'ր' => '謤', 'ց' => '謥', 'ւ' => '謧', 'փ' => '謨', 'ք' => '謩', 'օ' => '謪', 'ֆ' => '謫', 'և' => '謬', 'ֈ' => '謭', '։' => '謮', '֊' => '謯', '֋' => '謰', '֌' => '謱', '֍' => '謲', '֎' => '謳', '֏' => '謴', '֐' => '謵', '֑' => '謶', '֒' => '謷', '֓' => '謸', '֔' => '謹', '֕' => '謺', '֖' => '謻', '֗' => '謼', '֘' => '謽', '֙' => '謾', '֚' => '謿', '֛' => '譀', '֜' => '譁', '֝' => '譂', '֞' => '譃', '֟' => '譄', '֠' => '譅', '֡' => '帧', '֢' => '症', '֣' => '郑', '֤' => '证', '֥' => '芝', '֦' => '枝', '֧' => '支', '֨' => '吱', '֩' => '蜘', '֪' => '知', '֫' => '肢', '֬' => '脂', '֭' => '汁', '֮' => '之', '֯' => '织', 'ְ' => '职', 'ֱ' => '直', 'ֲ' => '植', 'ֳ' => '殖', 'ִ' => '执', 'ֵ' => '值', 'ֶ' => '侄', 'ַ' => '址', 'ָ' => '指', 'ֹ' => '止', 'ֺ' => '趾', 'ֻ' => '只', 'ּ' => '旨', 'ֽ' => '纸', '־' => '志', 'ֿ' => '挚', '' => '掷', '' => '至', '' => '致', '' => '置', '' => '帜', '' => '峙', '' => '制', '' => '智', '' => '秩', '' => '稚', '' => '质', '' => '炙', '' => '痔', '' => '滞', '' => '治', '' => '窒', '' => '中', '' => '盅', '' => '忠', '' => '钟', '' => '衷', '' => '终', '' => '种', '' => '肿', '' => '重', '' => '仲', '' => '众', '' => '舟', '' => '周', '' => '州', '' => '洲', '' => '诌', '' => '粥', '' => '轴', '' => '肘', '' => '帚', '' => '咒', '' => '皱', '' => '宙', '' => '昼', '' => '骤', '' => '珠', '' => '株', '' => '蛛', '' => '朱', '' => '猪', '' => '诸', '' => '诛', '' => '逐', '' => '竹', '' => '烛', '' => '煮', '' => '拄', '' => '瞩', '' => '嘱', '' => '主', '' => '著', '' => '柱', '' => '助', '' => '蛀', '' => '贮', '' => '铸', '' => '筑', '@' => '譆', 'A' => '譇', 'B' => '譈', 'C' => '證', 'D' => '譊', 'E' => '譋', 'F' => '譌', 'G' => '譍', 'H' => '譎', 'I' => '譏', 'J' => '譐', 'K' => '譑', 'L' => '譒', 'M' => '譓', 'N' => '譔', 'O' => '譕', 'P' => '譖', 'Q' => '譗', 'R' => '識', 'S' => '譙', 'T' => '譚', 'U' => '譛', 'V' => '譜', 'W' => '譝', 'X' => '譞', 'Y' => '譟', 'Z' => '譠', '[' => '譡', '\\' => '譢', ']' => '譣', '^' => '譤', '_' => '譥', '`' => '譧', 'a' => '譨', 'b' => '譩', 'c' => '譪', 'd' => '譫', 'e' => '譭', 'f' => '譮', 'g' => '譯', 'h' => '議', 'i' => '譱', 'j' => '譲', 'k' => '譳', 'l' => '譴', 'm' => '譵', 'n' => '譶', 'o' => '護', 'p' => '譸', 'q' => '譹', 'r' => '譺', 's' => '譻', 't' => '譼', 'u' => '譽', 'v' => '譾', 'w' => '譿', 'x' => '讀', 'y' => '讁', 'z' => '讂', '{' => '讃', '|' => '讄', '}' => '讅', '~' => '讆', '׀' => '讇', 'ׁ' => '讈', 'ׂ' => '讉', '׃' => '變', 'ׄ' => '讋', 'ׅ' => '讌', '׆' => '讍', 'ׇ' => '讎', '׈' => '讏', '׉' => '讐', '׊' => '讑', '׋' => '讒', '׌' => '讓', '׍' => '讔', '׎' => '讕', '׏' => '讖', 'א' => '讗', 'ב' => '讘', 'ג' => '讙', 'ד' => '讚', 'ה' => '讛', 'ו' => '讜', 'ז' => '讝', 'ח' => '讞', 'ט' => '讟', 'י' => '讬', 'ך' => '讱', 'כ' => '讻', 'ל' => '诇', 'ם' => '诐', 'מ' => '诪', 'ן' => '谉', 'נ' => '谞', 'ס' => '住', 'ע' => '注', 'ף' => '祝', 'פ' => '驻', 'ץ' => '抓', 'צ' => '爪', 'ק' => '拽', 'ר' => '专', 'ש' => '砖', 'ת' => '转', '׫' => '撰', '׬' => '赚', '׭' => '篆', '׮' => '桩', 'ׯ' => '庄', 'װ' => '装', 'ױ' => '妆', 'ײ' => '撞', '׳' => '壮', '״' => '状', '׵' => '椎', '׶' => '锥', '׷' => '追', '׸' => '赘', '׹' => '坠', '׺' => '缀', '׻' => '谆', '׼' => '准', '׽' => '捉', '׾' => '拙', '׿' => '卓', '' => '桌', '' => '琢', '' => '茁', '' => '酌', '' => '啄', '' => '着', '' => '灼', '' => '浊', '' => '兹', '' => '咨', '' => '资', '' => '姿', '' => '滋', '' => '淄', '' => '孜', '' => '紫', '' => '仔', '' => '籽', '' => '滓', '' => '子', '' => '自', '' => '渍', '' => '字', '' => '鬃', '' => '棕', '' => '踪', '' => '宗', '' => '综', '' => '总', '' => '纵', '' => '邹', '' => '走', '' => '奏', '' => '揍', '' => '租', '' => '足', '' => '卒', '' => '族', '' => '祖', '' => '诅', '' => '阻', '' => '组', '' => '钻', '' => '纂', '' => '嘴', '' => '醉', '' => '最', '' => '罪', '' => '尊', '' => '遵', '' => '昨', '' => '左', '' => '佐', '' => '柞', '' => '做', '' => '作', '' => '坐', '' => '座', '@' => '谸', 'A' => '谹', 'B' => '谺', 'C' => '谻', 'D' => '谼', 'E' => '谽', 'F' => '谾', 'G' => '谿', 'H' => '豀', 'I' => '豂', 'J' => '豃', 'K' => '豄', 'L' => '豅', 'M' => '豈', 'N' => '豊', 'O' => '豋', 'P' => '豍', 'Q' => '豎', 'R' => '豏', 'S' => '豐', 'T' => '豑', 'U' => '豒', 'V' => '豓', 'W' => '豔', 'X' => '豖', 'Y' => '豗', 'Z' => '豘', '[' => '豙', '\\' => '豛', ']' => '豜', '^' => '豝', '_' => '豞', '`' => '豟', 'a' => '豠', 'b' => '豣', 'c' => '豤', 'd' => '豥', 'e' => '豦', 'f' => '豧', 'g' => '豨', 'h' => '豩', 'i' => '豬', 'j' => '豭', 'k' => '豮', 'l' => '豯', 'm' => '豰', 'n' => '豱', 'o' => '豲', 'p' => '豴', 'q' => '豵', 'r' => '豶', 's' => '豷', 't' => '豻', 'u' => '豼', 'v' => '豽', 'w' => '豾', 'x' => '豿', 'y' => '貀', 'z' => '貁', '{' => '貃', '|' => '貄', '}' => '貆', '~' => '貇', '؀' => '貈', '؁' => '貋', '؂' => '貍', '؃' => '貎', '؄' => '貏', '؅' => '貐', '؆' => '貑', '؇' => '貒', '؈' => '貓', '؉' => '貕', '؊' => '貖', '؋' => '貗', '،' => '貙', '؍' => '貚', '؎' => '貛', '؏' => '貜', 'ؐ' => '貝', 'ؑ' => '貞', 'ؒ' => '貟', 'ؓ' => '負', 'ؔ' => '財', 'ؕ' => '貢', 'ؖ' => '貣', 'ؗ' => '貤', 'ؘ' => '貥', 'ؙ' => '貦', 'ؚ' => '貧', '؛' => '貨', '؜' => '販', '؝' => '貪', '؞' => '貫', '؟' => '責', 'ؠ' => '貭', 'ء' => '亍', 'آ' => '丌', 'أ' => '兀', 'ؤ' => '丐', 'إ' => '廿', 'ئ' => '卅', 'ا' => '丕', 'ب' => '亘', 'ة' => '丞', 'ت' => '鬲', 'ث' => '孬', 'ج' => '噩', 'ح' => '丨', 'خ' => '禺', 'د' => '丿', 'ذ' => '匕', 'ر' => '乇', 'ز' => '夭', 'س' => '爻', 'ش' => '卮', 'ص' => '氐', 'ض' => '囟', 'ط' => '胤', 'ظ' => '馗', 'ع' => '毓', 'غ' => '睾', 'ػ' => '鼗', 'ؼ' => '丶', 'ؽ' => '亟', 'ؾ' => '鼐', 'ؿ' => '乜', '' => '乩', '' => '亓', '' => '芈', '' => '孛', '' => '啬', '' => '嘏', '' => '仄', '' => '厍', '' => '厝', '' => '厣', '' => '厥', '' => '厮', '' => '靥', '' => '赝', '' => '匚', '' => '叵', '' => '匦', '' => '匮', '' => '匾', '' => '赜', '' => '卦', '' => '卣', '' => '刂', '' => '刈', '' => '刎', '' => '刭', '' => '刳', '' => '刿', '' => '剀', '' => '剌', '' => '剞', '' => '剡', '' => '剜', '' => '蒯', '' => '剽', '' => '劂', '' => '劁', '' => '劐', '' => '劓', '' => '冂', '' => '罔', '' => '亻', '' => '仃', '' => '仉', '' => '仂', '' => '仨', '' => '仡', '' => '仫', '' => '仞', '' => '伛', '' => '仳', '' => '伢', '' => '佤', '' => '仵', '' => '伥', '' => '伧', '' => '伉', '' => '伫', '' => '佞', '' => '佧', '' => '攸', '' => '佚', '' => '佝', '@' => '貮', 'A' => '貯', 'B' => '貰', 'C' => '貱', 'D' => '貲', 'E' => '貳', 'F' => '貴', 'G' => '貵', 'H' => '貶', 'I' => '買', 'J' => '貸', 'K' => '貹', 'L' => '貺', 'M' => '費', 'N' => '貼', 'O' => '貽', 'P' => '貾', 'Q' => '貿', 'R' => '賀', 'S' => '賁', 'T' => '賂', 'U' => '賃', 'V' => '賄', 'W' => '賅', 'X' => '賆', 'Y' => '資', 'Z' => '賈', '[' => '賉', '\\' => '賊', ']' => '賋', '^' => '賌', '_' => '賍', '`' => '賎', 'a' => '賏', 'b' => '賐', 'c' => '賑', 'd' => '賒', 'e' => '賓', 'f' => '賔', 'g' => '賕', 'h' => '賖', 'i' => '賗', 'j' => '賘', 'k' => '賙', 'l' => '賚', 'm' => '賛', 'n' => '賜', 'o' => '賝', 'p' => '賞', 'q' => '賟', 'r' => '賠', 's' => '賡', 't' => '賢', 'u' => '賣', 'v' => '賤', 'w' => '賥', 'x' => '賦', 'y' => '賧', 'z' => '賨', '{' => '賩', '|' => '質', '}' => '賫', '~' => '賬', 'ـ' => '賭', 'ف' => '賮', 'ق' => '賯', 'ك' => '賰', 'ل' => '賱', 'م' => '賲', 'ن' => '賳', 'ه' => '賴', 'و' => '賵', 'ى' => '賶', 'ي' => '賷', 'ً' => '賸', 'ٌ' => '賹', 'ٍ' => '賺', 'َ' => '賻', 'ُ' => '購', 'ِ' => '賽', 'ّ' => '賾', 'ْ' => '賿', 'ٓ' => '贀', 'ٔ' => '贁', 'ٕ' => '贂', 'ٖ' => '贃', 'ٗ' => '贄', '٘' => '贅', 'ٙ' => '贆', 'ٚ' => '贇', 'ٛ' => '贈', 'ٜ' => '贉', 'ٝ' => '贊', 'ٞ' => '贋', 'ٟ' => '贌', '٠' => '贍', '١' => '佟', '٢' => '佗', '٣' => '伲', '٤' => '伽', '٥' => '佶', '٦' => '佴', '٧' => '侑', '٨' => '侉', '٩' => '侃', '٪' => '侏', '٫' => '佾', '٬' => '佻', '٭' => '侪', 'ٮ' => '佼', 'ٯ' => '侬', 'ٰ' => '侔', 'ٱ' => '俦', 'ٲ' => '俨', 'ٳ' => '俪', 'ٴ' => '俅', 'ٵ' => '俚', 'ٶ' => '俣', 'ٷ' => '俜', 'ٸ' => '俑', 'ٹ' => '俟', 'ٺ' => '俸', 'ٻ' => '倩', 'ټ' => '偌', 'ٽ' => '俳', 'پ' => '倬', 'ٿ' => '倏', '' => '倮', '' => '倭', '' => '俾', '' => '倜', '' => '倌', '' => '倥', '' => '倨', '' => '偾', '' => '偃', '' => '偕', '' => '偈', '' => '偎', '' => '偬', '' => '偻', '' => '傥', '' => '傧', '' => '傩', '' => '傺', '' => '僖', '' => '儆', '' => '僭', '' => '僬', '' => '僦', '' => '僮', '' => '儇', '' => '儋', '' => '仝', '' => '氽', '' => '佘', '' => '佥', '' => '俎', '' => '龠', '' => '汆', '' => '籴', '' => '兮', '' => '巽', '' => '黉', '' => '馘', '' => '冁', '' => '夔', '' => '勹', '' => '匍', '' => '訇', '' => '匐', '' => '凫', '' => '夙', '' => '兕', '' => '亠', '' => '兖', '' => '亳', '' => '衮', '' => '袤', '' => '亵', '' => '脔', '' => '裒', '' => '禀', '' => '嬴', '' => '蠃', '' => '羸', '' => '冫', '' => '冱', '' => '冽', '' => '冼', '@' => '贎', 'A' => '贏', 'B' => '贐', 'C' => '贑', 'D' => '贒', 'E' => '贓', 'F' => '贔', 'G' => '贕', 'H' => '贖', 'I' => '贗', 'J' => '贘', 'K' => '贙', 'L' => '贚', 'M' => '贛', 'N' => '贜', 'O' => '贠', 'P' => '赑', 'Q' => '赒', 'R' => '赗', 'S' => '赟', 'T' => '赥', 'U' => '赨', 'V' => '赩', 'W' => '赪', 'X' => '赬', 'Y' => '赮', 'Z' => '赯', '[' => '赱', '\\' => '赲', ']' => '赸', '^' => '赹', '_' => '赺', '`' => '赻', 'a' => '赼', 'b' => '赽', 'c' => '赾', 'd' => '赿', 'e' => '趀', 'f' => '趂', 'g' => '趃', 'h' => '趆', 'i' => '趇', 'j' => '趈', 'k' => '趉', 'l' => '趌', 'm' => '趍', 'n' => '趎', 'o' => '趏', 'p' => '趐', 'q' => '趒', 'r' => '趓', 's' => '趕', 't' => '趖', 'u' => '趗', 'v' => '趘', 'w' => '趙', 'x' => '趚', 'y' => '趛', 'z' => '趜', '{' => '趝', '|' => '趞', '}' => '趠', '~' => '趡', 'ڀ' => '趢', 'ځ' => '趤', 'ڂ' => '趥', 'ڃ' => '趦', 'ڄ' => '趧', 'څ' => '趨', 'چ' => '趩', 'ڇ' => '趪', 'ڈ' => '趫', 'ډ' => '趬', 'ڊ' => '趭', 'ڋ' => '趮', 'ڌ' => '趯', 'ڍ' => '趰', 'ڎ' => '趲', 'ڏ' => '趶', 'ڐ' => '趷', 'ڑ' => '趹', 'ڒ' => '趻', 'ړ' => '趽', 'ڔ' => '跀', 'ڕ' => '跁', 'ږ' => '跂', 'ڗ' => '跅', 'ژ' => '跇', 'ڙ' => '跈', 'ښ' => '跉', 'ڛ' => '跊', 'ڜ' => '跍', 'ڝ' => '跐', 'ڞ' => '跒', 'ڟ' => '跓', 'ڠ' => '跔', 'ڡ' => '凇', 'ڢ' => '冖', 'ڣ' => '冢', 'ڤ' => '冥', 'ڥ' => '讠', 'ڦ' => '讦', 'ڧ' => '讧', 'ڨ' => '讪', 'ک' => '讴', 'ڪ' => '讵', 'ګ' => '讷', 'ڬ' => '诂', 'ڭ' => '诃', 'ڮ' => '诋', 'گ' => '诏', 'ڰ' => '诎', 'ڱ' => '诒', 'ڲ' => '诓', 'ڳ' => '诔', 'ڴ' => '诖', 'ڵ' => '诘', 'ڶ' => '诙', 'ڷ' => '诜', 'ڸ' => '诟', 'ڹ' => '诠', 'ں' => '诤', 'ڻ' => '诨', 'ڼ' => '诩', 'ڽ' => '诮', 'ھ' => '诰', 'ڿ' => '诳', '' => '诶', '' => '诹', '' => '诼', '' => '诿', '' => '谀', '' => '谂', '' => '谄', '' => '谇', '' => '谌', '' => '谏', '' => '谑', '' => '谒', '' => '谔', '' => '谕', '' => '谖', '' => '谙', '' => '谛', '' => '谘', '' => '谝', '' => '谟', '' => '谠', '' => '谡', '' => '谥', '' => '谧', '' => '谪', '' => '谫', '' => '谮', '' => '谯', '' => '谲', '' => '谳', '' => '谵', '' => '谶', '' => '卩', '' => '卺', '' => '阝', '' => '阢', '' => '阡', '' => '阱', '' => '阪', '' => '阽', '' => '阼', '' => '陂', '' => '陉', '' => '陔', '' => '陟', '' => '陧', '' => '陬', '' => '陲', '' => '陴', '' => '隈', '' => '隍', '' => '隗', '' => '隰', '' => '邗', '' => '邛', '' => '邝', '' => '邙', '' => '邬', '' => '邡', '' => '邴', '' => '邳', '' => '邶', '' => '邺', '@' => '跕', 'A' => '跘', 'B' => '跙', 'C' => '跜', 'D' => '跠', 'E' => '跡', 'F' => '跢', 'G' => '跥', 'H' => '跦', 'I' => '跧', 'J' => '跩', 'K' => '跭', 'L' => '跮', 'M' => '跰', 'N' => '跱', 'O' => '跲', 'P' => '跴', 'Q' => '跶', 'R' => '跼', 'S' => '跾', 'T' => '跿', 'U' => '踀', 'V' => '踁', 'W' => '踂', 'X' => '踃', 'Y' => '踄', 'Z' => '踆', '[' => '踇', '\\' => '踈', ']' => '踋', '^' => '踍', '_' => '踎', '`' => '踐', 'a' => '踑', 'b' => '踒', 'c' => '踓', 'd' => '踕', 'e' => '踖', 'f' => '踗', 'g' => '踘', 'h' => '踙', 'i' => '踚', 'j' => '踛', 'k' => '踜', 'l' => '踠', 'm' => '踡', 'n' => '踤', 'o' => '踥', 'p' => '踦', 'q' => '踧', 'r' => '踨', 's' => '踫', 't' => '踭', 'u' => '踰', 'v' => '踲', 'w' => '踳', 'x' => '踴', 'y' => '踶', 'z' => '踷', '{' => '踸', '|' => '踻', '}' => '踼', '~' => '踾', 'ۀ' => '踿', 'ہ' => '蹃', 'ۂ' => '蹅', 'ۃ' => '蹆', 'ۄ' => '蹌', 'ۅ' => '蹍', 'ۆ' => '蹎', 'ۇ' => '蹏', 'ۈ' => '蹐', 'ۉ' => '蹓', 'ۊ' => '蹔', 'ۋ' => '蹕', 'ی' => '蹖', 'ۍ' => '蹗', 'ێ' => '蹘', 'ۏ' => '蹚', 'ې' => '蹛', 'ۑ' => '蹜', 'ے' => '蹝', 'ۓ' => '蹞', '۔' => '蹟', 'ە' => '蹠', 'ۖ' => '蹡', 'ۗ' => '蹢', 'ۘ' => '蹣', 'ۙ' => '蹤', 'ۚ' => '蹥', 'ۛ' => '蹧', 'ۜ' => '蹨', '۝' => '蹪', '۞' => '蹫', '۟' => '蹮', '۠' => '蹱', 'ۡ' => '邸', 'ۢ' => '邰', 'ۣ' => '郏', 'ۤ' => '郅', 'ۥ' => '邾', 'ۦ' => '郐', 'ۧ' => '郄', 'ۨ' => '郇', '۩' => '郓', '۪' => '郦', '۫' => '郢', '۬' => '郜', 'ۭ' => '郗', 'ۮ' => '郛', 'ۯ' => '郫', '۰' => '郯', '۱' => '郾', '۲' => '鄄', '۳' => '鄢', '۴' => '鄞', '۵' => '鄣', '۶' => '鄱', '۷' => '鄯', '۸' => '鄹', '۹' => '酃', 'ۺ' => '酆', 'ۻ' => '刍', 'ۼ' => '奂', '۽' => '劢', '۾' => '劬', 'ۿ' => '劭', '' => '劾', '' => '哿', '' => '勐', '' => '勖', '' => '勰', '' => '叟', '' => '燮', '' => '矍', '' => '廴', '' => '凵', '' => '凼', '' => '鬯', '' => '厶', '' => '弁', '' => '畚', '' => '巯', '' => '坌', '' => '垩', '' => '垡', '' => '塾', '' => '墼', '' => '壅', '' => '壑', '' => '圩', '' => '圬', '' => '圪', '' => '圳', '' => '圹', '' => '圮', '' => '圯', '' => '坜', '' => '圻', '' => '坂', '' => '坩', '' => '垅', '' => '坫', '' => '垆', '' => '坼', '' => '坻', '' => '坨', '' => '坭', '' => '坶', '' => '坳', '' => '垭', '' => '垤', '' => '垌', '' => '垲', '' => '埏', '' => '垧', '' => '垴', '' => '垓', '' => '垠', '' => '埕', '' => '埘', '' => '埚', '' => '埙', '' => '埒', '' => '垸', '' => '埴', '' => '埯', '' => '埸', '' => '埤', '' => '埝', '@' => '蹳', 'A' => '蹵', 'B' => '蹷', 'C' => '蹸', 'D' => '蹹', 'E' => '蹺', 'F' => '蹻', 'G' => '蹽', 'H' => '蹾', 'I' => '躀', 'J' => '躂', 'K' => '躃', 'L' => '躄', 'M' => '躆', 'N' => '躈', 'O' => '躉', 'P' => '躊', 'Q' => '躋', 'R' => '躌', 'S' => '躍', 'T' => '躎', 'U' => '躑', 'V' => '躒', 'W' => '躓', 'X' => '躕', 'Y' => '躖', 'Z' => '躗', '[' => '躘', '\\' => '躙', ']' => '躚', '^' => '躛', '_' => '躝', '`' => '躟', 'a' => '躠', 'b' => '躡', 'c' => '躢', 'd' => '躣', 'e' => '躤', 'f' => '躥', 'g' => '躦', 'h' => '躧', 'i' => '躨', 'j' => '躩', 'k' => '躪', 'l' => '躭', 'm' => '躮', 'n' => '躰', 'o' => '躱', 'p' => '躳', 'q' => '躴', 'r' => '躵', 's' => '躶', 't' => '躷', 'u' => '躸', 'v' => '躹', 'w' => '躻', 'x' => '躼', 'y' => '躽', 'z' => '躾', '{' => '躿', '|' => '軀', '}' => '軁', '~' => '軂', '܀' => '軃', '܁' => '軄', '܂' => '軅', '܃' => '軆', '܄' => '軇', '܅' => '軈', '܆' => '軉', '܇' => '車', '܈' => '軋', '܉' => '軌', '܊' => '軍', '܋' => '軏', '܌' => '軐', '܍' => '軑', '܎' => '軒', '܏' => '軓', 'ܐ' => '軔', 'ܑ' => '軕', 'ܒ' => '軖', 'ܓ' => '軗', 'ܔ' => '軘', 'ܕ' => '軙', 'ܖ' => '軚', 'ܗ' => '軛', 'ܘ' => '軜', 'ܙ' => '軝', 'ܚ' => '軞', 'ܛ' => '軟', 'ܜ' => '軠', 'ܝ' => '軡', 'ܞ' => '転', 'ܟ' => '軣', 'ܠ' => '軤', 'ܡ' => '堋', 'ܢ' => '堍', 'ܣ' => '埽', 'ܤ' => '埭', 'ܥ' => '堀', 'ܦ' => '堞', 'ܧ' => '堙', 'ܨ' => '塄', 'ܩ' => '堠', 'ܪ' => '塥', 'ܫ' => '塬', 'ܬ' => '墁', 'ܭ' => '墉', 'ܮ' => '墚', 'ܯ' => '墀', 'ܰ' => '馨', 'ܱ' => '鼙', 'ܲ' => '懿', 'ܳ' => '艹', 'ܴ' => '艽', 'ܵ' => '艿', 'ܶ' => '芏', 'ܷ' => '芊', 'ܸ' => '芨', 'ܹ' => '芄', 'ܺ' => '芎', 'ܻ' => '芑', 'ܼ' => '芗', 'ܽ' => '芙', 'ܾ' => '芫', 'ܿ' => '芸', '' => '芾', '' => '芰', '' => '苈', '' => '苊', '' => '苣', '' => '芘', '' => '芷', '' => '芮', '' => '苋', '' => '苌', '' => '苁', '' => '芩', '' => '芴', '' => '芡', '' => '芪', '' => '芟', '' => '苄', '' => '苎', '' => '芤', '' => '苡', '' => '茉', '' => '苷', '' => '苤', '' => '茏', '' => '茇', '' => '苜', '' => '苴', '' => '苒', '' => '苘', '' => '茌', '' => '苻', '' => '苓', '' => '茑', '' => '茚', '' => '茆', '' => '茔', '' => '茕', '' => '苠', '' => '苕', '' => '茜', '' => '荑', '' => '荛', '' => '荜', '' => '茈', '' => '莒', '' => '茼', '' => '茴', '' => '茱', '' => '莛', '' => '荞', '' => '茯', '' => '荏', '' => '荇', '' => '荃', '' => '荟', '' => '荀', '' => '茗', '' => '荠', '' => '茭', '' => '茺', '' => '茳', '' => '荦', '' => '荥', '@' => '軥', 'A' => '軦', 'B' => '軧', 'C' => '軨', 'D' => '軩', 'E' => '軪', 'F' => '軫', 'G' => '軬', 'H' => '軭', 'I' => '軮', 'J' => '軯', 'K' => '軰', 'L' => '軱', 'M' => '軲', 'N' => '軳', 'O' => '軴', 'P' => '軵', 'Q' => '軶', 'R' => '軷', 'S' => '軸', 'T' => '軹', 'U' => '軺', 'V' => '軻', 'W' => '軼', 'X' => '軽', 'Y' => '軾', 'Z' => '軿', '[' => '輀', '\\' => '輁', ']' => '輂', '^' => '較', '_' => '輄', '`' => '輅', 'a' => '輆', 'b' => '輇', 'c' => '輈', 'd' => '載', 'e' => '輊', 'f' => '輋', 'g' => '輌', 'h' => '輍', 'i' => '輎', 'j' => '輏', 'k' => '輐', 'l' => '輑', 'm' => '輒', 'n' => '輓', 'o' => '輔', 'p' => '輕', 'q' => '輖', 'r' => '輗', 's' => '輘', 't' => '輙', 'u' => '輚', 'v' => '輛', 'w' => '輜', 'x' => '輝', 'y' => '輞', 'z' => '輟', '{' => '輠', '|' => '輡', '}' => '輢', '~' => '輣', '݀' => '輤', '݁' => '輥', '݂' => '輦', '݃' => '輧', '݄' => '輨', '݅' => '輩', '݆' => '輪', '݇' => '輫', '݈' => '輬', '݉' => '輭', '݊' => '輮', '݋' => '輯', '݌' => '輰', 'ݍ' => '輱', 'ݎ' => '輲', 'ݏ' => '輳', 'ݐ' => '輴', 'ݑ' => '輵', 'ݒ' => '輶', 'ݓ' => '輷', 'ݔ' => '輸', 'ݕ' => '輹', 'ݖ' => '輺', 'ݗ' => '輻', 'ݘ' => '輼', 'ݙ' => '輽', 'ݚ' => '輾', 'ݛ' => '輿', 'ݜ' => '轀', 'ݝ' => '轁', 'ݞ' => '轂', 'ݟ' => '轃', 'ݠ' => '轄', 'ݡ' => '荨', 'ݢ' => '茛', 'ݣ' => '荩', 'ݤ' => '荬', 'ݥ' => '荪', 'ݦ' => '荭', 'ݧ' => '荮', 'ݨ' => '莰', 'ݩ' => '荸', 'ݪ' => '莳', 'ݫ' => '莴', 'ݬ' => '莠', 'ݭ' => '莪', 'ݮ' => '莓', 'ݯ' => '莜', 'ݰ' => '莅', 'ݱ' => '荼', 'ݲ' => '莶', 'ݳ' => '莩', 'ݴ' => '荽', 'ݵ' => '莸', 'ݶ' => '荻', 'ݷ' => '莘', 'ݸ' => '莞', 'ݹ' => '莨', 'ݺ' => '莺', 'ݻ' => '莼', 'ݼ' => '菁', 'ݽ' => '萁', 'ݾ' => '菥', 'ݿ' => '菘', '' => '堇', '' => '萘', '' => '萋', '' => '菝', '' => '菽', '' => '菖', '' => '萜', '' => '萸', '' => '萑', '' => '萆', '' => '菔', '' => '菟', '' => '萏', '' => '萃', '' => '菸', '' => '菹', '' => '菪', '' => '菅', '' => '菀', '' => '萦', '' => '菰', '' => '菡', '' => '葜', '' => '葑', '' => '葚', '' => '葙', '' => '葳', '' => '蒇', '' => '蒈', '' => '葺', '' => '蒉', '' => '葸', '' => '萼', '' => '葆', '' => '葩', '' => '葶', '' => '蒌', '' => '蒎', '' => '萱', '' => '葭', '' => '蓁', '' => '蓍', '' => '蓐', '' => '蓦', '' => '蒽', '' => '蓓', '' => '蓊', '' => '蒿', '' => '蒺', '' => '蓠', '' => '蒡', '' => '蒹', '' => '蒴', '' => '蒗', '' => '蓥', '' => '蓣', '' => '蔌', '' => '甍', '' => '蔸', '' => '蓰', '' => '蔹', '' => '蔟', '' => '蔺', '@' => '轅', 'A' => '轆', 'B' => '轇', 'C' => '轈', 'D' => '轉', 'E' => '轊', 'F' => '轋', 'G' => '轌', 'H' => '轍', 'I' => '轎', 'J' => '轏', 'K' => '轐', 'L' => '轑', 'M' => '轒', 'N' => '轓', 'O' => '轔', 'P' => '轕', 'Q' => '轖', 'R' => '轗', 'S' => '轘', 'T' => '轙', 'U' => '轚', 'V' => '轛', 'W' => '轜', 'X' => '轝', 'Y' => '轞', 'Z' => '轟', '[' => '轠', '\\' => '轡', ']' => '轢', '^' => '轣', '_' => '轤', '`' => '轥', 'a' => '轪', 'b' => '辀', 'c' => '辌', 'd' => '辒', 'e' => '辝', 'f' => '辠', 'g' => '辡', 'h' => '辢', 'i' => '辤', 'j' => '辥', 'k' => '辦', 'l' => '辧', 'm' => '辪', 'n' => '辬', 'o' => '辭', 'p' => '辮', 'q' => '辯', 'r' => '農', 's' => '辳', 't' => '辴', 'u' => '辵', 'v' => '辷', 'w' => '辸', 'x' => '辺', 'y' => '辻', 'z' => '込', '{' => '辿', '|' => '迀', '}' => '迃', '~' => '迆', 'ހ' => '迉', 'ށ' => '迊', 'ނ' => '迋', 'ރ' => '迌', 'ބ' => '迍', 'ޅ' => '迏', 'ކ' => '迒', 'އ' => '迖', 'ވ' => '迗', 'މ' => '迚', 'ފ' => '迠', 'ދ' => '迡', 'ތ' => '迣', 'ލ' => '迧', 'ގ' => '迬', 'ޏ' => '迯', 'ސ' => '迱', 'ޑ' => '迲', 'ޒ' => '迴', 'ޓ' => '迵', 'ޔ' => '迶', 'ޕ' => '迺', 'ޖ' => '迻', 'ޗ' => '迼', 'ޘ' => '迾', 'ޙ' => '迿', 'ޚ' => '逇', 'ޛ' => '逈', 'ޜ' => '逌', 'ޝ' => '逎', 'ޞ' => '逓', 'ޟ' => '逕', 'ޠ' => '逘', 'ޡ' => '蕖', 'ޢ' => '蔻', 'ޣ' => '蓿', 'ޤ' => '蓼', 'ޥ' => '蕙', 'ަ' => '蕈', 'ާ' => '蕨', 'ި' => '蕤', 'ީ' => '蕞', 'ު' => '蕺', 'ޫ' => '瞢', 'ެ' => '蕃', 'ޭ' => '蕲', 'ޮ' => '蕻', 'ޯ' => '薤', 'ް' => '薨', 'ޱ' => '薇', '޲' => '薏', '޳' => '蕹', '޴' => '薮', '޵' => '薜', '޶' => '薅', '޷' => '薹', '޸' => '薷', '޹' => '薰', '޺' => '藓', '޻' => '藁', '޼' => '藜', '޽' => '藿', '޾' => '蘧', '޿' => '蘅', '' => '蘩', '' => '蘖', '' => '蘼', '' => '廾', '' => '弈', '' => '夼', '' => '奁', '' => '耷', '' => '奕', '' => '奚', '' => '奘', '' => '匏', '' => '尢', '' => '尥', '' => '尬', '' => '尴', '' => '扌', '' => '扪', '' => '抟', '' => '抻', '' => '拊', '' => '拚', '' => '拗', '' => '拮', '' => '挢', '' => '拶', '' => '挹', '' => '捋', '' => '捃', '' => '掭', '' => '揶', '' => '捱', '' => '捺', '' => '掎', '' => '掴', '' => '捭', '' => '掬', '' => '掊', '' => '捩', '' => '掮', '' => '掼', '' => '揲', '' => '揸', '' => '揠', '' => '揿', '' => '揄', '' => '揞', '' => '揎', '' => '摒', '' => '揆', '' => '掾', '' => '摅', '' => '摁', '' => '搋', '' => '搛', '' => '搠', '' => '搌', '' => '搦', '' => '搡', '' => '摞', '' => '撄', '' => '摭', '' => '撖', '@' => '這', 'A' => '逜', 'B' => '連', 'C' => '逤', 'D' => '逥', 'E' => '逧', 'F' => '逨', 'G' => '逩', 'H' => '逪', 'I' => '逫', 'J' => '逬', 'K' => '逰', 'L' => '週', 'M' => '進', 'N' => '逳', 'O' => '逴', 'P' => '逷', 'Q' => '逹', 'R' => '逺', 'S' => '逽', 'T' => '逿', 'U' => '遀', 'V' => '遃', 'W' => '遅', 'X' => '遆', 'Y' => '遈', 'Z' => '遉', '[' => '遊', '\\' => '運', ']' => '遌', '^' => '過', '_' => '達', '`' => '違', 'a' => '遖', 'b' => '遙', 'c' => '遚', 'd' => '遜', 'e' => '遝', 'f' => '遞', 'g' => '遟', 'h' => '遠', 'i' => '遡', 'j' => '遤', 'k' => '遦', 'l' => '遧', 'm' => '適', 'n' => '遪', 'o' => '遫', 'p' => '遬', 'q' => '遯', 'r' => '遰', 's' => '遱', 't' => '遲', 'u' => '遳', 'v' => '遶', 'w' => '遷', 'x' => '選', 'y' => '遹', 'z' => '遺', '{' => '遻', '|' => '遼', '}' => '遾', '~' => '邁', '߀' => '還', '߁' => '邅', '߂' => '邆', '߃' => '邇', '߄' => '邉', '߅' => '邊', '߆' => '邌', '߇' => '邍', '߈' => '邎', '߉' => '邏', 'ߊ' => '邐', 'ߋ' => '邒', 'ߌ' => '邔', 'ߍ' => '邖', 'ߎ' => '邘', 'ߏ' => '邚', 'ߐ' => '邜', 'ߑ' => '邞', 'ߒ' => '邟', 'ߓ' => '邠', 'ߔ' => '邤', 'ߕ' => '邥', 'ߖ' => '邧', 'ߗ' => '邨', 'ߘ' => '邩', 'ߙ' => '邫', 'ߚ' => '邭', 'ߛ' => '邲', 'ߜ' => '邷', 'ߝ' => '邼', 'ߞ' => '邽', 'ߟ' => '邿', 'ߠ' => '郀', 'ߡ' => '摺', 'ߢ' => '撷', 'ߣ' => '撸', 'ߤ' => '撙', 'ߥ' => '撺', 'ߦ' => '擀', 'ߧ' => '擐', 'ߨ' => '擗', 'ߩ' => '擤', 'ߪ' => '擢', '߫' => '攉', '߬' => '攥', '߭' => '攮', '߮' => '弋', '߯' => '忒', '߰' => '甙', '߱' => '弑', '߲' => '卟', '߳' => '叱', 'ߴ' => '叽', 'ߵ' => '叩', '߶' => '叨', '߷' => '叻', '߸' => '吒', '߹' => '吖', 'ߺ' => '吆', '߻' => '呋', '߼' => '呒', '߽' => '呓', '߾' => '呔', '߿' => '呖', '' => '呃', '' => '吡', '' => '呗', '' => '呙', '' => '吣', '' => '吲', '' => '咂', '' => '咔', '' => '呷', '' => '呱', '' => '呤', '' => '咚', '' => '咛', '' => '咄', '' => '呶', '' => '呦', '' => '咝', '' => '哐', '' => '咭', '' => '哂', '' => '咴', '' => '哒', '' => '咧', '' => '咦', '' => '哓', '' => '哔', '' => '呲', '' => '咣', '' => '哕', '' => '咻', '' => '咿', '' => '哌', '' => '哙', '' => '哚', '' => '哜', '' => '咩', '' => '咪', '' => '咤', '' => '哝', '' => '哏', '' => '哞', '' => '唛', '' => '哧', '' => '唠', '' => '哽', '' => '唔', '' => '哳', '' => '唢', '' => '唣', '' => '唏', '' => '唑', '' => '唧', '' => '唪', '' => '啧', '' => '喏', '' => '喵', '' => '啉', '' => '啭', '' => '啁', '' => '啕', '' => '唿', '' => '啐', '' => '唼', '@' => '郂', 'A' => '郃', 'B' => '郆', 'C' => '郈', 'D' => '郉', 'E' => '郋', 'F' => '郌', 'G' => '郍', 'H' => '郒', 'I' => '郔', 'J' => '郕', 'K' => '郖', 'L' => '郘', 'M' => '郙', 'N' => '郚', 'O' => '郞', 'P' => '郟', 'Q' => '郠', 'R' => '郣', 'S' => '郤', 'T' => '郥', 'U' => '郩', 'V' => '郪', 'W' => '郬', 'X' => '郮', 'Y' => '郰', 'Z' => '郱', '[' => '郲', '\\' => '郳', ']' => '郵', '^' => '郶', '_' => '郷', '`' => '郹', 'a' => '郺', 'b' => '郻', 'c' => '郼', 'd' => '郿', 'e' => '鄀', 'f' => '鄁', 'g' => '鄃', 'h' => '鄅', 'i' => '鄆', 'j' => '鄇', 'k' => '鄈', 'l' => '鄉', 'm' => '鄊', 'n' => '鄋', 'o' => '鄌', 'p' => '鄍', 'q' => '鄎', 'r' => '鄏', 's' => '鄐', 't' => '鄑', 'u' => '鄒', 'v' => '鄓', 'w' => '鄔', 'x' => '鄕', 'y' => '鄖', 'z' => '鄗', '{' => '鄘', '|' => '鄚', '}' => '鄛', '~' => '鄜', '' => '鄝', '' => '鄟', '' => '鄠', '' => '鄡', '' => '鄤', '' => '鄥', '' => '鄦', '' => '鄧', '' => '鄨', '' => '鄩', '' => '鄪', '' => '鄫', '' => '鄬', '' => '鄭', '' => '鄮', '' => '鄰', '' => '鄲', '' => '鄳', '' => '鄴', '' => '鄵', '' => '鄶', '' => '鄷', '' => '鄸', '' => '鄺', '' => '鄻', '' => '鄼', '' => '鄽', '' => '鄾', '' => '鄿', '' => '酀', '' => '酁', '' => '酂', '' => '酄', '' => '唷', '' => '啖', '' => '啵', '' => '啶', '' => '啷', '' => '唳', '' => '唰', '' => '啜', '' => '喋', '' => '嗒', '' => '喃', '' => '喱', '' => '喹', '' => '喈', '' => '喁', '' => '喟', '' => '啾', '' => '嗖', '' => '喑', '' => '啻', '' => '嗟', '' => '喽', '' => '喾', '' => '喔', '' => '喙', '' => '嗪', '' => '嗷', '' => '嗉', '' => '嘟', '' => '嗑', '' => '嗫', '' => '嗬', '' => '嗔', '' => '嗦', '' => '嗝', '' => '嗄', '' => '嗯', '' => '嗥', '' => '嗲', '' => '嗳', '' => '嗌', '' => '嗍', '' => '嗨', '' => '嗵', '' => '嗤', '' => '辔', '' => '嘞', '' => '嘈', '' => '嘌', '' => '嘁', '' => '嘤', '' => '嘣', '' => '嗾', '' => '嘀', '' => '嘧', '' => '嘭', '' => '噘', '' => '嘹', '' => '噗', '' => '嘬', '' => '噍', '' => '噢', '' => '噙', '' => '噜', '' => '噌', '' => '噔', '' => '嚆', '' => '噤', '' => '噱', '' => '噫', '' => '噻', '' => '噼', '' => '嚅', '' => '嚓', '' => '嚯', '' => '囔', '' => '囗', '' => '囝', '' => '囡', '' => '囵', '' => '囫', '' => '囹', '' => '囿', '' => '圄', '' => '圊', '' => '圉', '' => '圜', '' => '帏', '' => '帙', '' => '帔', '' => '帑', '' => '帱', '' => '帻', '' => '帼', '@' => '酅', 'A' => '酇', 'B' => '酈', 'C' => '酑', 'D' => '酓', 'E' => '酔', 'F' => '酕', 'G' => '酖', 'H' => '酘', 'I' => '酙', 'J' => '酛', 'K' => '酜', 'L' => '酟', 'M' => '酠', 'N' => '酦', 'O' => '酧', 'P' => '酨', 'Q' => '酫', 'R' => '酭', 'S' => '酳', 'T' => '酺', 'U' => '酻', 'V' => '酼', 'W' => '醀', 'X' => '醁', 'Y' => '醂', 'Z' => '醃', '[' => '醄', '\\' => '醆', ']' => '醈', '^' => '醊', '_' => '醎', '`' => '醏', 'a' => '醓', 'b' => '醔', 'c' => '醕', 'd' => '醖', 'e' => '醗', 'f' => '醘', 'g' => '醙', 'h' => '醜', 'i' => '醝', 'j' => '醞', 'k' => '醟', 'l' => '醠', 'm' => '醡', 'n' => '醤', 'o' => '醥', 'p' => '醦', 'q' => '醧', 'r' => '醨', 's' => '醩', 't' => '醫', 'u' => '醬', 'v' => '醰', 'w' => '醱', 'x' => '醲', 'y' => '醳', 'z' => '醶', '{' => '醷', '|' => '醸', '}' => '醹', '~' => '醻', '' => '醼', '' => '醽', '' => '醾', '' => '醿', '' => '釀', '' => '釁', '' => '釂', '' => '釃', '' => '釄', '' => '釅', '' => '釆', '' => '釈', '' => '釋', '' => '釐', '' => '釒', '' => '釓', '' => '釔', '' => '釕', '' => '釖', '' => '釗', '' => '釘', '' => '釙', '' => '釚', '' => '釛', '' => '針', '' => '釞', '' => '釟', '' => '釠', '' => '釡', '' => '釢', '' => '釣', '' => '釤', '' => '釥', '' => '帷', '' => '幄', '' => '幔', '' => '幛', '' => '幞', '' => '幡', '' => '岌', '' => '屺', '' => '岍', '' => '岐', '' => '岖', '' => '岈', '' => '岘', '' => '岙', '' => '岑', '' => '岚', '' => '岜', '' => '岵', '' => '岢', '' => '岽', '' => '岬', '' => '岫', '' => '岱', '' => '岣', '' => '峁', '' => '岷', '' => '峄', '' => '峒', '' => '峤', '' => '峋', '' => '峥', '' => '崂', '' => '崃', '' => '崧', '' => '崦', '' => '崮', '' => '崤', '' => '崞', '' => '崆', '' => '崛', '' => '嵘', '' => '崾', '' => '崴', '' => '崽', '' => '嵬', '' => '嵛', '' => '嵯', '' => '嵝', '' => '嵫', '' => '嵋', '' => '嵊', '' => '嵩', '' => '嵴', '' => '嶂', '' => '嶙', '' => '嶝', '' => '豳', '' => '嶷', '' => '巅', '' => '彳', '' => '彷', '' => '徂', '' => '徇', '' => '徉', '' => '後', '' => '徕', '' => '徙', '' => '徜', '' => '徨', '' => '徭', '' => '徵', '' => '徼', '' => '衢', '' => '彡', '' => '犭', '' => '犰', '' => '犴', '' => '犷', '' => '犸', '' => '狃', '' => '狁', '' => '狎', '' => '狍', '' => '狒', '' => '狨', '' => '狯', '' => '狩', '' => '狲', '' => '狴', '' => '狷', '' => '猁', '' => '狳', '' => '猃', '' => '狺', '@' => '釦', 'A' => '釧', 'B' => '釨', 'C' => '釩', 'D' => '釪', 'E' => '釫', 'F' => '釬', 'G' => '釭', 'H' => '釮', 'I' => '釯', 'J' => '釰', 'K' => '釱', 'L' => '釲', 'M' => '釳', 'N' => '釴', 'O' => '釵', 'P' => '釶', 'Q' => '釷', 'R' => '釸', 'S' => '釹', 'T' => '釺', 'U' => '釻', 'V' => '釼', 'W' => '釽', 'X' => '釾', 'Y' => '釿', 'Z' => '鈀', '[' => '鈁', '\\' => '鈂', ']' => '鈃', '^' => '鈄', '_' => '鈅', '`' => '鈆', 'a' => '鈇', 'b' => '鈈', 'c' => '鈉', 'd' => '鈊', 'e' => '鈋', 'f' => '鈌', 'g' => '鈍', 'h' => '鈎', 'i' => '鈏', 'j' => '鈐', 'k' => '鈑', 'l' => '鈒', 'm' => '鈓', 'n' => '鈔', 'o' => '鈕', 'p' => '鈖', 'q' => '鈗', 'r' => '鈘', 's' => '鈙', 't' => '鈚', 'u' => '鈛', 'v' => '鈜', 'w' => '鈝', 'x' => '鈞', 'y' => '鈟', 'z' => '鈠', '{' => '鈡', '|' => '鈢', '}' => '鈣', '~' => '鈤', '' => '鈥', '' => '鈦', '' => '鈧', '' => '鈨', '' => '鈩', '' => '鈪', '' => '鈫', '' => '鈬', '' => '鈭', '' => '鈮', '' => '鈯', '' => '鈰', '' => '鈱', '' => '鈲', '' => '鈳', '' => '鈴', '' => '鈵', '' => '鈶', '' => '鈷', '' => '鈸', '' => '鈹', '' => '鈺', '' => '鈻', '' => '鈼', '' => '鈽', '' => '鈾', '' => '鈿', '' => '鉀', '' => '鉁', '' => '鉂', '' => '鉃', '' => '鉄', '' => '鉅', '' => '狻', '' => '猗', '' => '猓', '' => '猡', '' => '猊', '' => '猞', '' => '猝', '' => '猕', '' => '猢', '' => '猹', '' => '猥', '' => '猬', '' => '猸', '' => '猱', '' => '獐', '' => '獍', '' => '獗', '' => '獠', '' => '獬', '' => '獯', '' => '獾', '' => '舛', '' => '夥', '' => '飧', '' => '夤', '' => '夂', '' => '饣', '' => '饧', '' => '饨', '' => '饩', '' => '饪', '' => '饫', '' => '饬', '' => '饴', '' => '饷', '' => '饽', '' => '馀', '' => '馄', '' => '馇', '' => '馊', '' => '馍', '' => '馐', '' => '馑', '' => '馓', '' => '馔', '' => '馕', '' => '庀', '' => '庑', '' => '庋', '' => '庖', '' => '庥', '' => '庠', '' => '庹', '' => '庵', '' => '庾', '' => '庳', '' => '赓', '' => '廒', '' => '廑', '' => '廛', '' => '廨', '' => '廪', '' => '膺', '' => '忄', '' => '忉', '' => '忖', '' => '忏', '' => '怃', '' => '忮', '' => '怄', '' => '忡', '' => '忤', '' => '忾', '' => '怅', '' => '怆', '' => '忪', '' => '忭', '' => '忸', '' => '怙', '' => '怵', '' => '怦', '' => '怛', '' => '怏', '' => '怍', '' => '怩', '' => '怫', '' => '怊', '' => '怿', '' => '怡', '' => '恸', '' => '恹', '' => '恻', '' => '恺', '' => '恂', '@' => '鉆', 'A' => '鉇', 'B' => '鉈', 'C' => '鉉', 'D' => '鉊', 'E' => '鉋', 'F' => '鉌', 'G' => '鉍', 'H' => '鉎', 'I' => '鉏', 'J' => '鉐', 'K' => '鉑', 'L' => '鉒', 'M' => '鉓', 'N' => '鉔', 'O' => '鉕', 'P' => '鉖', 'Q' => '鉗', 'R' => '鉘', 'S' => '鉙', 'T' => '鉚', 'U' => '鉛', 'V' => '鉜', 'W' => '鉝', 'X' => '鉞', 'Y' => '鉟', 'Z' => '鉠', '[' => '鉡', '\\' => '鉢', ']' => '鉣', '^' => '鉤', '_' => '鉥', '`' => '鉦', 'a' => '鉧', 'b' => '鉨', 'c' => '鉩', 'd' => '鉪', 'e' => '鉫', 'f' => '鉬', 'g' => '鉭', 'h' => '鉮', 'i' => '鉯', 'j' => '鉰', 'k' => '鉱', 'l' => '鉲', 'm' => '鉳', 'n' => '鉵', 'o' => '鉶', 'p' => '鉷', 'q' => '鉸', 'r' => '鉹', 's' => '鉺', 't' => '鉻', 'u' => '鉼', 'v' => '鉽', 'w' => '鉾', 'x' => '鉿', 'y' => '銀', 'z' => '銁', '{' => '銂', '|' => '銃', '}' => '銄', '~' => '銅', '' => '銆', '' => '銇', '' => '銈', '' => '銉', '' => '銊', '' => '銋', '' => '銌', '' => '銍', '' => '銏', '' => '銐', '' => '銑', '' => '銒', '' => '銓', '' => '銔', '' => '銕', '' => '銖', '' => '銗', '' => '銘', '' => '銙', '' => '銚', '' => '銛', '' => '銜', '' => '銝', '' => '銞', '' => '銟', '' => '銠', '' => '銡', '' => '銢', '' => '銣', '' => '銤', '' => '銥', '' => '銦', '' => '銧', '' => '恪', '' => '恽', '' => '悖', '' => '悚', '' => '悭', '' => '悝', '' => '悃', '' => '悒', '' => '悌', '' => '悛', '' => '惬', '' => '悻', '' => '悱', '' => '惝', '' => '惘', '' => '惆', '' => '惚', '' => '悴', '' => '愠', '' => '愦', '' => '愕', '' => '愣', '' => '惴', '' => '愀', '' => '愎', '' => '愫', '' => '慊', '' => '慵', '' => '憬', '' => '憔', '' => '憧', '' => '憷', '' => '懔', '' => '懵', '' => '忝', '' => '隳', '' => '闩', '' => '闫', '' => '闱', '' => '闳', '' => '闵', '' => '闶', '' => '闼', '' => '闾', '' => '阃', '' => '阄', '' => '阆', '' => '阈', '' => '阊', '' => '阋', '' => '阌', '' => '阍', '' => '阏', '' => '阒', '' => '阕', '' => '阖', '' => '阗', '' => '阙', '' => '阚', '' => '丬', '' => '爿', '' => '戕', '' => '氵', '' => '汔', '' => '汜', '' => '汊', '' => '沣', '' => '沅', '' => '沐', '' => '沔', '' => '沌', '' => '汨', '' => '汩', '' => '汴', '' => '汶', '' => '沆', '' => '沩', '' => '泐', '' => '泔', '' => '沭', '' => '泷', '' => '泸', '' => '泱', '' => '泗', '' => '沲', '' => '泠', '' => '泖', '' => '泺', '' => '泫', '' => '泮', '' => '沱', '' => '泓', '' => '泯', '' => '泾', '@' => '銨', 'A' => '銩', 'B' => '銪', 'C' => '銫', 'D' => '銬', 'E' => '銭', 'F' => '銯', 'G' => '銰', 'H' => '銱', 'I' => '銲', 'J' => '銳', 'K' => '銴', 'L' => '銵', 'M' => '銶', 'N' => '銷', 'O' => '銸', 'P' => '銹', 'Q' => '銺', 'R' => '銻', 'S' => '銼', 'T' => '銽', 'U' => '銾', 'V' => '銿', 'W' => '鋀', 'X' => '鋁', 'Y' => '鋂', 'Z' => '鋃', '[' => '鋄', '\\' => '鋅', ']' => '鋆', '^' => '鋇', '_' => '鋉', '`' => '鋊', 'a' => '鋋', 'b' => '鋌', 'c' => '鋍', 'd' => '鋎', 'e' => '鋏', 'f' => '鋐', 'g' => '鋑', 'h' => '鋒', 'i' => '鋓', 'j' => '鋔', 'k' => '鋕', 'l' => '鋖', 'm' => '鋗', 'n' => '鋘', 'o' => '鋙', 'p' => '鋚', 'q' => '鋛', 'r' => '鋜', 's' => '鋝', 't' => '鋞', 'u' => '鋟', 'v' => '鋠', 'w' => '鋡', 'x' => '鋢', 'y' => '鋣', 'z' => '鋤', '{' => '鋥', '|' => '鋦', '}' => '鋧', '~' => '鋨', '' => '鋩', '' => '鋪', '' => '鋫', '' => '鋬', '' => '鋭', '' => '鋮', '' => '鋯', '' => '鋰', '' => '鋱', '' => '鋲', '' => '鋳', '' => '鋴', '' => '鋵', '' => '鋶', '' => '鋷', '' => '鋸', '' => '鋹', '' => '鋺', '' => '鋻', '' => '鋼', '' => '鋽', '' => '鋾', '' => '鋿', '' => '錀', '' => '錁', '' => '錂', '' => '錃', '' => '錄', '' => '錅', '' => '錆', '' => '錇', '' => '錈', '' => '錉', '' => '洹', '' => '洧', '' => '洌', '' => '浃', '' => '浈', '' => '洇', '' => '洄', '' => '洙', '' => '洎', '' => '洫', '' => '浍', '' => '洮', '' => '洵', '' => '洚', '' => '浏', '' => '浒', '' => '浔', '' => '洳', '' => '涑', '' => '浯', '' => '涞', '' => '涠', '' => '浞', '' => '涓', '' => '涔', '' => '浜', '' => '浠', '' => '浼', '' => '浣', '' => '渚', '' => '淇', '' => '淅', '' => '淞', '' => '渎', '' => '涿', '' => '淠', '' => '渑', '' => '淦', '' => '淝', '' => '淙', '' => '渖', '' => '涫', '' => '渌', '' => '涮', '' => '渫', '' => '湮', '' => '湎', '' => '湫', '' => '溲', '' => '湟', '' => '溆', '' => '湓', '' => '湔', '' => '渲', '' => '渥', '' => '湄', '' => '滟', '' => '溱', '' => '溘', '' => '滠', '' => '漭', '' => '滢', '' => '溥', '' => '溧', '' => '溽', '' => '溻', '' => '溷', '' => '滗', '' => '溴', '' => '滏', '' => '溏', '' => '滂', '' => '溟', '' => '潢', '' => '潆', '' => '潇', '' => '漤', '' => '漕', '' => '滹', '' => '漯', '' => '漶', '' => '潋', '' => '潴', '' => '漪', '' => '漉', '' => '漩', '' => '澉', '' => '澍', '' => '澌', '' => '潸', '' => '潲', '' => '潼', '' => '潺', '' => '濑', '@' => '錊', 'A' => '錋', 'B' => '錌', 'C' => '錍', 'D' => '錎', 'E' => '錏', 'F' => '錐', 'G' => '錑', 'H' => '錒', 'I' => '錓', 'J' => '錔', 'K' => '錕', 'L' => '錖', 'M' => '錗', 'N' => '錘', 'O' => '錙', 'P' => '錚', 'Q' => '錛', 'R' => '錜', 'S' => '錝', 'T' => '錞', 'U' => '錟', 'V' => '錠', 'W' => '錡', 'X' => '錢', 'Y' => '錣', 'Z' => '錤', '[' => '錥', '\\' => '錦', ']' => '錧', '^' => '錨', '_' => '錩', '`' => '錪', 'a' => '錫', 'b' => '錬', 'c' => '錭', 'd' => '錮', 'e' => '錯', 'f' => '錰', 'g' => '錱', 'h' => '録', 'i' => '錳', 'j' => '錴', 'k' => '錵', 'l' => '錶', 'm' => '錷', 'n' => '錸', 'o' => '錹', 'p' => '錺', 'q' => '錻', 'r' => '錼', 's' => '錽', 't' => '錿', 'u' => '鍀', 'v' => '鍁', 'w' => '鍂', 'x' => '鍃', 'y' => '鍄', 'z' => '鍅', '{' => '鍆', '|' => '鍇', '}' => '鍈', '~' => '鍉', '' => '鍊', '' => '鍋', '' => '鍌', '' => '鍍', '' => '鍎', '' => '鍏', '' => '鍐', '' => '鍑', '' => '鍒', '' => '鍓', '' => '鍔', '' => '鍕', '' => '鍖', '' => '鍗', '' => '鍘', '' => '鍙', '' => '鍚', '' => '鍛', '' => '鍜', '' => '鍝', '' => '鍞', '' => '鍟', '' => '鍠', '' => '鍡', '' => '鍢', '' => '鍣', '' => '鍤', '' => '鍥', '' => '鍦', '' => '鍧', '' => '鍨', '' => '鍩', '' => '鍫', '' => '濉', '' => '澧', '' => '澹', '' => '澶', '' => '濂', '' => '濡', '' => '濮', '' => '濞', '' => '濠', '' => '濯', '' => '瀚', '' => '瀣', '' => '瀛', '' => '瀹', '' => '瀵', '' => '灏', '' => '灞', '' => '宀', '' => '宄', '' => '宕', '' => '宓', '' => '宥', '' => '宸', '' => '甯', '' => '骞', '' => '搴', '' => '寤', '' => '寮', '' => '褰', '' => '寰', '' => '蹇', '' => '謇', '' => '辶', '' => '迓', '' => '迕', '' => '迥', '' => '迮', '' => '迤', '' => '迩', '' => '迦', '' => '迳', '' => '迨', '' => '逅', '' => '逄', '' => '逋', '' => '逦', '' => '逑', '' => '逍', '' => '逖', '' => '逡', '' => '逵', '' => '逶', '' => '逭', '' => '逯', '' => '遄', '' => '遑', '' => '遒', '' => '遐', '' => '遨', '' => '遘', '' => '遢', '' => '遛', '' => '暹', '' => '遴', '' => '遽', '' => '邂', '' => '邈', '' => '邃', '' => '邋', '' => '彐', '' => '彗', '' => '彖', '' => '彘', '' => '尻', '' => '咫', '' => '屐', '' => '屙', '' => '孱', '' => '屣', '' => '屦', '' => '羼', '' => '弪', '' => '弩', '' => '弭', '' => '艴', '' => '弼', '' => '鬻', '' => '屮', '' => '妁', '' => '妃', '' => '妍', '' => '妩', '' => '妪', '' => '妣', '@' => '鍬', 'A' => '鍭', 'B' => '鍮', 'C' => '鍯', 'D' => '鍰', 'E' => '鍱', 'F' => '鍲', 'G' => '鍳', 'H' => '鍴', 'I' => '鍵', 'J' => '鍶', 'K' => '鍷', 'L' => '鍸', 'M' => '鍹', 'N' => '鍺', 'O' => '鍻', 'P' => '鍼', 'Q' => '鍽', 'R' => '鍾', 'S' => '鍿', 'T' => '鎀', 'U' => '鎁', 'V' => '鎂', 'W' => '鎃', 'X' => '鎄', 'Y' => '鎅', 'Z' => '鎆', '[' => '鎇', '\\' => '鎈', ']' => '鎉', '^' => '鎊', '_' => '鎋', '`' => '鎌', 'a' => '鎍', 'b' => '鎎', 'c' => '鎐', 'd' => '鎑', 'e' => '鎒', 'f' => '鎓', 'g' => '鎔', 'h' => '鎕', 'i' => '鎖', 'j' => '鎗', 'k' => '鎘', 'l' => '鎙', 'm' => '鎚', 'n' => '鎛', 'o' => '鎜', 'p' => '鎝', 'q' => '鎞', 'r' => '鎟', 's' => '鎠', 't' => '鎡', 'u' => '鎢', 'v' => '鎣', 'w' => '鎤', 'x' => '鎥', 'y' => '鎦', 'z' => '鎧', '{' => '鎨', '|' => '鎩', '}' => '鎪', '~' => '鎫', '' => '鎬', '' => '鎭', '' => '鎮', '' => '鎯', '' => '鎰', '' => '鎱', '' => '鎲', '' => '鎳', '' => '鎴', '' => '鎵', '' => '鎶', '' => '鎷', '' => '鎸', '' => '鎹', '' => '鎺', '' => '鎻', '' => '鎼', '' => '鎽', '' => '鎾', '' => '鎿', '' => '鏀', '' => '鏁', '' => '鏂', '' => '鏃', '' => '鏄', '' => '鏅', '' => '鏆', '' => '鏇', '' => '鏈', '' => '鏉', '' => '鏋', '' => '鏌', '' => '鏍', '' => '妗', '' => '姊', '' => '妫', '' => '妞', '' => '妤', '' => '姒', '' => '妲', '' => '妯', '' => '姗', '' => '妾', '' => '娅', '' => '娆', '' => '姝', '' => '娈', '' => '姣', '' => '姘', '' => '姹', '' => '娌', '' => '娉', '' => '娲', '' => '娴', '' => '娑', '' => '娣', '' => '娓', '' => '婀', '' => '婧', '' => '婊', '' => '婕', '' => '娼', '' => '婢', '' => '婵', '' => '胬', '' => '媪', '' => '媛', '' => '婷', '' => '婺', '' => '媾', '' => '嫫', '' => '媲', '' => '嫒', '' => '嫔', '' => '媸', '' => '嫠', '' => '嫣', '' => '嫱', '' => '嫖', '' => '嫦', '' => '嫘', '' => '嫜', '' => '嬉', '' => '嬗', '' => '嬖', '' => '嬲', '' => '嬷', '' => '孀', '' => '尕', '' => '尜', '' => '孚', '' => '孥', '' => '孳', '' => '孑', '' => '孓', '' => '孢', '' => '驵', '' => '驷', '' => '驸', '' => '驺', '' => '驿', '' => '驽', '' => '骀', '' => '骁', '' => '骅', '' => '骈', '' => '骊', '' => '骐', '' => '骒', '' => '骓', '' => '骖', '' => '骘', '' => '骛', '' => '骜', '' => '骝', '' => '骟', '' => '骠', '' => '骢', '' => '骣', '' => '骥', '' => '骧', '' => '纟', '' => '纡', '' => '纣', '' => '纥', '' => '纨', '' => '纩', '@' => '鏎', 'A' => '鏏', 'B' => '鏐', 'C' => '鏑', 'D' => '鏒', 'E' => '鏓', 'F' => '鏔', 'G' => '鏕', 'H' => '鏗', 'I' => '鏘', 'J' => '鏙', 'K' => '鏚', 'L' => '鏛', 'M' => '鏜', 'N' => '鏝', 'O' => '鏞', 'P' => '鏟', 'Q' => '鏠', 'R' => '鏡', 'S' => '鏢', 'T' => '鏣', 'U' => '鏤', 'V' => '鏥', 'W' => '鏦', 'X' => '鏧', 'Y' => '鏨', 'Z' => '鏩', '[' => '鏪', '\\' => '鏫', ']' => '鏬', '^' => '鏭', '_' => '鏮', '`' => '鏯', 'a' => '鏰', 'b' => '鏱', 'c' => '鏲', 'd' => '鏳', 'e' => '鏴', 'f' => '鏵', 'g' => '鏶', 'h' => '鏷', 'i' => '鏸', 'j' => '鏹', 'k' => '鏺', 'l' => '鏻', 'm' => '鏼', 'n' => '鏽', 'o' => '鏾', 'p' => '鏿', 'q' => '鐀', 'r' => '鐁', 's' => '鐂', 't' => '鐃', 'u' => '鐄', 'v' => '鐅', 'w' => '鐆', 'x' => '鐇', 'y' => '鐈', 'z' => '鐉', '{' => '鐊', '|' => '鐋', '}' => '鐌', '~' => '鐍', '' => '鐎', '' => '鐏', '' => '鐐', '' => '鐑', '' => '鐒', '' => '鐓', '' => '鐔', '' => '鐕', '' => '鐖', '' => '鐗', '' => '鐘', '' => '鐙', '' => '鐚', '' => '鐛', '' => '鐜', '' => '鐝', '' => '鐞', '' => '鐟', '' => '鐠', '' => '鐡', '' => '鐢', '' => '鐣', '' => '鐤', '' => '鐥', '' => '鐦', '' => '鐧', '' => '鐨', '' => '鐩', '' => '鐪', '' => '鐫', '' => '鐬', '' => '鐭', '' => '鐮', '' => '纭', '' => '纰', '' => '纾', '' => '绀', '' => '绁', '' => '绂', '' => '绉', '' => '绋', '' => '绌', '' => '绐', '' => '绔', '' => '绗', '' => '绛', '' => '绠', '' => '绡', '' => '绨', '' => '绫', '' => '绮', '' => '绯', '' => '绱', '' => '绲', '' => '缍', '' => '绶', '' => '绺', '' => '绻', '' => '绾', '' => '缁', '' => '缂', '' => '缃', '' => '缇', '' => '缈', '' => '缋', '' => '缌', '' => '缏', '' => '缑', '' => '缒', '' => '缗', '' => '缙', '' => '缜', '' => '缛', '' => '缟', '' => '缡', '' => '缢', '' => '缣', '' => '缤', '' => '缥', '' => '缦', '' => '缧', '' => '缪', '' => '缫', '' => '缬', '' => '缭', '' => '缯', '' => '缰', '' => '缱', '' => '缲', '' => '缳', '' => '缵', '' => '幺', '' => '畿', '' => '巛', '' => '甾', '' => '邕', '' => '玎', '' => '玑', '' => '玮', '' => '玢', '' => '玟', '' => '珏', '' => '珂', '' => '珑', '' => '玷', '' => '玳', '' => '珀', '' => '珉', '' => '珈', '' => '珥', '' => '珙', '' => '顼', '' => '琊', '' => '珩', '' => '珧', '' => '珞', '' => '玺', '' => '珲', '' => '琏', '' => '琪', '' => '瑛', '' => '琦', '' => '琥', '' => '琨', '' => '琰', '' => '琮', '' => '琬', '@' => '鐯', 'A' => '鐰', 'B' => '鐱', 'C' => '鐲', 'D' => '鐳', 'E' => '鐴', 'F' => '鐵', 'G' => '鐶', 'H' => '鐷', 'I' => '鐸', 'J' => '鐹', 'K' => '鐺', 'L' => '鐻', 'M' => '鐼', 'N' => '鐽', 'O' => '鐿', 'P' => '鑀', 'Q' => '鑁', 'R' => '鑂', 'S' => '鑃', 'T' => '鑄', 'U' => '鑅', 'V' => '鑆', 'W' => '鑇', 'X' => '鑈', 'Y' => '鑉', 'Z' => '鑊', '[' => '鑋', '\\' => '鑌', ']' => '鑍', '^' => '鑎', '_' => '鑏', '`' => '鑐', 'a' => '鑑', 'b' => '鑒', 'c' => '鑓', 'd' => '鑔', 'e' => '鑕', 'f' => '鑖', 'g' => '鑗', 'h' => '鑘', 'i' => '鑙', 'j' => '鑚', 'k' => '鑛', 'l' => '鑜', 'm' => '鑝', 'n' => '鑞', 'o' => '鑟', 'p' => '鑠', 'q' => '鑡', 'r' => '鑢', 's' => '鑣', 't' => '鑤', 'u' => '鑥', 'v' => '鑦', 'w' => '鑧', 'x' => '鑨', 'y' => '鑩', 'z' => '鑪', '{' => '鑬', '|' => '鑭', '}' => '鑮', '~' => '鑯', '' => '鑰', '' => '鑱', '' => '鑲', '' => '鑳', '' => '鑴', '' => '鑵', '' => '鑶', '' => '鑷', '' => '鑸', '' => '鑹', '' => '鑺', '' => '鑻', '' => '鑼', '' => '鑽', '' => '鑾', '' => '鑿', '' => '钀', '' => '钁', '' => '钂', '' => '钃', '' => '钄', '' => '钑', '' => '钖', '' => '钘', '' => '铇', '' => '铏', '' => '铓', '' => '铔', '' => '铚', '' => '铦', '' => '铻', '' => '锜', '' => '锠', '' => '琛', '' => '琚', '' => '瑁', '' => '瑜', '' => '瑗', '' => '瑕', '' => '瑙', '' => '瑷', '' => '瑭', '' => '瑾', '' => '璜', '' => '璎', '' => '璀', '' => '璁', '' => '璇', '' => '璋', '' => '璞', '' => '璨', '' => '璩', '' => '璐', '' => '璧', '' => '瓒', '' => '璺', '' => '韪', '' => '韫', '' => '韬', '' => '杌', '' => '杓', '' => '杞', '' => '杈', '' => '杩', '' => '枥', '' => '枇', '' => '杪', '' => '杳', '' => '枘', '' => '枧', '' => '杵', '' => '枨', '' => '枞', '' => '枭', '' => '枋', '' => '杷', '' => '杼', '' => '柰', '' => '栉', '' => '柘', '' => '栊', '' => '柩', '' => '枰', '' => '栌', '' => '柙', '' => '枵', '' => '柚', '' => '枳', '' => '柝', '' => '栀', '' => '柃', '' => '枸', '' => '柢', '' => '栎', '' => '柁', '' => '柽', '' => '栲', '' => '栳', '' => '桠', '' => '桡', '' => '桎', '' => '桢', '' => '桄', '' => '桤', '' => '梃', '' => '栝', '' => '桕', '' => '桦', '' => '桁', '' => '桧', '' => '桀', '' => '栾', '' => '桊', '' => '桉', '' => '栩', '' => '梵', '' => '梏', '' => '桴', '' => '桷', '' => '梓', '' => '桫', '' => '棂', '' => '楮', '' => '棼', '' => '椟', '' => '椠', '' => '棹', '@' => '锧', 'A' => '锳', 'B' => '锽', 'C' => '镃', 'D' => '镈', 'E' => '镋', 'F' => '镕', 'G' => '镚', 'H' => '镠', 'I' => '镮', 'J' => '镴', 'K' => '镵', 'L' => '長', 'M' => '镸', 'N' => '镹', 'O' => '镺', 'P' => '镻', 'Q' => '镼', 'R' => '镽', 'S' => '镾', 'T' => '門', 'U' => '閁', 'V' => '閂', 'W' => '閃', 'X' => '閄', 'Y' => '閅', 'Z' => '閆', '[' => '閇', '\\' => '閈', ']' => '閉', '^' => '閊', '_' => '開', '`' => '閌', 'a' => '閍', 'b' => '閎', 'c' => '閏', 'd' => '閐', 'e' => '閑', 'f' => '閒', 'g' => '間', 'h' => '閔', 'i' => '閕', 'j' => '閖', 'k' => '閗', 'l' => '閘', 'm' => '閙', 'n' => '閚', 'o' => '閛', 'p' => '閜', 'q' => '閝', 'r' => '閞', 's' => '閟', 't' => '閠', 'u' => '閡', 'v' => '関', 'w' => '閣', 'x' => '閤', 'y' => '閥', 'z' => '閦', '{' => '閧', '|' => '閨', '}' => '閩', '~' => '閪', '' => '閫', '' => '閬', '' => '閭', '' => '閮', '' => '閯', '' => '閰', '' => '閱', '' => '閲', '' => '閳', '' => '閴', '' => '閵', '' => '閶', '' => '閷', '' => '閸', '' => '閹', '' => '閺', '' => '閻', '' => '閼', '' => '閽', '' => '閾', '' => '閿', '' => '闀', '' => '闁', '' => '闂', '' => '闃', '' => '闄', '' => '闅', '' => '闆', '' => '闇', '' => '闈', '' => '闉', '' => '闊', '' => '闋', '' => '椤', '' => '棰', '' => '椋', '' => '椁', '' => '楗', '' => '棣', '' => '椐', '' => '楱', '' => '椹', '' => '楠', '' => '楂', '' => '楝', '' => '榄', '' => '楫', '' => '榀', '' => '榘', '' => '楸', '' => '椴', '' => '槌', '' => '榇', '' => '榈', '' => '槎', '' => '榉', '' => '楦', '' => '楣', '' => '楹', '' => '榛', '' => '榧', '' => '榻', '' => '榫', '' => '榭', '' => '槔', '' => '榱', '' => '槁', '' => '槊', '' => '槟', '' => '榕', '' => '槠', '' => '榍', '' => '槿', '' => '樯', '' => '槭', '' => '樗', '' => '樘', '' => '橥', '' => '槲', '' => '橄', '' => '樾', '' => '檠', '' => '橐', '' => '橛', '' => '樵', '' => '檎', '' => '橹', '' => '樽', '' => '樨', '' => '橘', '' => '橼', '' => '檑', '' => '檐', '' => '檩', '' => '檗', '' => '檫', '' => '猷', '' => '獒', '' => '殁', '' => '殂', '' => '殇', '' => '殄', '' => '殒', '' => '殓', '' => '殍', '' => '殚', '' => '殛', '' => '殡', '' => '殪', '' => '轫', '' => '轭', '' => '轱', '' => '轲', '' => '轳', '' => '轵', '' => '轶', '' => '轸', '' => '轷', '' => '轹', '' => '轺', '' => '轼', '' => '轾', '' => '辁', '' => '辂', '' => '辄', '' => '辇', '' => '辋', '@' => '闌', 'A' => '闍', 'B' => '闎', 'C' => '闏', 'D' => '闐', 'E' => '闑', 'F' => '闒', 'G' => '闓', 'H' => '闔', 'I' => '闕', 'J' => '闖', 'K' => '闗', 'L' => '闘', 'M' => '闙', 'N' => '闚', 'O' => '闛', 'P' => '關', 'Q' => '闝', 'R' => '闞', 'S' => '闟', 'T' => '闠', 'U' => '闡', 'V' => '闢', 'W' => '闣', 'X' => '闤', 'Y' => '闥', 'Z' => '闦', '[' => '闧', '\\' => '闬', ']' => '闿', '^' => '阇', '_' => '阓', '`' => '阘', 'a' => '阛', 'b' => '阞', 'c' => '阠', 'd' => '阣', 'e' => '阤', 'f' => '阥', 'g' => '阦', 'h' => '阧', 'i' => '阨', 'j' => '阩', 'k' => '阫', 'l' => '阬', 'm' => '阭', 'n' => '阯', 'o' => '阰', 'p' => '阷', 'q' => '阸', 'r' => '阹', 's' => '阺', 't' => '阾', 'u' => '陁', 'v' => '陃', 'w' => '陊', 'x' => '陎', 'y' => '陏', 'z' => '陑', '{' => '陒', '|' => '陓', '}' => '陖', '~' => '陗', '' => '陘', '' => '陙', '' => '陚', '' => '陜', '' => '陝', '' => '陞', '' => '陠', '' => '陣', '' => '陥', '' => '陦', '' => '陫', '' => '陭', '' => '陮', '' => '陯', '' => '陰', '' => '陱', '' => '陳', '' => '陸', '' => '陹', '' => '険', '' => '陻', '' => '陼', '' => '陽', '' => '陾', '' => '陿', '' => '隀', '' => '隁', '' => '隂', '' => '隃', '' => '隄', '' => '隇', '' => '隉', '' => '隊', '' => '辍', '' => '辎', '' => '辏', '' => '辘', '' => '辚', '' => '軎', '' => '戋', '' => '戗', '' => '戛', '' => '戟', '' => '戢', '' => '戡', '' => '戥', '' => '戤', '' => '戬', '' => '臧', '' => '瓯', '' => '瓴', '' => '瓿', '' => '甏', '' => '甑', '' => '甓', '' => '攴', '' => '旮', '' => '旯', '' => '旰', '' => '昊', '' => '昙', '' => '杲', '' => '昃', '' => '昕', '' => '昀', '' => '炅', '' => '曷', '' => '昝', '' => '昴', '' => '昱', '' => '昶', '' => '昵', '' => '耆', '' => '晟', '' => '晔', '' => '晁', '' => '晏', '' => '晖', '' => '晡', '' => '晗', '' => '晷', '' => '暄', '' => '暌', '' => '暧', '' => '暝', '' => '暾', '' => '曛', '' => '曜', '' => '曦', '' => '曩', '' => '贲', '' => '贳', '' => '贶', '' => '贻', '' => '贽', '' => '赀', '' => '赅', '' => '赆', '' => '赈', '' => '赉', '' => '赇', '' => '赍', '' => '赕', '' => '赙', '' => '觇', '' => '觊', '' => '觋', '' => '觌', '' => '觎', '' => '觏', '' => '觐', '' => '觑', '' => '牮', '' => '犟', '' => '牝', '' => '牦', '' => '牯', '' => '牾', '' => '牿', '' => '犄', '' => '犋', '' => '犍', '' => '犏', '' => '犒', '' => '挈', '' => '挲', '' => '掰', '@' => '隌', 'A' => '階', 'B' => '隑', 'C' => '隒', 'D' => '隓', 'E' => '隕', 'F' => '隖', 'G' => '隚', 'H' => '際', 'I' => '隝', 'J' => '隞', 'K' => '隟', 'L' => '隠', 'M' => '隡', 'N' => '隢', 'O' => '隣', 'P' => '隤', 'Q' => '隥', 'R' => '隦', 'S' => '隨', 'T' => '隩', 'U' => '險', 'V' => '隫', 'W' => '隬', 'X' => '隭', 'Y' => '隮', 'Z' => '隯', '[' => '隱', '\\' => '隲', ']' => '隴', '^' => '隵', '_' => '隷', '`' => '隸', 'a' => '隺', 'b' => '隻', 'c' => '隿', 'd' => '雂', 'e' => '雃', 'f' => '雈', 'g' => '雊', 'h' => '雋', 'i' => '雐', 'j' => '雑', 'k' => '雓', 'l' => '雔', 'm' => '雖', 'n' => '雗', 'o' => '雘', 'p' => '雙', 'q' => '雚', 'r' => '雛', 's' => '雜', 't' => '雝', 'u' => '雞', 'v' => '雟', 'w' => '雡', 'x' => '離', 'y' => '難', 'z' => '雤', '{' => '雥', '|' => '雦', '}' => '雧', '~' => '雫', '' => '雬', '' => '雭', '' => '雮', '' => '雰', '' => '雱', '' => '雲', '' => '雴', '' => '雵', '' => '雸', '' => '雺', '' => '電', '' => '雼', '' => '雽', '' => '雿', '' => '霂', '' => '霃', '' => '霅', '' => '霊', '' => '霋', '' => '霌', '' => '霐', '' => '霑', '' => '霒', '' => '霔', '' => '霕', '' => '霗', '' => '霘', '' => '霙', '' => '霚', '' => '霛', '' => '霝', '' => '霟', '' => '霠', '' => '搿', '' => '擘', '' => '耄', '' => '毪', '' => '毳', '' => '毽', '' => '毵', '' => '毹', '' => '氅', '' => '氇', '' => '氆', '' => '氍', '' => '氕', '' => '氘', '' => '氙', '' => '氚', '' => '氡', '' => '氩', '' => '氤', '' => '氪', '' => '氲', '' => '攵', '' => '敕', '' => '敫', '' => '牍', '' => '牒', '' => '牖', '' => '爰', '' => '虢', '' => '刖', '' => '肟', '' => '肜', '' => '肓', '' => '肼', '' => '朊', '' => '肽', '' => '肱', '' => '肫', '' => '肭', '' => '肴', '' => '肷', '' => '胧', '' => '胨', '' => '胩', '' => '胪', '' => '胛', '' => '胂', '' => '胄', '' => '胙', '' => '胍', '' => '胗', '' => '朐', '' => '胝', '' => '胫', '' => '胱', '' => '胴', '' => '胭', '' => '脍', '' => '脎', '' => '胲', '' => '胼', '' => '朕', '' => '脒', '' => '豚', '' => '脶', '' => '脞', '' => '脬', '' => '脘', '' => '脲', '' => '腈', '' => '腌', '' => '腓', '' => '腴', '' => '腙', '' => '腚', '' => '腱', '' => '腠', '' => '腩', '' => '腼', '' => '腽', '' => '腭', '' => '腧', '' => '塍', '' => '媵', '' => '膈', '' => '膂', '' => '膑', '' => '滕', '' => '膣', '' => '膪', '' => '臌', '' => '朦', '' => '臊', '' => '膻', '@' => '霡', 'A' => '霢', 'B' => '霣', 'C' => '霤', 'D' => '霥', 'E' => '霦', 'F' => '霧', 'G' => '霨', 'H' => '霩', 'I' => '霫', 'J' => '霬', 'K' => '霮', 'L' => '霯', 'M' => '霱', 'N' => '霳', 'O' => '霴', 'P' => '霵', 'Q' => '霶', 'R' => '霷', 'S' => '霺', 'T' => '霻', 'U' => '霼', 'V' => '霽', 'W' => '霿', 'X' => '靀', 'Y' => '靁', 'Z' => '靂', '[' => '靃', '\\' => '靄', ']' => '靅', '^' => '靆', '_' => '靇', '`' => '靈', 'a' => '靉', 'b' => '靊', 'c' => '靋', 'd' => '靌', 'e' => '靍', 'f' => '靎', 'g' => '靏', 'h' => '靐', 'i' => '靑', 'j' => '靔', 'k' => '靕', 'l' => '靗', 'm' => '靘', 'n' => '靚', 'o' => '靜', 'p' => '靝', 'q' => '靟', 'r' => '靣', 's' => '靤', 't' => '靦', 'u' => '靧', 'v' => '靨', 'w' => '靪', 'x' => '靫', 'y' => '靬', 'z' => '靭', '{' => '靮', '|' => '靯', '}' => '靰', '~' => '靱', '' => '靲', '' => '靵', '' => '靷', '' => '靸', '' => '靹', '' => '靺', '' => '靻', '' => '靽', '' => '靾', '' => '靿', '' => '鞀', '' => '鞁', '' => '鞂', '' => '鞃', '' => '鞄', '' => '鞆', '' => '鞇', '' => '鞈', '' => '鞉', '' => '鞊', '' => '鞌', '' => '鞎', '' => '鞏', '' => '鞐', '' => '鞓', '' => '鞕', '' => '鞖', '' => '鞗', '' => '鞙', '' => '鞚', '' => '鞛', '' => '鞜', '' => '鞝', '' => '臁', '' => '膦', '' => '欤', '' => '欷', '' => '欹', '' => '歃', '' => '歆', '' => '歙', '' => '飑', '' => '飒', '' => '飓', '' => '飕', '' => '飙', '' => '飚', '' => '殳', '' => '彀', '' => '毂', '' => '觳', '' => '斐', '' => '齑', '' => '斓', '' => '於', '' => '旆', '' => '旄', '' => '旃', '' => '旌', '' => '旎', '' => '旒', '' => '旖', '' => '炀', '' => '炜', '' => '炖', '' => '炝', '' => '炻', '' => '烀', '' => '炷', '' => '炫', '' => '炱', '' => '烨', '' => '烊', '' => '焐', '' => '焓', '' => '焖', '' => '焯', '' => '焱', '' => '煳', '' => '煜', '' => '煨', '' => '煅', '' => '煲', '' => '煊', '' => '煸', '' => '煺', '' => '熘', '' => '熳', '' => '熵', '' => '熨', '' => '熠', '' => '燠', '' => '燔', '' => '燧', '' => '燹', '' => '爝', '' => '爨', '' => '灬', '' => '焘', '' => '煦', '' => '熹', '' => '戾', '' => '戽', '' => '扃', '' => '扈', '' => '扉', '' => '礻', '' => '祀', '' => '祆', '' => '祉', '' => '祛', '' => '祜', '' => '祓', '' => '祚', '' => '祢', '' => '祗', '' => '祠', '' => '祯', '' => '祧', '' => '祺', '' => '禅', '' => '禊', '' => '禚', '' => '禧', '' => '禳', '' => '忑', '' => '忐', '@' => '鞞', 'A' => '鞟', 'B' => '鞡', 'C' => '鞢', 'D' => '鞤', 'E' => '鞥', 'F' => '鞦', 'G' => '鞧', 'H' => '鞨', 'I' => '鞩', 'J' => '鞪', 'K' => '鞬', 'L' => '鞮', 'M' => '鞰', 'N' => '鞱', 'O' => '鞳', 'P' => '鞵', 'Q' => '鞶', 'R' => '鞷', 'S' => '鞸', 'T' => '鞹', 'U' => '鞺', 'V' => '鞻', 'W' => '鞼', 'X' => '鞽', 'Y' => '鞾', 'Z' => '鞿', '[' => '韀', '\\' => '韁', ']' => '韂', '^' => '韃', '_' => '韄', '`' => '韅', 'a' => '韆', 'b' => '韇', 'c' => '韈', 'd' => '韉', 'e' => '韊', 'f' => '韋', 'g' => '韌', 'h' => '韍', 'i' => '韎', 'j' => '韏', 'k' => '韐', 'l' => '韑', 'm' => '韒', 'n' => '韓', 'o' => '韔', 'p' => '韕', 'q' => '韖', 'r' => '韗', 's' => '韘', 't' => '韙', 'u' => '韚', 'v' => '韛', 'w' => '韜', 'x' => '韝', 'y' => '韞', 'z' => '韟', '{' => '韠', '|' => '韡', '}' => '韢', '~' => '韣', '' => '韤', '' => '韥', '' => '韨', '' => '韮', '' => '韯', '' => '韰', '' => '韱', '' => '韲', '' => '韴', '' => '韷', '' => '韸', '' => '韹', '' => '韺', '' => '韻', '' => '韼', '' => '韽', '' => '韾', '' => '響', '' => '頀', '' => '頁', '' => '頂', '' => '頃', '' => '頄', '' => '項', '' => '順', '' => '頇', '' => '須', '' => '頉', '' => '頊', '' => '頋', '' => '頌', '' => '頍', '' => '頎', '' => '怼', '' => '恝', '' => '恚', '' => '恧', '' => '恁', '' => '恙', '' => '恣', '' => '悫', '' => '愆', '' => '愍', '' => '慝', '' => '憩', '' => '憝', '' => '懋', '' => '懑', '' => '戆', '' => '肀', '' => '聿', '' => '沓', '' => '泶', '' => '淼', '' => '矶', '' => '矸', '' => '砀', '' => '砉', '' => '砗', '' => '砘', '' => '砑', '' => '斫', '' => '砭', '' => '砜', '' => '砝', '' => '砹', '' => '砺', '' => '砻', '' => '砟', '' => '砼', '' => '砥', '' => '砬', '' => '砣', '' => '砩', '' => '硎', '' => '硭', '' => '硖', '' => '硗', '' => '砦', '' => '硐', '' => '硇', '' => '硌', '' => '硪', '' => '碛', '' => '碓', '' => '碚', '' => '碇', '' => '碜', '' => '碡', '' => '碣', '' => '碲', '' => '碹', '' => '碥', '' => '磔', '' => '磙', '' => '磉', '' => '磬', '' => '磲', '' => '礅', '' => '磴', '' => '礓', '' => '礤', '' => '礞', '' => '礴', '' => '龛', '' => '黹', '' => '黻', '' => '黼', '' => '盱', '' => '眄', '' => '眍', '' => '盹', '' => '眇', '' => '眈', '' => '眚', '' => '眢', '' => '眙', '' => '眭', '' => '眦', '' => '眵', '' => '眸', '' => '睐', '' => '睑', '' => '睇', '' => '睃', '' => '睚', '' => '睨', '@' => '頏', 'A' => '預', 'B' => '頑', 'C' => '頒', 'D' => '頓', 'E' => '頔', 'F' => '頕', 'G' => '頖', 'H' => '頗', 'I' => '領', 'J' => '頙', 'K' => '頚', 'L' => '頛', 'M' => '頜', 'N' => '頝', 'O' => '頞', 'P' => '頟', 'Q' => '頠', 'R' => '頡', 'S' => '頢', 'T' => '頣', 'U' => '頤', 'V' => '頥', 'W' => '頦', 'X' => '頧', 'Y' => '頨', 'Z' => '頩', '[' => '頪', '\\' => '頫', ']' => '頬', '^' => '頭', '_' => '頮', '`' => '頯', 'a' => '頰', 'b' => '頱', 'c' => '頲', 'd' => '頳', 'e' => '頴', 'f' => '頵', 'g' => '頶', 'h' => '頷', 'i' => '頸', 'j' => '頹', 'k' => '頺', 'l' => '頻', 'm' => '頼', 'n' => '頽', 'o' => '頾', 'p' => '頿', 'q' => '顀', 'r' => '顁', 's' => '顂', 't' => '顃', 'u' => '顄', 'v' => '顅', 'w' => '顆', 'x' => '顇', 'y' => '顈', 'z' => '顉', '{' => '顊', '|' => '顋', '}' => '題', '~' => '額', '' => '顎', '' => '顏', '' => '顐', '' => '顑', '' => '顒', '' => '顓', '' => '顔', '' => '顕', '' => '顖', '' => '顗', '' => '願', '' => '顙', '' => '顚', '' => '顛', '' => '顜', '' => '顝', '' => '類', '' => '顟', '' => '顠', '' => '顡', '' => '顢', '' => '顣', '' => '顤', '' => '顥', '' => '顦', '' => '顧', '' => '顨', '' => '顩', '' => '顪', '' => '顫', '' => '顬', '' => '顭', '' => '顮', '' => '睢', '' => '睥', '' => '睿', '' => '瞍', '' => '睽', '' => '瞀', '' => '瞌', '' => '瞑', '' => '瞟', '' => '瞠', '' => '瞰', '' => '瞵', '' => '瞽', '' => '町', '' => '畀', '' => '畎', '' => '畋', '' => '畈', '' => '畛', '' => '畲', '' => '畹', '' => '疃', '' => '罘', '' => '罡', '' => '罟', '' => '詈', '' => '罨', '' => '罴', '' => '罱', '' => '罹', '' => '羁', '' => '罾', '' => '盍', '' => '盥', '' => '蠲', '' => '钅', '' => '钆', '' => '钇', '' => '钋', '' => '钊', '' => '钌', '' => '钍', '' => '钏', '' => '钐', '' => '钔', '' => '钗', '' => '钕', '' => '钚', '' => '钛', '' => '钜', '' => '钣', '' => '钤', '' => '钫', '' => '钪', '' => '钭', '' => '钬', '' => '钯', '' => '钰', '' => '钲', '' => '钴', '' => '钶', '' => '钷', '' => '钸', '' => '钹', '' => '钺', '' => '钼', '' => '钽', '' => '钿', '' => '铄', '' => '铈', '' => '铉', '' => '铊', '' => '铋', '' => '铌', '' => '铍', '' => '铎', '' => '铐', '' => '铑', '' => '铒', '' => '铕', '' => '铖', '' => '铗', '' => '铙', '' => '铘', '' => '铛', '' => '铞', '' => '铟', '' => '铠', '' => '铢', '' => '铤', '' => '铥', '' => '铧', '' => '铨', '' => '铪', '@' => '顯', 'A' => '顰', 'B' => '顱', 'C' => '顲', 'D' => '顳', 'E' => '顴', 'F' => '颋', 'G' => '颎', 'H' => '颒', 'I' => '颕', 'J' => '颙', 'K' => '颣', 'L' => '風', 'M' => '颩', 'N' => '颪', 'O' => '颫', 'P' => '颬', 'Q' => '颭', 'R' => '颮', 'S' => '颯', 'T' => '颰', 'U' => '颱', 'V' => '颲', 'W' => '颳', 'X' => '颴', 'Y' => '颵', 'Z' => '颶', '[' => '颷', '\\' => '颸', ']' => '颹', '^' => '颺', '_' => '颻', '`' => '颼', 'a' => '颽', 'b' => '颾', 'c' => '颿', 'd' => '飀', 'e' => '飁', 'f' => '飂', 'g' => '飃', 'h' => '飄', 'i' => '飅', 'j' => '飆', 'k' => '飇', 'l' => '飈', 'm' => '飉', 'n' => '飊', 'o' => '飋', 'p' => '飌', 'q' => '飍', 'r' => '飏', 's' => '飐', 't' => '飔', 'u' => '飖', 'v' => '飗', 'w' => '飛', 'x' => '飜', 'y' => '飝', 'z' => '飠', '{' => '飡', '|' => '飢', '}' => '飣', '~' => '飤', '' => '飥', '' => '飦', '' => '飩', '' => '飪', '' => '飫', '' => '飬', '' => '飭', '' => '飮', '' => '飯', '' => '飰', '' => '飱', '' => '飲', '' => '飳', '' => '飴', '' => '飵', '' => '飶', '' => '飷', '' => '飸', '' => '飹', '' => '飺', '' => '飻', '' => '飼', '' => '飽', '' => '飾', '' => '飿', '' => '餀', '' => '餁', '' => '餂', '' => '餃', '' => '餄', '' => '餅', '' => '餆', '' => '餇', '' => '铩', '' => '铫', '' => '铮', '' => '铯', '' => '铳', '' => '铴', '' => '铵', '' => '铷', '' => '铹', '' => '铼', '' => '铽', '' => '铿', '' => '锃', '' => '锂', '' => '锆', '' => '锇', '' => '锉', '' => '锊', '' => '锍', '' => '锎', '' => '锏', '' => '锒', '' => '锓', '' => '锔', '' => '锕', '' => '锖', '' => '锘', '' => '锛', '' => '锝', '' => '锞', '' => '锟', '' => '锢', '' => '锪', '' => '锫', '' => '锩', '' => '锬', '' => '锱', '' => '锲', '' => '锴', '' => '锶', '' => '锷', '' => '锸', '' => '锼', '' => '锾', '' => '锿', '' => '镂', '' => '锵', '' => '镄', '' => '镅', '' => '镆', '' => '镉', '' => '镌', '' => '镎', '' => '镏', '' => '镒', '' => '镓', '' => '镔', '' => '镖', '' => '镗', '' => '镘', '' => '镙', '' => '镛', '' => '镞', '' => '镟', '' => '镝', '' => '镡', '' => '镢', '' => '镤', '' => '镥', '' => '镦', '' => '镧', '' => '镨', '' => '镩', '' => '镪', '' => '镫', '' => '镬', '' => '镯', '' => '镱', '' => '镲', '' => '镳', '' => '锺', '' => '矧', '' => '矬', '' => '雉', '' => '秕', '' => '秭', '' => '秣', '' => '秫', '' => '稆', '' => '嵇', '' => '稃', '' => '稂', '' => '稞', '' => '稔', '@' => '餈', 'A' => '餉', 'B' => '養', 'C' => '餋', 'D' => '餌', 'E' => '餎', 'F' => '餏', 'G' => '餑', 'H' => '餒', 'I' => '餓', 'J' => '餔', 'K' => '餕', 'L' => '餖', 'M' => '餗', 'N' => '餘', 'O' => '餙', 'P' => '餚', 'Q' => '餛', 'R' => '餜', 'S' => '餝', 'T' => '餞', 'U' => '餟', 'V' => '餠', 'W' => '餡', 'X' => '餢', 'Y' => '餣', 'Z' => '餤', '[' => '餥', '\\' => '餦', ']' => '餧', '^' => '館', '_' => '餩', '`' => '餪', 'a' => '餫', 'b' => '餬', 'c' => '餭', 'd' => '餯', 'e' => '餰', 'f' => '餱', 'g' => '餲', 'h' => '餳', 'i' => '餴', 'j' => '餵', 'k' => '餶', 'l' => '餷', 'm' => '餸', 'n' => '餹', 'o' => '餺', 'p' => '餻', 'q' => '餼', 'r' => '餽', 's' => '餾', 't' => '餿', 'u' => '饀', 'v' => '饁', 'w' => '饂', 'x' => '饃', 'y' => '饄', 'z' => '饅', '{' => '饆', '|' => '饇', '}' => '饈', '~' => '饉', '' => '饊', '' => '饋', '' => '饌', '' => '饍', '' => '饎', '' => '饏', '' => '饐', '' => '饑', '' => '饒', '' => '饓', '' => '饖', '' => '饗', '' => '饘', '' => '饙', '' => '饚', '' => '饛', '' => '饜', '' => '饝', '' => '饞', '' => '饟', '' => '饠', '' => '饡', '' => '饢', '' => '饤', '' => '饦', '' => '饳', '' => '饸', '' => '饹', '' => '饻', '' => '饾', '' => '馂', '' => '馃', '' => '馉', '' => '稹', '' => '稷', '' => '穑', '' => '黏', '' => '馥', '' => '穰', '' => '皈', '' => '皎', '' => '皓', '' => '皙', '' => '皤', '' => '瓞', '' => '瓠', '' => '甬', '' => '鸠', '' => '鸢', '' => '鸨', '' => '鸩', '' => '鸪', '' => '鸫', '' => '鸬', '' => '鸲', '' => '鸱', '' => '鸶', '' => '鸸', '' => '鸷', '' => '鸹', '' => '鸺', '' => '鸾', '' => '鹁', '' => '鹂', '' => '鹄', '' => '鹆', '' => '鹇', '' => '鹈', '' => '鹉', '' => '鹋', '' => '鹌', '' => '鹎', '' => '鹑', '' => '鹕', '' => '鹗', '' => '鹚', '' => '鹛', '' => '鹜', '' => '鹞', '' => '鹣', '' => '鹦', '' => '鹧', '' => '鹨', '' => '鹩', '' => '鹪', '' => '鹫', '' => '鹬', '' => '鹱', '' => '鹭', '' => '鹳', '' => '疒', '' => '疔', '' => '疖', '' => '疠', '' => '疝', '' => '疬', '' => '疣', '' => '疳', '' => '疴', '' => '疸', '' => '痄', '' => '疱', '' => '疰', '' => '痃', '' => '痂', '' => '痖', '' => '痍', '' => '痣', '' => '痨', '' => '痦', '' => '痤', '' => '痫', '' => '痧', '' => '瘃', '' => '痱', '' => '痼', '' => '痿', '' => '瘐', '' => '瘀', '' => '瘅', '' => '瘌', '' => '瘗', '' => '瘊', '' => '瘥', '' => '瘘', '' => '瘕', '' => '瘙', '@' => '馌', 'A' => '馎', 'B' => '馚', 'C' => '馛', 'D' => '馜', 'E' => '馝', 'F' => '馞', 'G' => '馟', 'H' => '馠', 'I' => '馡', 'J' => '馢', 'K' => '馣', 'L' => '馤', 'M' => '馦', 'N' => '馧', 'O' => '馩', 'P' => '馪', 'Q' => '馫', 'R' => '馬', 'S' => '馭', 'T' => '馮', 'U' => '馯', 'V' => '馰', 'W' => '馱', 'X' => '馲', 'Y' => '馳', 'Z' => '馴', '[' => '馵', '\\' => '馶', ']' => '馷', '^' => '馸', '_' => '馹', '`' => '馺', 'a' => '馻', 'b' => '馼', 'c' => '馽', 'd' => '馾', 'e' => '馿', 'f' => '駀', 'g' => '駁', 'h' => '駂', 'i' => '駃', 'j' => '駄', 'k' => '駅', 'l' => '駆', 'm' => '駇', 'n' => '駈', 'o' => '駉', 'p' => '駊', 'q' => '駋', 'r' => '駌', 's' => '駍', 't' => '駎', 'u' => '駏', 'v' => '駐', 'w' => '駑', 'x' => '駒', 'y' => '駓', 'z' => '駔', '{' => '駕', '|' => '駖', '}' => '駗', '~' => '駘', '' => '駙', '' => '駚', '' => '駛', '' => '駜', '' => '駝', '' => '駞', '' => '駟', '' => '駠', '' => '駡', '' => '駢', '' => '駣', '' => '駤', '' => '駥', '' => '駦', '' => '駧', '' => '駨', '' => '駩', '' => '駪', '' => '駫', '' => '駬', '' => '駭', '' => '駮', '' => '駯', '' => '駰', '' => '駱', '' => '駲', '' => '駳', '' => '駴', '' => '駵', '' => '駶', '' => '駷', '' => '駸', '' => '駹', '' => '瘛', '' => '瘼', '' => '瘢', '' => '瘠', '' => '癀', '' => '瘭', '' => '瘰', '' => '瘿', '' => '瘵', '' => '癃', '' => '瘾', '' => '瘳', '' => '癍', '' => '癞', '' => '癔', '' => '癜', '' => '癖', '' => '癫', '' => '癯', '' => '翊', '' => '竦', '' => '穸', '' => '穹', '' => '窀', '' => '窆', '' => '窈', '' => '窕', '' => '窦', '' => '窠', '' => '窬', '' => '窨', '' => '窭', '' => '窳', '' => '衤', '' => '衩', '' => '衲', '' => '衽', '' => '衿', '' => '袂', '' => '袢', '' => '裆', '' => '袷', '' => '袼', '' => '裉', '' => '裢', '' => '裎', '' => '裣', '' => '裥', '' => '裱', '' => '褚', '' => '裼', '' => '裨', '' => '裾', '' => '裰', '' => '褡', '' => '褙', '' => '褓', '' => '褛', '' => '褊', '' => '褴', '' => '褫', '' => '褶', '' => '襁', '' => '襦', '' => '襻', '' => '疋', '' => '胥', '' => '皲', '' => '皴', '' => '矜', '' => '耒', '' => '耔', '' => '耖', '' => '耜', '' => '耠', '' => '耢', '' => '耥', '' => '耦', '' => '耧', '' => '耩', '' => '耨', '' => '耱', '' => '耋', '' => '耵', '' => '聃', '' => '聆', '' => '聍', '' => '聒', '' => '聩', '' => '聱', '' => '覃', '' => '顸', '' => '颀', '' => '颃', '@' => '駺', 'A' => '駻', 'B' => '駼', 'C' => '駽', 'D' => '駾', 'E' => '駿', 'F' => '騀', 'G' => '騁', 'H' => '騂', 'I' => '騃', 'J' => '騄', 'K' => '騅', 'L' => '騆', 'M' => '騇', 'N' => '騈', 'O' => '騉', 'P' => '騊', 'Q' => '騋', 'R' => '騌', 'S' => '騍', 'T' => '騎', 'U' => '騏', 'V' => '騐', 'W' => '騑', 'X' => '騒', 'Y' => '験', 'Z' => '騔', '[' => '騕', '\\' => '騖', ']' => '騗', '^' => '騘', '_' => '騙', '`' => '騚', 'a' => '騛', 'b' => '騜', 'c' => '騝', 'd' => '騞', 'e' => '騟', 'f' => '騠', 'g' => '騡', 'h' => '騢', 'i' => '騣', 'j' => '騤', 'k' => '騥', 'l' => '騦', 'm' => '騧', 'n' => '騨', 'o' => '騩', 'p' => '騪', 'q' => '騫', 'r' => '騬', 's' => '騭', 't' => '騮', 'u' => '騯', 'v' => '騰', 'w' => '騱', 'x' => '騲', 'y' => '騳', 'z' => '騴', '{' => '騵', '|' => '騶', '}' => '騷', '~' => '騸', '' => '騹', '' => '騺', '' => '騻', '' => '騼', '' => '騽', '' => '騾', '' => '騿', '' => '驀', '' => '驁', '' => '驂', '' => '驃', '' => '驄', '' => '驅', '' => '驆', '' => '驇', '' => '驈', '' => '驉', '' => '驊', '' => '驋', '' => '驌', '' => '驍', '' => '驎', '' => '驏', '' => '驐', '' => '驑', '' => '驒', '' => '驓', '' => '驔', '' => '驕', '' => '驖', '' => '驗', '' => '驘', '' => '驙', '' => '颉', '' => '颌', '' => '颍', '' => '颏', '' => '颔', '' => '颚', '' => '颛', '' => '颞', '' => '颟', '' => '颡', '' => '颢', '' => '颥', '' => '颦', '' => '虍', '' => '虔', '' => '虬', '' => '虮', '' => '虿', '' => '虺', '' => '虼', '' => '虻', '' => '蚨', '' => '蚍', '' => '蚋', '' => '蚬', '' => '蚝', '' => '蚧', '' => '蚣', '' => '蚪', '' => '蚓', '' => '蚩', '' => '蚶', '' => '蛄', '' => '蚵', '' => '蛎', '' => '蚰', '' => '蚺', '' => '蚱', '' => '蚯', '' => '蛉', '' => '蛏', '' => '蚴', '' => '蛩', '' => '蛱', '' => '蛲', '' => '蛭', '' => '蛳', '' => '蛐', '' => '蜓', '' => '蛞', '' => '蛴', '' => '蛟', '' => '蛘', '' => '蛑', '' => '蜃', '' => '蜇', '' => '蛸', '' => '蜈', '' => '蜊', '' => '蜍', '' => '蜉', '' => '蜣', '' => '蜻', '' => '蜞', '' => '蜥', '' => '蜮', '' => '蜚', '' => '蜾', '' => '蝈', '' => '蜴', '' => '蜱', '' => '蜩', '' => '蜷', '' => '蜿', '' => '螂', '' => '蜢', '' => '蝽', '' => '蝾', '' => '蝻', '' => '蝠', '' => '蝰', '' => '蝌', '' => '蝮', '' => '螋', '' => '蝓', '' => '蝣', '' => '蝼', '' => '蝤', '' => '蝙', '' => '蝥', '' => '螓', '' => '螯', '' => '螨', '' => '蟒', '@' => '驚', 'A' => '驛', 'B' => '驜', 'C' => '驝', 'D' => '驞', 'E' => '驟', 'F' => '驠', 'G' => '驡', 'H' => '驢', 'I' => '驣', 'J' => '驤', 'K' => '驥', 'L' => '驦', 'M' => '驧', 'N' => '驨', 'O' => '驩', 'P' => '驪', 'Q' => '驫', 'R' => '驲', 'S' => '骃', 'T' => '骉', 'U' => '骍', 'V' => '骎', 'W' => '骔', 'X' => '骕', 'Y' => '骙', 'Z' => '骦', '[' => '骩', '\\' => '骪', ']' => '骫', '^' => '骬', '_' => '骭', '`' => '骮', 'a' => '骯', 'b' => '骲', 'c' => '骳', 'd' => '骴', 'e' => '骵', 'f' => '骹', 'g' => '骻', 'h' => '骽', 'i' => '骾', 'j' => '骿', 'k' => '髃', 'l' => '髄', 'm' => '髆', 'n' => '髇', 'o' => '髈', 'p' => '髉', 'q' => '髊', 'r' => '髍', 's' => '髎', 't' => '髏', 'u' => '髐', 'v' => '髒', 'w' => '體', 'x' => '髕', 'y' => '髖', 'z' => '髗', '{' => '髙', '|' => '髚', '}' => '髛', '~' => '髜', '' => '髝', '' => '髞', '' => '髠', '' => '髢', '' => '髣', '' => '髤', '' => '髥', '' => '髧', '' => '髨', '' => '髩', '' => '髪', '' => '髬', '' => '髮', '' => '髰', '' => '髱', '' => '髲', '' => '髳', '' => '髴', '' => '髵', '' => '髶', '' => '髷', '' => '髸', '' => '髺', '' => '髼', '' => '髽', '' => '髾', '' => '髿', '' => '鬀', '' => '鬁', '' => '鬂', '' => '鬄', '' => '鬅', '' => '鬆', '' => '蟆', '' => '螈', '' => '螅', '' => '螭', '' => '螗', '' => '螃', '' => '螫', '' => '蟥', '' => '螬', '' => '螵', '' => '螳', '' => '蟋', '' => '蟓', '' => '螽', '' => '蟑', '' => '蟀', '' => '蟊', '' => '蟛', '' => '蟪', '' => '蟠', '' => '蟮', '' => '蠖', '' => '蠓', '' => '蟾', '' => '蠊', '' => '蠛', '' => '蠡', '' => '蠹', '' => '蠼', '' => '缶', '' => '罂', '' => '罄', '' => '罅', '' => '舐', '' => '竺', '' => '竽', '' => '笈', '' => '笃', '' => '笄', '' => '笕', '' => '笊', '' => '笫', '' => '笏', '' => '筇', '' => '笸', '' => '笪', '' => '笙', '' => '笮', '' => '笱', '' => '笠', '' => '笥', '' => '笤', '' => '笳', '' => '笾', '' => '笞', '' => '筘', '' => '筚', '' => '筅', '' => '筵', '' => '筌', '' => '筝', '' => '筠', '' => '筮', '' => '筻', '' => '筢', '' => '筲', '' => '筱', '' => '箐', '' => '箦', '' => '箧', '' => '箸', '' => '箬', '' => '箝', '' => '箨', '' => '箅', '' => '箪', '' => '箜', '' => '箢', '' => '箫', '' => '箴', '' => '篑', '' => '篁', '' => '篌', '' => '篝', '' => '篚', '' => '篥', '' => '篦', '' => '篪', '' => '簌', '' => '篾', '' => '篼', '' => '簏', '' => '簖', '' => '簋', '@' => '鬇', 'A' => '鬉', 'B' => '鬊', 'C' => '鬋', 'D' => '鬌', 'E' => '鬍', 'F' => '鬎', 'G' => '鬐', 'H' => '鬑', 'I' => '鬒', 'J' => '鬔', 'K' => '鬕', 'L' => '鬖', 'M' => '鬗', 'N' => '鬘', 'O' => '鬙', 'P' => '鬚', 'Q' => '鬛', 'R' => '鬜', 'S' => '鬝', 'T' => '鬞', 'U' => '鬠', 'V' => '鬡', 'W' => '鬢', 'X' => '鬤', 'Y' => '鬥', 'Z' => '鬦', '[' => '鬧', '\\' => '鬨', ']' => '鬩', '^' => '鬪', '_' => '鬫', '`' => '鬬', 'a' => '鬭', 'b' => '鬮', 'c' => '鬰', 'd' => '鬱', 'e' => '鬳', 'f' => '鬴', 'g' => '鬵', 'h' => '鬶', 'i' => '鬷', 'j' => '鬸', 'k' => '鬹', 'l' => '鬺', 'm' => '鬽', 'n' => '鬾', 'o' => '鬿', 'p' => '魀', 'q' => '魆', 'r' => '魊', 's' => '魋', 't' => '魌', 'u' => '魎', 'v' => '魐', 'w' => '魒', 'x' => '魓', 'y' => '魕', 'z' => '魖', '{' => '魗', '|' => '魘', '}' => '魙', '~' => '魚', '' => '魛', '' => '魜', '' => '魝', '' => '魞', '' => '魟', '' => '魠', '' => '魡', '' => '魢', '' => '魣', '' => '魤', '' => '魥', '' => '魦', '' => '魧', '' => '魨', '' => '魩', '' => '魪', '' => '魫', '' => '魬', '' => '魭', '' => '魮', '' => '魯', '' => '魰', '' => '魱', '' => '魲', '' => '魳', '' => '魴', '' => '魵', '' => '魶', '' => '魷', '' => '魸', '' => '魹', '' => '魺', '' => '魻', '' => '簟', '' => '簪', '' => '簦', '' => '簸', '' => '籁', '' => '籀', '' => '臾', '' => '舁', '' => '舂', '' => '舄', '' => '臬', '' => '衄', '' => '舡', '' => '舢', '' => '舣', '' => '舭', '' => '舯', '' => '舨', '' => '舫', '' => '舸', '' => '舻', '' => '舳', '' => '舴', '' => '舾', '' => '艄', '' => '艉', '' => '艋', '' => '艏', '' => '艚', '' => '艟', '' => '艨', '' => '衾', '' => '袅', '' => '袈', '' => '裘', '' => '裟', '' => '襞', '' => '羝', '' => '羟', '' => '羧', '' => '羯', '' => '羰', '' => '羲', '' => '籼', '' => '敉', '' => '粑', '' => '粝', '' => '粜', '' => '粞', '' => '粢', '' => '粲', '' => '粼', '' => '粽', '' => '糁', '' => '糇', '' => '糌', '' => '糍', '' => '糈', '' => '糅', '' => '糗', '' => '糨', '' => '艮', '' => '暨', '' => '羿', '' => '翎', '' => '翕', '' => '翥', '' => '翡', '' => '翦', '' => '翩', '' => '翮', '' => '翳', '' => '糸', '' => '絷', '' => '綦', '' => '綮', '' => '繇', '' => '纛', '' => '麸', '' => '麴', '' => '赳', '' => '趄', '' => '趔', '' => '趑', '' => '趱', '' => '赧', '' => '赭', '' => '豇', '' => '豉', '' => '酊', '' => '酐', '' => '酎', '' => '酏', '' => '酤', '@' => '魼', 'A' => '魽', 'B' => '魾', 'C' => '魿', 'D' => '鮀', 'E' => '鮁', 'F' => '鮂', 'G' => '鮃', 'H' => '鮄', 'I' => '鮅', 'J' => '鮆', 'K' => '鮇', 'L' => '鮈', 'M' => '鮉', 'N' => '鮊', 'O' => '鮋', 'P' => '鮌', 'Q' => '鮍', 'R' => '鮎', 'S' => '鮏', 'T' => '鮐', 'U' => '鮑', 'V' => '鮒', 'W' => '鮓', 'X' => '鮔', 'Y' => '鮕', 'Z' => '鮖', '[' => '鮗', '\\' => '鮘', ']' => '鮙', '^' => '鮚', '_' => '鮛', '`' => '鮜', 'a' => '鮝', 'b' => '鮞', 'c' => '鮟', 'd' => '鮠', 'e' => '鮡', 'f' => '鮢', 'g' => '鮣', 'h' => '鮤', 'i' => '鮥', 'j' => '鮦', 'k' => '鮧', 'l' => '鮨', 'm' => '鮩', 'n' => '鮪', 'o' => '鮫', 'p' => '鮬', 'q' => '鮭', 'r' => '鮮', 's' => '鮯', 't' => '鮰', 'u' => '鮱', 'v' => '鮲', 'w' => '鮳', 'x' => '鮴', 'y' => '鮵', 'z' => '鮶', '{' => '鮷', '|' => '鮸', '}' => '鮹', '~' => '鮺', '' => '鮻', '' => '鮼', '' => '鮽', '' => '鮾', '' => '鮿', '' => '鯀', '' => '鯁', '' => '鯂', '' => '鯃', '' => '鯄', '' => '鯅', '' => '鯆', '' => '鯇', '' => '鯈', '' => '鯉', '' => '鯊', '' => '鯋', '' => '鯌', '' => '鯍', '' => '鯎', '' => '鯏', '' => '鯐', '' => '鯑', '' => '鯒', '' => '鯓', '' => '鯔', '' => '鯕', '' => '鯖', '' => '鯗', '' => '鯘', '' => '鯙', '' => '鯚', '' => '鯛', '' => '酢', '' => '酡', '' => '酰', '' => '酩', '' => '酯', '' => '酽', '' => '酾', '' => '酲', '' => '酴', '' => '酹', '' => '醌', '' => '醅', '' => '醐', '' => '醍', '' => '醑', '' => '醢', '' => '醣', '' => '醪', '' => '醭', '' => '醮', '' => '醯', '' => '醵', '' => '醴', '' => '醺', '' => '豕', '' => '鹾', '' => '趸', '' => '跫', '' => '踅', '' => '蹙', '' => '蹩', '' => '趵', '' => '趿', '' => '趼', '' => '趺', '' => '跄', '' => '跖', '' => '跗', '' => '跚', '' => '跞', '' => '跎', '' => '跏', '' => '跛', '' => '跆', '' => '跬', '' => '跷', '' => '跸', '' => '跣', '' => '跹', '' => '跻', '' => '跤', '' => '踉', '' => '跽', '' => '踔', '' => '踝', '' => '踟', '' => '踬', '' => '踮', '' => '踣', '' => '踯', '' => '踺', '' => '蹀', '' => '踹', '' => '踵', '' => '踽', '' => '踱', '' => '蹉', '' => '蹁', '' => '蹂', '' => '蹑', '' => '蹒', '' => '蹊', '' => '蹰', '' => '蹶', '' => '蹼', '' => '蹯', '' => '蹴', '' => '躅', '' => '躏', '' => '躔', '' => '躐', '' => '躜', '' => '躞', '' => '豸', '' => '貂', '' => '貊', '' => '貅', '' => '貘', '' => '貔', '' => '斛', '' => '觖', '' => '觞', '' => '觚', '' => '觜', '@' => '鯜', 'A' => '鯝', 'B' => '鯞', 'C' => '鯟', 'D' => '鯠', 'E' => '鯡', 'F' => '鯢', 'G' => '鯣', 'H' => '鯤', 'I' => '鯥', 'J' => '鯦', 'K' => '鯧', 'L' => '鯨', 'M' => '鯩', 'N' => '鯪', 'O' => '鯫', 'P' => '鯬', 'Q' => '鯭', 'R' => '鯮', 'S' => '鯯', 'T' => '鯰', 'U' => '鯱', 'V' => '鯲', 'W' => '鯳', 'X' => '鯴', 'Y' => '鯵', 'Z' => '鯶', '[' => '鯷', '\\' => '鯸', ']' => '鯹', '^' => '鯺', '_' => '鯻', '`' => '鯼', 'a' => '鯽', 'b' => '鯾', 'c' => '鯿', 'd' => '鰀', 'e' => '鰁', 'f' => '鰂', 'g' => '鰃', 'h' => '鰄', 'i' => '鰅', 'j' => '鰆', 'k' => '鰇', 'l' => '鰈', 'm' => '鰉', 'n' => '鰊', 'o' => '鰋', 'p' => '鰌', 'q' => '鰍', 'r' => '鰎', 's' => '鰏', 't' => '鰐', 'u' => '鰑', 'v' => '鰒', 'w' => '鰓', 'x' => '鰔', 'y' => '鰕', 'z' => '鰖', '{' => '鰗', '|' => '鰘', '}' => '鰙', '~' => '鰚', '' => '鰛', '' => '鰜', '' => '鰝', '' => '鰞', '' => '鰟', '' => '鰠', '' => '鰡', '' => '鰢', '' => '鰣', '' => '鰤', '' => '鰥', '' => '鰦', '' => '鰧', '' => '鰨', '' => '鰩', '' => '鰪', '' => '鰫', '' => '鰬', '' => '鰭', '' => '鰮', '' => '鰯', '' => '鰰', '' => '鰱', '' => '鰲', '' => '鰳', '' => '鰴', '' => '鰵', '' => '鰶', '' => '鰷', '' => '鰸', '' => '鰹', '' => '鰺', '' => '鰻', '' => '觥', '' => '觫', '' => '觯', '' => '訾', '' => '謦', '' => '靓', '' => '雩', '' => '雳', '' => '雯', '' => '霆', '' => '霁', '' => '霈', '' => '霏', '' => '霎', '' => '霪', '' => '霭', '' => '霰', '' => '霾', '' => '龀', '' => '龃', '' => '龅', '' => '龆', '' => '龇', '' => '龈', '' => '龉', '' => '龊', '' => '龌', '' => '黾', '' => '鼋', '' => '鼍', '' => '隹', '' => '隼', '' => '隽', '' => '雎', '' => '雒', '' => '瞿', '' => '雠', '' => '銎', '' => '銮', '' => '鋈', '' => '錾', '' => '鍪', '' => '鏊', '' => '鎏', '' => '鐾', '' => '鑫', '' => '鱿', '' => '鲂', '' => '鲅', '' => '鲆', '' => '鲇', '' => '鲈', '' => '稣', '' => '鲋', '' => '鲎', '' => '鲐', '' => '鲑', '' => '鲒', '' => '鲔', '' => '鲕', '' => '鲚', '' => '鲛', '' => '鲞', '' => '鲟', '' => '鲠', '' => '鲡', '' => '鲢', '' => '鲣', '' => '鲥', '' => '鲦', '' => '鲧', '' => '鲨', '' => '鲩', '' => '鲫', '' => '鲭', '' => '鲮', '' => '鲰', '' => '鲱', '' => '鲲', '' => '鲳', '' => '鲴', '' => '鲵', '' => '鲶', '' => '鲷', '' => '鲺', '' => '鲻', '' => '鲼', '' => '鲽', '' => '鳄', '' => '鳅', '' => '鳆', '' => '鳇', '' => '鳊', '' => '鳋', '@' => '鰼', 'A' => '鰽', 'B' => '鰾', 'C' => '鰿', 'D' => '鱀', 'E' => '鱁', 'F' => '鱂', 'G' => '鱃', 'H' => '鱄', 'I' => '鱅', 'J' => '鱆', 'K' => '鱇', 'L' => '鱈', 'M' => '鱉', 'N' => '鱊', 'O' => '鱋', 'P' => '鱌', 'Q' => '鱍', 'R' => '鱎', 'S' => '鱏', 'T' => '鱐', 'U' => '鱑', 'V' => '鱒', 'W' => '鱓', 'X' => '鱔', 'Y' => '鱕', 'Z' => '鱖', '[' => '鱗', '\\' => '鱘', ']' => '鱙', '^' => '鱚', '_' => '鱛', '`' => '鱜', 'a' => '鱝', 'b' => '鱞', 'c' => '鱟', 'd' => '鱠', 'e' => '鱡', 'f' => '鱢', 'g' => '鱣', 'h' => '鱤', 'i' => '鱥', 'j' => '鱦', 'k' => '鱧', 'l' => '鱨', 'm' => '鱩', 'n' => '鱪', 'o' => '鱫', 'p' => '鱬', 'q' => '鱭', 'r' => '鱮', 's' => '鱯', 't' => '鱰', 'u' => '鱱', 'v' => '鱲', 'w' => '鱳', 'x' => '鱴', 'y' => '鱵', 'z' => '鱶', '{' => '鱷', '|' => '鱸', '}' => '鱹', '~' => '鱺', '' => '鱻', '' => '鱽', '' => '鱾', '' => '鲀', '' => '鲃', '' => '鲄', '' => '鲉', '' => '鲊', '' => '鲌', '' => '鲏', '' => '鲓', '' => '鲖', '' => '鲗', '' => '鲘', '' => '鲙', '' => '鲝', '' => '鲪', '' => '鲬', '' => '鲯', '' => '鲹', '' => '鲾', '' => '鲿', '' => '鳀', '' => '鳁', '' => '鳂', '' => '鳈', '' => '鳉', '' => '鳑', '' => '鳒', '' => '鳚', '' => '鳛', '' => '鳠', '' => '鳡', '' => '鳌', '' => '鳍', '' => '鳎', '' => '鳏', '' => '鳐', '' => '鳓', '' => '鳔', '' => '鳕', '' => '鳗', '' => '鳘', '' => '鳙', '' => '鳜', '' => '鳝', '' => '鳟', '' => '鳢', '' => '靼', '' => '鞅', '' => '鞑', '' => '鞒', '' => '鞔', '' => '鞯', '' => '鞫', '' => '鞣', '' => '鞲', '' => '鞴', '' => '骱', '' => '骰', '' => '骷', '' => '鹘', '' => '骶', '' => '骺', '' => '骼', '' => '髁', '' => '髀', '' => '髅', '' => '髂', '' => '髋', '' => '髌', '' => '髑', '' => '魅', '' => '魃', '' => '魇', '' => '魉', '' => '魈', '' => '魍', '' => '魑', '' => '飨', '' => '餍', '' => '餮', '' => '饕', '' => '饔', '' => '髟', '' => '髡', '' => '髦', '' => '髯', '' => '髫', '' => '髻', '' => '髭', '' => '髹', '' => '鬈', '' => '鬏', '' => '鬓', '' => '鬟', '' => '鬣', '' => '麽', '' => '麾', '' => '縻', '' => '麂', '' => '麇', '' => '麈', '' => '麋', '' => '麒', '' => '鏖', '' => '麝', '' => '麟', '' => '黛', '' => '黜', '' => '黝', '' => '黠', '' => '黟', '' => '黢', '' => '黩', '' => '黧', '' => '黥', '' => '黪', '' => '黯', '' => '鼢', '' => '鼬', '' => '鼯', '' => '鼹', '' => '鼷', '' => '鼽', '' => '鼾', '' => '齄', '@' => '鳣', 'A' => '鳤', 'B' => '鳥', 'C' => '鳦', 'D' => '鳧', 'E' => '鳨', 'F' => '鳩', 'G' => '鳪', 'H' => '鳫', 'I' => '鳬', 'J' => '鳭', 'K' => '鳮', 'L' => '鳯', 'M' => '鳰', 'N' => '鳱', 'O' => '鳲', 'P' => '鳳', 'Q' => '鳴', 'R' => '鳵', 'S' => '鳶', 'T' => '鳷', 'U' => '鳸', 'V' => '鳹', 'W' => '鳺', 'X' => '鳻', 'Y' => '鳼', 'Z' => '鳽', '[' => '鳾', '\\' => '鳿', ']' => '鴀', '^' => '鴁', '_' => '鴂', '`' => '鴃', 'a' => '鴄', 'b' => '鴅', 'c' => '鴆', 'd' => '鴇', 'e' => '鴈', 'f' => '鴉', 'g' => '鴊', 'h' => '鴋', 'i' => '鴌', 'j' => '鴍', 'k' => '鴎', 'l' => '鴏', 'm' => '鴐', 'n' => '鴑', 'o' => '鴒', 'p' => '鴓', 'q' => '鴔', 'r' => '鴕', 's' => '鴖', 't' => '鴗', 'u' => '鴘', 'v' => '鴙', 'w' => '鴚', 'x' => '鴛', 'y' => '鴜', 'z' => '鴝', '{' => '鴞', '|' => '鴟', '}' => '鴠', '~' => '鴡', '' => '鴢', '' => '鴣', '' => '鴤', '' => '鴥', '' => '鴦', '' => '鴧', '' => '鴨', '' => '鴩', '' => '鴪', '' => '鴫', '' => '鴬', '' => '鴭', '' => '鴮', '' => '鴯', '' => '鴰', '' => '鴱', '' => '鴲', '' => '鴳', '' => '鴴', '' => '鴵', '' => '鴶', '' => '鴷', '' => '鴸', '' => '鴹', '' => '鴺', '' => '鴻', '' => '鴼', '' => '鴽', '' => '鴾', '' => '鴿', '' => '鵀', '' => '鵁', '' => '鵂', '@' => '鵃', 'A' => '鵄', 'B' => '鵅', 'C' => '鵆', 'D' => '鵇', 'E' => '鵈', 'F' => '鵉', 'G' => '鵊', 'H' => '鵋', 'I' => '鵌', 'J' => '鵍', 'K' => '鵎', 'L' => '鵏', 'M' => '鵐', 'N' => '鵑', 'O' => '鵒', 'P' => '鵓', 'Q' => '鵔', 'R' => '鵕', 'S' => '鵖', 'T' => '鵗', 'U' => '鵘', 'V' => '鵙', 'W' => '鵚', 'X' => '鵛', 'Y' => '鵜', 'Z' => '鵝', '[' => '鵞', '\\' => '鵟', ']' => '鵠', '^' => '鵡', '_' => '鵢', '`' => '鵣', 'a' => '鵤', 'b' => '鵥', 'c' => '鵦', 'd' => '鵧', 'e' => '鵨', 'f' => '鵩', 'g' => '鵪', 'h' => '鵫', 'i' => '鵬', 'j' => '鵭', 'k' => '鵮', 'l' => '鵯', 'm' => '鵰', 'n' => '鵱', 'o' => '鵲', 'p' => '鵳', 'q' => '鵴', 'r' => '鵵', 's' => '鵶', 't' => '鵷', 'u' => '鵸', 'v' => '鵹', 'w' => '鵺', 'x' => '鵻', 'y' => '鵼', 'z' => '鵽', '{' => '鵾', '|' => '鵿', '}' => '鶀', '~' => '鶁', '' => '鶂', '' => '鶃', '' => '鶄', '' => '鶅', '' => '鶆', '' => '鶇', '' => '鶈', '' => '鶉', '' => '鶊', '' => '鶋', '' => '鶌', '' => '鶍', '' => '鶎', '' => '鶏', '' => '鶐', '' => '鶑', '' => '鶒', '' => '鶓', '' => '鶔', '' => '鶕', '' => '鶖', '' => '鶗', '' => '鶘', '' => '鶙', '' => '鶚', '' => '鶛', '' => '鶜', '' => '鶝', '' => '鶞', '' => '鶟', '' => '鶠', '' => '鶡', '' => '鶢', '@' => '鶣', 'A' => '鶤', 'B' => '鶥', 'C' => '鶦', 'D' => '鶧', 'E' => '鶨', 'F' => '鶩', 'G' => '鶪', 'H' => '鶫', 'I' => '鶬', 'J' => '鶭', 'K' => '鶮', 'L' => '鶯', 'M' => '鶰', 'N' => '鶱', 'O' => '鶲', 'P' => '鶳', 'Q' => '鶴', 'R' => '鶵', 'S' => '鶶', 'T' => '鶷', 'U' => '鶸', 'V' => '鶹', 'W' => '鶺', 'X' => '鶻', 'Y' => '鶼', 'Z' => '鶽', '[' => '鶾', '\\' => '鶿', ']' => '鷀', '^' => '鷁', '_' => '鷂', '`' => '鷃', 'a' => '鷄', 'b' => '鷅', 'c' => '鷆', 'd' => '鷇', 'e' => '鷈', 'f' => '鷉', 'g' => '鷊', 'h' => '鷋', 'i' => '鷌', 'j' => '鷍', 'k' => '鷎', 'l' => '鷏', 'm' => '鷐', 'n' => '鷑', 'o' => '鷒', 'p' => '鷓', 'q' => '鷔', 'r' => '鷕', 's' => '鷖', 't' => '鷗', 'u' => '鷘', 'v' => '鷙', 'w' => '鷚', 'x' => '鷛', 'y' => '鷜', 'z' => '鷝', '{' => '鷞', '|' => '鷟', '}' => '鷠', '~' => '鷡', '' => '鷢', '' => '鷣', '' => '鷤', '' => '鷥', '' => '鷦', '' => '鷧', '' => '鷨', '' => '鷩', '' => '鷪', '' => '鷫', '' => '鷬', '' => '鷭', '' => '鷮', '' => '鷯', '' => '鷰', '' => '鷱', '' => '鷲', '' => '鷳', '' => '鷴', '' => '鷵', '' => '鷶', '' => '鷷', '' => '鷸', '' => '鷹', '' => '鷺', '' => '鷻', '' => '鷼', '' => '鷽', '' => '鷾', '' => '鷿', '' => '鸀', '' => '鸁', '' => '鸂', '@' => '鸃', 'A' => '鸄', 'B' => '鸅', 'C' => '鸆', 'D' => '鸇', 'E' => '鸈', 'F' => '鸉', 'G' => '鸊', 'H' => '鸋', 'I' => '鸌', 'J' => '鸍', 'K' => '鸎', 'L' => '鸏', 'M' => '鸐', 'N' => '鸑', 'O' => '鸒', 'P' => '鸓', 'Q' => '鸔', 'R' => '鸕', 'S' => '鸖', 'T' => '鸗', 'U' => '鸘', 'V' => '鸙', 'W' => '鸚', 'X' => '鸛', 'Y' => '鸜', 'Z' => '鸝', '[' => '鸞', '\\' => '鸤', ']' => '鸧', '^' => '鸮', '_' => '鸰', '`' => '鸴', 'a' => '鸻', 'b' => '鸼', 'c' => '鹀', 'd' => '鹍', 'e' => '鹐', 'f' => '鹒', 'g' => '鹓', 'h' => '鹔', 'i' => '鹖', 'j' => '鹙', 'k' => '鹝', 'l' => '鹟', 'm' => '鹠', 'n' => '鹡', 'o' => '鹢', 'p' => '鹥', 'q' => '鹮', 'r' => '鹯', 's' => '鹲', 't' => '鹴', 'u' => '鹵', 'v' => '鹶', 'w' => '鹷', 'x' => '鹸', 'y' => '鹹', 'z' => '鹺', '{' => '鹻', '|' => '鹼', '}' => '鹽', '~' => '麀', '' => '麁', '' => '麃', '' => '麄', '' => '麅', '' => '麆', '' => '麉', '' => '麊', '' => '麌', '' => '麍', '' => '麎', '' => '麏', '' => '麐', '' => '麑', '' => '麔', '' => '麕', '' => '麖', '' => '麗', '' => '麘', '' => '麙', '' => '麚', '' => '麛', '' => '麜', '' => '麞', '' => '麠', '' => '麡', '' => '麢', '' => '麣', '' => '麤', '' => '麥', '' => '麧', '' => '麨', '' => '麩', '' => '麪', '@' => '麫', 'A' => '麬', 'B' => '麭', 'C' => '麮', 'D' => '麯', 'E' => '麰', 'F' => '麱', 'G' => '麲', 'H' => '麳', 'I' => '麵', 'J' => '麶', 'K' => '麷', 'L' => '麹', 'M' => '麺', 'N' => '麼', 'O' => '麿', 'P' => '黀', 'Q' => '黁', 'R' => '黂', 'S' => '黃', 'T' => '黅', 'U' => '黆', 'V' => '黇', 'W' => '黈', 'X' => '黊', 'Y' => '黋', 'Z' => '黌', '[' => '黐', '\\' => '黒', ']' => '黓', '^' => '黕', '_' => '黖', '`' => '黗', 'a' => '黙', 'b' => '黚', 'c' => '點', 'd' => '黡', 'e' => '黣', 'f' => '黤', 'g' => '黦', 'h' => '黨', 'i' => '黫', 'j' => '黬', 'k' => '黭', 'l' => '黮', 'm' => '黰', 'n' => '黱', 'o' => '黲', 'p' => '黳', 'q' => '黴', 'r' => '黵', 's' => '黶', 't' => '黷', 'u' => '黸', 'v' => '黺', 'w' => '黽', 'x' => '黿', 'y' => '鼀', 'z' => '鼁', '{' => '鼂', '|' => '鼃', '}' => '鼄', '~' => '鼅', '' => '鼆', '' => '鼇', '' => '鼈', '' => '鼉', '' => '鼊', '' => '鼌', '' => '鼏', '' => '鼑', '' => '鼒', '' => '鼔', '' => '鼕', '' => '鼖', '' => '鼘', '' => '鼚', '' => '鼛', '' => '鼜', '' => '鼝', '' => '鼞', '' => '鼟', '' => '鼡', '' => '鼣', '' => '鼤', '' => '鼥', '' => '鼦', '' => '鼧', '' => '鼨', '' => '鼩', '' => '鼪', '' => '鼫', '' => '鼭', '' => '鼮', '' => '鼰', '' => '鼱', '@' => '鼲', 'A' => '鼳', 'B' => '鼴', 'C' => '鼵', 'D' => '鼶', 'E' => '鼸', 'F' => '鼺', 'G' => '鼼', 'H' => '鼿', 'I' => '齀', 'J' => '齁', 'K' => '齂', 'L' => '齃', 'M' => '齅', 'N' => '齆', 'O' => '齇', 'P' => '齈', 'Q' => '齉', 'R' => '齊', 'S' => '齋', 'T' => '齌', 'U' => '齍', 'V' => '齎', 'W' => '齏', 'X' => '齒', 'Y' => '齓', 'Z' => '齔', '[' => '齕', '\\' => '齖', ']' => '齗', '^' => '齘', '_' => '齙', '`' => '齚', 'a' => '齛', 'b' => '齜', 'c' => '齝', 'd' => '齞', 'e' => '齟', 'f' => '齠', 'g' => '齡', 'h' => '齢', 'i' => '齣', 'j' => '齤', 'k' => '齥', 'l' => '齦', 'm' => '齧', 'n' => '齨', 'o' => '齩', 'p' => '齪', 'q' => '齫', 'r' => '齬', 's' => '齭', 't' => '齮', 'u' => '齯', 'v' => '齰', 'w' => '齱', 'x' => '齲', 'y' => '齳', 'z' => '齴', '{' => '齵', '|' => '齶', '}' => '齷', '~' => '齸', '' => '齹', '' => '齺', '' => '齻', '' => '齼', '' => '齽', '' => '齾', '' => '龁', '' => '龂', '' => '龍', '' => '龎', '' => '龏', '' => '龐', '' => '龑', '' => '龒', '' => '龓', '' => '龔', '' => '龕', '' => '龖', '' => '龗', '' => '龘', '' => '龜', '' => '龝', '' => '龞', '' => '龡', '' => '龢', '' => '龣', '' => '龤', '' => '龥', '' => '郎', '' => '凉', '' => '秊', '' => '裏', '' => '隣', '@' => '兀', 'A' => '嗀', 'B' => '﨎', 'C' => '﨏', 'D' => '﨑', 'E' => '﨓', 'F' => '﨔', 'G' => '礼', 'H' => '﨟', 'I' => '蘒', 'J' => '﨡', 'K' => '﨣', 'L' => '﨤', 'M' => '﨧', 'N' => '﨨', 'O' => '﨩', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1257.php000064400000007040150432043200016650 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '‚', '' => '„', '' => '…', '' => '†', '' => '‡', '' => '‰', '' => '‹', '' => '¨', '' => 'ˇ', '' => '¸', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '™', '' => '›', '' => '¯', '' => '˛', '' => ' ', '' => '¢', '' => '£', '' => '¤', '' => '¦', '' => '§', '' => 'Ø', '' => '©', '' => 'Ŗ', '' => '«', '' => '¬', '' => '­', '' => '®', '' => 'Æ', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => 'ø', '' => '¹', '' => 'ŗ', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => 'æ', '' => 'Ą', '' => 'Į', '' => 'Ā', '' => 'Ć', '' => 'Ä', '' => 'Å', '' => 'Ę', '' => 'Ē', '' => 'Č', '' => 'É', '' => 'Ź', '' => 'Ė', '' => 'Ģ', '' => 'Ķ', '' => 'Ī', '' => 'Ļ', '' => 'Š', '' => 'Ń', '' => 'Ņ', '' => 'Ó', '' => 'Ō', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ų', '' => 'Ł', '' => 'Ś', '' => 'Ū', '' => 'Ü', '' => 'Ż', '' => 'Ž', '' => 'ß', '' => 'ą', '' => 'į', '' => 'ā', '' => 'ć', '' => 'ä', '' => 'å', '' => 'ę', '' => 'ē', '' => 'č', '' => 'é', '' => 'ź', '' => 'ė', '' => 'ģ', '' => 'ķ', '' => 'ī', '' => 'ļ', '' => 'š', '' => 'ń', '' => 'ņ', '' => 'ó', '' => 'ō', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ų', '' => 'ł', '' => 'ś', '' => 'ū', '' => 'ü', '' => 'ż', '' => 'ž', '' => '˙', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-10.php000064400000007304150432043200016210 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'Ą', '' => 'Ē', '' => 'Ģ', '' => 'Ī', '' => 'Ĩ', '' => 'Ķ', '' => '§', '' => 'Ļ', '' => 'Đ', '' => 'Š', '' => 'Ŧ', '' => 'Ž', '' => '­', '' => 'Ū', '' => 'Ŋ', '' => '°', '' => 'ą', '' => 'ē', '' => 'ģ', '' => 'ī', '' => 'ĩ', '' => 'ķ', '' => '·', '' => 'ļ', '' => 'đ', '' => 'š', '' => 'ŧ', '' => 'ž', '' => '―', '' => 'ū', '' => 'ŋ', '' => 'Ā', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Į', '' => 'Č', '' => 'É', '' => 'Ę', '' => 'Ë', '' => 'Ė', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ð', '' => 'Ņ', '' => 'Ō', '' => 'Ó', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => 'Ũ', '' => 'Ø', '' => 'Ų', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ý', '' => 'Þ', '' => 'ß', '' => 'ā', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'į', '' => 'č', '' => 'é', '' => 'ę', '' => 'ë', '' => 'ė', '' => 'í', '' => 'î', '' => 'ï', '' => 'ð', '' => 'ņ', '' => 'ō', '' => 'ó', '' => 'ô', '' => 'õ', '' => 'ö', '' => 'ũ', '' => 'ø', '' => 'ų', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ý', '' => 'þ', '' => 'ĸ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp850.php000064400000007341150432043200015425 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'ä', '' => 'à', '' => 'å', '' => 'ç', '' => 'ê', '' => 'ë', '' => 'è', '' => 'ï', '' => 'î', '' => 'ì', '' => 'Ä', '' => 'Å', '' => 'É', '' => 'æ', '' => 'Æ', '' => 'ô', '' => 'ö', '' => 'ò', '' => 'û', '' => 'ù', '' => 'ÿ', '' => 'Ö', '' => 'Ü', '' => 'ø', '' => '£', '' => 'Ø', '' => '×', '' => 'ƒ', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'ñ', '' => 'Ñ', '' => 'ª', '' => 'º', '' => '¿', '' => '®', '' => '¬', '' => '½', '' => '¼', '' => '¡', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => 'Á', '' => 'Â', '' => 'À', '' => '©', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '¢', '' => '¥', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => 'ã', '' => 'Ã', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '¤', '' => 'ð', '' => 'Ð', '' => 'Ê', '' => 'Ë', '' => 'È', '' => 'ı', '' => 'Í', '' => 'Î', '' => 'Ï', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '¦', '' => 'Ì', '' => '▀', '' => 'Ó', '' => 'ß', '' => 'Ô', '' => 'Ò', '' => 'õ', '' => 'Õ', '' => 'µ', '' => 'þ', '' => 'Þ', '' => 'Ú', '' => 'Û', '' => 'Ù', '' => 'ý', '' => 'Ý', '' => '¯', '' => '´', '' => '­', '' => '±', '' => '‗', '' => '¾', '' => '¶', '' => '§', '' => '÷', '' => '¸', '' => '°', '' => '¨', '' => '·', '' => '¹', '' => '³', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp857.php000064400000007263150432043200015437 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'ä', '' => 'à', '' => 'å', '' => 'ç', '' => 'ê', '' => 'ë', '' => 'è', '' => 'ï', '' => 'î', '' => 'ı', '' => 'Ä', '' => 'Å', '' => 'É', '' => 'æ', '' => 'Æ', '' => 'ô', '' => 'ö', '' => 'ò', '' => 'û', '' => 'ù', '' => 'İ', '' => 'Ö', '' => 'Ü', '' => 'ø', '' => '£', '' => 'Ø', '' => 'Ş', '' => 'ş', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'ñ', '' => 'Ñ', '' => 'Ğ', '' => 'ğ', '' => '¿', '' => '®', '' => '¬', '' => '½', '' => '¼', '' => '¡', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => 'Á', '' => 'Â', '' => 'À', '' => '©', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '¢', '' => '¥', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => 'ã', '' => 'Ã', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '¤', '' => 'º', '' => 'ª', '' => 'Ê', '' => 'Ë', '' => 'È', '' => 'Í', '' => 'Î', '' => 'Ï', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '¦', '' => 'Ì', '' => '▀', '' => 'Ó', '' => 'ß', '' => 'Ô', '' => 'Ò', '' => 'õ', '' => 'Õ', '' => 'µ', '' => '×', '' => 'Ú', '' => 'Û', '' => 'Ù', '' => 'ì', '' => 'ÿ', '' => '¯', '' => '´', '' => '­', '' => '±', '' => '¾', '' => '¶', '' => '§', '' => '÷', '' => '¸', '' => '°', '' => '¨', '' => '·', '' => '¹', '' => '³', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp424.php000064400000006212150432043200015416 0ustar00 '', '' => '', '' => '', '' => '', '' => 'œ', '' => ' ', '' => '†', '' => '', '' => '—', ' ' => '', ' ' => 'Ž', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '…', '' => '', '' => '‡', '' => '', '' => '', '' => '’', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => '€', '!' => '', '"' => '‚', '#' => 'ƒ', '$' => '„', '%' => ' ', '&' => '', '\'' => '', '(' => 'ˆ', ')' => '‰', '*' => 'Š', '+' => '‹', ',' => 'Œ', '-' => '', '.' => '', '/' => '', 0 => '', 1 => '‘', 2 => '', 3 => '“', 4 => '”', 5 => '•', 6 => '–', 7 => '', 8 => '˜', 9 => '™', ':' => 'š', ';' => '›', '<' => '', '=' => '', '>' => 'ž', '?' => '', '@' => ' ', 'A' => 'א', 'B' => 'ב', 'C' => 'ג', 'D' => 'ד', 'E' => 'ה', 'F' => 'ו', 'G' => 'ז', 'H' => 'ח', 'I' => 'ט', 'J' => '¢', 'K' => '.', 'L' => '<', 'M' => '(', 'N' => '+', 'O' => '|', 'P' => '&', 'Q' => 'י', 'R' => 'ך', 'S' => 'כ', 'T' => 'ל', 'U' => 'ם', 'V' => 'מ', 'W' => 'ן', 'X' => 'נ', 'Y' => 'ס', 'Z' => '!', '[' => '$', '\\' => '*', ']' => ')', '^' => ';', '_' => '¬', '`' => '-', 'a' => '/', 'b' => 'ע', 'c' => 'ף', 'd' => 'פ', 'e' => 'ץ', 'f' => 'צ', 'g' => 'ק', 'h' => 'ר', 'i' => 'ש', 'j' => '¦', 'k' => ',', 'l' => '%', 'm' => '_', 'n' => '>', 'o' => '?', 'q' => 'ת', 't' => ' ', 'x' => '‗', 'y' => '`', 'z' => ':', '{' => '#', '|' => '@', '}' => '\'', '~' => '=', '' => '"', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => '«', '' => '»', '' => '±', '' => '°', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => '¸', '' => '¤', '' => 'µ', '' => '~', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => '®', '' => '^', '' => '£', '' => '¥', '' => '·', '' => '©', '' => '§', '' => '¶', '' => '¼', '' => '½', '' => '¾', '' => '[', '' => ']', '' => '¯', '' => '¨', '' => '´', '' => '×', '' => '{', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => '­', '' => '}', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => '¹', '' => '\\', '' => '÷', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => '²', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => '³', '' => 'Ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp775.php000064400000007347150432043200015441 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ć', '' => 'ü', '' => 'é', '' => 'ā', '' => 'ä', '' => 'ģ', '' => 'å', '' => 'ć', '' => 'ł', '' => 'ē', '' => 'Ŗ', '' => 'ŗ', '' => 'ī', '' => 'Ź', '' => 'Ä', '' => 'Å', '' => 'É', '' => 'æ', '' => 'Æ', '' => 'ō', '' => 'ö', '' => 'Ģ', '' => '¢', '' => 'Ś', '' => 'ś', '' => 'Ö', '' => 'Ü', '' => 'ø', '' => '£', '' => 'Ø', '' => '×', '' => '¤', '' => 'Ā', '' => 'Ī', '' => 'ó', '' => 'Ż', '' => 'ż', '' => 'ź', '' => '”', '' => '¦', '' => '©', '' => '®', '' => '¬', '' => '½', '' => '¼', '' => 'Ł', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => 'Ą', '' => 'Č', '' => 'Ę', '' => 'Ė', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => 'Į', '' => 'Š', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => 'Ų', '' => 'Ū', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => 'Ž', '' => 'ą', '' => 'č', '' => 'ę', '' => 'ė', '' => 'į', '' => 'š', '' => 'ų', '' => 'ū', '' => 'ž', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'Ó', '' => 'ß', '' => 'Ō', '' => 'Ń', '' => 'õ', '' => 'Õ', '' => 'µ', '' => 'ń', '' => 'Ķ', '' => 'ķ', '' => 'Ļ', '' => 'ļ', '' => 'ņ', '' => 'Ē', '' => 'Ņ', '' => '’', '' => '­', '' => '±', '' => '“', '' => '¾', '' => '¶', '' => '§', '' => '÷', '' => '„', '' => '°', '' => '∙', '' => '·', '' => '¹', '' => '³', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1256.php000064400000007330150432043200016651 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => 'پ', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'ٹ', '' => '‹', '' => 'Œ', '' => 'چ', '' => 'ژ', '' => 'ڈ', '' => 'گ', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => 'ک', '' => '™', '' => 'ڑ', '' => '›', '' => 'œ', '' => '‌', '' => '‍', '' => 'ں', '' => ' ', '' => '،', '' => '¢', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => 'ھ', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => '؛', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '؟', '' => 'ہ', '' => 'ء', '' => 'آ', '' => 'أ', '' => 'ؤ', '' => 'إ', '' => 'ئ', '' => 'ا', '' => 'ب', '' => 'ة', '' => 'ت', '' => 'ث', '' => 'ج', '' => 'ح', '' => 'خ', '' => 'د', '' => 'ذ', '' => 'ر', '' => 'ز', '' => 'س', '' => 'ش', '' => 'ص', '' => 'ض', '' => '×', '' => 'ط', '' => 'ظ', '' => 'ع', '' => 'غ', '' => 'ـ', '' => 'ف', '' => 'ق', '' => 'ك', '' => 'à', '' => 'ل', '' => 'â', '' => 'م', '' => 'ن', '' => 'ه', '' => 'و', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ى', '' => 'ي', '' => 'î', '' => 'ï', '' => 'ً', '' => 'ٌ', '' => 'ٍ', '' => 'َ', '' => 'ô', '' => 'ُ', '' => 'ِ', '' => '÷', '' => 'ّ', '' => 'ù', '' => 'ْ', '' => 'û', '' => 'ü', '' => '‎', '' => '‏', '' => 'ے', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp866.php000064400000007367150432043200015444 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'А', '' => 'Б', '' => 'В', '' => 'Г', '' => 'Д', '' => 'Е', '' => 'Ж', '' => 'З', '' => 'И', '' => 'Й', '' => 'К', '' => 'Л', '' => 'М', '' => 'Н', '' => 'О', '' => 'П', '' => 'Р', '' => 'С', '' => 'Т', '' => 'У', '' => 'Ф', '' => 'Х', '' => 'Ц', '' => 'Ч', '' => 'Ш', '' => 'Щ', '' => 'Ъ', '' => 'Ы', '' => 'Ь', '' => 'Э', '' => 'Ю', '' => 'Я', '' => 'а', '' => 'б', '' => 'в', '' => 'г', '' => 'д', '' => 'е', '' => 'ж', '' => 'з', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ф', '' => 'х', '' => 'ц', '' => 'ч', '' => 'ш', '' => 'щ', '' => 'ъ', '' => 'ы', '' => 'ь', '' => 'э', '' => 'ю', '' => 'я', '' => 'Ё', '' => 'ё', '' => 'Є', '' => 'є', '' => 'Ї', '' => 'ї', '' => 'Ў', '' => 'ў', '' => '°', '' => '∙', '' => '·', '' => '√', '' => '№', '' => '¤', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-11.php000064400000007242150432043200016212 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'ก', '' => 'ข', '' => 'ฃ', '' => 'ค', '' => 'ฅ', '' => 'ฆ', '' => 'ง', '' => 'จ', '' => 'ฉ', '' => 'ช', '' => 'ซ', '' => 'ฌ', '' => 'ญ', '' => 'ฎ', '' => 'ฏ', '' => 'ฐ', '' => 'ฑ', '' => 'ฒ', '' => 'ณ', '' => 'ด', '' => 'ต', '' => 'ถ', '' => 'ท', '' => 'ธ', '' => 'น', '' => 'บ', '' => 'ป', '' => 'ผ', '' => 'ฝ', '' => 'พ', '' => 'ฟ', '' => 'ภ', '' => 'ม', '' => 'ย', '' => 'ร', '' => 'ฤ', '' => 'ล', '' => 'ฦ', '' => 'ว', '' => 'ศ', '' => 'ษ', '' => 'ส', '' => 'ห', '' => 'ฬ', '' => 'อ', '' => 'ฮ', '' => 'ฯ', '' => 'ะ', '' => 'ั', '' => 'า', '' => 'ำ', '' => 'ิ', '' => 'ี', '' => 'ึ', '' => 'ื', '' => 'ุ', '' => 'ู', '' => 'ฺ', '' => '฿', '' => 'เ', '' => 'แ', '' => 'โ', '' => 'ใ', '' => 'ไ', '' => 'ๅ', '' => 'ๆ', '' => '็', '' => '่', '' => '้', '' => '๊', '' => '๋', '' => '์', '' => 'ํ', '' => '๎', '' => '๏', '' => '๐', '' => '๑', '' => '๒', '' => '๓', '' => '๔', '' => '๕', '' => '๖', '' => '๗', '' => '๘', '' => '๙', '' => '๚', '' => '๛', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp500.php000064400000007303150432043200015413 0ustar00 '', '' => '', '' => '', '' => '', '' => 'œ', '' => ' ', '' => '†', '' => '', '' => '—', ' ' => '', ' ' => 'Ž', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '…', '' => '', '' => '‡', '' => '', '' => '', '' => '’', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => '€', '!' => '', '"' => '‚', '#' => 'ƒ', '$' => '„', '%' => ' ', '&' => '', '\'' => '', '(' => 'ˆ', ')' => '‰', '*' => 'Š', '+' => '‹', ',' => 'Œ', '-' => '', '.' => '', '/' => '', 0 => '', 1 => '‘', 2 => '', 3 => '“', 4 => '”', 5 => '•', 6 => '–', 7 => '', 8 => '˜', 9 => '™', ':' => 'š', ';' => '›', '<' => '', '=' => '', '>' => 'ž', '?' => '', '@' => ' ', 'A' => ' ', 'B' => 'â', 'C' => 'ä', 'D' => 'à', 'E' => 'á', 'F' => 'ã', 'G' => 'å', 'H' => 'ç', 'I' => 'ñ', 'J' => '[', 'K' => '.', 'L' => '<', 'M' => '(', 'N' => '+', 'O' => '!', 'P' => '&', 'Q' => 'é', 'R' => 'ê', 'S' => 'ë', 'T' => 'è', 'U' => 'í', 'V' => 'î', 'W' => 'ï', 'X' => 'ì', 'Y' => 'ß', 'Z' => ']', '[' => '$', '\\' => '*', ']' => ')', '^' => ';', '_' => '^', '`' => '-', 'a' => '/', 'b' => 'Â', 'c' => 'Ä', 'd' => 'À', 'e' => 'Á', 'f' => 'Ã', 'g' => 'Å', 'h' => 'Ç', 'i' => 'Ñ', 'j' => '¦', 'k' => ',', 'l' => '%', 'm' => '_', 'n' => '>', 'o' => '?', 'p' => 'ø', 'q' => 'É', 'r' => 'Ê', 's' => 'Ë', 't' => 'È', 'u' => 'Í', 'v' => 'Î', 'w' => 'Ï', 'x' => 'Ì', 'y' => '`', 'z' => ':', '{' => '#', '|' => '@', '}' => '\'', '~' => '=', '' => '"', '' => 'Ø', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => '«', '' => '»', '' => 'ð', '' => 'ý', '' => 'þ', '' => '±', '' => '°', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 'ª', '' => 'º', '' => 'æ', '' => '¸', '' => 'Æ', '' => '¤', '' => 'µ', '' => '~', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => '¡', '' => '¿', '' => 'Ð', '' => 'Ý', '' => 'Þ', '' => '®', '' => '¢', '' => '£', '' => '¥', '' => '·', '' => '©', '' => '§', '' => '¶', '' => '¼', '' => '½', '' => '¾', '' => '¬', '' => '|', '' => '¯', '' => '¨', '' => '´', '' => '×', '' => '{', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => '­', '' => 'ô', '' => 'ö', '' => 'ò', '' => 'ó', '' => 'õ', '' => '}', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => '¹', '' => 'û', '' => 'ü', '' => 'ù', '' => 'ú', '' => 'ÿ', '' => '\\', '' => '÷', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => '²', '' => 'Ô', '' => 'Ö', '' => 'Ò', '' => 'Ó', '' => 'Õ', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => '³', '' => 'Û', '' => 'Ü', '' => 'Ù', '' => 'Ú', '' => 'Ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-14.php000064400000007331150432043200016214 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'Ḃ', '' => 'ḃ', '' => '£', '' => 'Ċ', '' => 'ċ', '' => 'Ḋ', '' => '§', '' => 'Ẁ', '' => '©', '' => 'Ẃ', '' => 'ḋ', '' => 'Ỳ', '' => '­', '' => '®', '' => 'Ÿ', '' => 'Ḟ', '' => 'ḟ', '' => 'Ġ', '' => 'ġ', '' => 'Ṁ', '' => 'ṁ', '' => '¶', '' => 'Ṗ', '' => 'ẁ', '' => 'ṗ', '' => 'ẃ', '' => 'Ṡ', '' => 'ỳ', '' => 'Ẅ', '' => 'ẅ', '' => 'ṡ', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ŵ', '' => 'Ñ', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => 'Ṫ', '' => 'Ø', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ý', '' => 'Ŷ', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'ŵ', '' => 'ñ', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'õ', '' => 'ö', '' => 'ṫ', '' => 'ø', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ý', '' => 'ŷ', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-6.php000064400000006040150432043200016131 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '¤', '' => '،', '' => '­', '' => '؛', '' => '؟', '' => 'ء', '' => 'آ', '' => 'أ', '' => 'ؤ', '' => 'إ', '' => 'ئ', '' => 'ا', '' => 'ب', '' => 'ة', '' => 'ت', '' => 'ث', '' => 'ج', '' => 'ح', '' => 'خ', '' => 'د', '' => 'ذ', '' => 'ر', '' => 'ز', '' => 'س', '' => 'ش', '' => 'ص', '' => 'ض', '' => 'ط', '' => 'ظ', '' => 'ع', '' => 'غ', '' => 'ـ', '' => 'ف', '' => 'ق', '' => 'ك', '' => 'ل', '' => 'م', '' => 'ن', '' => 'ه', '' => 'و', '' => 'ى', '' => 'ي', '' => 'ً', '' => 'ٌ', '' => 'ٍ', '' => 'َ', '' => 'ُ', '' => 'ِ', '' => 'ّ', '' => 'ْ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-1.php000064400000007303150432043200016127 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '¡', '' => '¢', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => 'ª', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => 'º', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '¿', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ð', '' => 'Ñ', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ø', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ý', '' => 'Þ', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'ð', '' => 'ñ', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ø', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ý', '' => 'þ', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp860.php000064400000007400150432043200015422 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'ã', '' => 'à', '' => 'Á', '' => 'ç', '' => 'ê', '' => 'Ê', '' => 'è', '' => 'Í', '' => 'Ô', '' => 'ì', '' => 'Ã', '' => 'Â', '' => 'É', '' => 'À', '' => 'È', '' => 'ô', '' => 'õ', '' => 'ò', '' => 'Ú', '' => 'ù', '' => 'Ì', '' => 'Õ', '' => 'Ü', '' => '¢', '' => '£', '' => 'Ù', '' => '₧', '' => 'Ó', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'ñ', '' => 'Ñ', '' => 'ª', '' => 'º', '' => '¿', '' => 'Ò', '' => '¬', '' => '½', '' => '¼', '' => '¡', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'α', '' => 'ß', '' => 'Γ', '' => 'π', '' => 'Σ', '' => 'σ', '' => 'µ', '' => 'τ', '' => 'Φ', '' => 'Θ', '' => 'Ω', '' => 'δ', '' => '∞', '' => 'φ', '' => 'ε', '' => '∩', '' => '≡', '' => '±', '' => '≥', '' => '≤', '' => '⌠', '' => '⌡', '' => '÷', '' => '≈', '' => '°', '' => '∙', '' => '·', '' => '√', '' => 'ⁿ', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-13.php000064400000007307150432043200016216 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '”', '' => '¢', '' => '£', '' => '¤', '' => '„', '' => '¦', '' => '§', '' => 'Ø', '' => '©', '' => 'Ŗ', '' => '«', '' => '¬', '' => '­', '' => '®', '' => 'Æ', '' => '°', '' => '±', '' => '²', '' => '³', '' => '“', '' => 'µ', '' => '¶', '' => '·', '' => 'ø', '' => '¹', '' => 'ŗ', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => 'æ', '' => 'Ą', '' => 'Į', '' => 'Ā', '' => 'Ć', '' => 'Ä', '' => 'Å', '' => 'Ę', '' => 'Ē', '' => 'Č', '' => 'É', '' => 'Ź', '' => 'Ė', '' => 'Ģ', '' => 'Ķ', '' => 'Ī', '' => 'Ļ', '' => 'Š', '' => 'Ń', '' => 'Ņ', '' => 'Ó', '' => 'Ō', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ų', '' => 'Ł', '' => 'Ś', '' => 'Ū', '' => 'Ü', '' => 'Ż', '' => 'Ž', '' => 'ß', '' => 'ą', '' => 'į', '' => 'ā', '' => 'ć', '' => 'ä', '' => 'å', '' => 'ę', '' => 'ē', '' => 'č', '' => 'é', '' => 'ź', '' => 'ė', '' => 'ģ', '' => 'ķ', '' => 'ī', '' => 'ļ', '' => 'š', '' => 'ń', '' => 'ņ', '' => 'ó', '' => 'ō', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ų', '' => 'ł', '' => 'ś', '' => 'ū', '' => 'ü', '' => 'ż', '' => 'ž', '' => '’', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp874.php000064400000006522150432043200015433 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '…', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => ' ', '' => 'ก', '' => 'ข', '' => 'ฃ', '' => 'ค', '' => 'ฅ', '' => 'ฆ', '' => 'ง', '' => 'จ', '' => 'ฉ', '' => 'ช', '' => 'ซ', '' => 'ฌ', '' => 'ญ', '' => 'ฎ', '' => 'ฏ', '' => 'ฐ', '' => 'ฑ', '' => 'ฒ', '' => 'ณ', '' => 'ด', '' => 'ต', '' => 'ถ', '' => 'ท', '' => 'ธ', '' => 'น', '' => 'บ', '' => 'ป', '' => 'ผ', '' => 'ฝ', '' => 'พ', '' => 'ฟ', '' => 'ภ', '' => 'ม', '' => 'ย', '' => 'ร', '' => 'ฤ', '' => 'ล', '' => 'ฦ', '' => 'ว', '' => 'ศ', '' => 'ษ', '' => 'ส', '' => 'ห', '' => 'ฬ', '' => 'อ', '' => 'ฮ', '' => 'ฯ', '' => 'ะ', '' => 'ั', '' => 'า', '' => 'ำ', '' => 'ิ', '' => 'ี', '' => 'ึ', '' => 'ื', '' => 'ุ', '' => 'ู', '' => 'ฺ', '' => '฿', '' => 'เ', '' => 'แ', '' => 'โ', '' => 'ใ', '' => 'ไ', '' => 'ๅ', '' => 'ๆ', '' => '็', '' => '่', '' => '้', '' => '๊', '' => '๋', '' => '์', '' => 'ํ', '' => '๎', '' => '๏', '' => '๐', '' => '๑', '' => '๒', '' => '๓', '' => '๔', '' => '๕', '' => '๖', '' => '๗', '' => '๘', '' => '๙', '' => '๚', '' => '๛', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-3.php000064400000007132150432043200016131 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'Ħ', '' => '˘', '' => '£', '' => '¤', '' => 'Ĥ', '' => '§', '' => '¨', '' => 'İ', '' => 'Ş', '' => 'Ğ', '' => 'Ĵ', '' => '­', '' => 'Ż', '' => '°', '' => 'ħ', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => 'ĥ', '' => '·', '' => '¸', '' => 'ı', '' => 'ş', '' => 'ğ', '' => 'ĵ', '' => '½', '' => 'ż', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ä', '' => 'Ċ', '' => 'Ĉ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ñ', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Ġ', '' => 'Ö', '' => '×', '' => 'Ĝ', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ŭ', '' => 'Ŝ', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ä', '' => 'ċ', '' => 'ĉ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'ñ', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'ġ', '' => 'ö', '' => '÷', '' => 'ĝ', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ŭ', '' => 'ŝ', '' => '˙', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-15.php000064400000007304150432043200016215 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '¡', '' => '¢', '' => '£', '' => '€', '' => '¥', '' => 'Š', '' => '§', '' => 'š', '' => '©', '' => 'ª', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => 'Ž', '' => 'µ', '' => '¶', '' => '·', '' => 'ž', '' => '¹', '' => 'º', '' => '»', '' => 'Œ', '' => 'œ', '' => 'Ÿ', '' => '¿', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ð', '' => 'Ñ', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ø', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ý', '' => 'Þ', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'ð', '' => 'ñ', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ø', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ý', '' => 'þ', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-16.php000064400000007306150432043200016220 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'Ą', '' => 'ą', '' => 'Ł', '' => '€', '' => '„', '' => 'Š', '' => '§', '' => 'š', '' => '©', '' => 'Ș', '' => '«', '' => 'Ź', '' => '­', '' => 'ź', '' => 'Ż', '' => '°', '' => '±', '' => 'Č', '' => 'ł', '' => 'Ž', '' => '”', '' => '¶', '' => '·', '' => 'ž', '' => 'č', '' => 'ș', '' => '»', '' => 'Œ', '' => 'œ', '' => 'Ÿ', '' => 'ż', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ă', '' => 'Ä', '' => 'Ć', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Đ', '' => 'Ń', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Ő', '' => 'Ö', '' => 'Ś', '' => 'Ű', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ę', '' => 'Ț', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ă', '' => 'ä', '' => 'ć', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'đ', '' => 'ń', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'ő', '' => 'ö', '' => 'ś', '' => 'ű', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ę', '' => 'ț', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1251.php000064400000007306150432043200016647 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ђ', '' => 'Ѓ', '' => '‚', '' => 'ѓ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => '€', '' => '‰', '' => 'Љ', '' => '‹', '' => 'Њ', '' => 'Ќ', '' => 'Ћ', '' => 'Џ', '' => 'ђ', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '™', '' => 'љ', '' => '›', '' => 'њ', '' => 'ќ', '' => 'ћ', '' => 'џ', '' => ' ', '' => 'Ў', '' => 'ў', '' => 'Ј', '' => '¤', '' => 'Ґ', '' => '¦', '' => '§', '' => 'Ё', '' => '©', '' => 'Є', '' => '«', '' => '¬', '' => '­', '' => '®', '' => 'Ї', '' => '°', '' => '±', '' => 'І', '' => 'і', '' => 'ґ', '' => 'µ', '' => '¶', '' => '·', '' => 'ё', '' => '№', '' => 'є', '' => '»', '' => 'ј', '' => 'Ѕ', '' => 'ѕ', '' => 'ї', '' => 'А', '' => 'Б', '' => 'В', '' => 'Г', '' => 'Д', '' => 'Е', '' => 'Ж', '' => 'З', '' => 'И', '' => 'Й', '' => 'К', '' => 'Л', '' => 'М', '' => 'Н', '' => 'О', '' => 'П', '' => 'Р', '' => 'С', '' => 'Т', '' => 'У', '' => 'Ф', '' => 'Х', '' => 'Ц', '' => 'Ч', '' => 'Ш', '' => 'Щ', '' => 'Ъ', '' => 'Ы', '' => 'Ь', '' => 'Э', '' => 'Ю', '' => 'Я', '' => 'а', '' => 'б', '' => 'в', '' => 'г', '' => 'д', '' => 'е', '' => 'ж', '' => 'з', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ф', '' => 'х', '' => 'ц', '' => 'ч', '' => 'ш', '' => 'щ', '' => 'ъ', '' => 'ы', '' => 'ь', '' => 'э', '' => 'ю', '' => 'я', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1255.php000064400000006576150432043200016663 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => '‹', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => '›', '' => ' ', '' => '¡', '' => '¢', '' => '£', '' => '₪', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => '×', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => '÷', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '¿', '' => 'ְ', '' => 'ֱ', '' => 'ֲ', '' => 'ֳ', '' => 'ִ', '' => 'ֵ', '' => 'ֶ', '' => 'ַ', '' => 'ָ', '' => 'ֹ', '' => 'ֻ', '' => 'ּ', '' => 'ֽ', '' => '־', '' => 'ֿ', '' => '׀', '' => 'ׁ', '' => 'ׂ', '' => '׃', '' => 'װ', '' => 'ױ', '' => 'ײ', '' => '׳', '' => '״', '' => 'א', '' => 'ב', '' => 'ג', '' => 'ד', '' => 'ה', '' => 'ו', '' => 'ז', '' => 'ח', '' => 'ט', '' => 'י', '' => 'ך', '' => 'כ', '' => 'ל', '' => 'ם', '' => 'מ', '' => 'ן', '' => 'נ', '' => 'ס', '' => 'ע', '' => 'ף', '' => 'פ', '' => 'ץ', '' => 'צ', '' => 'ק', '' => 'ר', '' => 'ש', '' => 'ת', '' => '‎', '' => '‏', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp852.php000064400000007340150432043200015426 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'ä', '' => 'ů', '' => 'ć', '' => 'ç', '' => 'ł', '' => 'ë', '' => 'Ő', '' => 'ő', '' => 'î', '' => 'Ź', '' => 'Ä', '' => 'Ć', '' => 'É', '' => 'Ĺ', '' => 'ĺ', '' => 'ô', '' => 'ö', '' => 'Ľ', '' => 'ľ', '' => 'Ś', '' => 'ś', '' => 'Ö', '' => 'Ü', '' => 'Ť', '' => 'ť', '' => 'Ł', '' => '×', '' => 'č', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'Ą', '' => 'ą', '' => 'Ž', '' => 'ž', '' => 'Ę', '' => 'ę', '' => '¬', '' => 'ź', '' => 'Č', '' => 'ş', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => 'Á', '' => 'Â', '' => 'Ě', '' => 'Ş', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => 'Ż', '' => 'ż', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => 'Ă', '' => 'ă', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '¤', '' => 'đ', '' => 'Đ', '' => 'Ď', '' => 'Ë', '' => 'ď', '' => 'Ň', '' => 'Í', '' => 'Î', '' => 'ě', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => 'Ţ', '' => 'Ů', '' => '▀', '' => 'Ó', '' => 'ß', '' => 'Ô', '' => 'Ń', '' => 'ń', '' => 'ň', '' => 'Š', '' => 'š', '' => 'Ŕ', '' => 'Ú', '' => 'ŕ', '' => 'Ű', '' => 'ý', '' => 'Ý', '' => 'ţ', '' => '´', '' => '­', '' => '˝', '' => '˛', '' => 'ˇ', '' => '˘', '' => '§', '' => '÷', '' => '¸', '' => '°', '' => '¨', '' => '˙', '' => 'ű', '' => 'Ř', '' => 'ř', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp864.php000064400000007303150432043200015430 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '٪', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '°', '' => '·', '' => '∙', '' => '√', '' => '▒', '' => '─', '' => '│', '' => '┼', '' => '┤', '' => '┬', '' => '├', '' => '┴', '' => '┐', '' => '┌', '' => '└', '' => '┘', '' => 'β', '' => '∞', '' => 'φ', '' => '±', '' => '½', '' => '¼', '' => '≈', '' => '«', '' => '»', '' => 'ﻷ', '' => 'ﻸ', '' => 'ﻻ', '' => 'ﻼ', '' => ' ', '' => '­', '' => 'ﺂ', '' => '£', '' => '¤', '' => 'ﺄ', '' => 'ﺎ', '' => 'ﺏ', '' => 'ﺕ', '' => 'ﺙ', '' => '،', '' => 'ﺝ', '' => 'ﺡ', '' => 'ﺥ', '' => '٠', '' => '١', '' => '٢', '' => '٣', '' => '٤', '' => '٥', '' => '٦', '' => '٧', '' => '٨', '' => '٩', '' => 'ﻑ', '' => '؛', '' => 'ﺱ', '' => 'ﺵ', '' => 'ﺹ', '' => '؟', '' => '¢', '' => 'ﺀ', '' => 'ﺁ', '' => 'ﺃ', '' => 'ﺅ', '' => 'ﻊ', '' => 'ﺋ', '' => 'ﺍ', '' => 'ﺑ', '' => 'ﺓ', '' => 'ﺗ', '' => 'ﺛ', '' => 'ﺟ', '' => 'ﺣ', '' => 'ﺧ', '' => 'ﺩ', '' => 'ﺫ', '' => 'ﺭ', '' => 'ﺯ', '' => 'ﺳ', '' => 'ﺷ', '' => 'ﺻ', '' => 'ﺿ', '' => 'ﻁ', '' => 'ﻅ', '' => 'ﻋ', '' => 'ﻏ', '' => '¦', '' => '¬', '' => '÷', '' => '×', '' => 'ﻉ', '' => 'ـ', '' => 'ﻓ', '' => 'ﻗ', '' => 'ﻛ', '' => 'ﻟ', '' => 'ﻣ', '' => 'ﻧ', '' => 'ﻫ', '' => 'ﻭ', '' => 'ﻯ', '' => 'ﻳ', '' => 'ﺽ', '' => 'ﻌ', '' => 'ﻎ', '' => 'ﻍ', '' => 'ﻡ', '' => 'ﹽ', '' => 'ّ', '' => 'ﻥ', '' => 'ﻩ', '' => 'ﻬ', '' => 'ﻰ', '' => 'ﻲ', '' => 'ﻐ', '' => 'ﻕ', '' => 'ﻵ', '' => 'ﻶ', '' => 'ﻝ', '' => 'ﻙ', '' => 'ﻱ', '' => '■', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp856.php000064400000006172150432043200015434 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'א', '' => 'ב', '' => 'ג', '' => 'ד', '' => 'ה', '' => 'ו', '' => 'ז', '' => 'ח', '' => 'ט', '' => 'י', '' => 'ך', '' => 'כ', '' => 'ל', '' => 'ם', '' => 'מ', '' => 'ן', '' => 'נ', '' => 'ס', '' => 'ע', '' => 'ף', '' => 'פ', '' => 'ץ', '' => 'צ', '' => 'ק', '' => 'ר', '' => 'ש', '' => 'ת', '' => '£', '' => '×', '' => '®', '' => '¬', '' => '½', '' => '¼', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '©', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '¢', '' => '¥', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '¤', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '¦', '' => '▀', '' => 'µ', '' => '¯', '' => '´', '' => '­', '' => '±', '' => '‗', '' => '¾', '' => '¶', '' => '§', '' => '÷', '' => '¸', '' => '°', '' => '¨', '' => '·', '' => '¹', '' => '³', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp1026.php000064400000007303150432043200015477 0ustar00 '', '' => '', '' => '', '' => '', '' => 'œ', '' => ' ', '' => '†', '' => '', '' => '—', ' ' => '', ' ' => 'Ž', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '…', '' => '', '' => '‡', '' => '', '' => '', '' => '’', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => '€', '!' => '', '"' => '‚', '#' => 'ƒ', '$' => '„', '%' => ' ', '&' => '', '\'' => '', '(' => 'ˆ', ')' => '‰', '*' => 'Š', '+' => '‹', ',' => 'Œ', '-' => '', '.' => '', '/' => '', 0 => '', 1 => '‘', 2 => '', 3 => '“', 4 => '”', 5 => '•', 6 => '–', 7 => '', 8 => '˜', 9 => '™', ':' => 'š', ';' => '›', '<' => '', '=' => '', '>' => 'ž', '?' => '', '@' => ' ', 'A' => ' ', 'B' => 'â', 'C' => 'ä', 'D' => 'à', 'E' => 'á', 'F' => 'ã', 'G' => 'å', 'H' => '{', 'I' => 'ñ', 'J' => 'Ç', 'K' => '.', 'L' => '<', 'M' => '(', 'N' => '+', 'O' => '!', 'P' => '&', 'Q' => 'é', 'R' => 'ê', 'S' => 'ë', 'T' => 'è', 'U' => 'í', 'V' => 'î', 'W' => 'ï', 'X' => 'ì', 'Y' => 'ß', 'Z' => 'Ğ', '[' => 'İ', '\\' => '*', ']' => ')', '^' => ';', '_' => '^', '`' => '-', 'a' => '/', 'b' => 'Â', 'c' => 'Ä', 'd' => 'À', 'e' => 'Á', 'f' => 'Ã', 'g' => 'Å', 'h' => '[', 'i' => 'Ñ', 'j' => 'ş', 'k' => ',', 'l' => '%', 'm' => '_', 'n' => '>', 'o' => '?', 'p' => 'ø', 'q' => 'É', 'r' => 'Ê', 's' => 'Ë', 't' => 'È', 'u' => 'Í', 'v' => 'Î', 'w' => 'Ï', 'x' => 'Ì', 'y' => 'ı', 'z' => ':', '{' => 'Ö', '|' => 'Ş', '}' => '\'', '~' => '=', '' => 'Ü', '' => 'Ø', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => '«', '' => '»', '' => '}', '' => '`', '' => '¦', '' => '±', '' => '°', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 'ª', '' => 'º', '' => 'æ', '' => '¸', '' => 'Æ', '' => '¤', '' => 'µ', '' => 'ö', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => '¡', '' => '¿', '' => ']', '' => '$', '' => '@', '' => '®', '' => '¢', '' => '£', '' => '¥', '' => '·', '' => '©', '' => '§', '' => '¶', '' => '¼', '' => '½', '' => '¾', '' => '¬', '' => '|', '' => '¯', '' => '¨', '' => '´', '' => '×', '' => 'ç', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => '­', '' => 'ô', '' => '~', '' => 'ò', '' => 'ó', '' => 'õ', '' => 'ğ', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => '¹', '' => 'û', '' => '\\', '' => 'ù', '' => 'ú', '' => 'ÿ', '' => 'ü', '' => '÷', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => '²', '' => 'Ô', '' => '#', '' => 'Ò', '' => 'Ó', '' => 'Õ', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => '³', '' => 'Û', '' => '"', '' => 'Ù', '' => 'Ú', '' => 'Ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp862.php000064400000007401150432043200015425 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'א', '' => 'ב', '' => 'ג', '' => 'ד', '' => 'ה', '' => 'ו', '' => 'ז', '' => 'ח', '' => 'ט', '' => 'י', '' => 'ך', '' => 'כ', '' => 'ל', '' => 'ם', '' => 'מ', '' => 'ן', '' => 'נ', '' => 'ס', '' => 'ע', '' => 'ף', '' => 'פ', '' => 'ץ', '' => 'צ', '' => 'ק', '' => 'ר', '' => 'ש', '' => 'ת', '' => '¢', '' => '£', '' => '¥', '' => '₧', '' => 'ƒ', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'ñ', '' => 'Ñ', '' => 'ª', '' => 'º', '' => '¿', '' => '⌐', '' => '¬', '' => '½', '' => '¼', '' => '¡', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'α', '' => 'ß', '' => 'Γ', '' => 'π', '' => 'Σ', '' => 'σ', '' => 'µ', '' => 'τ', '' => 'Φ', '' => 'Θ', '' => 'Ω', '' => 'δ', '' => '∞', '' => 'φ', '' => 'ε', '' => '∩', '' => '≡', '' => '±', '' => '≥', '' => '≤', '' => '⌠', '' => '⌡', '' => '÷', '' => '≈', '' => '°', '' => '∙', '' => '·', '' => '√', '' => 'ⁿ', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1252.php000064400000007211150432043200016643 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => 'Ž', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '¡', '' => '¢', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => 'ª', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => 'º', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '¿', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ð', '' => 'Ñ', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ø', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'Ý', '' => 'Þ', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'ð', '' => 'ñ', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ø', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ý', '' => 'þ', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-5.php000064400000007304150432043200016134 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'Ё', '' => 'Ђ', '' => 'Ѓ', '' => 'Є', '' => 'Ѕ', '' => 'І', '' => 'Ї', '' => 'Ј', '' => 'Љ', '' => 'Њ', '' => 'Ћ', '' => 'Ќ', '' => '­', '' => 'Ў', '' => 'Џ', '' => 'А', '' => 'Б', '' => 'В', '' => 'Г', '' => 'Д', '' => 'Е', '' => 'Ж', '' => 'З', '' => 'И', '' => 'Й', '' => 'К', '' => 'Л', '' => 'М', '' => 'Н', '' => 'О', '' => 'П', '' => 'Р', '' => 'С', '' => 'Т', '' => 'У', '' => 'Ф', '' => 'Х', '' => 'Ц', '' => 'Ч', '' => 'Ш', '' => 'Щ', '' => 'Ъ', '' => 'Ы', '' => 'Ь', '' => 'Э', '' => 'Ю', '' => 'Я', '' => 'а', '' => 'б', '' => 'в', '' => 'г', '' => 'д', '' => 'е', '' => 'ж', '' => 'з', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ф', '' => 'х', '' => 'ц', '' => 'ч', '' => 'ш', '' => 'щ', '' => 'ъ', '' => 'ы', '' => 'ь', '' => 'э', '' => 'ю', '' => 'я', '' => '№', '' => 'ё', '' => 'ђ', '' => 'ѓ', '' => 'є', '' => 'ѕ', '' => 'і', '' => 'ї', '' => 'ј', '' => 'љ', '' => 'њ', '' => 'ћ', '' => 'ќ', '' => '§', '' => 'ў', '' => 'џ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp037.php000064400000007303150432043200015420 0ustar00 '', '' => '', '' => '', '' => '', '' => 'œ', '' => ' ', '' => '†', '' => '', '' => '—', ' ' => '', ' ' => 'Ž', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '…', '' => '', '' => '‡', '' => '', '' => '', '' => '’', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => '€', '!' => '', '"' => '‚', '#' => 'ƒ', '$' => '„', '%' => ' ', '&' => '', '\'' => '', '(' => 'ˆ', ')' => '‰', '*' => 'Š', '+' => '‹', ',' => 'Œ', '-' => '', '.' => '', '/' => '', 0 => '', 1 => '‘', 2 => '', 3 => '“', 4 => '”', 5 => '•', 6 => '–', 7 => '', 8 => '˜', 9 => '™', ':' => 'š', ';' => '›', '<' => '', '=' => '', '>' => 'ž', '?' => '', '@' => ' ', 'A' => ' ', 'B' => 'â', 'C' => 'ä', 'D' => 'à', 'E' => 'á', 'F' => 'ã', 'G' => 'å', 'H' => 'ç', 'I' => 'ñ', 'J' => '¢', 'K' => '.', 'L' => '<', 'M' => '(', 'N' => '+', 'O' => '|', 'P' => '&', 'Q' => 'é', 'R' => 'ê', 'S' => 'ë', 'T' => 'è', 'U' => 'í', 'V' => 'î', 'W' => 'ï', 'X' => 'ì', 'Y' => 'ß', 'Z' => '!', '[' => '$', '\\' => '*', ']' => ')', '^' => ';', '_' => '¬', '`' => '-', 'a' => '/', 'b' => 'Â', 'c' => 'Ä', 'd' => 'À', 'e' => 'Á', 'f' => 'Ã', 'g' => 'Å', 'h' => 'Ç', 'i' => 'Ñ', 'j' => '¦', 'k' => ',', 'l' => '%', 'm' => '_', 'n' => '>', 'o' => '?', 'p' => 'ø', 'q' => 'É', 'r' => 'Ê', 's' => 'Ë', 't' => 'È', 'u' => 'Í', 'v' => 'Î', 'w' => 'Ï', 'x' => 'Ì', 'y' => '`', 'z' => ':', '{' => '#', '|' => '@', '}' => '\'', '~' => '=', '' => '"', '' => 'Ø', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => '«', '' => '»', '' => 'ð', '' => 'ý', '' => 'þ', '' => '±', '' => '°', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 'ª', '' => 'º', '' => 'æ', '' => '¸', '' => 'Æ', '' => '¤', '' => 'µ', '' => '~', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => '¡', '' => '¿', '' => 'Ð', '' => 'Ý', '' => 'Þ', '' => '®', '' => '^', '' => '£', '' => '¥', '' => '·', '' => '©', '' => '§', '' => '¶', '' => '¼', '' => '½', '' => '¾', '' => '[', '' => ']', '' => '¯', '' => '¨', '' => '´', '' => '×', '' => '{', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => '­', '' => 'ô', '' => 'ö', '' => 'ò', '' => 'ó', '' => 'õ', '' => '}', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => '¹', '' => 'û', '' => 'ü', '' => 'ù', '' => 'ú', '' => 'ÿ', '' => '\\', '' => '÷', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => '²', '' => 'Ô', '' => 'Ö', '' => 'Ò', '' => 'Ó', '' => 'Õ', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => '³', '' => 'Û', '' => 'Ü', '' => 'Ù', '' => 'Ú', '' => 'Ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1254.php000064400000007153150432043200016652 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => 'Ÿ', '' => ' ', '' => '¡', '' => '¢', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => 'ª', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => 'º', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '¿', '' => 'À', '' => 'Á', '' => 'Â', '' => 'Ã', '' => 'Ä', '' => 'Å', '' => 'Æ', '' => 'Ç', '' => 'È', '' => 'É', '' => 'Ê', '' => 'Ë', '' => 'Ì', '' => 'Í', '' => 'Î', '' => 'Ï', '' => 'Ğ', '' => 'Ñ', '' => 'Ò', '' => 'Ó', '' => 'Ô', '' => 'Õ', '' => 'Ö', '' => '×', '' => 'Ø', '' => 'Ù', '' => 'Ú', '' => 'Û', '' => 'Ü', '' => 'İ', '' => 'Ş', '' => 'ß', '' => 'à', '' => 'á', '' => 'â', '' => 'ã', '' => 'ä', '' => 'å', '' => 'æ', '' => 'ç', '' => 'è', '' => 'é', '' => 'ê', '' => 'ë', '' => 'ì', '' => 'í', '' => 'î', '' => 'ï', '' => 'ğ', '' => 'ñ', '' => 'ò', '' => 'ó', '' => 'ô', '' => 'õ', '' => 'ö', '' => '÷', '' => 'ø', '' => 'ù', '' => 'ú', '' => 'û', '' => 'ü', '' => 'ı', '' => 'ş', '' => 'ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp863.php000064400000007401150432043200015426 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'Â', '' => 'à', '' => '¶', '' => 'ç', '' => 'ê', '' => 'ë', '' => 'è', '' => 'ï', '' => 'î', '' => '‗', '' => 'À', '' => '§', '' => 'É', '' => 'È', '' => 'Ê', '' => 'ô', '' => 'Ë', '' => 'Ï', '' => 'û', '' => 'ù', '' => '¤', '' => 'Ô', '' => 'Ü', '' => '¢', '' => '£', '' => 'Ù', '' => 'Û', '' => 'ƒ', '' => '¦', '' => '´', '' => 'ó', '' => 'ú', '' => '¨', '' => '¸', '' => '³', '' => '¯', '' => 'Î', '' => '⌐', '' => '¬', '' => '½', '' => '¼', '' => '¾', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'α', '' => 'ß', '' => 'Γ', '' => 'π', '' => 'Σ', '' => 'σ', '' => 'µ', '' => 'τ', '' => 'Φ', '' => 'Θ', '' => 'Ω', '' => 'δ', '' => '∞', '' => 'φ', '' => 'ε', '' => '∩', '' => '≡', '' => '±', '' => '≥', '' => '≤', '' => '⌠', '' => '⌡', '' => '÷', '' => '≈', '' => '°', '' => '∙', '' => '·', '' => '√', '' => 'ⁿ', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp865.php000064400000007401150432043200015430 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ç', '' => 'ü', '' => 'é', '' => 'â', '' => 'ä', '' => 'à', '' => 'å', '' => 'ç', '' => 'ê', '' => 'ë', '' => 'è', '' => 'ï', '' => 'î', '' => 'ì', '' => 'Ä', '' => 'Å', '' => 'É', '' => 'æ', '' => 'Æ', '' => 'ô', '' => 'ö', '' => 'ò', '' => 'û', '' => 'ù', '' => 'ÿ', '' => 'Ö', '' => 'Ü', '' => 'ø', '' => '£', '' => 'Ø', '' => '₧', '' => 'ƒ', '' => 'á', '' => 'í', '' => 'ó', '' => 'ú', '' => 'ñ', '' => 'Ñ', '' => 'ª', '' => 'º', '' => '¿', '' => '⌐', '' => '¬', '' => '½', '' => '¼', '' => '¡', '' => '«', '' => '¤', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'α', '' => 'ß', '' => 'Γ', '' => 'π', '' => 'Σ', '' => 'σ', '' => 'µ', '' => 'τ', '' => 'Φ', '' => 'Θ', '' => 'Ω', '' => 'δ', '' => '∞', '' => 'φ', '' => 'ε', '' => '∩', '' => '≡', '' => '±', '' => '≥', '' => '≤', '' => '⌠', '' => '⌡', '' => '÷', '' => '≈', '' => '°', '' => '∙', '' => '·', '' => '√', '' => 'ⁿ', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.windows-1250.php000064400000007211150432043200016641 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '‚', '' => '„', '' => '…', '' => '†', '' => '‡', '' => '‰', '' => 'Š', '' => '‹', '' => 'Ś', '' => 'Ť', '' => 'Ž', '' => 'Ź', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '™', '' => 'š', '' => '›', '' => 'ś', '' => 'ť', '' => 'ž', '' => 'ź', '' => ' ', '' => 'ˇ', '' => '˘', '' => 'Ł', '' => '¤', '' => 'Ą', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => 'Ş', '' => '«', '' => '¬', '' => '­', '' => '®', '' => 'Ż', '' => '°', '' => '±', '' => '˛', '' => 'ł', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => 'ą', '' => 'ş', '' => '»', '' => 'Ľ', '' => '˝', '' => 'ľ', '' => 'ż', '' => 'Ŕ', '' => 'Á', '' => 'Â', '' => 'Ă', '' => 'Ä', '' => 'Ĺ', '' => 'Ć', '' => 'Ç', '' => 'Č', '' => 'É', '' => 'Ę', '' => 'Ë', '' => 'Ě', '' => 'Í', '' => 'Î', '' => 'Ď', '' => 'Đ', '' => 'Ń', '' => 'Ň', '' => 'Ó', '' => 'Ô', '' => 'Ő', '' => 'Ö', '' => '×', '' => 'Ř', '' => 'Ů', '' => 'Ú', '' => 'Ű', '' => 'Ü', '' => 'Ý', '' => 'Ţ', '' => 'ß', '' => 'ŕ', '' => 'á', '' => 'â', '' => 'ă', '' => 'ä', '' => 'ĺ', '' => 'ć', '' => 'ç', '' => 'č', '' => 'é', '' => 'ę', '' => 'ë', '' => 'ě', '' => 'í', '' => 'î', '' => 'ď', '' => 'đ', '' => 'ń', '' => 'ň', '' => 'ó', '' => 'ô', '' => 'ő', '' => 'ö', '' => '÷', '' => 'ř', '' => 'ů', '' => 'ú', '' => 'ű', '' => 'ü', '' => 'ý', '' => 'ţ', '' => '˙', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp855.php000064400000007341150432043200015432 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'ђ', '' => 'Ђ', '' => 'ѓ', '' => 'Ѓ', '' => 'ё', '' => 'Ё', '' => 'є', '' => 'Є', '' => 'ѕ', '' => 'Ѕ', '' => 'і', '' => 'І', '' => 'ї', '' => 'Ї', '' => 'ј', '' => 'Ј', '' => 'љ', '' => 'Љ', '' => 'њ', '' => 'Њ', '' => 'ћ', '' => 'Ћ', '' => 'ќ', '' => 'Ќ', '' => 'ў', '' => 'Ў', '' => 'џ', '' => 'Џ', '' => 'ю', '' => 'Ю', '' => 'ъ', '' => 'Ъ', '' => 'а', '' => 'А', '' => 'б', '' => 'Б', '' => 'ц', '' => 'Ц', '' => 'д', '' => 'Д', '' => 'е', '' => 'Е', '' => 'ф', '' => 'Ф', '' => 'г', '' => 'Г', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => 'х', '' => 'Х', '' => 'и', '' => 'И', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => 'й', '' => 'Й', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => 'к', '' => 'К', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '¤', '' => 'л', '' => 'Л', '' => 'м', '' => 'М', '' => 'н', '' => 'Н', '' => 'о', '' => 'О', '' => 'п', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => 'П', '' => 'я', '' => '▀', '' => 'Я', '' => 'р', '' => 'Р', '' => 'с', '' => 'С', '' => 'т', '' => 'Т', '' => 'у', '' => 'У', '' => 'ж', '' => 'Ж', '' => 'в', '' => 'В', '' => 'ь', '' => 'Ь', '' => '№', '' => '­', '' => 'ы', '' => 'Ы', '' => 'з', '' => 'З', '' => 'ш', '' => 'Ш', '' => 'э', '' => 'Э', '' => 'щ', '' => 'Щ', '' => 'ч', '' => 'Ч', '' => '§', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.big5.php000064400000707243150432043200015424 0ustar00 ' ', 'A' => ',', 'B' => '、', 'C' => '。', 'D' => '.', 'E' => '•', 'F' => ';', 'G' => ':', 'H' => '?', 'I' => '!', 'J' => '︰', 'K' => '…', 'L' => '‥', 'M' => '﹐', 'N' => '、', 'O' => '﹒', 'P' => '·', 'Q' => '﹔', 'R' => '﹕', 'S' => '﹖', 'T' => '﹗', 'U' => '|', 'V' => '–', 'W' => '︱', 'X' => '—', 'Y' => '︳', 'Z' => '�', '[' => '︴', '\\' => '﹏', ']' => '(', '^' => ')', '_' => '︵', '`' => '︶', 'a' => '{', 'b' => '}', 'c' => '︷', 'd' => '︸', 'e' => '〔', 'f' => '〕', 'g' => '︹', 'h' => '︺', 'i' => '【', 'j' => '】', 'k' => '︻', 'l' => '︼', 'm' => '《', 'n' => '》', 'o' => '︽', 'p' => '︾', 'q' => '〈', 'r' => '〉', 's' => '︿', 't' => '﹀', 'u' => '「', 'v' => '」', 'w' => '﹁', 'x' => '﹂', 'y' => '『', 'z' => '』', '{' => '﹃', '|' => '﹄', '}' => '﹙', '~' => '﹚', '' => '﹛', '' => '﹜', '' => '﹝', '' => '﹞', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '〝', '' => '〞', '' => '‵', '' => '′', '' => '#', '' => '&', '' => '*', '' => '※', '' => '§', '' => '〃', '' => '○', '' => '●', '' => '△', '' => '▲', '' => '◎', '' => '☆', '' => '★', '' => '◇', '' => '◆', '' => '□', '' => '■', '' => '▽', '' => '▼', '' => '㊣', '' => '℅', '' => '‾', '' => '�', '' => '_', '' => '�', '' => '﹉', '' => '﹊', '' => '﹍', '' => '﹎', '' => '﹋', '' => '﹌', '' => '﹟', '' => '﹠', '' => '﹡', '' => '+', '' => '-', '' => '×', '' => '÷', '' => '±', '' => '√', '' => '<', '' => '>', '' => '=', '' => '≦', '' => '≧', '' => '≠', '' => '∞', '' => '≒', '' => '≡', '' => '﹢', '' => '﹣', '' => '﹤', '' => '﹥', '' => '﹦', '' => '∼', '' => '∩', '' => '∪', '' => '⊥', '' => '∠', '' => '∟', '' => '⊿', '' => '㏒', '' => '㏑', '' => '∫', '' => '∮', '' => '∵', '' => '∴', '' => '♀', '' => '♂', '' => '♁', '' => '☉', '' => '↑', '' => '↓', '' => '←', '' => '→', '' => '↖', '' => '↗', '' => '↙', '' => '↘', '' => '∥', '' => '∣', '' => '�', '@' => '�', 'A' => '/', 'B' => '\', 'C' => '$', 'D' => '¥', 'E' => '〒', 'F' => '¢', 'G' => '£', 'H' => '%', 'I' => '@', 'J' => '℃', 'K' => '℉', 'L' => '﹩', 'M' => '﹪', 'N' => '﹫', 'O' => '㏕', 'P' => '㎜', 'Q' => '㎝', 'R' => '㎞', 'S' => '㏎', 'T' => '㎡', 'U' => '㎎', 'V' => '㎏', 'W' => '㏄', 'X' => '°', 'Y' => '兙', 'Z' => '兛', '[' => '兞', '\\' => '兝', ']' => '兡', '^' => '兣', '_' => '嗧', '`' => '瓩', 'a' => '糎', 'b' => '▁', 'c' => '▂', 'd' => '▃', 'e' => '▄', 'f' => '▅', 'g' => '▆', 'h' => '▇', 'i' => '█', 'j' => '▏', 'k' => '▎', 'l' => '▍', 'm' => '▌', 'n' => '▋', 'o' => '▊', 'p' => '▉', 'q' => '┼', 'r' => '┴', 's' => '┬', 't' => '┤', 'u' => '├', 'v' => '▔', 'w' => '─', 'x' => '│', 'y' => '▕', 'z' => '┌', '{' => '┐', '|' => '└', '}' => '┘', '~' => '╭', '' => '╮', '' => '╰', '' => '╯', '' => '═', '' => '╞', '' => '╪', '' => '╡', '' => '◢', '' => '◣', '' => '◥', '' => '◤', '' => '╱', '' => '╲', '' => '╳', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => 'Ⅰ', '' => 'Ⅱ', '' => 'Ⅲ', '' => 'Ⅳ', '' => 'Ⅴ', '' => 'Ⅵ', '' => 'Ⅶ', '' => 'Ⅷ', '' => 'Ⅸ', '' => 'Ⅹ', '' => '〡', '' => '〢', '' => '〣', '' => '〤', '' => '〥', '' => '〦', '' => '〧', '' => '〨', '' => '〩', '' => '�', '' => '卄', '' => '�', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 's', '' => 't', '' => 'u', '' => 'v', '@' => 'w', 'A' => 'x', 'B' => 'y', 'C' => 'z', 'D' => 'Α', 'E' => 'Β', 'F' => 'Γ', 'G' => 'Δ', 'H' => 'Ε', 'I' => 'Ζ', 'J' => 'Η', 'K' => 'Θ', 'L' => 'Ι', 'M' => 'Κ', 'N' => 'Λ', 'O' => 'Μ', 'P' => 'Ν', 'Q' => 'Ξ', 'R' => 'Ο', 'S' => 'Π', 'T' => 'Ρ', 'U' => 'Σ', 'V' => 'Τ', 'W' => 'Υ', 'X' => 'Φ', 'Y' => 'Χ', 'Z' => 'Ψ', '[' => 'Ω', '\\' => 'α', ']' => 'β', '^' => 'γ', '_' => 'δ', '`' => 'ε', 'a' => 'ζ', 'b' => 'η', 'c' => 'θ', 'd' => 'ι', 'e' => 'κ', 'f' => 'λ', 'g' => 'μ', 'h' => 'ν', 'i' => 'ξ', 'j' => 'ο', 'k' => 'π', 'l' => 'ρ', 'm' => 'σ', 'n' => 'τ', 'o' => 'υ', 'p' => 'φ', 'q' => 'χ', 'r' => 'ψ', 's' => 'ω', 't' => 'ㄅ', 'u' => 'ㄆ', 'v' => 'ㄇ', 'w' => 'ㄈ', 'x' => 'ㄉ', 'y' => 'ㄊ', 'z' => 'ㄋ', '{' => 'ㄌ', '|' => 'ㄍ', '}' => 'ㄎ', '~' => 'ㄏ', '' => 'ㄐ', '' => 'ㄑ', '' => 'ㄒ', '' => 'ㄓ', '' => 'ㄔ', '' => 'ㄕ', '' => 'ㄖ', '' => 'ㄗ', '' => 'ㄘ', '' => 'ㄙ', '' => 'ㄚ', '' => 'ㄛ', '' => 'ㄜ', '' => 'ㄝ', '' => 'ㄞ', '' => 'ㄟ', '' => 'ㄠ', '' => 'ㄡ', '' => 'ㄢ', '' => 'ㄣ', '' => 'ㄤ', '' => 'ㄥ', '' => 'ㄦ', '' => 'ㄧ', '' => 'ㄨ', '' => 'ㄩ', '' => '˙', '' => 'ˉ', '' => 'ˊ', '' => 'ˇ', '' => 'ˋ', '@' => '一', 'A' => '乙', 'B' => '丁', 'C' => '七', 'D' => '乃', 'E' => '九', 'F' => '了', 'G' => '二', 'H' => '人', 'I' => '儿', 'J' => '入', 'K' => '八', 'L' => '几', 'M' => '刀', 'N' => '刁', 'O' => '力', 'P' => '匕', 'Q' => '十', 'R' => '卜', 'S' => '又', 'T' => '三', 'U' => '下', 'V' => '丈', 'W' => '上', 'X' => '丫', 'Y' => '丸', 'Z' => '凡', '[' => '久', '\\' => '么', ']' => '也', '^' => '乞', '_' => '于', '`' => '亡', 'a' => '兀', 'b' => '刃', 'c' => '勺', 'd' => '千', 'e' => '叉', 'f' => '口', 'g' => '土', 'h' => '士', 'i' => '夕', 'j' => '大', 'k' => '女', 'l' => '子', 'm' => '孑', 'n' => '孓', 'o' => '寸', 'p' => '小', 'q' => '尢', 'r' => '尸', 's' => '山', 't' => '川', 'u' => '工', 'v' => '己', 'w' => '已', 'x' => '巳', 'y' => '巾', 'z' => '干', '{' => '廾', '|' => '弋', '}' => '弓', '~' => '才', '' => '丑', '' => '丐', '' => '不', '' => '中', '' => '丰', '' => '丹', '' => '之', '' => '尹', '' => '予', '' => '云', '' => '井', '' => '互', '' => '五', '' => '亢', '' => '仁', '' => '什', '' => '仃', '' => '仆', '' => '仇', '' => '仍', '' => '今', '' => '介', '' => '仄', '' => '元', '' => '允', '' => '內', '' => '六', '' => '兮', '' => '公', '' => '冗', '' => '凶', '' => '分', '' => '切', '' => '刈', '' => '勻', '' => '勾', '' => '勿', '' => '化', '' => '匹', '' => '午', '' => '升', '' => '卅', '' => '卞', '' => '厄', '' => '友', '' => '及', '' => '反', '' => '壬', '' => '天', '' => '夫', '' => '太', '' => '夭', '' => '孔', '' => '少', '' => '尤', '' => '尺', '' => '屯', '' => '巴', '' => '幻', '' => '廿', '' => '弔', '' => '引', '' => '心', '' => '戈', '' => '戶', '' => '手', '' => '扎', '' => '支', '' => '文', '' => '斗', '' => '斤', '' => '方', '' => '日', '' => '曰', '' => '月', '' => '木', '' => '欠', '' => '止', '' => '歹', '' => '毋', '' => '比', '' => '毛', '' => '氏', '' => '水', '' => '火', '' => '爪', '' => '父', '' => '爻', '' => '片', '' => '牙', '' => '牛', '' => '犬', '' => '王', '' => '丙', '@' => '世', 'A' => '丕', 'B' => '且', 'C' => '丘', 'D' => '主', 'E' => '乍', 'F' => '乏', 'G' => '乎', 'H' => '以', 'I' => '付', 'J' => '仔', 'K' => '仕', 'L' => '他', 'M' => '仗', 'N' => '代', 'O' => '令', 'P' => '仙', 'Q' => '仞', 'R' => '充', 'S' => '兄', 'T' => '冉', 'U' => '冊', 'V' => '冬', 'W' => '凹', 'X' => '出', 'Y' => '凸', 'Z' => '刊', '[' => '加', '\\' => '功', ']' => '包', '^' => '匆', '_' => '北', '`' => '匝', 'a' => '仟', 'b' => '半', 'c' => '卉', 'd' => '卡', 'e' => '占', 'f' => '卯', 'g' => '卮', 'h' => '去', 'i' => '可', 'j' => '古', 'k' => '右', 'l' => '召', 'm' => '叮', 'n' => '叩', 'o' => '叨', 'p' => '叼', 'q' => '司', 'r' => '叵', 's' => '叫', 't' => '另', 'u' => '只', 'v' => '史', 'w' => '叱', 'x' => '台', 'y' => '句', 'z' => '叭', '{' => '叻', '|' => '四', '}' => '囚', '~' => '外', '' => '央', '' => '失', '' => '奴', '' => '奶', '' => '孕', '' => '它', '' => '尼', '' => '巨', '' => '巧', '' => '左', '' => '市', '' => '布', '' => '平', '' => '幼', '' => '弁', '' => '弘', '' => '弗', '' => '必', '' => '戊', '' => '打', '' => '扔', '' => '扒', '' => '扑', '' => '斥', '' => '旦', '' => '朮', '' => '本', '' => '未', '' => '末', '' => '札', '' => '正', '' => '母', '' => '民', '' => '氐', '' => '永', '' => '汁', '' => '汀', '' => '氾', '' => '犯', '' => '玄', '' => '玉', '' => '瓜', '' => '瓦', '' => '甘', '' => '生', '' => '用', '' => '甩', '' => '田', '' => '由', '' => '甲', '' => '申', '' => '疋', '' => '白', '' => '皮', '' => '皿', '' => '目', '' => '矛', '' => '矢', '' => '石', '' => '示', '' => '禾', '' => '穴', '' => '立', '' => '丞', '' => '丟', '' => '乒', '' => '乓', '' => '乩', '' => '亙', '' => '交', '' => '亦', '' => '亥', '' => '仿', '' => '伉', '' => '伙', '' => '伊', '' => '伕', '' => '伍', '' => '伐', '' => '休', '' => '伏', '' => '仲', '' => '件', '' => '任', '' => '仰', '' => '仳', '' => '份', '' => '企', '' => '伋', '' => '光', '' => '兇', '' => '兆', '' => '先', '' => '全', '@' => '共', 'A' => '再', 'B' => '冰', 'C' => '列', 'D' => '刑', 'E' => '划', 'F' => '刎', 'G' => '刖', 'H' => '劣', 'I' => '匈', 'J' => '匡', 'K' => '匠', 'L' => '印', 'M' => '危', 'N' => '吉', 'O' => '吏', 'P' => '同', 'Q' => '吊', 'R' => '吐', 'S' => '吁', 'T' => '吋', 'U' => '各', 'V' => '向', 'W' => '名', 'X' => '合', 'Y' => '吃', 'Z' => '后', '[' => '吆', '\\' => '吒', ']' => '因', '^' => '回', '_' => '囝', '`' => '圳', 'a' => '地', 'b' => '在', 'c' => '圭', 'd' => '圬', 'e' => '圯', 'f' => '圩', 'g' => '夙', 'h' => '多', 'i' => '夷', 'j' => '夸', 'k' => '妄', 'l' => '奸', 'm' => '妃', 'n' => '好', 'o' => '她', 'p' => '如', 'q' => '妁', 'r' => '字', 's' => '存', 't' => '宇', 'u' => '守', 'v' => '宅', 'w' => '安', 'x' => '寺', 'y' => '尖', 'z' => '屹', '{' => '州', '|' => '帆', '}' => '并', '~' => '年', '' => '式', '' => '弛', '' => '忙', '' => '忖', '' => '戎', '' => '戌', '' => '戍', '' => '成', '' => '扣', '' => '扛', '' => '托', '' => '收', '' => '早', '' => '旨', '' => '旬', '' => '旭', '' => '曲', '' => '曳', '' => '有', '' => '朽', '' => '朴', '' => '朱', '' => '朵', '' => '次', '' => '此', '' => '死', '' => '氖', '' => '汝', '' => '汗', '' => '汙', '' => '江', '' => '池', '' => '汐', '' => '汕', '' => '污', '' => '汛', '' => '汍', '' => '汎', '' => '灰', '' => '牟', '' => '牝', '' => '百', '' => '竹', '' => '米', '' => '糸', '' => '缶', '' => '羊', '' => '羽', '' => '老', '' => '考', '' => '而', '' => '耒', '' => '耳', '' => '聿', '' => '肉', '' => '肋', '' => '肌', '' => '臣', '' => '自', '' => '至', '' => '臼', '' => '舌', '' => '舛', '' => '舟', '' => '艮', '' => '色', '' => '艾', '' => '虫', '' => '血', '' => '行', '' => '衣', '' => '西', '' => '阡', '' => '串', '' => '亨', '' => '位', '' => '住', '' => '佇', '' => '佗', '' => '佞', '' => '伴', '' => '佛', '' => '何', '' => '估', '' => '佐', '' => '佑', '' => '伽', '' => '伺', '' => '伸', '' => '佃', '' => '佔', '' => '似', '' => '但', '' => '佣', '@' => '作', 'A' => '你', 'B' => '伯', 'C' => '低', 'D' => '伶', 'E' => '余', 'F' => '佝', 'G' => '佈', 'H' => '佚', 'I' => '兌', 'J' => '克', 'K' => '免', 'L' => '兵', 'M' => '冶', 'N' => '冷', 'O' => '別', 'P' => '判', 'Q' => '利', 'R' => '刪', 'S' => '刨', 'T' => '劫', 'U' => '助', 'V' => '努', 'W' => '劬', 'X' => '匣', 'Y' => '即', 'Z' => '卵', '[' => '吝', '\\' => '吭', ']' => '吞', '^' => '吾', '_' => '否', '`' => '呎', 'a' => '吧', 'b' => '呆', 'c' => '呃', 'd' => '吳', 'e' => '呈', 'f' => '呂', 'g' => '君', 'h' => '吩', 'i' => '告', 'j' => '吹', 'k' => '吻', 'l' => '吸', 'm' => '吮', 'n' => '吵', 'o' => '吶', 'p' => '吠', 'q' => '吼', 'r' => '呀', 's' => '吱', 't' => '含', 'u' => '吟', 'v' => '听', 'w' => '囪', 'x' => '困', 'y' => '囤', 'z' => '囫', '{' => '坊', '|' => '坑', '}' => '址', '~' => '坍', '' => '均', '' => '坎', '' => '圾', '' => '坐', '' => '坏', '' => '圻', '' => '壯', '' => '夾', '' => '妝', '' => '妒', '' => '妨', '' => '妞', '' => '妣', '' => '妙', '' => '妖', '' => '妍', '' => '妤', '' => '妓', '' => '妊', '' => '妥', '' => '孝', '' => '孜', '' => '孚', '' => '孛', '' => '完', '' => '宋', '' => '宏', '' => '尬', '' => '局', '' => '屁', '' => '尿', '' => '尾', '' => '岐', '' => '岑', '' => '岔', '' => '岌', '' => '巫', '' => '希', '' => '序', '' => '庇', '' => '床', '' => '廷', '' => '弄', '' => '弟', '' => '彤', '' => '形', '' => '彷', '' => '役', '' => '忘', '' => '忌', '' => '志', '' => '忍', '' => '忱', '' => '快', '' => '忸', '' => '忪', '' => '戒', '' => '我', '' => '抄', '' => '抗', '' => '抖', '' => '技', '' => '扶', '' => '抉', '' => '扭', '' => '把', '' => '扼', '' => '找', '' => '批', '' => '扳', '' => '抒', '' => '扯', '' => '折', '' => '扮', '' => '投', '' => '抓', '' => '抑', '' => '抆', '' => '改', '' => '攻', '' => '攸', '' => '旱', '' => '更', '' => '束', '' => '李', '' => '杏', '' => '材', '' => '村', '' => '杜', '' => '杖', '' => '杞', '' => '杉', '' => '杆', '' => '杠', '@' => '杓', 'A' => '杗', 'B' => '步', 'C' => '每', 'D' => '求', 'E' => '汞', 'F' => '沙', 'G' => '沁', 'H' => '沈', 'I' => '沉', 'J' => '沅', 'K' => '沛', 'L' => '汪', 'M' => '決', 'N' => '沐', 'O' => '汰', 'P' => '沌', 'Q' => '汨', 'R' => '沖', 'S' => '沒', 'T' => '汽', 'U' => '沃', 'V' => '汲', 'W' => '汾', 'X' => '汴', 'Y' => '沆', 'Z' => '汶', '[' => '沍', '\\' => '沔', ']' => '沘', '^' => '沂', '_' => '灶', '`' => '灼', 'a' => '災', 'b' => '灸', 'c' => '牢', 'd' => '牡', 'e' => '牠', 'f' => '狄', 'g' => '狂', 'h' => '玖', 'i' => '甬', 'j' => '甫', 'k' => '男', 'l' => '甸', 'm' => '皂', 'n' => '盯', 'o' => '矣', 'p' => '私', 'q' => '秀', 'r' => '禿', 's' => '究', 't' => '系', 'u' => '罕', 'v' => '肖', 'w' => '肓', 'x' => '肝', 'y' => '肘', 'z' => '肛', '{' => '肚', '|' => '育', '}' => '良', '~' => '芒', '' => '芋', '' => '芍', '' => '見', '' => '角', '' => '言', '' => '谷', '' => '豆', '' => '豕', '' => '貝', '' => '赤', '' => '走', '' => '足', '' => '身', '' => '車', '' => '辛', '' => '辰', '' => '迂', '' => '迆', '' => '迅', '' => '迄', '' => '巡', '' => '邑', '' => '邢', '' => '邪', '' => '邦', '' => '那', '' => '酉', '' => '釆', '' => '里', '' => '防', '' => '阮', '' => '阱', '' => '阪', '' => '阬', '' => '並', '' => '乖', '' => '乳', '' => '事', '' => '些', '' => '亞', '' => '享', '' => '京', '' => '佯', '' => '依', '' => '侍', '' => '佳', '' => '使', '' => '佬', '' => '供', '' => '例', '' => '來', '' => '侃', '' => '佰', '' => '併', '' => '侈', '' => '佩', '' => '佻', '' => '侖', '' => '佾', '' => '侏', '' => '侑', '' => '佺', '' => '兔', '' => '兒', '' => '兕', '' => '兩', '' => '具', '' => '其', '' => '典', '' => '冽', '' => '函', '' => '刻', '' => '券', '' => '刷', '' => '刺', '' => '到', '' => '刮', '' => '制', '' => '剁', '' => '劾', '' => '劻', '' => '卒', '' => '協', '' => '卓', '' => '卑', '' => '卦', '' => '卷', '' => '卸', '' => '卹', '' => '取', '' => '叔', '' => '受', '' => '味', '' => '呵', '@' => '咖', 'A' => '呸', 'B' => '咕', 'C' => '咀', 'D' => '呻', 'E' => '呷', 'F' => '咄', 'G' => '咒', 'H' => '咆', 'I' => '呼', 'J' => '咐', 'K' => '呱', 'L' => '呶', 'M' => '和', 'N' => '咚', 'O' => '呢', 'P' => '周', 'Q' => '咋', 'R' => '命', 'S' => '咎', 'T' => '固', 'U' => '垃', 'V' => '坷', 'W' => '坪', 'X' => '坩', 'Y' => '坡', 'Z' => '坦', '[' => '坤', '\\' => '坼', ']' => '夜', '^' => '奉', '_' => '奇', '`' => '奈', 'a' => '奄', 'b' => '奔', 'c' => '妾', 'd' => '妻', 'e' => '委', 'f' => '妹', 'g' => '妮', 'h' => '姑', 'i' => '姆', 'j' => '姐', 'k' => '姍', 'l' => '始', 'm' => '姓', 'n' => '姊', 'o' => '妯', 'p' => '妳', 'q' => '姒', 'r' => '姅', 's' => '孟', 't' => '孤', 'u' => '季', 'v' => '宗', 'w' => '定', 'x' => '官', 'y' => '宜', 'z' => '宙', '{' => '宛', '|' => '尚', '}' => '屈', '~' => '居', '' => '屆', '' => '岷', '' => '岡', '' => '岸', '' => '岩', '' => '岫', '' => '岱', '' => '岳', '' => '帘', '' => '帚', '' => '帖', '' => '帕', '' => '帛', '' => '帑', '' => '幸', '' => '庚', '' => '店', '' => '府', '' => '底', '' => '庖', '' => '延', '' => '弦', '' => '弧', '' => '弩', '' => '往', '' => '征', '' => '彿', '' => '彼', '' => '忝', '' => '忠', '' => '忽', '' => '念', '' => '忿', '' => '怏', '' => '怔', '' => '怯', '' => '怵', '' => '怖', '' => '怪', '' => '怕', '' => '怡', '' => '性', '' => '怩', '' => '怫', '' => '怛', '' => '或', '' => '戕', '' => '房', '' => '戾', '' => '所', '' => '承', '' => '拉', '' => '拌', '' => '拄', '' => '抿', '' => '拂', '' => '抹', '' => '拒', '' => '招', '' => '披', '' => '拓', '' => '拔', '' => '拋', '' => '拈', '' => '抨', '' => '抽', '' => '押', '' => '拐', '' => '拙', '' => '拇', '' => '拍', '' => '抵', '' => '拚', '' => '抱', '' => '拘', '' => '拖', '' => '拗', '' => '拆', '' => '抬', '' => '拎', '' => '放', '' => '斧', '' => '於', '' => '旺', '' => '昔', '' => '易', '' => '昌', '' => '昆', '' => '昂', '' => '明', '' => '昀', '' => '昏', '' => '昕', '' => '昊', '@' => '昇', 'A' => '服', 'B' => '朋', 'C' => '杭', 'D' => '枋', 'E' => '枕', 'F' => '東', 'G' => '果', 'H' => '杳', 'I' => '杷', 'J' => '枇', 'K' => '枝', 'L' => '林', 'M' => '杯', 'N' => '杰', 'O' => '板', 'P' => '枉', 'Q' => '松', 'R' => '析', 'S' => '杵', 'T' => '枚', 'U' => '枓', 'V' => '杼', 'W' => '杪', 'X' => '杲', 'Y' => '欣', 'Z' => '武', '[' => '歧', '\\' => '歿', ']' => '氓', '^' => '氛', '_' => '泣', '`' => '注', 'a' => '泳', 'b' => '沱', 'c' => '泌', 'd' => '泥', 'e' => '河', 'f' => '沽', 'g' => '沾', 'h' => '沼', 'i' => '波', 'j' => '沫', 'k' => '法', 'l' => '泓', 'm' => '沸', 'n' => '泄', 'o' => '油', 'p' => '況', 'q' => '沮', 'r' => '泗', 's' => '泅', 't' => '泱', 'u' => '沿', 'v' => '治', 'w' => '泡', 'x' => '泛', 'y' => '泊', 'z' => '沬', '{' => '泯', '|' => '泜', '}' => '泖', '~' => '泠', '' => '炕', '' => '炎', '' => '炒', '' => '炊', '' => '炙', '' => '爬', '' => '爭', '' => '爸', '' => '版', '' => '牧', '' => '物', '' => '狀', '' => '狎', '' => '狙', '' => '狗', '' => '狐', '' => '玩', '' => '玨', '' => '玟', '' => '玫', '' => '玥', '' => '甽', '' => '疝', '' => '疙', '' => '疚', '' => '的', '' => '盂', '' => '盲', '' => '直', '' => '知', '' => '矽', '' => '社', '' => '祀', '' => '祁', '' => '秉', '' => '秈', '' => '空', '' => '穹', '' => '竺', '' => '糾', '' => '罔', '' => '羌', '' => '羋', '' => '者', '' => '肺', '' => '肥', '' => '肢', '' => '肱', '' => '股', '' => '肫', '' => '肩', '' => '肴', '' => '肪', '' => '肯', '' => '臥', '' => '臾', '' => '舍', '' => '芳', '' => '芝', '' => '芙', '' => '芭', '' => '芽', '' => '芟', '' => '芹', '' => '花', '' => '芬', '' => '芥', '' => '芯', '' => '芸', '' => '芣', '' => '芰', '' => '芾', '' => '芷', '' => '虎', '' => '虱', '' => '初', '' => '表', '' => '軋', '' => '迎', '' => '返', '' => '近', '' => '邵', '' => '邸', '' => '邱', '' => '邶', '' => '采', '' => '金', '' => '長', '' => '門', '' => '阜', '' => '陀', '' => '阿', '' => '阻', '' => '附', '@' => '陂', 'A' => '隹', 'B' => '雨', 'C' => '青', 'D' => '非', 'E' => '亟', 'F' => '亭', 'G' => '亮', 'H' => '信', 'I' => '侵', 'J' => '侯', 'K' => '便', 'L' => '俠', 'M' => '俑', 'N' => '俏', 'O' => '保', 'P' => '促', 'Q' => '侶', 'R' => '俘', 'S' => '俟', 'T' => '俊', 'U' => '俗', 'V' => '侮', 'W' => '俐', 'X' => '俄', 'Y' => '係', 'Z' => '俚', '[' => '俎', '\\' => '俞', ']' => '侷', '^' => '兗', '_' => '冒', '`' => '冑', 'a' => '冠', 'b' => '剎', 'c' => '剃', 'd' => '削', 'e' => '前', 'f' => '剌', 'g' => '剋', 'h' => '則', 'i' => '勇', 'j' => '勉', 'k' => '勃', 'l' => '勁', 'm' => '匍', 'n' => '南', 'o' => '卻', 'p' => '厚', 'q' => '叛', 'r' => '咬', 's' => '哀', 't' => '咨', 'u' => '哎', 'v' => '哉', 'w' => '咸', 'x' => '咦', 'y' => '咳', 'z' => '哇', '{' => '哂', '|' => '咽', '}' => '咪', '~' => '品', '' => '哄', '' => '哈', '' => '咯', '' => '咫', '' => '咱', '' => '咻', '' => '咩', '' => '咧', '' => '咿', '' => '囿', '' => '垂', '' => '型', '' => '垠', '' => '垣', '' => '垢', '' => '城', '' => '垮', '' => '垓', '' => '奕', '' => '契', '' => '奏', '' => '奎', '' => '奐', '' => '姜', '' => '姘', '' => '姿', '' => '姣', '' => '姨', '' => '娃', '' => '姥', '' => '姪', '' => '姚', '' => '姦', '' => '威', '' => '姻', '' => '孩', '' => '宣', '' => '宦', '' => '室', '' => '客', '' => '宥', '' => '封', '' => '屎', '' => '屏', '' => '屍', '' => '屋', '' => '峙', '' => '峒', '' => '巷', '' => '帝', '' => '帥', '' => '帟', '' => '幽', '' => '庠', '' => '度', '' => '建', '' => '弈', '' => '弭', '' => '彥', '' => '很', '' => '待', '' => '徊', '' => '律', '' => '徇', '' => '後', '' => '徉', '' => '怒', '' => '思', '' => '怠', '' => '急', '' => '怎', '' => '怨', '' => '恍', '' => '恰', '' => '恨', '' => '恢', '' => '恆', '' => '恃', '' => '恬', '' => '恫', '' => '恪', '' => '恤', '' => '扁', '' => '拜', '' => '挖', '' => '按', '' => '拼', '' => '拭', '' => '持', '' => '拮', '' => '拽', '' => '指', '' => '拱', '' => '拷', '@' => '拯', 'A' => '括', 'B' => '拾', 'C' => '拴', 'D' => '挑', 'E' => '挂', 'F' => '政', 'G' => '故', 'H' => '斫', 'I' => '施', 'J' => '既', 'K' => '春', 'L' => '昭', 'M' => '映', 'N' => '昧', 'O' => '是', 'P' => '星', 'Q' => '昨', 'R' => '昱', 'S' => '昤', 'T' => '曷', 'U' => '柿', 'V' => '染', 'W' => '柱', 'X' => '柔', 'Y' => '某', 'Z' => '柬', '[' => '架', '\\' => '枯', ']' => '柵', '^' => '柩', '_' => '柯', '`' => '柄', 'a' => '柑', 'b' => '枴', 'c' => '柚', 'd' => '查', 'e' => '枸', 'f' => '柏', 'g' => '柞', 'h' => '柳', 'i' => '枰', 'j' => '柙', 'k' => '柢', 'l' => '柝', 'm' => '柒', 'n' => '歪', 'o' => '殃', 'p' => '殆', 'q' => '段', 'r' => '毒', 's' => '毗', 't' => '氟', 'u' => '泉', 'v' => '洋', 'w' => '洲', 'x' => '洪', 'y' => '流', 'z' => '津', '{' => '洌', '|' => '洱', '}' => '洞', '~' => '洗', '' => '活', '' => '洽', '' => '派', '' => '洶', '' => '洛', '' => '泵', '' => '洹', '' => '洧', '' => '洸', '' => '洩', '' => '洮', '' => '洵', '' => '洎', '' => '洫', '' => '炫', '' => '為', '' => '炳', '' => '炬', '' => '炯', '' => '炭', '' => '炸', '' => '炮', '' => '炤', '' => '爰', '' => '牲', '' => '牯', '' => '牴', '' => '狩', '' => '狠', '' => '狡', '' => '玷', '' => '珊', '' => '玻', '' => '玲', '' => '珍', '' => '珀', '' => '玳', '' => '甚', '' => '甭', '' => '畏', '' => '界', '' => '畎', '' => '畋', '' => '疫', '' => '疤', '' => '疥', '' => '疢', '' => '疣', '' => '癸', '' => '皆', '' => '皇', '' => '皈', '' => '盈', '' => '盆', '' => '盃', '' => '盅', '' => '省', '' => '盹', '' => '相', '' => '眉', '' => '看', '' => '盾', '' => '盼', '' => '眇', '' => '矜', '' => '砂', '' => '研', '' => '砌', '' => '砍', '' => '祆', '' => '祉', '' => '祈', '' => '祇', '' => '禹', '' => '禺', '' => '科', '' => '秒', '' => '秋', '' => '穿', '' => '突', '' => '竿', '' => '竽', '' => '籽', '' => '紂', '' => '紅', '' => '紀', '' => '紉', '' => '紇', '' => '約', '' => '紆', '' => '缸', '' => '美', '' => '羿', '' => '耄', '@' => '耐', 'A' => '耍', 'B' => '耑', 'C' => '耶', 'D' => '胖', 'E' => '胥', 'F' => '胚', 'G' => '胃', 'H' => '胄', 'I' => '背', 'J' => '胡', 'K' => '胛', 'L' => '胎', 'M' => '胞', 'N' => '胤', 'O' => '胝', 'P' => '致', 'Q' => '舢', 'R' => '苧', 'S' => '范', 'T' => '茅', 'U' => '苣', 'V' => '苛', 'W' => '苦', 'X' => '茄', 'Y' => '若', 'Z' => '茂', '[' => '茉', '\\' => '苒', ']' => '苗', '^' => '英', '_' => '茁', '`' => '苜', 'a' => '苔', 'b' => '苑', 'c' => '苞', 'd' => '苓', 'e' => '苟', 'f' => '苯', 'g' => '茆', 'h' => '虐', 'i' => '虹', 'j' => '虻', 'k' => '虺', 'l' => '衍', 'm' => '衫', 'n' => '要', 'o' => '觔', 'p' => '計', 'q' => '訂', 'r' => '訃', 's' => '貞', 't' => '負', 'u' => '赴', 'v' => '赳', 'w' => '趴', 'x' => '軍', 'y' => '軌', 'z' => '述', '{' => '迦', '|' => '迢', '}' => '迪', '~' => '迥', '' => '迭', '' => '迫', '' => '迤', '' => '迨', '' => '郊', '' => '郎', '' => '郁', '' => '郃', '' => '酋', '' => '酊', '' => '重', '' => '閂', '' => '限', '' => '陋', '' => '陌', '' => '降', '' => '面', '' => '革', '' => '韋', '' => '韭', '' => '音', '' => '頁', '' => '風', '' => '飛', '' => '食', '' => '首', '' => '香', '' => '乘', '' => '亳', '' => '倌', '' => '倍', '' => '倣', '' => '俯', '' => '倦', '' => '倥', '' => '俸', '' => '倩', '' => '倖', '' => '倆', '' => '值', '' => '借', '' => '倚', '' => '倒', '' => '們', '' => '俺', '' => '倀', '' => '倔', '' => '倨', '' => '俱', '' => '倡', '' => '個', '' => '候', '' => '倘', '' => '俳', '' => '修', '' => '倭', '' => '倪', '' => '俾', '' => '倫', '' => '倉', '' => '兼', '' => '冤', '' => '冥', '' => '冢', '' => '凍', '' => '凌', '' => '准', '' => '凋', '' => '剖', '' => '剜', '' => '剔', '' => '剛', '' => '剝', '' => '匪', '' => '卿', '' => '原', '' => '厝', '' => '叟', '' => '哨', '' => '唐', '' => '唁', '' => '唷', '' => '哼', '' => '哥', '' => '哲', '' => '唆', '' => '哺', '' => '唔', '' => '哩', '' => '哭', '' => '員', '' => '唉', '' => '哮', '' => '哪', '@' => '哦', 'A' => '唧', 'B' => '唇', 'C' => '哽', 'D' => '唏', 'E' => '圃', 'F' => '圄', 'G' => '埂', 'H' => '埔', 'I' => '埋', 'J' => '埃', 'K' => '堉', 'L' => '夏', 'M' => '套', 'N' => '奘', 'O' => '奚', 'P' => '娑', 'Q' => '娘', 'R' => '娜', 'S' => '娟', 'T' => '娛', 'U' => '娓', 'V' => '姬', 'W' => '娠', 'X' => '娣', 'Y' => '娩', 'Z' => '娥', '[' => '娌', '\\' => '娉', ']' => '孫', '^' => '屘', '_' => '宰', '`' => '害', 'a' => '家', 'b' => '宴', 'c' => '宮', 'd' => '宵', 'e' => '容', 'f' => '宸', 'g' => '射', 'h' => '屑', 'i' => '展', 'j' => '屐', 'k' => '峭', 'l' => '峽', 'm' => '峻', 'n' => '峪', 'o' => '峨', 'p' => '峰', 'q' => '島', 'r' => '崁', 's' => '峴', 't' => '差', 'u' => '席', 'v' => '師', 'w' => '庫', 'x' => '庭', 'y' => '座', 'z' => '弱', '{' => '徒', '|' => '徑', '}' => '徐', '~' => '恙', '' => '恣', '' => '恥', '' => '恐', '' => '恕', '' => '恭', '' => '恩', '' => '息', '' => '悄', '' => '悟', '' => '悚', '' => '悍', '' => '悔', '' => '悌', '' => '悅', '' => '悖', '' => '扇', '' => '拳', '' => '挈', '' => '拿', '' => '捎', '' => '挾', '' => '振', '' => '捕', '' => '捂', '' => '捆', '' => '捏', '' => '捉', '' => '挺', '' => '捐', '' => '挽', '' => '挪', '' => '挫', '' => '挨', '' => '捍', '' => '捌', '' => '效', '' => '敉', '' => '料', '' => '旁', '' => '旅', '' => '時', '' => '晉', '' => '晏', '' => '晃', '' => '晒', '' => '晌', '' => '晅', '' => '晁', '' => '書', '' => '朔', '' => '朕', '' => '朗', '' => '校', '' => '核', '' => '案', '' => '框', '' => '桓', '' => '根', '' => '桂', '' => '桔', '' => '栩', '' => '梳', '' => '栗', '' => '桌', '' => '桑', '' => '栽', '' => '柴', '' => '桐', '' => '桀', '' => '格', '' => '桃', '' => '株', '' => '桅', '' => '栓', '' => '栘', '' => '桁', '' => '殊', '' => '殉', '' => '殷', '' => '氣', '' => '氧', '' => '氨', '' => '氦', '' => '氤', '' => '泰', '' => '浪', '' => '涕', '' => '消', '' => '涇', '' => '浦', '' => '浸', '' => '海', '' => '浙', '' => '涓', '@' => '浬', 'A' => '涉', 'B' => '浮', 'C' => '浚', 'D' => '浴', 'E' => '浩', 'F' => '涌', 'G' => '涊', 'H' => '浹', 'I' => '涅', 'J' => '浥', 'K' => '涔', 'L' => '烊', 'M' => '烘', 'N' => '烤', 'O' => '烙', 'P' => '烈', 'Q' => '烏', 'R' => '爹', 'S' => '特', 'T' => '狼', 'U' => '狹', 'V' => '狽', 'W' => '狸', 'X' => '狷', 'Y' => '玆', 'Z' => '班', '[' => '琉', '\\' => '珮', ']' => '珠', '^' => '珪', '_' => '珞', '`' => '畔', 'a' => '畝', 'b' => '畜', 'c' => '畚', 'd' => '留', 'e' => '疾', 'f' => '病', 'g' => '症', 'h' => '疲', 'i' => '疳', 'j' => '疽', 'k' => '疼', 'l' => '疹', 'm' => '痂', 'n' => '疸', 'o' => '皋', 'p' => '皰', 'q' => '益', 'r' => '盍', 's' => '盎', 't' => '眩', 'u' => '真', 'v' => '眠', 'w' => '眨', 'x' => '矩', 'y' => '砰', 'z' => '砧', '{' => '砸', '|' => '砝', '}' => '破', '~' => '砷', '' => '砥', '' => '砭', '' => '砠', '' => '砟', '' => '砲', '' => '祕', '' => '祐', '' => '祠', '' => '祟', '' => '祖', '' => '神', '' => '祝', '' => '祗', '' => '祚', '' => '秤', '' => '秣', '' => '秧', '' => '租', '' => '秦', '' => '秩', '' => '秘', '' => '窄', '' => '窈', '' => '站', '' => '笆', '' => '笑', '' => '粉', '' => '紡', '' => '紗', '' => '紋', '' => '紊', '' => '素', '' => '索', '' => '純', '' => '紐', '' => '紕', '' => '級', '' => '紜', '' => '納', '' => '紙', '' => '紛', '' => '缺', '' => '罟', '' => '羔', '' => '翅', '' => '翁', '' => '耆', '' => '耘', '' => '耕', '' => '耙', '' => '耗', '' => '耽', '' => '耿', '' => '胱', '' => '脂', '' => '胰', '' => '脅', '' => '胭', '' => '胴', '' => '脆', '' => '胸', '' => '胳', '' => '脈', '' => '能', '' => '脊', '' => '胼', '' => '胯', '' => '臭', '' => '臬', '' => '舀', '' => '舐', '' => '航', '' => '舫', '' => '舨', '' => '般', '' => '芻', '' => '茫', '' => '荒', '' => '荔', '' => '荊', '' => '茸', '' => '荐', '' => '草', '' => '茵', '' => '茴', '' => '荏', '' => '茲', '' => '茹', '' => '茶', '' => '茗', '' => '荀', '' => '茱', '' => '茨', '' => '荃', '@' => '虔', 'A' => '蚊', 'B' => '蚪', 'C' => '蚓', 'D' => '蚤', 'E' => '蚩', 'F' => '蚌', 'G' => '蚣', 'H' => '蚜', 'I' => '衰', 'J' => '衷', 'K' => '袁', 'L' => '袂', 'M' => '衽', 'N' => '衹', 'O' => '記', 'P' => '訐', 'Q' => '討', 'R' => '訌', 'S' => '訕', 'T' => '訊', 'U' => '託', 'V' => '訓', 'W' => '訖', 'X' => '訏', 'Y' => '訑', 'Z' => '豈', '[' => '豺', '\\' => '豹', ']' => '財', '^' => '貢', '_' => '起', '`' => '躬', 'a' => '軒', 'b' => '軔', 'c' => '軏', 'd' => '辱', 'e' => '送', 'f' => '逆', 'g' => '迷', 'h' => '退', 'i' => '迺', 'j' => '迴', 'k' => '逃', 'l' => '追', 'm' => '逅', 'n' => '迸', 'o' => '邕', 'p' => '郡', 'q' => '郝', 'r' => '郢', 's' => '酒', 't' => '配', 'u' => '酌', 'v' => '釘', 'w' => '針', 'x' => '釗', 'y' => '釜', 'z' => '釙', '{' => '閃', '|' => '院', '}' => '陣', '~' => '陡', '' => '陛', '' => '陝', '' => '除', '' => '陘', '' => '陞', '' => '隻', '' => '飢', '' => '馬', '' => '骨', '' => '高', '' => '鬥', '' => '鬲', '' => '鬼', '' => '乾', '' => '偺', '' => '偽', '' => '停', '' => '假', '' => '偃', '' => '偌', '' => '做', '' => '偉', '' => '健', '' => '偶', '' => '偎', '' => '偕', '' => '偵', '' => '側', '' => '偷', '' => '偏', '' => '倏', '' => '偯', '' => '偭', '' => '兜', '' => '冕', '' => '凰', '' => '剪', '' => '副', '' => '勒', '' => '務', '' => '勘', '' => '動', '' => '匐', '' => '匏', '' => '匙', '' => '匿', '' => '區', '' => '匾', '' => '參', '' => '曼', '' => '商', '' => '啪', '' => '啦', '' => '啄', '' => '啞', '' => '啡', '' => '啃', '' => '啊', '' => '唱', '' => '啖', '' => '問', '' => '啕', '' => '唯', '' => '啤', '' => '唸', '' => '售', '' => '啜', '' => '唬', '' => '啣', '' => '唳', '' => '啁', '' => '啗', '' => '圈', '' => '國', '' => '圉', '' => '域', '' => '堅', '' => '堊', '' => '堆', '' => '埠', '' => '埤', '' => '基', '' => '堂', '' => '堵', '' => '執', '' => '培', '' => '夠', '' => '奢', '' => '娶', '' => '婁', '' => '婉', '' => '婦', '' => '婪', '' => '婀', '@' => '娼', 'A' => '婢', 'B' => '婚', 'C' => '婆', 'D' => '婊', 'E' => '孰', 'F' => '寇', 'G' => '寅', 'H' => '寄', 'I' => '寂', 'J' => '宿', 'K' => '密', 'L' => '尉', 'M' => '專', 'N' => '將', 'O' => '屠', 'P' => '屜', 'Q' => '屝', 'R' => '崇', 'S' => '崆', 'T' => '崎', 'U' => '崛', 'V' => '崖', 'W' => '崢', 'X' => '崑', 'Y' => '崩', 'Z' => '崔', '[' => '崙', '\\' => '崤', ']' => '崧', '^' => '崗', '_' => '巢', '`' => '常', 'a' => '帶', 'b' => '帳', 'c' => '帷', 'd' => '康', 'e' => '庸', 'f' => '庶', 'g' => '庵', 'h' => '庾', 'i' => '張', 'j' => '強', 'k' => '彗', 'l' => '彬', 'm' => '彩', 'n' => '彫', 'o' => '得', 'p' => '徙', 'q' => '從', 'r' => '徘', 's' => '御', 't' => '徠', 'u' => '徜', 'v' => '恿', 'w' => '患', 'x' => '悉', 'y' => '悠', 'z' => '您', '{' => '惋', '|' => '悴', '}' => '惦', '~' => '悽', '' => '情', '' => '悻', '' => '悵', '' => '惜', '' => '悼', '' => '惘', '' => '惕', '' => '惆', '' => '惟', '' => '悸', '' => '惚', '' => '惇', '' => '戚', '' => '戛', '' => '扈', '' => '掠', '' => '控', '' => '捲', '' => '掖', '' => '探', '' => '接', '' => '捷', '' => '捧', '' => '掘', '' => '措', '' => '捱', '' => '掩', '' => '掉', '' => '掃', '' => '掛', '' => '捫', '' => '推', '' => '掄', '' => '授', '' => '掙', '' => '採', '' => '掬', '' => '排', '' => '掏', '' => '掀', '' => '捻', '' => '捩', '' => '捨', '' => '捺', '' => '敝', '' => '敖', '' => '救', '' => '教', '' => '敗', '' => '啟', '' => '敏', '' => '敘', '' => '敕', '' => '敔', '' => '斜', '' => '斛', '' => '斬', '' => '族', '' => '旋', '' => '旌', '' => '旎', '' => '晝', '' => '晚', '' => '晤', '' => '晨', '' => '晦', '' => '晞', '' => '曹', '' => '勗', '' => '望', '' => '梁', '' => '梯', '' => '梢', '' => '梓', '' => '梵', '' => '桿', '' => '桶', '' => '梱', '' => '梧', '' => '梗', '' => '械', '' => '梃', '' => '棄', '' => '梭', '' => '梆', '' => '梅', '' => '梔', '' => '條', '' => '梨', '' => '梟', '' => '梡', '' => '梂', '' => '欲', '' => '殺', '@' => '毫', 'A' => '毬', 'B' => '氫', 'C' => '涎', 'D' => '涼', 'E' => '淳', 'F' => '淙', 'G' => '液', 'H' => '淡', 'I' => '淌', 'J' => '淤', 'K' => '添', 'L' => '淺', 'M' => '清', 'N' => '淇', 'O' => '淋', 'P' => '涯', 'Q' => '淑', 'R' => '涮', 'S' => '淞', 'T' => '淹', 'U' => '涸', 'V' => '混', 'W' => '淵', 'X' => '淅', 'Y' => '淒', 'Z' => '渚', '[' => '涵', '\\' => '淚', ']' => '淫', '^' => '淘', '_' => '淪', '`' => '深', 'a' => '淮', 'b' => '淨', 'c' => '淆', 'd' => '淄', 'e' => '涪', 'f' => '淬', 'g' => '涿', 'h' => '淦', 'i' => '烹', 'j' => '焉', 'k' => '焊', 'l' => '烽', 'm' => '烯', 'n' => '爽', 'o' => '牽', 'p' => '犁', 'q' => '猜', 'r' => '猛', 's' => '猖', 't' => '猓', 'u' => '猙', 'v' => '率', 'w' => '琅', 'x' => '琊', 'y' => '球', 'z' => '理', '{' => '現', '|' => '琍', '}' => '瓠', '~' => '瓶', '' => '瓷', '' => '甜', '' => '產', '' => '略', '' => '畦', '' => '畢', '' => '異', '' => '疏', '' => '痔', '' => '痕', '' => '疵', '' => '痊', '' => '痍', '' => '皎', '' => '盔', '' => '盒', '' => '盛', '' => '眷', '' => '眾', '' => '眼', '' => '眶', '' => '眸', '' => '眺', '' => '硫', '' => '硃', '' => '硎', '' => '祥', '' => '票', '' => '祭', '' => '移', '' => '窒', '' => '窕', '' => '笠', '' => '笨', '' => '笛', '' => '第', '' => '符', '' => '笙', '' => '笞', '' => '笮', '' => '粒', '' => '粗', '' => '粕', '' => '絆', '' => '絃', '' => '統', '' => '紮', '' => '紹', '' => '紼', '' => '絀', '' => '細', '' => '紳', '' => '組', '' => '累', '' => '終', '' => '紲', '' => '紱', '' => '缽', '' => '羞', '' => '羚', '' => '翌', '' => '翎', '' => '習', '' => '耜', '' => '聊', '' => '聆', '' => '脯', '' => '脖', '' => '脣', '' => '脫', '' => '脩', '' => '脰', '' => '脤', '' => '舂', '' => '舵', '' => '舷', '' => '舶', '' => '船', '' => '莎', '' => '莞', '' => '莘', '' => '荸', '' => '莢', '' => '莖', '' => '莽', '' => '莫', '' => '莒', '' => '莊', '' => '莓', '' => '莉', '' => '莠', '' => '荷', '' => '荻', '' => '荼', '@' => '莆', 'A' => '莧', 'B' => '處', 'C' => '彪', 'D' => '蛇', 'E' => '蛀', 'F' => '蚶', 'G' => '蛄', 'H' => '蚵', 'I' => '蛆', 'J' => '蛋', 'K' => '蚱', 'L' => '蚯', 'M' => '蛉', 'N' => '術', 'O' => '袞', 'P' => '袈', 'Q' => '被', 'R' => '袒', 'S' => '袖', 'T' => '袍', 'U' => '袋', 'V' => '覓', 'W' => '規', 'X' => '訪', 'Y' => '訝', 'Z' => '訣', '[' => '訥', '\\' => '許', ']' => '設', '^' => '訟', '_' => '訛', '`' => '訢', 'a' => '豉', 'b' => '豚', 'c' => '販', 'd' => '責', 'e' => '貫', 'f' => '貨', 'g' => '貪', 'h' => '貧', 'i' => '赧', 'j' => '赦', 'k' => '趾', 'l' => '趺', 'm' => '軛', 'n' => '軟', 'o' => '這', 'p' => '逍', 'q' => '通', 'r' => '逗', 's' => '連', 't' => '速', 'u' => '逝', 'v' => '逐', 'w' => '逕', 'x' => '逞', 'y' => '造', 'z' => '透', '{' => '逢', '|' => '逖', '}' => '逛', '~' => '途', '' => '部', '' => '郭', '' => '都', '' => '酗', '' => '野', '' => '釵', '' => '釦', '' => '釣', '' => '釧', '' => '釭', '' => '釩', '' => '閉', '' => '陪', '' => '陵', '' => '陳', '' => '陸', '' => '陰', '' => '陴', '' => '陶', '' => '陷', '' => '陬', '' => '雀', '' => '雪', '' => '雩', '' => '章', '' => '竟', '' => '頂', '' => '頃', '' => '魚', '' => '鳥', '' => '鹵', '' => '鹿', '' => '麥', '' => '麻', '' => '傢', '' => '傍', '' => '傅', '' => '備', '' => '傑', '' => '傀', '' => '傖', '' => '傘', '' => '傚', '' => '最', '' => '凱', '' => '割', '' => '剴', '' => '創', '' => '剩', '' => '勞', '' => '勝', '' => '勛', '' => '博', '' => '厥', '' => '啻', '' => '喀', '' => '喧', '' => '啼', '' => '喊', '' => '喝', '' => '喘', '' => '喂', '' => '喜', '' => '喪', '' => '喔', '' => '喇', '' => '喋', '' => '喃', '' => '喳', '' => '單', '' => '喟', '' => '唾', '' => '喲', '' => '喚', '' => '喻', '' => '喬', '' => '喱', '' => '啾', '' => '喉', '' => '喫', '' => '喙', '' => '圍', '' => '堯', '' => '堪', '' => '場', '' => '堤', '' => '堰', '' => '報', '' => '堡', '' => '堝', '' => '堠', '' => '壹', '' => '壺', '' => '奠', '@' => '婷', 'A' => '媚', 'B' => '婿', 'C' => '媒', 'D' => '媛', 'E' => '媧', 'F' => '孳', 'G' => '孱', 'H' => '寒', 'I' => '富', 'J' => '寓', 'K' => '寐', 'L' => '尊', 'M' => '尋', 'N' => '就', 'O' => '嵌', 'P' => '嵐', 'Q' => '崴', 'R' => '嵇', 'S' => '巽', 'T' => '幅', 'U' => '帽', 'V' => '幀', 'W' => '幃', 'X' => '幾', 'Y' => '廊', 'Z' => '廁', '[' => '廂', '\\' => '廄', ']' => '弼', '^' => '彭', '_' => '復', '`' => '循', 'a' => '徨', 'b' => '惑', 'c' => '惡', 'd' => '悲', 'e' => '悶', 'f' => '惠', 'g' => '愜', 'h' => '愣', 'i' => '惺', 'j' => '愕', 'k' => '惰', 'l' => '惻', 'm' => '惴', 'n' => '慨', 'o' => '惱', 'p' => '愎', 'q' => '惶', 'r' => '愉', 's' => '愀', 't' => '愒', 'u' => '戟', 'v' => '扉', 'w' => '掣', 'x' => '掌', 'y' => '描', 'z' => '揀', '{' => '揩', '|' => '揉', '}' => '揆', '~' => '揍', '' => '插', '' => '揣', '' => '提', '' => '握', '' => '揖', '' => '揭', '' => '揮', '' => '捶', '' => '援', '' => '揪', '' => '換', '' => '摒', '' => '揚', '' => '揹', '' => '敞', '' => '敦', '' => '敢', '' => '散', '' => '斑', '' => '斐', '' => '斯', '' => '普', '' => '晰', '' => '晴', '' => '晶', '' => '景', '' => '暑', '' => '智', '' => '晾', '' => '晷', '' => '曾', '' => '替', '' => '期', '' => '朝', '' => '棺', '' => '棕', '' => '棠', '' => '棘', '' => '棗', '' => '椅', '' => '棟', '' => '棵', '' => '森', '' => '棧', '' => '棹', '' => '棒', '' => '棲', '' => '棣', '' => '棋', '' => '棍', '' => '植', '' => '椒', '' => '椎', '' => '棉', '' => '棚', '' => '楮', '' => '棻', '' => '款', '' => '欺', '' => '欽', '' => '殘', '' => '殖', '' => '殼', '' => '毯', '' => '氮', '' => '氯', '' => '氬', '' => '港', '' => '游', '' => '湔', '' => '渡', '' => '渲', '' => '湧', '' => '湊', '' => '渠', '' => '渥', '' => '渣', '' => '減', '' => '湛', '' => '湘', '' => '渤', '' => '湖', '' => '湮', '' => '渭', '' => '渦', '' => '湯', '' => '渴', '' => '湍', '' => '渺', '' => '測', '' => '湃', '' => '渝', '' => '渾', '' => '滋', '@' => '溉', 'A' => '渙', 'B' => '湎', 'C' => '湣', 'D' => '湄', 'E' => '湲', 'F' => '湩', 'G' => '湟', 'H' => '焙', 'I' => '焚', 'J' => '焦', 'K' => '焰', 'L' => '無', 'M' => '然', 'N' => '煮', 'O' => '焜', 'P' => '牌', 'Q' => '犄', 'R' => '犀', 'S' => '猶', 'T' => '猥', 'U' => '猴', 'V' => '猩', 'W' => '琺', 'X' => '琪', 'Y' => '琳', 'Z' => '琢', '[' => '琥', '\\' => '琵', ']' => '琶', '^' => '琴', '_' => '琯', '`' => '琛', 'a' => '琦', 'b' => '琨', 'c' => '甥', 'd' => '甦', 'e' => '畫', 'f' => '番', 'g' => '痢', 'h' => '痛', 'i' => '痣', 'j' => '痙', 'k' => '痘', 'l' => '痞', 'm' => '痠', 'n' => '登', 'o' => '發', 'p' => '皖', 'q' => '皓', 'r' => '皴', 's' => '盜', 't' => '睏', 'u' => '短', 'v' => '硝', 'w' => '硬', 'x' => '硯', 'y' => '稍', 'z' => '稈', '{' => '程', '|' => '稅', '}' => '稀', '~' => '窘', '' => '窗', '' => '窖', '' => '童', '' => '竣', '' => '等', '' => '策', '' => '筆', '' => '筐', '' => '筒', '' => '答', '' => '筍', '' => '筋', '' => '筏', '' => '筑', '' => '粟', '' => '粥', '' => '絞', '' => '結', '' => '絨', '' => '絕', '' => '紫', '' => '絮', '' => '絲', '' => '絡', '' => '給', '' => '絢', '' => '絰', '' => '絳', '' => '善', '' => '翔', '' => '翕', '' => '耋', '' => '聒', '' => '肅', '' => '腕', '' => '腔', '' => '腋', '' => '腑', '' => '腎', '' => '脹', '' => '腆', '' => '脾', '' => '腌', '' => '腓', '' => '腴', '' => '舒', '' => '舜', '' => '菩', '' => '萃', '' => '菸', '' => '萍', '' => '菠', '' => '菅', '' => '萋', '' => '菁', '' => '華', '' => '菱', '' => '菴', '' => '著', '' => '萊', '' => '菰', '' => '萌', '' => '菌', '' => '菽', '' => '菲', '' => '菊', '' => '萸', '' => '萎', '' => '萄', '' => '菜', '' => '萇', '' => '菔', '' => '菟', '' => '虛', '' => '蛟', '' => '蛙', '' => '蛭', '' => '蛔', '' => '蛛', '' => '蛤', '' => '蛐', '' => '蛞', '' => '街', '' => '裁', '' => '裂', '' => '袱', '' => '覃', '' => '視', '' => '註', '' => '詠', '' => '評', '' => '詞', '' => '証', '' => '詁', '@' => '詔', 'A' => '詛', 'B' => '詐', 'C' => '詆', 'D' => '訴', 'E' => '診', 'F' => '訶', 'G' => '詖', 'H' => '象', 'I' => '貂', 'J' => '貯', 'K' => '貼', 'L' => '貳', 'M' => '貽', 'N' => '賁', 'O' => '費', 'P' => '賀', 'Q' => '貴', 'R' => '買', 'S' => '貶', 'T' => '貿', 'U' => '貸', 'V' => '越', 'W' => '超', 'X' => '趁', 'Y' => '跎', 'Z' => '距', '[' => '跋', '\\' => '跚', ']' => '跑', '^' => '跌', '_' => '跛', '`' => '跆', 'a' => '軻', 'b' => '軸', 'c' => '軼', 'd' => '辜', 'e' => '逮', 'f' => '逵', 'g' => '週', 'h' => '逸', 'i' => '進', 'j' => '逶', 'k' => '鄂', 'l' => '郵', 'm' => '鄉', 'n' => '郾', 'o' => '酣', 'p' => '酥', 'q' => '量', 'r' => '鈔', 's' => '鈕', 't' => '鈣', 'u' => '鈉', 'v' => '鈞', 'w' => '鈍', 'x' => '鈐', 'y' => '鈇', 'z' => '鈑', '{' => '閔', '|' => '閏', '}' => '開', '~' => '閑', '' => '間', '' => '閒', '' => '閎', '' => '隊', '' => '階', '' => '隋', '' => '陽', '' => '隅', '' => '隆', '' => '隍', '' => '陲', '' => '隄', '' => '雁', '' => '雅', '' => '雄', '' => '集', '' => '雇', '' => '雯', '' => '雲', '' => '韌', '' => '項', '' => '順', '' => '須', '' => '飧', '' => '飪', '' => '飯', '' => '飩', '' => '飲', '' => '飭', '' => '馮', '' => '馭', '' => '黃', '' => '黍', '' => '黑', '' => '亂', '' => '傭', '' => '債', '' => '傲', '' => '傳', '' => '僅', '' => '傾', '' => '催', '' => '傷', '' => '傻', '' => '傯', '' => '僇', '' => '剿', '' => '剷', '' => '剽', '' => '募', '' => '勦', '' => '勤', '' => '勢', '' => '勣', '' => '匯', '' => '嗟', '' => '嗨', '' => '嗓', '' => '嗦', '' => '嗎', '' => '嗜', '' => '嗇', '' => '嗑', '' => '嗣', '' => '嗤', '' => '嗯', '' => '嗚', '' => '嗡', '' => '嗅', '' => '嗆', '' => '嗥', '' => '嗉', '' => '園', '' => '圓', '' => '塞', '' => '塑', '' => '塘', '' => '塗', '' => '塚', '' => '塔', '' => '填', '' => '塌', '' => '塭', '' => '塊', '' => '塢', '' => '塒', '' => '塋', '' => '奧', '' => '嫁', '' => '嫉', '' => '嫌', '' => '媾', '' => '媽', '' => '媼', '@' => '媳', 'A' => '嫂', 'B' => '媲', 'C' => '嵩', 'D' => '嵯', 'E' => '幌', 'F' => '幹', 'G' => '廉', 'H' => '廈', 'I' => '弒', 'J' => '彙', 'K' => '徬', 'L' => '微', 'M' => '愚', 'N' => '意', 'O' => '慈', 'P' => '感', 'Q' => '想', 'R' => '愛', 'S' => '惹', 'T' => '愁', 'U' => '愈', 'V' => '慎', 'W' => '慌', 'X' => '慄', 'Y' => '慍', 'Z' => '愾', '[' => '愴', '\\' => '愧', ']' => '愍', '^' => '愆', '_' => '愷', '`' => '戡', 'a' => '戢', 'b' => '搓', 'c' => '搾', 'd' => '搞', 'e' => '搪', 'f' => '搭', 'g' => '搽', 'h' => '搬', 'i' => '搏', 'j' => '搜', 'k' => '搔', 'l' => '損', 'm' => '搶', 'n' => '搖', 'o' => '搗', 'p' => '搆', 'q' => '敬', 'r' => '斟', 's' => '新', 't' => '暗', 'u' => '暉', 'v' => '暇', 'w' => '暈', 'x' => '暖', 'y' => '暄', 'z' => '暘', '{' => '暍', '|' => '會', '}' => '榔', '~' => '業', '' => '楚', '' => '楷', '' => '楠', '' => '楔', '' => '極', '' => '椰', '' => '概', '' => '楊', '' => '楨', '' => '楫', '' => '楞', '' => '楓', '' => '楹', '' => '榆', '' => '楝', '' => '楣', '' => '楛', '' => '歇', '' => '歲', '' => '毀', '' => '殿', '' => '毓', '' => '毽', '' => '溢', '' => '溯', '' => '滓', '' => '溶', '' => '滂', '' => '源', '' => '溝', '' => '滇', '' => '滅', '' => '溥', '' => '溘', '' => '溼', '' => '溺', '' => '溫', '' => '滑', '' => '準', '' => '溜', '' => '滄', '' => '滔', '' => '溪', '' => '溧', '' => '溴', '' => '煎', '' => '煙', '' => '煩', '' => '煤', '' => '煉', '' => '照', '' => '煜', '' => '煬', '' => '煦', '' => '煌', '' => '煥', '' => '煞', '' => '煆', '' => '煨', '' => '煖', '' => '爺', '' => '牒', '' => '猷', '' => '獅', '' => '猿', '' => '猾', '' => '瑯', '' => '瑚', '' => '瑕', '' => '瑟', '' => '瑞', '' => '瑁', '' => '琿', '' => '瑙', '' => '瑛', '' => '瑜', '' => '當', '' => '畸', '' => '瘀', '' => '痰', '' => '瘁', '' => '痲', '' => '痱', '' => '痺', '' => '痿', '' => '痴', '' => '痳', '' => '盞', '' => '盟', '' => '睛', '' => '睫', '' => '睦', '' => '睞', '' => '督', '@' => '睹', 'A' => '睪', 'B' => '睬', 'C' => '睜', 'D' => '睥', 'E' => '睨', 'F' => '睢', 'G' => '矮', 'H' => '碎', 'I' => '碰', 'J' => '碗', 'K' => '碘', 'L' => '碌', 'M' => '碉', 'N' => '硼', 'O' => '碑', 'P' => '碓', 'Q' => '硿', 'R' => '祺', 'S' => '祿', 'T' => '禁', 'U' => '萬', 'V' => '禽', 'W' => '稜', 'X' => '稚', 'Y' => '稠', 'Z' => '稔', '[' => '稟', '\\' => '稞', ']' => '窟', '^' => '窠', '_' => '筷', '`' => '節', 'a' => '筠', 'b' => '筮', 'c' => '筧', 'd' => '粱', 'e' => '粳', 'f' => '粵', 'g' => '經', 'h' => '絹', 'i' => '綑', 'j' => '綁', 'k' => '綏', 'l' => '絛', 'm' => '置', 'n' => '罩', 'o' => '罪', 'p' => '署', 'q' => '義', 'r' => '羨', 's' => '群', 't' => '聖', 'u' => '聘', 'v' => '肆', 'w' => '肄', 'x' => '腱', 'y' => '腰', 'z' => '腸', '{' => '腥', '|' => '腮', '}' => '腳', '~' => '腫', '' => '腹', '' => '腺', '' => '腦', '' => '舅', '' => '艇', '' => '蒂', '' => '葷', '' => '落', '' => '萱', '' => '葵', '' => '葦', '' => '葫', '' => '葉', '' => '葬', '' => '葛', '' => '萼', '' => '萵', '' => '葡', '' => '董', '' => '葩', '' => '葭', '' => '葆', '' => '虞', '' => '虜', '' => '號', '' => '蛹', '' => '蜓', '' => '蜈', '' => '蜇', '' => '蜀', '' => '蛾', '' => '蛻', '' => '蜂', '' => '蜃', '' => '蜆', '' => '蜊', '' => '衙', '' => '裟', '' => '裔', '' => '裙', '' => '補', '' => '裘', '' => '裝', '' => '裡', '' => '裊', '' => '裕', '' => '裒', '' => '覜', '' => '解', '' => '詫', '' => '該', '' => '詳', '' => '試', '' => '詩', '' => '詰', '' => '誇', '' => '詼', '' => '詣', '' => '誠', '' => '話', '' => '誅', '' => '詭', '' => '詢', '' => '詮', '' => '詬', '' => '詹', '' => '詻', '' => '訾', '' => '詨', '' => '豢', '' => '貊', '' => '貉', '' => '賊', '' => '資', '' => '賈', '' => '賄', '' => '貲', '' => '賃', '' => '賂', '' => '賅', '' => '跡', '' => '跟', '' => '跨', '' => '路', '' => '跳', '' => '跺', '' => '跪', '' => '跤', '' => '跦', '' => '躲', '' => '較', '' => '載', '' => '軾', '' => '輊', '@' => '辟', 'A' => '農', 'B' => '運', 'C' => '遊', 'D' => '道', 'E' => '遂', 'F' => '達', 'G' => '逼', 'H' => '違', 'I' => '遐', 'J' => '遇', 'K' => '遏', 'L' => '過', 'M' => '遍', 'N' => '遑', 'O' => '逾', 'P' => '遁', 'Q' => '鄒', 'R' => '鄗', 'S' => '酬', 'T' => '酪', 'U' => '酩', 'V' => '釉', 'W' => '鈷', 'X' => '鉗', 'Y' => '鈸', 'Z' => '鈽', '[' => '鉀', '\\' => '鈾', ']' => '鉛', '^' => '鉋', '_' => '鉤', '`' => '鉑', 'a' => '鈴', 'b' => '鉉', 'c' => '鉍', 'd' => '鉅', 'e' => '鈹', 'f' => '鈿', 'g' => '鉚', 'h' => '閘', 'i' => '隘', 'j' => '隔', 'k' => '隕', 'l' => '雍', 'm' => '雋', 'n' => '雉', 'o' => '雊', 'p' => '雷', 'q' => '電', 'r' => '雹', 's' => '零', 't' => '靖', 'u' => '靴', 'v' => '靶', 'w' => '預', 'x' => '頑', 'y' => '頓', 'z' => '頊', '{' => '頒', '|' => '頌', '}' => '飼', '~' => '飴', '' => '飽', '' => '飾', '' => '馳', '' => '馱', '' => '馴', '' => '髡', '' => '鳩', '' => '麂', '' => '鼎', '' => '鼓', '' => '鼠', '' => '僧', '' => '僮', '' => '僥', '' => '僖', '' => '僭', '' => '僚', '' => '僕', '' => '像', '' => '僑', '' => '僱', '' => '僎', '' => '僩', '' => '兢', '' => '凳', '' => '劃', '' => '劂', '' => '匱', '' => '厭', '' => '嗾', '' => '嘀', '' => '嘛', '' => '嘗', '' => '嗽', '' => '嘔', '' => '嘆', '' => '嘉', '' => '嘍', '' => '嘎', '' => '嗷', '' => '嘖', '' => '嘟', '' => '嘈', '' => '嘐', '' => '嗶', '' => '團', '' => '圖', '' => '塵', '' => '塾', '' => '境', '' => '墓', '' => '墊', '' => '塹', '' => '墅', '' => '塽', '' => '壽', '' => '夥', '' => '夢', '' => '夤', '' => '奪', '' => '奩', '' => '嫡', '' => '嫦', '' => '嫩', '' => '嫗', '' => '嫖', '' => '嫘', '' => '嫣', '' => '孵', '' => '寞', '' => '寧', '' => '寡', '' => '寥', '' => '實', '' => '寨', '' => '寢', '' => '寤', '' => '察', '' => '對', '' => '屢', '' => '嶄', '' => '嶇', '' => '幛', '' => '幣', '' => '幕', '' => '幗', '' => '幔', '' => '廓', '' => '廖', '' => '弊', '' => '彆', '' => '彰', '' => '徹', '' => '慇', '@' => '愿', 'A' => '態', 'B' => '慷', 'C' => '慢', 'D' => '慣', 'E' => '慟', 'F' => '慚', 'G' => '慘', 'H' => '慵', 'I' => '截', 'J' => '撇', 'K' => '摘', 'L' => '摔', 'M' => '撤', 'N' => '摸', 'O' => '摟', 'P' => '摺', 'Q' => '摑', 'R' => '摧', 'S' => '搴', 'T' => '摭', 'U' => '摻', 'V' => '敲', 'W' => '斡', 'X' => '旗', 'Y' => '旖', 'Z' => '暢', '[' => '暨', '\\' => '暝', ']' => '榜', '^' => '榨', '_' => '榕', '`' => '槁', 'a' => '榮', 'b' => '槓', 'c' => '構', 'd' => '榛', 'e' => '榷', 'f' => '榻', 'g' => '榫', 'h' => '榴', 'i' => '槐', 'j' => '槍', 'k' => '榭', 'l' => '槌', 'm' => '榦', 'n' => '槃', 'o' => '榣', 'p' => '歉', 'q' => '歌', 'r' => '氳', 's' => '漳', 't' => '演', 'u' => '滾', 'v' => '漓', 'w' => '滴', 'x' => '漩', 'y' => '漾', 'z' => '漠', '{' => '漬', '|' => '漏', '}' => '漂', '~' => '漢', '' => '滿', '' => '滯', '' => '漆', '' => '漱', '' => '漸', '' => '漲', '' => '漣', '' => '漕', '' => '漫', '' => '漯', '' => '澈', '' => '漪', '' => '滬', '' => '漁', '' => '滲', '' => '滌', '' => '滷', '' => '熔', '' => '熙', '' => '煽', '' => '熊', '' => '熄', '' => '熒', '' => '爾', '' => '犒', '' => '犖', '' => '獄', '' => '獐', '' => '瑤', '' => '瑣', '' => '瑪', '' => '瑰', '' => '瑭', '' => '甄', '' => '疑', '' => '瘧', '' => '瘍', '' => '瘋', '' => '瘉', '' => '瘓', '' => '盡', '' => '監', '' => '瞄', '' => '睽', '' => '睿', '' => '睡', '' => '磁', '' => '碟', '' => '碧', '' => '碳', '' => '碩', '' => '碣', '' => '禎', '' => '福', '' => '禍', '' => '種', '' => '稱', '' => '窪', '' => '窩', '' => '竭', '' => '端', '' => '管', '' => '箕', '' => '箋', '' => '筵', '' => '算', '' => '箝', '' => '箔', '' => '箏', '' => '箸', '' => '箇', '' => '箄', '' => '粹', '' => '粽', '' => '精', '' => '綻', '' => '綰', '' => '綜', '' => '綽', '' => '綾', '' => '綠', '' => '緊', '' => '綴', '' => '網', '' => '綱', '' => '綺', '' => '綢', '' => '綿', '' => '綵', '' => '綸', '' => '維', '' => '緒', '' => '緇', '' => '綬', '@' => '罰', 'A' => '翠', 'B' => '翡', 'C' => '翟', 'D' => '聞', 'E' => '聚', 'F' => '肇', 'G' => '腐', 'H' => '膀', 'I' => '膏', 'J' => '膈', 'K' => '膊', 'L' => '腿', 'M' => '膂', 'N' => '臧', 'O' => '臺', 'P' => '與', 'Q' => '舔', 'R' => '舞', 'S' => '艋', 'T' => '蓉', 'U' => '蒿', 'V' => '蓆', 'W' => '蓄', 'X' => '蒙', 'Y' => '蒞', 'Z' => '蒲', '[' => '蒜', '\\' => '蓋', ']' => '蒸', '^' => '蓀', '_' => '蓓', '`' => '蒐', 'a' => '蒼', 'b' => '蓑', 'c' => '蓊', 'd' => '蜿', 'e' => '蜜', 'f' => '蜻', 'g' => '蜢', 'h' => '蜥', 'i' => '蜴', 'j' => '蜘', 'k' => '蝕', 'l' => '蜷', 'm' => '蜩', 'n' => '裳', 'o' => '褂', 'p' => '裴', 'q' => '裹', 'r' => '裸', 's' => '製', 't' => '裨', 'u' => '褚', 'v' => '裯', 'w' => '誦', 'x' => '誌', 'y' => '語', 'z' => '誣', '{' => '認', '|' => '誡', '}' => '誓', '~' => '誤', '' => '說', '' => '誥', '' => '誨', '' => '誘', '' => '誑', '' => '誚', '' => '誧', '' => '豪', '' => '貍', '' => '貌', '' => '賓', '' => '賑', '' => '賒', '' => '赫', '' => '趙', '' => '趕', '' => '跼', '' => '輔', '' => '輒', '' => '輕', '' => '輓', '' => '辣', '' => '遠', '' => '遘', '' => '遜', '' => '遣', '' => '遙', '' => '遞', '' => '遢', '' => '遝', '' => '遛', '' => '鄙', '' => '鄘', '' => '鄞', '' => '酵', '' => '酸', '' => '酷', '' => '酴', '' => '鉸', '' => '銀', '' => '銅', '' => '銘', '' => '銖', '' => '鉻', '' => '銓', '' => '銜', '' => '銨', '' => '鉼', '' => '銑', '' => '閡', '' => '閨', '' => '閩', '' => '閣', '' => '閥', '' => '閤', '' => '隙', '' => '障', '' => '際', '' => '雌', '' => '雒', '' => '需', '' => '靼', '' => '鞅', '' => '韶', '' => '頗', '' => '領', '' => '颯', '' => '颱', '' => '餃', '' => '餅', '' => '餌', '' => '餉', '' => '駁', '' => '骯', '' => '骰', '' => '髦', '' => '魁', '' => '魂', '' => '鳴', '' => '鳶', '' => '鳳', '' => '麼', '' => '鼻', '' => '齊', '' => '億', '' => '儀', '' => '僻', '' => '僵', '' => '價', '' => '儂', '' => '儈', '' => '儉', '' => '儅', '' => '凜', '@' => '劇', 'A' => '劈', 'B' => '劉', 'C' => '劍', 'D' => '劊', 'E' => '勰', 'F' => '厲', 'G' => '嘮', 'H' => '嘻', 'I' => '嘹', 'J' => '嘲', 'K' => '嘿', 'L' => '嘴', 'M' => '嘩', 'N' => '噓', 'O' => '噎', 'P' => '噗', 'Q' => '噴', 'R' => '嘶', 'S' => '嘯', 'T' => '嘰', 'U' => '墀', 'V' => '墟', 'W' => '增', 'X' => '墳', 'Y' => '墜', 'Z' => '墮', '[' => '墩', '\\' => '墦', ']' => '奭', '^' => '嬉', '_' => '嫻', '`' => '嬋', 'a' => '嫵', 'b' => '嬌', 'c' => '嬈', 'd' => '寮', 'e' => '寬', 'f' => '審', 'g' => '寫', 'h' => '層', 'i' => '履', 'j' => '嶝', 'k' => '嶔', 'l' => '幢', 'm' => '幟', 'n' => '幡', 'o' => '廢', 'p' => '廚', 'q' => '廟', 'r' => '廝', 's' => '廣', 't' => '廠', 'u' => '彈', 'v' => '影', 'w' => '德', 'x' => '徵', 'y' => '慶', 'z' => '慧', '{' => '慮', '|' => '慝', '}' => '慕', '~' => '憂', '' => '慼', '' => '慰', '' => '慫', '' => '慾', '' => '憧', '' => '憐', '' => '憫', '' => '憎', '' => '憬', '' => '憚', '' => '憤', '' => '憔', '' => '憮', '' => '戮', '' => '摩', '' => '摯', '' => '摹', '' => '撞', '' => '撲', '' => '撈', '' => '撐', '' => '撰', '' => '撥', '' => '撓', '' => '撕', '' => '撩', '' => '撒', '' => '撮', '' => '播', '' => '撫', '' => '撚', '' => '撬', '' => '撙', '' => '撢', '' => '撳', '' => '敵', '' => '敷', '' => '數', '' => '暮', '' => '暫', '' => '暴', '' => '暱', '' => '樣', '' => '樟', '' => '槨', '' => '樁', '' => '樞', '' => '標', '' => '槽', '' => '模', '' => '樓', '' => '樊', '' => '槳', '' => '樂', '' => '樅', '' => '槭', '' => '樑', '' => '歐', '' => '歎', '' => '殤', '' => '毅', '' => '毆', '' => '漿', '' => '潼', '' => '澄', '' => '潑', '' => '潦', '' => '潔', '' => '澆', '' => '潭', '' => '潛', '' => '潸', '' => '潮', '' => '澎', '' => '潺', '' => '潰', '' => '潤', '' => '澗', '' => '潘', '' => '滕', '' => '潯', '' => '潠', '' => '潟', '' => '熟', '' => '熬', '' => '熱', '' => '熨', '' => '牖', '' => '犛', '' => '獎', '' => '獗', '' => '瑩', '' => '璋', '' => '璃', '@' => '瑾', 'A' => '璀', 'B' => '畿', 'C' => '瘠', 'D' => '瘩', 'E' => '瘟', 'F' => '瘤', 'G' => '瘦', 'H' => '瘡', 'I' => '瘢', 'J' => '皚', 'K' => '皺', 'L' => '盤', 'M' => '瞎', 'N' => '瞇', 'O' => '瞌', 'P' => '瞑', 'Q' => '瞋', 'R' => '磋', 'S' => '磅', 'T' => '確', 'U' => '磊', 'V' => '碾', 'W' => '磕', 'X' => '碼', 'Y' => '磐', 'Z' => '稿', '[' => '稼', '\\' => '穀', ']' => '稽', '^' => '稷', '_' => '稻', '`' => '窯', 'a' => '窮', 'b' => '箭', 'c' => '箱', 'd' => '範', 'e' => '箴', 'f' => '篆', 'g' => '篇', 'h' => '篁', 'i' => '箠', 'j' => '篌', 'k' => '糊', 'l' => '締', 'm' => '練', 'n' => '緯', 'o' => '緻', 'p' => '緘', 'q' => '緬', 'r' => '緝', 's' => '編', 't' => '緣', 'u' => '線', 'v' => '緞', 'w' => '緩', 'x' => '綞', 'y' => '緙', 'z' => '緲', '{' => '緹', '|' => '罵', '}' => '罷', '~' => '羯', '' => '翩', '' => '耦', '' => '膛', '' => '膜', '' => '膝', '' => '膠', '' => '膚', '' => '膘', '' => '蔗', '' => '蔽', '' => '蔚', '' => '蓮', '' => '蔬', '' => '蔭', '' => '蔓', '' => '蔑', '' => '蔣', '' => '蔡', '' => '蔔', '' => '蓬', '' => '蔥', '' => '蓿', '' => '蔆', '' => '螂', '' => '蝴', '' => '蝶', '' => '蝠', '' => '蝦', '' => '蝸', '' => '蝨', '' => '蝙', '' => '蝗', '' => '蝌', '' => '蝓', '' => '衛', '' => '衝', '' => '褐', '' => '複', '' => '褒', '' => '褓', '' => '褕', '' => '褊', '' => '誼', '' => '諒', '' => '談', '' => '諄', '' => '誕', '' => '請', '' => '諸', '' => '課', '' => '諉', '' => '諂', '' => '調', '' => '誰', '' => '論', '' => '諍', '' => '誶', '' => '誹', '' => '諛', '' => '豌', '' => '豎', '' => '豬', '' => '賠', '' => '賞', '' => '賦', '' => '賤', '' => '賬', '' => '賭', '' => '賢', '' => '賣', '' => '賜', '' => '質', '' => '賡', '' => '赭', '' => '趟', '' => '趣', '' => '踫', '' => '踐', '' => '踝', '' => '踢', '' => '踏', '' => '踩', '' => '踟', '' => '踡', '' => '踞', '' => '躺', '' => '輝', '' => '輛', '' => '輟', '' => '輩', '' => '輦', '' => '輪', '' => '輜', '' => '輞', '@' => '輥', 'A' => '適', 'B' => '遮', 'C' => '遨', 'D' => '遭', 'E' => '遷', 'F' => '鄰', 'G' => '鄭', 'H' => '鄧', 'I' => '鄱', 'J' => '醇', 'K' => '醉', 'L' => '醋', 'M' => '醃', 'N' => '鋅', 'O' => '銻', 'P' => '銷', 'Q' => '鋪', 'R' => '銬', 'S' => '鋤', 'T' => '鋁', 'U' => '銳', 'V' => '銼', 'W' => '鋒', 'X' => '鋇', 'Y' => '鋰', 'Z' => '銲', '[' => '閭', '\\' => '閱', ']' => '霄', '^' => '霆', '_' => '震', '`' => '霉', 'a' => '靠', 'b' => '鞍', 'c' => '鞋', 'd' => '鞏', 'e' => '頡', 'f' => '頫', 'g' => '頜', 'h' => '颳', 'i' => '養', 'j' => '餓', 'k' => '餒', 'l' => '餘', 'm' => '駝', 'n' => '駐', 'o' => '駟', 'p' => '駛', 'q' => '駑', 'r' => '駕', 's' => '駒', 't' => '駙', 'u' => '骷', 'v' => '髮', 'w' => '髯', 'x' => '鬧', 'y' => '魅', 'z' => '魄', '{' => '魷', '|' => '魯', '}' => '鴆', '~' => '鴉', '' => '鴃', '' => '麩', '' => '麾', '' => '黎', '' => '墨', '' => '齒', '' => '儒', '' => '儘', '' => '儔', '' => '儐', '' => '儕', '' => '冀', '' => '冪', '' => '凝', '' => '劑', '' => '劓', '' => '勳', '' => '噙', '' => '噫', '' => '噹', '' => '噩', '' => '噤', '' => '噸', '' => '噪', '' => '器', '' => '噥', '' => '噱', '' => '噯', '' => '噬', '' => '噢', '' => '噶', '' => '壁', '' => '墾', '' => '壇', '' => '壅', '' => '奮', '' => '嬝', '' => '嬴', '' => '學', '' => '寰', '' => '導', '' => '彊', '' => '憲', '' => '憑', '' => '憩', '' => '憊', '' => '懍', '' => '憶', '' => '憾', '' => '懊', '' => '懈', '' => '戰', '' => '擅', '' => '擁', '' => '擋', '' => '撻', '' => '撼', '' => '據', '' => '擄', '' => '擇', '' => '擂', '' => '操', '' => '撿', '' => '擒', '' => '擔', '' => '撾', '' => '整', '' => '曆', '' => '曉', '' => '暹', '' => '曄', '' => '曇', '' => '暸', '' => '樽', '' => '樸', '' => '樺', '' => '橙', '' => '橫', '' => '橘', '' => '樹', '' => '橄', '' => '橢', '' => '橡', '' => '橋', '' => '橇', '' => '樵', '' => '機', '' => '橈', '' => '歙', '' => '歷', '' => '氅', '' => '濂', '' => '澱', '' => '澡', '@' => '濃', 'A' => '澤', 'B' => '濁', 'C' => '澧', 'D' => '澳', 'E' => '激', 'F' => '澹', 'G' => '澶', 'H' => '澦', 'I' => '澠', 'J' => '澴', 'K' => '熾', 'L' => '燉', 'M' => '燐', 'N' => '燒', 'O' => '燈', 'P' => '燕', 'Q' => '熹', 'R' => '燎', 'S' => '燙', 'T' => '燜', 'U' => '燃', 'V' => '燄', 'W' => '獨', 'X' => '璜', 'Y' => '璣', 'Z' => '璘', '[' => '璟', '\\' => '璞', ']' => '瓢', '^' => '甌', '_' => '甍', '`' => '瘴', 'a' => '瘸', 'b' => '瘺', 'c' => '盧', 'd' => '盥', 'e' => '瞠', 'f' => '瞞', 'g' => '瞟', 'h' => '瞥', 'i' => '磨', 'j' => '磚', 'k' => '磬', 'l' => '磧', 'm' => '禦', 'n' => '積', 'o' => '穎', 'p' => '穆', 'q' => '穌', 'r' => '穋', 's' => '窺', 't' => '篙', 'u' => '簑', 'v' => '築', 'w' => '篤', 'x' => '篛', 'y' => '篡', 'z' => '篩', '{' => '篦', '|' => '糕', '}' => '糖', '~' => '縊', '' => '縑', '' => '縈', '' => '縛', '' => '縣', '' => '縞', '' => '縝', '' => '縉', '' => '縐', '' => '罹', '' => '羲', '' => '翰', '' => '翱', '' => '翮', '' => '耨', '' => '膳', '' => '膩', '' => '膨', '' => '臻', '' => '興', '' => '艘', '' => '艙', '' => '蕊', '' => '蕙', '' => '蕈', '' => '蕨', '' => '蕩', '' => '蕃', '' => '蕉', '' => '蕭', '' => '蕪', '' => '蕞', '' => '螃', '' => '螟', '' => '螞', '' => '螢', '' => '融', '' => '衡', '' => '褪', '' => '褲', '' => '褥', '' => '褫', '' => '褡', '' => '親', '' => '覦', '' => '諦', '' => '諺', '' => '諫', '' => '諱', '' => '謀', '' => '諜', '' => '諧', '' => '諮', '' => '諾', '' => '謁', '' => '謂', '' => '諷', '' => '諭', '' => '諳', '' => '諶', '' => '諼', '' => '豫', '' => '豭', '' => '貓', '' => '賴', '' => '蹄', '' => '踱', '' => '踴', '' => '蹂', '' => '踹', '' => '踵', '' => '輻', '' => '輯', '' => '輸', '' => '輳', '' => '辨', '' => '辦', '' => '遵', '' => '遴', '' => '選', '' => '遲', '' => '遼', '' => '遺', '' => '鄴', '' => '醒', '' => '錠', '' => '錶', '' => '鋸', '' => '錳', '' => '錯', '' => '錢', '' => '鋼', '' => '錫', '' => '錄', '' => '錚', '@' => '錐', 'A' => '錦', 'B' => '錡', 'C' => '錕', 'D' => '錮', 'E' => '錙', 'F' => '閻', 'G' => '隧', 'H' => '隨', 'I' => '險', 'J' => '雕', 'K' => '霎', 'L' => '霑', 'M' => '霖', 'N' => '霍', 'O' => '霓', 'P' => '霏', 'Q' => '靛', 'R' => '靜', 'S' => '靦', 'T' => '鞘', 'U' => '頰', 'V' => '頸', 'W' => '頻', 'X' => '頷', 'Y' => '頭', 'Z' => '頹', '[' => '頤', '\\' => '餐', ']' => '館', '^' => '餞', '_' => '餛', '`' => '餡', 'a' => '餚', 'b' => '駭', 'c' => '駢', 'd' => '駱', 'e' => '骸', 'f' => '骼', 'g' => '髻', 'h' => '髭', 'i' => '鬨', 'j' => '鮑', 'k' => '鴕', 'l' => '鴣', 'm' => '鴦', 'n' => '鴨', 'o' => '鴒', 'p' => '鴛', 'q' => '默', 'r' => '黔', 's' => '龍', 't' => '龜', 'u' => '優', 'v' => '償', 'w' => '儡', 'x' => '儲', 'y' => '勵', 'z' => '嚎', '{' => '嚀', '|' => '嚐', '}' => '嚅', '~' => '嚇', '' => '嚏', '' => '壕', '' => '壓', '' => '壑', '' => '壎', '' => '嬰', '' => '嬪', '' => '嬤', '' => '孺', '' => '尷', '' => '屨', '' => '嶼', '' => '嶺', '' => '嶽', '' => '嶸', '' => '幫', '' => '彌', '' => '徽', '' => '應', '' => '懂', '' => '懇', '' => '懦', '' => '懋', '' => '戲', '' => '戴', '' => '擎', '' => '擊', '' => '擘', '' => '擠', '' => '擰', '' => '擦', '' => '擬', '' => '擱', '' => '擢', '' => '擭', '' => '斂', '' => '斃', '' => '曙', '' => '曖', '' => '檀', '' => '檔', '' => '檄', '' => '檢', '' => '檜', '' => '櫛', '' => '檣', '' => '橾', '' => '檗', '' => '檐', '' => '檠', '' => '歜', '' => '殮', '' => '毚', '' => '氈', '' => '濘', '' => '濱', '' => '濟', '' => '濠', '' => '濛', '' => '濤', '' => '濫', '' => '濯', '' => '澀', '' => '濬', '' => '濡', '' => '濩', '' => '濕', '' => '濮', '' => '濰', '' => '燧', '' => '營', '' => '燮', '' => '燦', '' => '燥', '' => '燭', '' => '燬', '' => '燴', '' => '燠', '' => '爵', '' => '牆', '' => '獰', '' => '獲', '' => '璩', '' => '環', '' => '璦', '' => '璨', '' => '癆', '' => '療', '' => '癌', '' => '盪', '' => '瞳', '' => '瞪', '' => '瞰', '' => '瞬', '@' => '瞧', 'A' => '瞭', 'B' => '矯', 'C' => '磷', 'D' => '磺', 'E' => '磴', 'F' => '磯', 'G' => '礁', 'H' => '禧', 'I' => '禪', 'J' => '穗', 'K' => '窿', 'L' => '簇', 'M' => '簍', 'N' => '篾', 'O' => '篷', 'P' => '簌', 'Q' => '篠', 'R' => '糠', 'S' => '糜', 'T' => '糞', 'U' => '糢', 'V' => '糟', 'W' => '糙', 'X' => '糝', 'Y' => '縮', 'Z' => '績', '[' => '繆', '\\' => '縷', ']' => '縲', '^' => '繃', '_' => '縫', '`' => '總', 'a' => '縱', 'b' => '繅', 'c' => '繁', 'd' => '縴', 'e' => '縹', 'f' => '繈', 'g' => '縵', 'h' => '縿', 'i' => '縯', 'j' => '罄', 'k' => '翳', 'l' => '翼', 'm' => '聱', 'n' => '聲', 'o' => '聰', 'p' => '聯', 'q' => '聳', 'r' => '臆', 's' => '臃', 't' => '膺', 'u' => '臂', 'v' => '臀', 'w' => '膿', 'x' => '膽', 'y' => '臉', 'z' => '膾', '{' => '臨', '|' => '舉', '}' => '艱', '~' => '薪', '' => '薄', '' => '蕾', '' => '薜', '' => '薑', '' => '薔', '' => '薯', '' => '薛', '' => '薇', '' => '薨', '' => '薊', '' => '虧', '' => '蟀', '' => '蟑', '' => '螳', '' => '蟒', '' => '蟆', '' => '螫', '' => '螻', '' => '螺', '' => '蟈', '' => '蟋', '' => '褻', '' => '褶', '' => '襄', '' => '褸', '' => '褽', '' => '覬', '' => '謎', '' => '謗', '' => '謙', '' => '講', '' => '謊', '' => '謠', '' => '謝', '' => '謄', '' => '謐', '' => '豁', '' => '谿', '' => '豳', '' => '賺', '' => '賽', '' => '購', '' => '賸', '' => '賻', '' => '趨', '' => '蹉', '' => '蹋', '' => '蹈', '' => '蹊', '' => '轄', '' => '輾', '' => '轂', '' => '轅', '' => '輿', '' => '避', '' => '遽', '' => '還', '' => '邁', '' => '邂', '' => '邀', '' => '鄹', '' => '醣', '' => '醞', '' => '醜', '' => '鍍', '' => '鎂', '' => '錨', '' => '鍵', '' => '鍊', '' => '鍥', '' => '鍋', '' => '錘', '' => '鍾', '' => '鍬', '' => '鍛', '' => '鍰', '' => '鍚', '' => '鍔', '' => '闊', '' => '闋', '' => '闌', '' => '闈', '' => '闆', '' => '隱', '' => '隸', '' => '雖', '' => '霜', '' => '霞', '' => '鞠', '' => '韓', '' => '顆', '' => '颶', '' => '餵', '' => '騁', '@' => '駿', 'A' => '鮮', 'B' => '鮫', 'C' => '鮪', 'D' => '鮭', 'E' => '鴻', 'F' => '鴿', 'G' => '麋', 'H' => '黏', 'I' => '點', 'J' => '黜', 'K' => '黝', 'L' => '黛', 'M' => '鼾', 'N' => '齋', 'O' => '叢', 'P' => '嚕', 'Q' => '嚮', 'R' => '壙', 'S' => '壘', 'T' => '嬸', 'U' => '彝', 'V' => '懣', 'W' => '戳', 'X' => '擴', 'Y' => '擲', 'Z' => '擾', '[' => '攆', '\\' => '擺', ']' => '擻', '^' => '擷', '_' => '斷', '`' => '曜', 'a' => '朦', 'b' => '檳', 'c' => '檬', 'd' => '櫃', 'e' => '檻', 'f' => '檸', 'g' => '櫂', 'h' => '檮', 'i' => '檯', 'j' => '歟', 'k' => '歸', 'l' => '殯', 'm' => '瀉', 'n' => '瀋', 'o' => '濾', 'p' => '瀆', 'q' => '濺', 'r' => '瀑', 's' => '瀏', 't' => '燻', 'u' => '燼', 'v' => '燾', 'w' => '燸', 'x' => '獷', 'y' => '獵', 'z' => '璧', '{' => '璿', '|' => '甕', '}' => '癖', '~' => '癘', '¡' => '癒', '¢' => '瞽', '£' => '瞿', '¤' => '瞻', '¥' => '瞼', '¦' => '礎', '§' => '禮', '¨' => '穡', '©' => '穢', 'ª' => '穠', '«' => '竄', '¬' => '竅', '­' => '簫', '®' => '簧', '¯' => '簪', '°' => '簞', '±' => '簣', '²' => '簡', '³' => '糧', '´' => '織', 'µ' => '繕', '¶' => '繞', '·' => '繚', '¸' => '繡', '¹' => '繒', 'º' => '繙', '»' => '罈', '¼' => '翹', '½' => '翻', '¾' => '職', '¿' => '聶', '' => '臍', '' => '臏', '' => '舊', '' => '藏', '' => '薩', '' => '藍', '' => '藐', '' => '藉', '' => '薰', '' => '薺', '' => '薹', '' => '薦', '' => '蟯', '' => '蟬', '' => '蟲', '' => '蟠', '' => '覆', '' => '覲', '' => '觴', '' => '謨', '' => '謹', '' => '謬', '' => '謫', '' => '豐', '' => '贅', '' => '蹙', '' => '蹣', '' => '蹦', '' => '蹤', '' => '蹟', '' => '蹕', '' => '軀', '' => '轉', '' => '轍', '' => '邇', '' => '邃', '' => '邈', '' => '醫', '' => '醬', '' => '釐', '' => '鎔', '' => '鎊', '' => '鎖', '' => '鎢', '' => '鎳', '' => '鎮', '' => '鎬', '' => '鎰', '' => '鎘', '' => '鎚', '' => '鎗', '' => '闔', '' => '闖', '' => '闐', '' => '闕', '' => '離', '' => '雜', '' => '雙', '' => '雛', '' => '雞', '' => '霤', '' => '鞣', '' => '鞦', '@' => '鞭', 'A' => '韹', 'B' => '額', 'C' => '顏', 'D' => '題', 'E' => '顎', 'F' => '顓', 'G' => '颺', 'H' => '餾', 'I' => '餿', 'J' => '餽', 'K' => '餮', 'L' => '馥', 'M' => '騎', 'N' => '髁', 'O' => '鬃', 'P' => '鬆', 'Q' => '魏', 'R' => '魎', 'S' => '魍', 'T' => '鯊', 'U' => '鯉', 'V' => '鯽', 'W' => '鯈', 'X' => '鯀', 'Y' => '鵑', 'Z' => '鵝', '[' => '鵠', '\\' => '黠', ']' => '鼕', '^' => '鼬', '_' => '儳', '`' => '嚥', 'a' => '壞', 'b' => '壟', 'c' => '壢', 'd' => '寵', 'e' => '龐', 'f' => '廬', 'g' => '懲', 'h' => '懷', 'i' => '懶', 'j' => '懵', 'k' => '攀', 'l' => '攏', 'm' => '曠', 'n' => '曝', 'o' => '櫥', 'p' => '櫝', 'q' => '櫚', 'r' => '櫓', 's' => '瀛', 't' => '瀟', 'u' => '瀨', 'v' => '瀚', 'w' => '瀝', 'x' => '瀕', 'y' => '瀘', 'z' => '爆', '{' => '爍', '|' => '牘', '}' => '犢', '~' => '獸', 'á' => '獺', 'â' => '璽', 'ã' => '瓊', 'ä' => '瓣', 'å' => '疇', 'æ' => '疆', 'ç' => '癟', 'è' => '癡', 'é' => '矇', 'ê' => '礙', 'ë' => '禱', 'ì' => '穫', 'í' => '穩', 'î' => '簾', 'ï' => '簿', 'ð' => '簸', 'ñ' => '簽', 'ò' => '簷', 'ó' => '籀', 'ô' => '繫', 'õ' => '繭', 'ö' => '繹', '÷' => '繩', 'ø' => '繪', 'ù' => '羅', 'ú' => '繳', 'û' => '羶', 'ü' => '羹', 'ý' => '羸', 'þ' => '臘', 'ÿ' => '藩', '' => '藝', '' => '藪', '' => '藕', '' => '藤', '' => '藥', '' => '藷', '' => '蟻', '' => '蠅', '' => '蠍', '' => '蟹', '' => '蟾', '' => '襠', '' => '襟', '' => '襖', '' => '襞', '' => '譁', '' => '譜', '' => '識', '' => '證', '' => '譚', '' => '譎', '' => '譏', '' => '譆', '' => '譙', '' => '贈', '' => '贊', '' => '蹼', '' => '蹲', '' => '躇', '' => '蹶', '' => '蹬', '' => '蹺', '' => '蹴', '' => '轔', '' => '轎', '' => '辭', '' => '邊', '' => '邋', '' => '醱', '' => '醮', '' => '鏡', '' => '鏑', '' => '鏟', '' => '鏃', '' => '鏈', '' => '鏜', '' => '鏝', '' => '鏖', '' => '鏢', '' => '鏍', '' => '鏘', '' => '鏤', '' => '鏗', '' => '鏨', '' => '關', '' => '隴', '' => '難', '' => '霪', '' => '霧', '' => '靡', '' => '韜', '' => '韻', '' => '類', '@' => '願', 'A' => '顛', 'B' => '颼', 'C' => '饅', 'D' => '饉', 'E' => '騖', 'F' => '騙', 'G' => '鬍', 'H' => '鯨', 'I' => '鯧', 'J' => '鯖', 'K' => '鯛', 'L' => '鶉', 'M' => '鵡', 'N' => '鵲', 'O' => '鵪', 'P' => '鵬', 'Q' => '麒', 'R' => '麗', 'S' => '麓', 'T' => '麴', 'U' => '勸', 'V' => '嚨', 'W' => '嚷', 'X' => '嚶', 'Y' => '嚴', 'Z' => '嚼', '[' => '壤', '\\' => '孀', ']' => '孃', '^' => '孽', '_' => '寶', '`' => '巉', 'a' => '懸', 'b' => '懺', 'c' => '攘', 'd' => '攔', 'e' => '攙', 'f' => '曦', 'g' => '朧', 'h' => '櫬', 'i' => '瀾', 'j' => '瀰', 'k' => '瀲', 'l' => '爐', 'm' => '獻', 'n' => '瓏', 'o' => '癢', 'p' => '癥', 'q' => '礦', 'r' => '礪', 's' => '礬', 't' => '礫', 'u' => '竇', 'v' => '競', 'w' => '籌', 'x' => '籃', 'y' => '籍', 'z' => '糯', '{' => '糰', '|' => '辮', '}' => '繽', '~' => '繼', 'ġ' => '纂', 'Ģ' => '罌', 'ģ' => '耀', 'Ĥ' => '臚', 'ĥ' => '艦', 'Ħ' => '藻', 'ħ' => '藹', 'Ĩ' => '蘑', 'ĩ' => '藺', 'Ī' => '蘆', 'ī' => '蘋', 'Ĭ' => '蘇', 'ĭ' => '蘊', 'Į' => '蠔', 'į' => '蠕', 'İ' => '襤', 'ı' => '覺', 'IJ' => '觸', 'ij' => '議', 'Ĵ' => '譬', 'ĵ' => '警', 'Ķ' => '譯', 'ķ' => '譟', 'ĸ' => '譫', 'Ĺ' => '贏', 'ĺ' => '贍', 'Ļ' => '躉', 'ļ' => '躁', 'Ľ' => '躅', 'ľ' => '躂', 'Ŀ' => '醴', '' => '釋', '' => '鐘', '' => '鐃', '' => '鏽', '' => '闡', '' => '霰', '' => '飄', '' => '饒', '' => '饑', '' => '馨', '' => '騫', '' => '騰', '' => '騷', '' => '騵', '' => '鰓', '' => '鰍', '' => '鹹', '' => '麵', '' => '黨', '' => '鼯', '' => '齟', '' => '齣', '' => '齡', '' => '儷', '' => '儸', '' => '囁', '' => '囀', '' => '囂', '' => '夔', '' => '屬', '' => '巍', '' => '懼', '' => '懾', '' => '攝', '' => '攜', '' => '斕', '' => '曩', '' => '櫻', '' => '欄', '' => '櫺', '' => '殲', '' => '灌', '' => '爛', '' => '犧', '' => '瓖', '' => '瓔', '' => '癩', '' => '矓', '' => '籐', '' => '纏', '' => '續', '' => '羼', '' => '蘗', '' => '蘭', '' => '蘚', '' => '蠣', '' => '蠢', '' => '蠡', '' => '蠟', '' => '襪', '' => '襬', '' => '覽', '' => '譴', '@' => '護', 'A' => '譽', 'B' => '贓', 'C' => '躊', 'D' => '躍', 'E' => '躋', 'F' => '轟', 'G' => '辯', 'H' => '醺', 'I' => '鐮', 'J' => '鐳', 'K' => '鐵', 'L' => '鐺', 'M' => '鐸', 'N' => '鐲', 'O' => '鐫', 'P' => '闢', 'Q' => '霸', 'R' => '霹', 'S' => '露', 'T' => '響', 'U' => '顧', 'V' => '顥', 'W' => '饗', 'X' => '驅', 'Y' => '驃', 'Z' => '驀', '[' => '騾', '\\' => '髏', ']' => '魔', '^' => '魑', '_' => '鰭', '`' => '鰥', 'a' => '鶯', 'b' => '鶴', 'c' => '鷂', 'd' => '鶸', 'e' => '麝', 'f' => '黯', 'g' => '鼙', 'h' => '齜', 'i' => '齦', 'j' => '齧', 'k' => '儼', 'l' => '儻', 'm' => '囈', 'n' => '囊', 'o' => '囉', 'p' => '孿', 'q' => '巔', 'r' => '巒', 's' => '彎', 't' => '懿', 'u' => '攤', 'v' => '權', 'w' => '歡', 'x' => '灑', 'y' => '灘', 'z' => '玀', '{' => '瓤', '|' => '疊', '}' => '癮', '~' => '癬', 'š' => '禳', 'Ţ' => '籠', 'ţ' => '籟', 'Ť' => '聾', 'ť' => '聽', 'Ŧ' => '臟', 'ŧ' => '襲', 'Ũ' => '襯', 'ũ' => '觼', 'Ū' => '讀', 'ū' => '贖', 'Ŭ' => '贗', 'ŭ' => '躑', 'Ů' => '躓', 'ů' => '轡', 'Ű' => '酈', 'ű' => '鑄', 'Ų' => '鑑', 'ų' => '鑒', 'Ŵ' => '霽', 'ŵ' => '霾', 'Ŷ' => '韃', 'ŷ' => '韁', 'Ÿ' => '顫', 'Ź' => '饕', 'ź' => '驕', 'Ż' => '驍', 'ż' => '髒', 'Ž' => '鬚', 'ž' => '鱉', 'ſ' => '鰱', '' => '鰾', '' => '鰻', '' => '鷓', '' => '鷗', '' => '鼴', '' => '齬', '' => '齪', '' => '龔', '' => '囌', '' => '巖', '' => '戀', '' => '攣', '' => '攫', '' => '攪', '' => '曬', '' => '欐', '' => '瓚', '' => '竊', '' => '籤', '' => '籣', '' => '籥', '' => '纓', '' => '纖', '' => '纔', '' => '臢', '' => '蘸', '' => '蘿', '' => '蠱', '' => '變', '' => '邐', '' => '邏', '' => '鑣', '' => '鑠', '' => '鑤', '' => '靨', '' => '顯', '' => '饜', '' => '驚', '' => '驛', '' => '驗', '' => '髓', '' => '體', '' => '髑', '' => '鱔', '' => '鱗', '' => '鱖', '' => '鷥', '' => '麟', '' => '黴', '' => '囑', '' => '壩', '' => '攬', '' => '灞', '' => '癱', '' => '癲', '' => '矗', '' => '罐', '' => '羈', '' => '蠶', '' => '蠹', '' => '衢', '' => '讓', '' => '讒', '@' => '讖', 'A' => '艷', 'B' => '贛', 'C' => '釀', 'D' => '鑪', 'E' => '靂', 'F' => '靈', 'G' => '靄', 'H' => '韆', 'I' => '顰', 'J' => '驟', 'K' => '鬢', 'L' => '魘', 'M' => '鱟', 'N' => '鷹', 'O' => '鷺', 'P' => '鹼', 'Q' => '鹽', 'R' => '鼇', 'S' => '齷', 'T' => '齲', 'U' => '廳', 'V' => '欖', 'W' => '灣', 'X' => '籬', 'Y' => '籮', 'Z' => '蠻', '[' => '觀', '\\' => '躡', ']' => '釁', '^' => '鑲', '_' => '鑰', '`' => '顱', 'a' => '饞', 'b' => '髖', 'c' => '鬣', 'd' => '黌', 'e' => '灤', 'f' => '矚', 'g' => '讚', 'h' => '鑷', 'i' => '韉', 'j' => '驢', 'k' => '驥', 'l' => '纜', 'm' => '讜', 'n' => '躪', 'o' => '釅', 'p' => '鑽', 'q' => '鑾', 'r' => '鑼', 's' => '鱷', 't' => '鱸', 'u' => '黷', 'v' => '豔', 'w' => '鑿', 'x' => '鸚', 'y' => '爨', 'z' => '驪', '{' => '鬱', '|' => '鸛', '}' => '鸞', '~' => '籲', 'ơ' => 'ヾ', 'Ƣ' => 'ゝ', 'ƣ' => 'ゞ', 'Ƥ' => '々', 'ƥ' => 'ぁ', 'Ʀ' => 'あ', 'Ƨ' => 'ぃ', 'ƨ' => 'い', 'Ʃ' => 'ぅ', 'ƪ' => 'う', 'ƫ' => 'ぇ', 'Ƭ' => 'え', 'ƭ' => 'ぉ', 'Ʈ' => 'お', 'Ư' => 'か', 'ư' => 'が', 'Ʊ' => 'き', 'Ʋ' => 'ぎ', 'Ƴ' => 'く', 'ƴ' => 'ぐ', 'Ƶ' => 'け', 'ƶ' => 'げ', 'Ʒ' => 'こ', 'Ƹ' => 'ご', 'ƹ' => 'さ', 'ƺ' => 'ざ', 'ƻ' => 'し', 'Ƽ' => 'じ', 'ƽ' => 'す', 'ƾ' => 'ず', 'ƿ' => 'せ', '' => 'ぜ', '' => 'そ', '' => 'ぞ', '' => 'た', '' => 'だ', '' => 'ち', '' => 'ぢ', '' => 'っ', '' => 'つ', '' => 'づ', '' => 'て', '' => 'で', '' => 'と', '' => 'ど', '' => 'な', '' => 'に', '' => 'ぬ', '' => 'ね', '' => 'の', '' => 'は', '' => 'ば', '' => 'ぱ', '' => 'ひ', '' => 'び', '' => 'ぴ', '' => 'ふ', '' => 'ぶ', '' => 'ぷ', '' => 'へ', '' => 'べ', '' => 'ぺ', '' => 'ほ', '' => 'ぼ', '' => 'ぽ', '' => 'ま', '' => 'み', '' => 'む', '' => 'め', '' => 'も', '' => 'ゃ', '' => 'や', '' => 'ゅ', '' => 'ゆ', '' => 'ょ', '' => 'よ', '' => 'ら', '' => 'り', '' => 'る', '' => 'れ', '' => 'ろ', '' => 'ゎ', '' => 'わ', '' => 'ゐ', '' => 'ゑ', '' => 'を', '' => 'ん', '' => 'ァ', '' => 'ア', '' => 'ィ', '' => 'イ', '' => 'ゥ', '' => 'ウ', '' => 'ェ', '@' => 'エ', 'A' => 'ォ', 'B' => 'オ', 'C' => 'カ', 'D' => 'ガ', 'E' => 'キ', 'F' => 'ギ', 'G' => 'ク', 'H' => 'グ', 'I' => 'ケ', 'J' => 'ゲ', 'K' => 'コ', 'L' => 'ゴ', 'M' => 'サ', 'N' => 'ザ', 'O' => 'シ', 'P' => 'ジ', 'Q' => 'ス', 'R' => 'ズ', 'S' => 'セ', 'T' => 'ゼ', 'U' => 'ソ', 'V' => 'ゾ', 'W' => 'タ', 'X' => 'ダ', 'Y' => 'チ', 'Z' => 'ヂ', '[' => 'ッ', '\\' => 'ツ', ']' => 'ヅ', '^' => 'テ', '_' => 'デ', '`' => 'ト', 'a' => 'ド', 'b' => 'ナ', 'c' => 'ニ', 'd' => 'ヌ', 'e' => 'ネ', 'f' => 'ノ', 'g' => 'ハ', 'h' => 'バ', 'i' => 'パ', 'j' => 'ヒ', 'k' => 'ビ', 'l' => 'ピ', 'm' => 'フ', 'n' => 'ブ', 'o' => 'プ', 'p' => 'ヘ', 'q' => 'ベ', 'r' => 'ペ', 's' => 'ホ', 't' => 'ボ', 'u' => 'ポ', 'v' => 'マ', 'w' => 'ミ', 'x' => 'ム', 'y' => 'メ', 'z' => 'モ', '{' => 'ャ', '|' => 'ヤ', '}' => 'ュ', '~' => 'ユ', 'ǡ' => 'ョ', 'Ǣ' => 'ヨ', 'ǣ' => 'ラ', 'Ǥ' => 'リ', 'ǥ' => 'ル', 'Ǧ' => 'レ', 'ǧ' => 'ロ', 'Ǩ' => 'ヮ', 'ǩ' => 'ワ', 'Ǫ' => 'ヰ', 'ǫ' => 'ヱ', 'Ǭ' => 'ヲ', 'ǭ' => 'ン', 'Ǯ' => 'ヴ', 'ǯ' => 'ヵ', 'ǰ' => 'ヶ', 'DZ' => 'Д', 'Dz' => 'Е', 'dz' => 'Ё', 'Ǵ' => 'Ж', 'ǵ' => 'З', 'Ƕ' => 'И', 'Ƿ' => 'Й', 'Ǹ' => 'К', 'ǹ' => 'Л', 'Ǻ' => 'М', 'ǻ' => 'У', 'Ǽ' => 'Ф', 'ǽ' => 'Х', 'Ǿ' => 'Ц', 'ǿ' => 'Ч', '' => 'Ш', '' => 'Щ', '' => 'Ъ', '' => 'Ы', '' => 'Ь', '' => 'Э', '' => 'Ю', '' => 'Я', '' => 'а', '' => 'б', '' => 'в', '' => 'г', '' => 'д', '' => 'е', '' => 'ё', '' => 'ж', '' => 'з', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ф', '' => 'х', '' => 'ц', '' => 'ч', '' => 'ш', '' => 'щ', '' => 'ъ', '' => 'ы', '' => 'ь', '' => 'э', '' => 'ю', '' => 'я', '' => '①', '' => '②', '' => '③', '' => '④', '' => '⑤', '' => '⑥', '' => '⑦', '' => '⑧', '' => '⑨', '' => '⑩', '' => '⑴', '' => '⑵', '' => '⑶', '' => '⑷', '' => '⑸', '' => '⑹', '' => '⑺', '' => '⑻', '' => '⑼', '' => '⑽', '@' => '乂', 'A' => '乜', 'B' => '凵', 'C' => '匚', 'D' => '厂', 'E' => '万', 'F' => '丌', 'G' => '乇', 'H' => '亍', 'I' => '囗', 'J' => '兀', 'K' => '屮', 'L' => '彳', 'M' => '丏', 'N' => '冇', 'O' => '与', 'P' => '丮', 'Q' => '亓', 'R' => '仂', 'S' => '仉', 'T' => '仈', 'U' => '冘', 'V' => '勼', 'W' => '卬', 'X' => '厹', 'Y' => '圠', 'Z' => '夃', '[' => '夬', '\\' => '尐', ']' => '巿', '^' => '旡', '_' => '殳', '`' => '毌', 'a' => '气', 'b' => '爿', 'c' => '丱', 'd' => '丼', 'e' => '仨', 'f' => '仜', 'g' => '仩', 'h' => '仡', 'i' => '仝', 'j' => '仚', 'k' => '刌', 'l' => '匜', 'm' => '卌', 'n' => '圢', 'o' => '圣', 'p' => '夗', 'q' => '夯', 'r' => '宁', 's' => '宄', 't' => '尒', 'u' => '尻', 'v' => '屴', 'w' => '屳', 'x' => '帄', 'y' => '庀', 'z' => '庂', '{' => '忉', '|' => '戉', '}' => '扐', '~' => '氕', 'ɡ' => '氶', 'ɢ' => '汃', 'ɣ' => '氿', 'ɤ' => '氻', 'ɥ' => '犮', 'ɦ' => '犰', 'ɧ' => '玊', 'ɨ' => '禸', 'ɩ' => '肊', 'ɪ' => '阞', 'ɫ' => '伎', 'ɬ' => '优', 'ɭ' => '伬', 'ɮ' => '仵', 'ɯ' => '伔', 'ɰ' => '仱', 'ɱ' => '伀', 'ɲ' => '价', 'ɳ' => '伈', 'ɴ' => '伝', 'ɵ' => '伂', 'ɶ' => '伅', 'ɷ' => '伢', 'ɸ' => '伓', 'ɹ' => '伄', 'ɺ' => '仴', 'ɻ' => '伒', 'ɼ' => '冱', 'ɽ' => '刓', 'ɾ' => '刉', 'ɿ' => '刐', '' => '劦', '' => '匢', '' => '匟', '' => '卍', '' => '厊', '' => '吇', '' => '囡', '' => '囟', '' => '圮', '' => '圪', '' => '圴', '' => '夼', '' => '妀', '' => '奼', '' => '妅', '' => '奻', '' => '奾', '' => '奷', '' => '奿', '' => '孖', '' => '尕', '' => '尥', '' => '屼', '' => '屺', '' => '屻', '' => '屾', '' => '巟', '' => '幵', '' => '庄', '' => '异', '' => '弚', '' => '彴', '' => '忕', '' => '忔', '' => '忏', '' => '扜', '' => '扞', '' => '扤', '' => '扡', '' => '扦', '' => '扢', '' => '扙', '' => '扠', '' => '扚', '' => '扥', '' => '旯', '' => '旮', '' => '朾', '' => '朹', '' => '朸', '' => '朻', '' => '机', '' => '朿', '' => '朼', '' => '朳', '' => '氘', '' => '汆', '' => '汒', '' => '汜', '' => '汏', '' => '汊', '' => '汔', '' => '汋', '@' => '汌', 'A' => '灱', 'B' => '牞', 'C' => '犴', 'D' => '犵', 'E' => '玎', 'F' => '甪', 'G' => '癿', 'H' => '穵', 'I' => '网', 'J' => '艸', 'K' => '艼', 'L' => '芀', 'M' => '艽', 'N' => '艿', 'O' => '虍', 'P' => '襾', 'Q' => '邙', 'R' => '邗', 'S' => '邘', 'T' => '邛', 'U' => '邔', 'V' => '阢', 'W' => '阤', 'X' => '阠', 'Y' => '阣', 'Z' => '佖', '[' => '伻', '\\' => '佢', ']' => '佉', '^' => '体', '_' => '佤', '`' => '伾', 'a' => '佧', 'b' => '佒', 'c' => '佟', 'd' => '佁', 'e' => '佘', 'f' => '伭', 'g' => '伳', 'h' => '伿', 'i' => '佡', 'j' => '冏', 'k' => '冹', 'l' => '刜', 'm' => '刞', 'n' => '刡', 'o' => '劭', 'p' => '劮', 'q' => '匉', 'r' => '卣', 's' => '卲', 't' => '厎', 'u' => '厏', 'v' => '吰', 'w' => '吷', 'x' => '吪', 'y' => '呔', 'z' => '呅', '{' => '吙', '|' => '吜', '}' => '吥', '~' => '吘', 'ʡ' => '吽', 'ʢ' => '呏', 'ʣ' => '呁', 'ʤ' => '吨', 'ʥ' => '吤', 'ʦ' => '呇', 'ʧ' => '囮', 'ʨ' => '囧', 'ʩ' => '囥', 'ʪ' => '坁', 'ʫ' => '坅', 'ʬ' => '坌', 'ʭ' => '坉', 'ʮ' => '坋', 'ʯ' => '坒', 'ʰ' => '夆', 'ʱ' => '奀', 'ʲ' => '妦', 'ʳ' => '妘', 'ʴ' => '妠', 'ʵ' => '妗', 'ʶ' => '妎', 'ʷ' => '妢', 'ʸ' => '妐', 'ʹ' => '妏', 'ʺ' => '妧', 'ʻ' => '妡', 'ʼ' => '宎', 'ʽ' => '宒', 'ʾ' => '尨', 'ʿ' => '尪', '' => '岍', '' => '岏', '' => '岈', '' => '岋', '' => '岉', '' => '岒', '' => '岊', '' => '岆', '' => '岓', '' => '岕', '' => '巠', '' => '帊', '' => '帎', '' => '庋', '' => '庉', '' => '庌', '' => '庈', '' => '庍', '' => '弅', '' => '弝', '' => '彸', '' => '彶', '' => '忒', '' => '忑', '' => '忐', '' => '忭', '' => '忨', '' => '忮', '' => '忳', '' => '忡', '' => '忤', '' => '忣', '' => '忺', '' => '忯', '' => '忷', '' => '忻', '' => '怀', '' => '忴', '' => '戺', '' => '抃', '' => '抌', '' => '抎', '' => '抏', '' => '抔', '' => '抇', '' => '扱', '' => '扻', '' => '扺', '' => '扰', '' => '抁', '' => '抈', '' => '扷', '' => '扽', '' => '扲', '' => '扴', '' => '攷', '' => '旰', '' => '旴', '' => '旳', '' => '旲', '' => '旵', '' => '杅', '' => '杇', '@' => '杙', 'A' => '杕', 'B' => '杌', 'C' => '杈', 'D' => '杝', 'E' => '杍', 'F' => '杚', 'G' => '杋', 'H' => '毐', 'I' => '氙', 'J' => '氚', 'K' => '汸', 'L' => '汧', 'M' => '汫', 'N' => '沄', 'O' => '沋', 'P' => '沏', 'Q' => '汱', 'R' => '汯', 'S' => '汩', 'T' => '沚', 'U' => '汭', 'V' => '沇', 'W' => '沕', 'X' => '沜', 'Y' => '汦', 'Z' => '汳', '[' => '汥', '\\' => '汻', ']' => '沎', '^' => '灴', '_' => '灺', '`' => '牣', 'a' => '犿', 'b' => '犽', 'c' => '狃', 'd' => '狆', 'e' => '狁', 'f' => '犺', 'g' => '狅', 'h' => '玕', 'i' => '玗', 'j' => '玓', 'k' => '玔', 'l' => '玒', 'm' => '町', 'n' => '甹', 'o' => '疔', 'p' => '疕', 'q' => '皁', 'r' => '礽', 's' => '耴', 't' => '肕', 'u' => '肙', 'v' => '肐', 'w' => '肒', 'x' => '肜', 'y' => '芐', 'z' => '芏', '{' => '芅', '|' => '芎', '}' => '芑', '~' => '芓', 'ˡ' => '芊', 'ˢ' => '芃', 'ˣ' => '芄', 'ˤ' => '豸', '˥' => '迉', '˦' => '辿', '˧' => '邟', '˨' => '邡', '˩' => '邥', '˪' => '邞', '˫' => '邧', 'ˬ' => '邠', '˭' => '阰', 'ˮ' => '阨', '˯' => '阯', '˰' => '阭', '˱' => '丳', '˲' => '侘', '˳' => '佼', '˴' => '侅', '˵' => '佽', '˶' => '侀', '˷' => '侇', '˸' => '佶', '˹' => '佴', '˺' => '侉', '˻' => '侄', '˼' => '佷', '˽' => '佌', '˾' => '侗', '˿' => '佪', '' => '侚', '' => '佹', '' => '侁', '' => '佸', '' => '侐', '' => '侜', '' => '侔', '' => '侞', '' => '侒', '' => '侂', '' => '侕', '' => '佫', '' => '佮', '' => '冞', '' => '冼', '' => '冾', '' => '刵', '' => '刲', '' => '刳', '' => '剆', '' => '刱', '' => '劼', '' => '匊', '' => '匋', '' => '匼', '' => '厒', '' => '厔', '' => '咇', '' => '呿', '' => '咁', '' => '咑', '' => '咂', '' => '咈', '' => '呫', '' => '呺', '' => '呾', '' => '呥', '' => '呬', '' => '呴', '' => '呦', '' => '咍', '' => '呯', '' => '呡', '' => '呠', '' => '咘', '' => '呣', '' => '呧', '' => '呤', '' => '囷', '' => '囹', '' => '坯', '' => '坲', '' => '坭', '' => '坫', '' => '坱', '' => '坰', '' => '坶', '' => '垀', '' => '坵', '' => '坻', '' => '坳', '' => '坴', '' => '坢', '@' => '坨', 'A' => '坽', 'B' => '夌', 'C' => '奅', 'D' => '妵', 'E' => '妺', 'F' => '姏', 'G' => '姎', 'H' => '妲', 'I' => '姌', 'J' => '姁', 'K' => '妶', 'L' => '妼', 'M' => '姃', 'N' => '姖', 'O' => '妱', 'P' => '妽', 'Q' => '姀', 'R' => '姈', 'S' => '妴', 'T' => '姇', 'U' => '孢', 'V' => '孥', 'W' => '宓', 'X' => '宕', 'Y' => '屄', 'Z' => '屇', '[' => '岮', '\\' => '岤', ']' => '岠', '^' => '岵', '_' => '岯', '`' => '岨', 'a' => '岬', 'b' => '岟', 'c' => '岣', 'd' => '岭', 'e' => '岢', 'f' => '岪', 'g' => '岧', 'h' => '岝', 'i' => '岥', 'j' => '岶', 'k' => '岰', 'l' => '岦', 'm' => '帗', 'n' => '帔', 'o' => '帙', 'p' => '弨', 'q' => '弢', 'r' => '弣', 's' => '弤', 't' => '彔', 'u' => '徂', 'v' => '彾', 'w' => '彽', 'x' => '忞', 'y' => '忥', 'z' => '怭', '{' => '怦', '|' => '怙', '}' => '怲', '~' => '怋', '̡' => '怴', '̢' => '怊', '̣' => '怗', '̤' => '怳', '̥' => '怚', '̦' => '怞', '̧' => '怬', '̨' => '怢', '̩' => '怍', '̪' => '怐', '̫' => '怮', '̬' => '怓', '̭' => '怑', '̮' => '怌', '̯' => '怉', '̰' => '怜', '̱' => '戔', '̲' => '戽', '̳' => '抭', '̴' => '抴', '̵' => '拑', '̶' => '抾', '̷' => '抪', '̸' => '抶', '̹' => '拊', '̺' => '抮', '̻' => '抳', '̼' => '抯', '̽' => '抻', '̾' => '抩', '̿' => '抰', '' => '抸', '' => '攽', '' => '斨', '' => '斻', '' => '昉', '' => '旼', '' => '昄', '' => '昒', '' => '昈', '' => '旻', '' => '昃', '' => '昋', '' => '昍', '' => '昅', '' => '旽', '' => '昑', '' => '昐', '' => '曶', '' => '朊', '' => '枅', '' => '杬', '' => '枎', '' => '枒', '' => '杶', '' => '杻', '' => '枘', '' => '枆', '' => '构', '' => '杴', '' => '枍', '' => '枌', '' => '杺', '' => '枟', '' => '枑', '' => '枙', '' => '枃', '' => '杽', '' => '极', '' => '杸', '' => '杹', '' => '枔', '' => '欥', '' => '殀', '' => '歾', '' => '毞', '' => '氝', '' => '沓', '' => '泬', '' => '泫', '' => '泮', '' => '泙', '' => '沶', '' => '泔', '' => '沭', '' => '泧', '' => '沷', '' => '泐', '' => '泂', '' => '沺', '' => '泃', '' => '泆', '' => '泭', '' => '泲', '@' => '泒', 'A' => '泝', 'B' => '沴', 'C' => '沊', 'D' => '沝', 'E' => '沀', 'F' => '泞', 'G' => '泀', 'H' => '洰', 'I' => '泍', 'J' => '泇', 'K' => '沰', 'L' => '泹', 'M' => '泏', 'N' => '泩', 'O' => '泑', 'P' => '炔', 'Q' => '炘', 'R' => '炅', 'S' => '炓', 'T' => '炆', 'U' => '炄', 'V' => '炑', 'W' => '炖', 'X' => '炂', 'Y' => '炚', 'Z' => '炃', '[' => '牪', '\\' => '狖', ']' => '狋', '^' => '狘', '_' => '狉', '`' => '狜', 'a' => '狒', 'b' => '狔', 'c' => '狚', 'd' => '狌', 'e' => '狑', 'f' => '玤', 'g' => '玡', 'h' => '玭', 'i' => '玦', 'j' => '玢', 'k' => '玠', 'l' => '玬', 'm' => '玝', 'n' => '瓝', 'o' => '瓨', 'p' => '甿', 'q' => '畀', 'r' => '甾', 's' => '疌', 't' => '疘', 'u' => '皯', 'v' => '盳', 'w' => '盱', 'x' => '盰', 'y' => '盵', 'z' => '矸', '{' => '矼', '|' => '矹', '}' => '矻', '~' => '矺', '͡' => '矷', '͢' => '祂', 'ͣ' => '礿', 'ͤ' => '秅', 'ͥ' => '穸', 'ͦ' => '穻', 'ͧ' => '竻', 'ͨ' => '籵', 'ͩ' => '糽', 'ͪ' => '耵', 'ͫ' => '肏', 'ͬ' => '肮', 'ͭ' => '肣', 'ͮ' => '肸', 'ͯ' => '肵', 'Ͱ' => '肭', 'ͱ' => '舠', 'Ͳ' => '芠', 'ͳ' => '苀', 'ʹ' => '芫', '͵' => '芚', 'Ͷ' => '芘', 'ͷ' => '芛', '͸' => '芵', '͹' => '芧', 'ͺ' => '芮', 'ͻ' => '芼', 'ͼ' => '芞', 'ͽ' => '芺', ';' => '芴', 'Ϳ' => '芨', '' => '芡', '' => '芩', '' => '苂', '' => '芤', '' => '苃', '' => '芶', '' => '芢', '' => '虰', '' => '虯', '' => '虭', '' => '虮', '' => '豖', '' => '迒', '' => '迋', '' => '迓', '' => '迍', '' => '迖', '' => '迕', '' => '迗', '' => '邲', '' => '邴', '' => '邯', '' => '邳', '' => '邰', '' => '阹', '' => '阽', '' => '阼', '' => '阺', '' => '陃', '' => '俍', '' => '俅', '' => '俓', '' => '侲', '' => '俉', '' => '俋', '' => '俁', '' => '俔', '' => '俜', '' => '俙', '' => '侻', '' => '侳', '' => '俛', '' => '俇', '' => '俖', '' => '侺', '' => '俀', '' => '侹', '' => '俬', '' => '剄', '' => '剉', '' => '勀', '' => '勂', '' => '匽', '' => '卼', '' => '厗', '' => '厖', '' => '厙', '' => '厘', '' => '咺', '' => '咡', '' => '咭', '' => '咥', '' => '哏', '@' => '哃', 'A' => '茍', 'B' => '咷', 'C' => '咮', 'D' => '哖', 'E' => '咶', 'F' => '哅', 'G' => '哆', 'H' => '咠', 'I' => '呰', 'J' => '咼', 'K' => '咢', 'L' => '咾', 'M' => '呲', 'N' => '哞', 'O' => '咰', 'P' => '垵', 'Q' => '垞', 'R' => '垟', 'S' => '垤', 'T' => '垌', 'U' => '垗', 'V' => '垝', 'W' => '垛', 'X' => '垔', 'Y' => '垘', 'Z' => '垏', '[' => '垙', '\\' => '垥', ']' => '垚', '^' => '垕', '_' => '壴', '`' => '复', 'a' => '奓', 'b' => '姡', 'c' => '姞', 'd' => '姮', 'e' => '娀', 'f' => '姱', 'g' => '姝', 'h' => '姺', 'i' => '姽', 'j' => '姼', 'k' => '姶', 'l' => '姤', 'm' => '姲', 'n' => '姷', 'o' => '姛', 'p' => '姩', 'q' => '姳', 'r' => '姵', 's' => '姠', 't' => '姾', 'u' => '姴', 'v' => '姭', 'w' => '宨', 'x' => '屌', 'y' => '峐', 'z' => '峘', '{' => '峌', '|' => '峗', '}' => '峋', '~' => '峛', 'Ρ' => '峞', '΢' => '峚', 'Σ' => '峉', 'Τ' => '峇', 'Υ' => '峊', 'Φ' => '峖', 'Χ' => '峓', 'Ψ' => '峔', 'Ω' => '峏', 'Ϊ' => '峈', 'Ϋ' => '峆', 'ά' => '峎', 'έ' => '峟', 'ή' => '峸', 'ί' => '巹', 'ΰ' => '帡', 'α' => '帢', 'β' => '帣', 'γ' => '帠', 'δ' => '帤', 'ε' => '庰', 'ζ' => '庤', 'η' => '庢', 'θ' => '庛', 'ι' => '庣', 'κ' => '庥', 'λ' => '弇', 'μ' => '弮', 'ν' => '彖', 'ξ' => '徆', 'ο' => '怷', '' => '怹', '' => '恔', '' => '恲', '' => '恞', '' => '恅', '' => '恓', '' => '恇', '' => '恉', '' => '恛', '' => '恌', '' => '恀', '' => '恂', '' => '恟', '' => '怤', '' => '恄', '' => '恘', '' => '恦', '' => '恮', '' => '扂', '' => '扃', '' => '拏', '' => '挍', '' => '挋', '' => '拵', '' => '挎', '' => '挃', '' => '拫', '' => '拹', '' => '挏', '' => '挌', '' => '拸', '' => '拶', '' => '挀', '' => '挓', '' => '挔', '' => '拺', '' => '挕', '' => '拻', '' => '拰', '' => '敁', '' => '敃', '' => '斪', '' => '斿', '' => '昶', '' => '昡', '' => '昲', '' => '昵', '' => '昜', '' => '昦', '' => '昢', '' => '昳', '' => '昫', '' => '昺', '' => '昝', '' => '昴', '' => '昹', '' => '昮', '' => '朏', '' => '朐', '' => '柁', '' => '柲', '' => '柈', '' => '枺', '@' => '柜', 'A' => '枻', 'B' => '柸', 'C' => '柘', 'D' => '柀', 'E' => '枷', 'F' => '柅', 'G' => '柫', 'H' => '柤', 'I' => '柟', 'J' => '枵', 'K' => '柍', 'L' => '枳', 'M' => '柷', 'N' => '柶', 'O' => '柮', 'P' => '柣', 'Q' => '柂', 'R' => '枹', 'S' => '柎', 'T' => '柧', 'U' => '柰', 'V' => '枲', 'W' => '柼', 'X' => '柆', 'Y' => '柭', 'Z' => '柌', '[' => '枮', '\\' => '柦', ']' => '柛', '^' => '柺', '_' => '柉', '`' => '柊', 'a' => '柃', 'b' => '柪', 'c' => '柋', 'd' => '欨', 'e' => '殂', 'f' => '殄', 'g' => '殶', 'h' => '毖', 'i' => '毘', 'j' => '毠', 'k' => '氠', 'l' => '氡', 'm' => '洨', 'n' => '洴', 'o' => '洭', 'p' => '洟', 'q' => '洼', 'r' => '洿', 's' => '洒', 't' => '洊', 'u' => '泚', 'v' => '洳', 'w' => '洄', 'x' => '洙', 'y' => '洺', 'z' => '洚', '{' => '洑', '|' => '洀', '}' => '洝', '~' => '浂', 'ϡ' => '洁', 'Ϣ' => '洘', 'ϣ' => '洷', 'Ϥ' => '洃', 'ϥ' => '洏', 'Ϧ' => '浀', 'ϧ' => '洇', 'Ϩ' => '洠', 'ϩ' => '洬', 'Ϫ' => '洈', 'ϫ' => '洢', 'Ϭ' => '洉', 'ϭ' => '洐', 'Ϯ' => '炷', 'ϯ' => '炟', 'ϰ' => '炾', 'ϱ' => '炱', 'ϲ' => '炰', 'ϳ' => '炡', 'ϴ' => '炴', 'ϵ' => '炵', '϶' => '炩', 'Ϸ' => '牁', 'ϸ' => '牉', 'Ϲ' => '牊', 'Ϻ' => '牬', 'ϻ' => '牰', 'ϼ' => '牳', 'Ͻ' => '牮', 'Ͼ' => '狊', 'Ͽ' => '狤', '' => '狨', '' => '狫', '' => '狟', '' => '狪', '' => '狦', '' => '狣', '' => '玅', '' => '珌', '' => '珂', '' => '珈', '' => '珅', '' => '玹', '' => '玶', '' => '玵', '' => '玴', '' => '珫', '' => '玿', '' => '珇', '' => '玾', '' => '珃', '' => '珆', '' => '玸', '' => '珋', '' => '瓬', '' => '瓮', '' => '甮', '' => '畇', '' => '畈', '' => '疧', '' => '疪', '' => '癹', '' => '盄', '' => '眈', '' => '眃', '' => '眄', '' => '眅', '' => '眊', '' => '盷', '' => '盻', '' => '盺', '' => '矧', '' => '矨', '' => '砆', '' => '砑', '' => '砒', '' => '砅', '' => '砐', '' => '砏', '' => '砎', '' => '砉', '' => '砃', '' => '砓', '' => '祊', '' => '祌', '' => '祋', '' => '祅', '' => '祄', '' => '秕', '' => '种', '' => '秏', '' => '秖', '' => '秎', '' => '窀', '@' => '穾', 'A' => '竑', 'B' => '笀', 'C' => '笁', 'D' => '籺', 'E' => '籸', 'F' => '籹', 'G' => '籿', 'H' => '粀', 'I' => '粁', 'J' => '紃', 'K' => '紈', 'L' => '紁', 'M' => '罘', 'N' => '羑', 'O' => '羍', 'P' => '羾', 'Q' => '耇', 'R' => '耎', 'S' => '耏', 'T' => '耔', 'U' => '耷', 'V' => '胘', 'W' => '胇', 'X' => '胠', 'Y' => '胑', 'Z' => '胈', '[' => '胂', '\\' => '胐', ']' => '胅', '^' => '胣', '_' => '胙', '`' => '胜', 'a' => '胊', 'b' => '胕', 'c' => '胉', 'd' => '胏', 'e' => '胗', 'f' => '胦', 'g' => '胍', 'h' => '臿', 'i' => '舡', 'j' => '芔', 'k' => '苙', 'l' => '苾', 'm' => '苹', 'n' => '茇', 'o' => '苨', 'p' => '茀', 'q' => '苕', 'r' => '茺', 's' => '苫', 't' => '苖', 'u' => '苴', 'v' => '苬', 'w' => '苡', 'x' => '苲', 'y' => '苵', 'z' => '茌', '{' => '苻', '|' => '苶', '}' => '苰', '~' => '苪', 'С' => '苤', 'Т' => '苠', 'У' => '苺', 'Ф' => '苳', 'Х' => '苭', 'Ц' => '虷', 'Ч' => '虴', 'Ш' => '虼', 'Щ' => '虳', 'Ъ' => '衁', 'Ы' => '衎', 'Ь' => '衧', 'Э' => '衪', 'Ю' => '衩', 'Я' => '觓', 'а' => '訄', 'б' => '訇', 'в' => '赲', 'г' => '迣', 'д' => '迡', 'е' => '迮', 'ж' => '迠', 'з' => '郱', 'и' => '邽', 'й' => '邿', 'к' => '郕', 'л' => '郅', 'м' => '邾', 'н' => '郇', 'о' => '郋', 'п' => '郈', '' => '釔', '' => '釓', '' => '陔', '' => '陏', '' => '陑', '' => '陓', '' => '陊', '' => '陎', '' => '倞', '' => '倅', '' => '倇', '' => '倓', '' => '倢', '' => '倰', '' => '倛', '' => '俵', '' => '俴', '' => '倳', '' => '倷', '' => '倬', '' => '俶', '' => '俷', '' => '倗', '' => '倜', '' => '倠', '' => '倧', '' => '倵', '' => '倯', '' => '倱', '' => '倎', '' => '党', '' => '冔', '' => '冓', '' => '凊', '' => '凄', '' => '凅', '' => '凈', '' => '凎', '' => '剡', '' => '剚', '' => '剒', '' => '剞', '' => '剟', '' => '剕', '' => '剢', '' => '勍', '' => '匎', '' => '厞', '' => '唦', '' => '哢', '' => '唗', '' => '唒', '' => '哧', '' => '哳', '' => '哤', '' => '唚', '' => '哿', '' => '唄', '' => '唈', '' => '哫', '' => '唑', '' => '唅', '' => '哱', '@' => '唊', 'A' => '哻', 'B' => '哷', 'C' => '哸', 'D' => '哠', 'E' => '唎', 'F' => '唃', 'G' => '唋', 'H' => '圁', 'I' => '圂', 'J' => '埌', 'K' => '堲', 'L' => '埕', 'M' => '埒', 'N' => '垺', 'O' => '埆', 'P' => '垽', 'Q' => '垼', 'R' => '垸', 'S' => '垶', 'T' => '垿', 'U' => '埇', 'V' => '埐', 'W' => '垹', 'X' => '埁', 'Y' => '夎', 'Z' => '奊', '[' => '娙', '\\' => '娖', ']' => '娭', '^' => '娮', '_' => '娕', '`' => '娏', 'a' => '娗', 'b' => '娊', 'c' => '娞', 'd' => '娳', 'e' => '孬', 'f' => '宧', 'g' => '宭', 'h' => '宬', 'i' => '尃', 'j' => '屖', 'k' => '屔', 'l' => '峬', 'm' => '峿', 'n' => '峮', 'o' => '峱', 'p' => '峷', 'q' => '崀', 'r' => '峹', 's' => '帩', 't' => '帨', 'u' => '庨', 'v' => '庮', 'w' => '庪', 'x' => '庬', 'y' => '弳', 'z' => '弰', '{' => '彧', '|' => '恝', '}' => '恚', '~' => '恧', 'ѡ' => '恁', 'Ѣ' => '悢', 'ѣ' => '悈', 'Ѥ' => '悀', 'ѥ' => '悒', 'Ѧ' => '悁', 'ѧ' => '悝', 'Ѩ' => '悃', 'ѩ' => '悕', 'Ѫ' => '悛', 'ѫ' => '悗', 'Ѭ' => '悇', 'ѭ' => '悜', 'Ѯ' => '悎', 'ѯ' => '戙', 'Ѱ' => '扆', 'ѱ' => '拲', 'Ѳ' => '挐', 'ѳ' => '捖', 'Ѵ' => '挬', 'ѵ' => '捄', 'Ѷ' => '捅', 'ѷ' => '挶', 'Ѹ' => '捃', 'ѹ' => '揤', 'Ѻ' => '挹', 'ѻ' => '捋', 'Ѽ' => '捊', 'ѽ' => '挼', 'Ѿ' => '挩', 'ѿ' => '捁', '' => '挴', '' => '捘', '' => '捔', '' => '捙', '' => '挭', '' => '捇', '' => '挳', '' => '捚', '' => '捑', '' => '挸', '' => '捗', '' => '捀', '' => '捈', '' => '敊', '' => '敆', '' => '旆', '' => '旃', '' => '旄', '' => '旂', '' => '晊', '' => '晟', '' => '晇', '' => '晑', '' => '朒', '' => '朓', '' => '栟', '' => '栚', '' => '桉', '' => '栲', '' => '栳', '' => '栻', '' => '桋', '' => '桏', '' => '栖', '' => '栱', '' => '栜', '' => '栵', '' => '栫', '' => '栭', '' => '栯', '' => '桎', '' => '桄', '' => '栴', '' => '栝', '' => '栒', '' => '栔', '' => '栦', '' => '栨', '' => '栮', '' => '桍', '' => '栺', '' => '栥', '' => '栠', '' => '欬', '' => '欯', '' => '欭', '' => '欱', '' => '欴', '' => '歭', '' => '肂', '' => '殈', '' => '毦', '' => '毤', '@' => '毨', 'A' => '毣', 'B' => '毢', 'C' => '毧', 'D' => '氥', 'E' => '浺', 'F' => '浣', 'G' => '浤', 'H' => '浶', 'I' => '洍', 'J' => '浡', 'K' => '涒', 'L' => '浘', 'M' => '浢', 'N' => '浭', 'O' => '浯', 'P' => '涑', 'Q' => '涍', 'R' => '淯', 'S' => '浿', 'T' => '涆', 'U' => '浞', 'V' => '浧', 'W' => '浠', 'X' => '涗', 'Y' => '浰', 'Z' => '浼', '[' => '浟', '\\' => '涂', ']' => '涘', '^' => '洯', '_' => '浨', '`' => '涋', 'a' => '浾', 'b' => '涀', 'c' => '涄', 'd' => '洖', 'e' => '涃', 'f' => '浻', 'g' => '浽', 'h' => '浵', 'i' => '涐', 'j' => '烜', 'k' => '烓', 'l' => '烑', 'm' => '烝', 'n' => '烋', 'o' => '缹', 'p' => '烢', 'q' => '烗', 'r' => '烒', 's' => '烞', 't' => '烠', 'u' => '烔', 'v' => '烍', 'w' => '烅', 'x' => '烆', 'y' => '烇', 'z' => '烚', '{' => '烎', '|' => '烡', '}' => '牂', '~' => '牸', 'ҡ' => '牷', 'Ң' => '牶', 'ң' => '猀', 'Ҥ' => '狺', 'ҥ' => '狴', 'Ҧ' => '狾', 'ҧ' => '狶', 'Ҩ' => '狳', 'ҩ' => '狻', 'Ҫ' => '猁', 'ҫ' => '珓', 'Ҭ' => '珙', 'ҭ' => '珥', 'Ү' => '珖', 'ү' => '玼', 'Ұ' => '珧', 'ұ' => '珣', 'Ҳ' => '珩', 'ҳ' => '珜', 'Ҵ' => '珒', 'ҵ' => '珛', 'Ҷ' => '珔', 'ҷ' => '珝', 'Ҹ' => '珚', 'ҹ' => '珗', 'Һ' => '珘', 'һ' => '珨', 'Ҽ' => '瓞', 'ҽ' => '瓟', 'Ҿ' => '瓴', 'ҿ' => '瓵', '' => '甡', '' => '畛', '' => '畟', '' => '疰', '' => '痁', '' => '疻', '' => '痄', '' => '痀', '' => '疿', '' => '疶', '' => '疺', '' => '皊', '' => '盉', '' => '眝', '' => '眛', '' => '眐', '' => '眓', '' => '眒', '' => '眣', '' => '眑', '' => '眕', '' => '眙', '' => '眚', '' => '眢', '' => '眧', '' => '砣', '' => '砬', '' => '砢', '' => '砵', '' => '砯', '' => '砨', '' => '砮', '' => '砫', '' => '砡', '' => '砩', '' => '砳', '' => '砪', '' => '砱', '' => '祔', '' => '祛', '' => '祏', '' => '祜', '' => '祓', '' => '祒', '' => '祑', '' => '秫', '' => '秬', '' => '秠', '' => '秮', '' => '秭', '' => '秪', '' => '秜', '' => '秞', '' => '秝', '' => '窆', '' => '窉', '' => '窅', '' => '窋', '' => '窌', '' => '窊', '' => '窇', '' => '竘', '' => '笐', '@' => '笄', 'A' => '笓', 'B' => '笅', 'C' => '笏', 'D' => '笈', 'E' => '笊', 'F' => '笎', 'G' => '笉', 'H' => '笒', 'I' => '粄', 'J' => '粑', 'K' => '粊', 'L' => '粌', 'M' => '粈', 'N' => '粍', 'O' => '粅', 'P' => '紞', 'Q' => '紝', 'R' => '紑', 'S' => '紎', 'T' => '紘', 'U' => '紖', 'V' => '紓', 'W' => '紟', 'X' => '紒', 'Y' => '紏', 'Z' => '紌', '[' => '罜', '\\' => '罡', ']' => '罞', '^' => '罠', '_' => '罝', '`' => '罛', 'a' => '羖', 'b' => '羒', 'c' => '翃', 'd' => '翂', 'e' => '翀', 'f' => '耖', 'g' => '耾', 'h' => '耹', 'i' => '胺', 'j' => '胲', 'k' => '胹', 'l' => '胵', 'm' => '脁', 'n' => '胻', 'o' => '脀', 'p' => '舁', 'q' => '舯', 'r' => '舥', 's' => '茳', 't' => '茭', 'u' => '荄', 'v' => '茙', 'w' => '荑', 'x' => '茥', 'y' => '荖', 'z' => '茿', '{' => '荁', '|' => '茦', '}' => '茜', '~' => '茢', 'ӡ' => '荂', 'Ӣ' => '荎', 'ӣ' => '茛', 'Ӥ' => '茪', 'ӥ' => '茈', 'Ӧ' => '茼', 'ӧ' => '荍', 'Ө' => '茖', 'ө' => '茤', 'Ӫ' => '茠', 'ӫ' => '茷', 'Ӭ' => '茯', 'ӭ' => '茩', 'Ӯ' => '荇', 'ӯ' => '荅', 'Ӱ' => '荌', 'ӱ' => '荓', 'Ӳ' => '茞', 'ӳ' => '茬', 'Ӵ' => '荋', 'ӵ' => '茧', 'Ӷ' => '荈', 'ӷ' => '虓', 'Ӹ' => '虒', 'ӹ' => '蚢', 'Ӻ' => '蚨', 'ӻ' => '蚖', 'Ӽ' => '蚍', 'ӽ' => '蚑', 'Ӿ' => '蚞', 'ӿ' => '蚇', '' => '蚗', '' => '蚆', '' => '蚋', '' => '蚚', '' => '蚅', '' => '蚥', '' => '蚙', '' => '蚡', '' => '蚧', '' => '蚕', '' => '蚘', '' => '蚎', '' => '蚝', '' => '蚐', '' => '蚔', '' => '衃', '' => '衄', '' => '衭', '' => '衵', '' => '衶', '' => '衲', '' => '袀', '' => '衱', '' => '衿', '' => '衯', '' => '袃', '' => '衾', '' => '衴', '' => '衼', '' => '訒', '' => '豇', '' => '豗', '' => '豻', '' => '貤', '' => '貣', '' => '赶', '' => '赸', '' => '趵', '' => '趷', '' => '趶', '' => '軑', '' => '軓', '' => '迾', '' => '迵', '' => '适', '' => '迿', '' => '迻', '' => '逄', '' => '迼', '' => '迶', '' => '郖', '' => '郠', '' => '郙', '' => '郚', '' => '郣', '' => '郟', '' => '郥', '' => '郘', '' => '郛', '' => '郗', '' => '郜', '' => '郤', '' => '酐', '@' => '酎', 'A' => '酏', 'B' => '釕', 'C' => '釢', 'D' => '釚', 'E' => '陜', 'F' => '陟', 'G' => '隼', 'H' => '飣', 'I' => '髟', 'J' => '鬯', 'K' => '乿', 'L' => '偰', 'M' => '偪', 'N' => '偡', 'O' => '偞', 'P' => '偠', 'Q' => '偓', 'R' => '偋', 'S' => '偝', 'T' => '偲', 'U' => '偈', 'V' => '偍', 'W' => '偁', 'X' => '偛', 'Y' => '偊', 'Z' => '偢', '[' => '倕', '\\' => '偅', ']' => '偟', '^' => '偩', '_' => '偫', '`' => '偣', 'a' => '偤', 'b' => '偆', 'c' => '偀', 'd' => '偮', 'e' => '偳', 'f' => '偗', 'g' => '偑', 'h' => '凐', 'i' => '剫', 'j' => '剭', 'k' => '剬', 'l' => '剮', 'm' => '勖', 'n' => '勓', 'o' => '匭', 'p' => '厜', 'q' => '啵', 'r' => '啶', 's' => '唼', 't' => '啍', 'u' => '啐', 'v' => '唴', 'w' => '唪', 'x' => '啑', 'y' => '啢', 'z' => '唶', '{' => '唵', '|' => '唰', '}' => '啒', '~' => '啅', 'ԡ' => '唌', 'Ԣ' => '唲', 'ԣ' => '啥', 'Ԥ' => '啎', 'ԥ' => '唹', 'Ԧ' => '啈', 'ԧ' => '唭', 'Ԩ' => '唻', 'ԩ' => '啀', 'Ԫ' => '啋', 'ԫ' => '圊', 'Ԭ' => '圇', 'ԭ' => '埻', 'Ԯ' => '堔', 'ԯ' => '埢', '԰' => '埶', 'Ա' => '埜', 'Բ' => '埴', 'Գ' => '堀', 'Դ' => '埭', 'Ե' => '埽', 'Զ' => '堈', 'Է' => '埸', 'Ը' => '堋', 'Թ' => '埳', 'Ժ' => '埏', 'Ի' => '堇', 'Լ' => '埮', 'Խ' => '埣', 'Ծ' => '埲', 'Կ' => '埥', '' => '埬', '' => '埡', '' => '堎', '' => '埼', '' => '堐', '' => '埧', '' => '堁', '' => '堌', '' => '埱', '' => '埩', '' => '埰', '' => '堍', '' => '堄', '' => '奜', '' => '婠', '' => '婘', '' => '婕', '' => '婧', '' => '婞', '' => '娸', '' => '娵', '' => '婭', '' => '婐', '' => '婟', '' => '婥', '' => '婬', '' => '婓', '' => '婤', '' => '婗', '' => '婃', '' => '婝', '' => '婒', '' => '婄', '' => '婛', '' => '婈', '' => '媎', '' => '娾', '' => '婍', '' => '娹', '' => '婌', '' => '婰', '' => '婩', '' => '婇', '' => '婑', '' => '婖', '' => '婂', '' => '婜', '' => '孲', '' => '孮', '' => '寁', '' => '寀', '' => '屙', '' => '崞', '' => '崋', '' => '崝', '' => '崚', '' => '崠', '' => '崌', '' => '崨', '' => '崍', '' => '崦', '' => '崥', '' => '崏', '@' => '崰', 'A' => '崒', 'B' => '崣', 'C' => '崟', 'D' => '崮', 'E' => '帾', 'F' => '帴', 'G' => '庱', 'H' => '庴', 'I' => '庹', 'J' => '庲', 'K' => '庳', 'L' => '弶', 'M' => '弸', 'N' => '徛', 'O' => '徖', 'P' => '徟', 'Q' => '悊', 'R' => '悐', 'S' => '悆', 'T' => '悾', 'U' => '悰', 'V' => '悺', 'W' => '惓', 'X' => '惔', 'Y' => '惏', 'Z' => '惤', '[' => '惙', '\\' => '惝', ']' => '惈', '^' => '悱', '_' => '惛', '`' => '悷', 'a' => '惊', 'b' => '悿', 'c' => '惃', 'd' => '惍', 'e' => '惀', 'f' => '挲', 'g' => '捥', 'h' => '掊', 'i' => '掂', 'j' => '捽', 'k' => '掽', 'l' => '掞', 'm' => '掭', 'n' => '掝', 'o' => '掗', 'p' => '掫', 'q' => '掎', 'r' => '捯', 's' => '掇', 't' => '掐', 'u' => '据', 'v' => '掯', 'w' => '捵', 'x' => '掜', 'y' => '捭', 'z' => '掮', '{' => '捼', '|' => '掤', '}' => '挻', '~' => '掟', 'ա' => '捸', 'բ' => '掅', 'գ' => '掁', 'դ' => '掑', 'ե' => '掍', 'զ' => '捰', 'է' => '敓', 'ը' => '旍', 'թ' => '晥', 'ժ' => '晡', 'ի' => '晛', 'լ' => '晙', 'խ' => '晜', 'ծ' => '晢', 'կ' => '朘', 'հ' => '桹', 'ձ' => '梇', 'ղ' => '梐', 'ճ' => '梜', 'մ' => '桭', 'յ' => '桮', 'ն' => '梮', 'շ' => '梫', 'ո' => '楖', 'չ' => '桯', 'պ' => '梣', 'ջ' => '梬', 'ռ' => '梩', 'ս' => '桵', 'վ' => '桴', 'տ' => '梲', '' => '梏', '' => '桷', '' => '梒', '' => '桼', '' => '桫', '' => '桲', '' => '梪', '' => '梀', '' => '桱', '' => '桾', '' => '梛', '' => '梖', '' => '梋', '' => '梠', '' => '梉', '' => '梤', '' => '桸', '' => '桻', '' => '梑', '' => '梌', '' => '梊', '' => '桽', '' => '欶', '' => '欳', '' => '欷', '' => '欸', '' => '殑', '' => '殏', '' => '殍', '' => '殎', '' => '殌', '' => '氪', '' => '淀', '' => '涫', '' => '涴', '' => '涳', '' => '湴', '' => '涬', '' => '淩', '' => '淢', '' => '涷', '' => '淶', '' => '淔', '' => '渀', '' => '淈', '' => '淠', '' => '淟', '' => '淖', '' => '涾', '' => '淥', '' => '淜', '' => '淝', '' => '淛', '' => '淴', '' => '淊', '' => '涽', '' => '淭', '' => '淰', '' => '涺', '' => '淕', '' => '淂', '' => '淏', '' => '淉', '@' => '淐', 'A' => '淲', 'B' => '淓', 'C' => '淽', 'D' => '淗', 'E' => '淍', 'F' => '淣', 'G' => '涻', 'H' => '烺', 'I' => '焍', 'J' => '烷', 'K' => '焗', 'L' => '烴', 'M' => '焌', 'N' => '烰', 'O' => '焄', 'P' => '烳', 'Q' => '焐', 'R' => '烼', 'S' => '烿', 'T' => '焆', 'U' => '焓', 'V' => '焀', 'W' => '烸', 'X' => '烶', 'Y' => '焋', 'Z' => '焂', '[' => '焎', '\\' => '牾', ']' => '牻', '^' => '牼', '_' => '牿', '`' => '猝', 'a' => '猗', 'b' => '猇', 'c' => '猑', 'd' => '猘', 'e' => '猊', 'f' => '猈', 'g' => '狿', 'h' => '猏', 'i' => '猞', 'j' => '玈', 'k' => '珶', 'l' => '珸', 'm' => '珵', 'n' => '琄', 'o' => '琁', 'p' => '珽', 'q' => '琇', 'r' => '琀', 's' => '珺', 't' => '珼', 'u' => '珿', 'v' => '琌', 'w' => '琋', 'x' => '珴', 'y' => '琈', 'z' => '畤', '{' => '畣', '|' => '痎', '}' => '痒', '~' => '痏', '֡' => '痋', '֢' => '痌', '֣' => '痑', '֤' => '痐', '֥' => '皏', '֦' => '皉', '֧' => '盓', '֨' => '眹', '֩' => '眯', '֪' => '眭', '֫' => '眱', '֬' => '眲', '֭' => '眴', '֮' => '眳', '֯' => '眽', 'ְ' => '眥', 'ֱ' => '眻', 'ֲ' => '眵', 'ֳ' => '硈', 'ִ' => '硒', 'ֵ' => '硉', 'ֶ' => '硍', 'ַ' => '硊', 'ָ' => '硌', 'ֹ' => '砦', 'ֺ' => '硅', 'ֻ' => '硐', 'ּ' => '祤', 'ֽ' => '祧', '־' => '祩', 'ֿ' => '祪', '' => '祣', '' => '祫', '' => '祡', '' => '离', '' => '秺', '' => '秸', '' => '秶', '' => '秷', '' => '窏', '' => '窔', '' => '窐', '' => '笵', '' => '筇', '' => '笴', '' => '笥', '' => '笰', '' => '笢', '' => '笤', '' => '笳', '' => '笘', '' => '笪', '' => '笝', '' => '笱', '' => '笫', '' => '笭', '' => '笯', '' => '笲', '' => '笸', '' => '笚', '' => '笣', '' => '粔', '' => '粘', '' => '粖', '' => '粣', '' => '紵', '' => '紽', '' => '紸', '' => '紶', '' => '紺', '' => '絅', '' => '紬', '' => '紩', '' => '絁', '' => '絇', '' => '紾', '' => '紿', '' => '絊', '' => '紻', '' => '紨', '' => '罣', '' => '羕', '' => '羜', '' => '羝', '' => '羛', '' => '翊', '' => '翋', '' => '翍', '' => '翐', '' => '翑', '' => '翇', '' => '翏', '' => '翉', '' => '耟', '@' => '耞', 'A' => '耛', 'B' => '聇', 'C' => '聃', 'D' => '聈', 'E' => '脘', 'F' => '脥', 'G' => '脙', 'H' => '脛', 'I' => '脭', 'J' => '脟', 'K' => '脬', 'L' => '脞', 'M' => '脡', 'N' => '脕', 'O' => '脧', 'P' => '脝', 'Q' => '脢', 'R' => '舑', 'S' => '舸', 'T' => '舳', 'U' => '舺', 'V' => '舴', 'W' => '舲', 'X' => '艴', 'Y' => '莐', 'Z' => '莣', '[' => '莨', '\\' => '莍', ']' => '荺', '^' => '荳', '_' => '莤', '`' => '荴', 'a' => '莏', 'b' => '莁', 'c' => '莕', 'd' => '莙', 'e' => '荵', 'f' => '莔', 'g' => '莩', 'h' => '荽', 'i' => '莃', 'j' => '莌', 'k' => '莝', 'l' => '莛', 'm' => '莪', 'n' => '莋', 'o' => '荾', 'p' => '莥', 'q' => '莯', 'r' => '莈', 's' => '莗', 't' => '莰', 'u' => '荿', 'v' => '莦', 'w' => '莇', 'x' => '莮', 'y' => '荶', 'z' => '莚', '{' => '虙', '|' => '虖', '}' => '蚿', '~' => '蚷', 'ס' => '蛂', 'ע' => '蛁', 'ף' => '蛅', 'פ' => '蚺', 'ץ' => '蚰', 'צ' => '蛈', 'ק' => '蚹', 'ר' => '蚳', 'ש' => '蚸', 'ת' => '蛌', '׫' => '蚴', '׬' => '蚻', '׭' => '蚼', '׮' => '蛃', 'ׯ' => '蚽', 'װ' => '蚾', 'ױ' => '衒', 'ײ' => '袉', '׳' => '袕', '״' => '袨', '׵' => '袢', '׶' => '袪', '׷' => '袚', '׸' => '袑', '׹' => '袡', '׺' => '袟', '׻' => '袘', '׼' => '袧', '׽' => '袙', '׾' => '袛', '׿' => '袗', '' => '袤', '' => '袬', '' => '袌', '' => '袓', '' => '袎', '' => '覂', '' => '觖', '' => '觙', '' => '觕', '' => '訰', '' => '訧', '' => '訬', '' => '訞', '' => '谹', '' => '谻', '' => '豜', '' => '豝', '' => '豽', '' => '貥', '' => '赽', '' => '赻', '' => '赹', '' => '趼', '' => '跂', '' => '趹', '' => '趿', '' => '跁', '' => '軘', '' => '軞', '' => '軝', '' => '軜', '' => '軗', '' => '軠', '' => '軡', '' => '逤', '' => '逋', '' => '逑', '' => '逜', '' => '逌', '' => '逡', '' => '郯', '' => '郪', '' => '郰', '' => '郴', '' => '郲', '' => '郳', '' => '郔', '' => '郫', '' => '郬', '' => '郩', '' => '酖', '' => '酘', '' => '酚', '' => '酓', '' => '酕', '' => '釬', '' => '釴', '' => '釱', '' => '釳', '' => '釸', '' => '釤', '' => '釹', '' => '釪', '@' => '釫', 'A' => '釷', 'B' => '釨', 'C' => '釮', 'D' => '镺', 'E' => '閆', 'F' => '閈', 'G' => '陼', 'H' => '陭', 'I' => '陫', 'J' => '陱', 'K' => '陯', 'L' => '隿', 'M' => '靪', 'N' => '頄', 'O' => '飥', 'P' => '馗', 'Q' => '傛', 'R' => '傕', 'S' => '傔', 'T' => '傞', 'U' => '傋', 'V' => '傣', 'W' => '傃', 'X' => '傌', 'Y' => '傎', 'Z' => '傝', '[' => '偨', '\\' => '傜', ']' => '傒', '^' => '傂', '_' => '傇', '`' => '兟', 'a' => '凔', 'b' => '匒', 'c' => '匑', 'd' => '厤', 'e' => '厧', 'f' => '喑', 'g' => '喨', 'h' => '喥', 'i' => '喭', 'j' => '啷', 'k' => '噅', 'l' => '喢', 'm' => '喓', 'n' => '喈', 'o' => '喏', 'p' => '喵', 'q' => '喁', 'r' => '喣', 's' => '喒', 't' => '喤', 'u' => '啽', 'v' => '喌', 'w' => '喦', 'x' => '啿', 'y' => '喕', 'z' => '喡', '{' => '喎', '|' => '圌', '}' => '堩', '~' => '堷', 'ء' => '堙', 'آ' => '堞', 'أ' => '堧', 'ؤ' => '堣', 'إ' => '堨', 'ئ' => '埵', 'ا' => '塈', 'ب' => '堥', 'ة' => '堜', 'ت' => '堛', 'ث' => '堳', 'ج' => '堿', 'ح' => '堶', 'خ' => '堮', 'د' => '堹', 'ذ' => '堸', 'ر' => '堭', 'ز' => '堬', 'س' => '堻', 'ش' => '奡', 'ص' => '媯', 'ض' => '媔', 'ط' => '媟', 'ظ' => '婺', 'ع' => '媢', 'غ' => '媞', 'ػ' => '婸', 'ؼ' => '媦', 'ؽ' => '婼', 'ؾ' => '媥', 'ؿ' => '媬', '' => '媕', '' => '媮', '' => '娷', '' => '媄', '' => '媊', '' => '媗', '' => '媃', '' => '媋', '' => '媩', '' => '婻', '' => '婽', '' => '媌', '' => '媜', '' => '媏', '' => '媓', '' => '媝', '' => '寪', '' => '寍', '' => '寋', '' => '寔', '' => '寑', '' => '寊', '' => '寎', '' => '尌', '' => '尰', '' => '崷', '' => '嵃', '' => '嵫', '' => '嵁', '' => '嵋', '' => '崿', '' => '崵', '' => '嵑', '' => '嵎', '' => '嵕', '' => '崳', '' => '崺', '' => '嵒', '' => '崽', '' => '崱', '' => '嵙', '' => '嵂', '' => '崹', '' => '嵉', '' => '崸', '' => '崼', '' => '崲', '' => '崶', '' => '嵀', '' => '嵅', '' => '幄', '' => '幁', '' => '彘', '' => '徦', '' => '徥', '' => '徫', '' => '惉', '' => '悹', '' => '惌', '' => '惢', '' => '惎', '' => '惄', '' => '愔', '@' => '惲', 'A' => '愊', 'B' => '愖', 'C' => '愅', 'D' => '惵', 'E' => '愓', 'F' => '惸', 'G' => '惼', 'H' => '惾', 'I' => '惁', 'J' => '愃', 'K' => '愘', 'L' => '愝', 'M' => '愐', 'N' => '惿', 'O' => '愄', 'P' => '愋', 'Q' => '扊', 'R' => '掔', 'S' => '掱', 'T' => '掰', 'U' => '揎', 'V' => '揥', 'W' => '揨', 'X' => '揯', 'Y' => '揃', 'Z' => '撝', '[' => '揳', '\\' => '揊', ']' => '揠', '^' => '揶', '_' => '揕', '`' => '揲', 'a' => '揵', 'b' => '摡', 'c' => '揟', 'd' => '掾', 'e' => '揝', 'f' => '揜', 'g' => '揄', 'h' => '揘', 'i' => '揓', 'j' => '揂', 'k' => '揇', 'l' => '揌', 'm' => '揋', 'n' => '揈', 'o' => '揰', 'p' => '揗', 'q' => '揙', 'r' => '攲', 's' => '敧', 't' => '敪', 'u' => '敤', 'v' => '敜', 'w' => '敨', 'x' => '敥', 'y' => '斌', 'z' => '斝', '{' => '斞', '|' => '斮', '}' => '旐', '~' => '旒', '١' => '晼', '٢' => '晬', '٣' => '晻', '٤' => '暀', '٥' => '晱', '٦' => '晹', '٧' => '晪', '٨' => '晲', '٩' => '朁', '٪' => '椌', '٫' => '棓', '٬' => '椄', '٭' => '棜', 'ٮ' => '椪', 'ٯ' => '棬', 'ٰ' => '棪', 'ٱ' => '棱', 'ٲ' => '椏', 'ٳ' => '棖', 'ٴ' => '棷', 'ٵ' => '棫', 'ٶ' => '棤', 'ٷ' => '棶', 'ٸ' => '椓', 'ٹ' => '椐', 'ٺ' => '棳', 'ٻ' => '棡', 'ټ' => '椇', 'ٽ' => '棌', 'پ' => '椈', 'ٿ' => '楰', '' => '梴', '' => '椑', '' => '棯', '' => '棆', '' => '椔', '' => '棸', '' => '棐', '' => '棽', '' => '棼', '' => '棨', '' => '椋', '' => '椊', '' => '椗', '' => '棎', '' => '棈', '' => '棝', '' => '棞', '' => '棦', '' => '棴', '' => '棑', '' => '椆', '' => '棔', '' => '棩', '' => '椕', '' => '椥', '' => '棇', '' => '欹', '' => '欻', '' => '欿', '' => '欼', '' => '殔', '' => '殗', '' => '殙', '' => '殕', '' => '殽', '' => '毰', '' => '毲', '' => '毳', '' => '氰', '' => '淼', '' => '湆', '' => '湇', '' => '渟', '' => '湉', '' => '溈', '' => '渼', '' => '渽', '' => '湅', '' => '湢', '' => '渫', '' => '渿', '' => '湁', '' => '湝', '' => '湳', '' => '渜', '' => '渳', '' => '湋', '' => '湀', '' => '湑', '' => '渻', '' => '渃', '' => '渮', '' => '湞', '@' => '湨', 'A' => '湜', 'B' => '湡', 'C' => '渱', 'D' => '渨', 'E' => '湠', 'F' => '湱', 'G' => '湫', 'H' => '渹', 'I' => '渢', 'J' => '渰', 'K' => '湓', 'L' => '湥', 'M' => '渧', 'N' => '湸', 'O' => '湤', 'P' => '湷', 'Q' => '湕', 'R' => '湹', 'S' => '湒', 'T' => '湦', 'U' => '渵', 'V' => '渶', 'W' => '湚', 'X' => '焠', 'Y' => '焞', 'Z' => '焯', '[' => '烻', '\\' => '焮', ']' => '焱', '^' => '焣', '_' => '焥', '`' => '焢', 'a' => '焲', 'b' => '焟', 'c' => '焨', 'd' => '焺', 'e' => '焛', 'f' => '牋', 'g' => '牚', 'h' => '犈', 'i' => '犉', 'j' => '犆', 'k' => '犅', 'l' => '犋', 'm' => '猒', 'n' => '猋', 'o' => '猰', 'p' => '猢', 'q' => '猱', 'r' => '猳', 's' => '猧', 't' => '猲', 'u' => '猭', 'v' => '猦', 'w' => '猣', 'x' => '猵', 'y' => '猌', 'z' => '琮', '{' => '琬', '|' => '琰', '}' => '琫', '~' => '琖', 'ڡ' => '琚', 'ڢ' => '琡', 'ڣ' => '琭', 'ڤ' => '琱', 'ڥ' => '琤', 'ڦ' => '琣', 'ڧ' => '琝', 'ڨ' => '琩', 'ک' => '琠', 'ڪ' => '琲', 'ګ' => '瓻', 'ڬ' => '甯', 'ڭ' => '畯', 'ڮ' => '畬', 'گ' => '痧', 'ڰ' => '痚', 'ڱ' => '痡', 'ڲ' => '痦', 'ڳ' => '痝', 'ڴ' => '痟', 'ڵ' => '痤', 'ڶ' => '痗', 'ڷ' => '皕', 'ڸ' => '皒', 'ڹ' => '盚', 'ں' => '睆', 'ڻ' => '睇', 'ڼ' => '睄', 'ڽ' => '睍', 'ھ' => '睅', 'ڿ' => '睊', '' => '睎', '' => '睋', '' => '睌', '' => '矞', '' => '矬', '' => '硠', '' => '硤', '' => '硥', '' => '硜', '' => '硭', '' => '硱', '' => '硪', '' => '确', '' => '硰', '' => '硩', '' => '硨', '' => '硞', '' => '硢', '' => '祴', '' => '祳', '' => '祲', '' => '祰', '' => '稂', '' => '稊', '' => '稃', '' => '稌', '' => '稄', '' => '窙', '' => '竦', '' => '竤', '' => '筊', '' => '笻', '' => '筄', '' => '筈', '' => '筌', '' => '筎', '' => '筀', '' => '筘', '' => '筅', '' => '粢', '' => '粞', '' => '粨', '' => '粡', '' => '絘', '' => '絯', '' => '絣', '' => '絓', '' => '絖', '' => '絧', '' => '絪', '' => '絏', '' => '絭', '' => '絜', '' => '絫', '' => '絒', '' => '絔', '' => '絩', '' => '絑', '' => '絟', '' => '絎', '' => '缾', '' => '缿', '' => '罥', '@' => '罦', 'A' => '羢', 'B' => '羠', 'C' => '羡', 'D' => '翗', 'E' => '聑', 'F' => '聏', 'G' => '聐', 'H' => '胾', 'I' => '胔', 'J' => '腃', 'K' => '腊', 'L' => '腒', 'M' => '腏', 'N' => '腇', 'O' => '脽', 'P' => '腍', 'Q' => '脺', 'R' => '臦', 'S' => '臮', 'T' => '臷', 'U' => '臸', 'V' => '臹', 'W' => '舄', 'X' => '舼', 'Y' => '舽', 'Z' => '舿', '[' => '艵', '\\' => '茻', ']' => '菏', '^' => '菹', '_' => '萣', '`' => '菀', 'a' => '菨', 'b' => '萒', 'c' => '菧', 'd' => '菤', 'e' => '菼', 'f' => '菶', 'g' => '萐', 'h' => '菆', 'i' => '菈', 'j' => '菫', 'k' => '菣', 'l' => '莿', 'm' => '萁', 'n' => '菝', 'o' => '菥', 'p' => '菘', 'q' => '菿', 'r' => '菡', 's' => '菋', 't' => '菎', 'u' => '菖', 'v' => '菵', 'w' => '菉', 'x' => '萉', 'y' => '萏', 'z' => '菞', '{' => '萑', '|' => '萆', '}' => '菂', '~' => '菳', 'ۡ' => '菕', 'ۢ' => '菺', 'ۣ' => '菇', 'ۤ' => '菑', 'ۥ' => '菪', 'ۦ' => '萓', 'ۧ' => '菃', 'ۨ' => '菬', '۩' => '菮', '۪' => '菄', '۫' => '菻', '۬' => '菗', 'ۭ' => '菢', 'ۮ' => '萛', 'ۯ' => '菛', '۰' => '菾', '۱' => '蛘', '۲' => '蛢', '۳' => '蛦', '۴' => '蛓', '۵' => '蛣', '۶' => '蛚', '۷' => '蛪', '۸' => '蛝', '۹' => '蛫', 'ۺ' => '蛜', 'ۻ' => '蛬', 'ۼ' => '蛩', '۽' => '蛗', '۾' => '蛨', 'ۿ' => '蛑', '' => '衈', '' => '衖', '' => '衕', '' => '袺', '' => '裗', '' => '袹', '' => '袸', '' => '裀', '' => '袾', '' => '袶', '' => '袼', '' => '袷', '' => '袽', '' => '袲', '' => '褁', '' => '裉', '' => '覕', '' => '覘', '' => '覗', '' => '觝', '' => '觚', '' => '觛', '' => '詎', '' => '詍', '' => '訹', '' => '詙', '' => '詀', '' => '詗', '' => '詘', '' => '詄', '' => '詅', '' => '詒', '' => '詈', '' => '詑', '' => '詊', '' => '詌', '' => '詏', '' => '豟', '' => '貁', '' => '貀', '' => '貺', '' => '貾', '' => '貰', '' => '貹', '' => '貵', '' => '趄', '' => '趀', '' => '趉', '' => '跘', '' => '跓', '' => '跍', '' => '跇', '' => '跖', '' => '跜', '' => '跏', '' => '跕', '' => '跙', '' => '跈', '' => '跗', '' => '跅', '' => '軯', '' => '軷', '' => '軺', '@' => '軹', 'A' => '軦', 'B' => '軮', 'C' => '軥', 'D' => '軵', 'E' => '軧', 'F' => '軨', 'G' => '軶', 'H' => '軫', 'I' => '軱', 'J' => '軬', 'K' => '軴', 'L' => '軩', 'M' => '逭', 'N' => '逴', 'O' => '逯', 'P' => '鄆', 'Q' => '鄬', 'R' => '鄄', 'S' => '郿', 'T' => '郼', 'U' => '鄈', 'V' => '郹', 'W' => '郻', 'X' => '鄁', 'Y' => '鄀', 'Z' => '鄇', '[' => '鄅', '\\' => '鄃', ']' => '酡', '^' => '酤', '_' => '酟', '`' => '酢', 'a' => '酠', 'b' => '鈁', 'c' => '鈊', 'd' => '鈥', 'e' => '鈃', 'f' => '鈚', 'g' => '鈦', 'h' => '鈏', 'i' => '鈌', 'j' => '鈀', 'k' => '鈒', 'l' => '釿', 'm' => '釽', 'n' => '鈆', 'o' => '鈄', 'p' => '鈧', 'q' => '鈂', 'r' => '鈜', 's' => '鈤', 't' => '鈙', 'u' => '鈗', 'v' => '鈅', 'w' => '鈖', 'x' => '镻', 'y' => '閍', 'z' => '閌', '{' => '閐', '|' => '隇', '}' => '陾', '~' => '隈', 'ܡ' => '隉', 'ܢ' => '隃', 'ܣ' => '隀', 'ܤ' => '雂', 'ܥ' => '雈', 'ܦ' => '雃', 'ܧ' => '雱', 'ܨ' => '雰', 'ܩ' => '靬', 'ܪ' => '靰', 'ܫ' => '靮', 'ܬ' => '頇', 'ܭ' => '颩', 'ܮ' => '飫', 'ܯ' => '鳦', 'ܰ' => '黹', 'ܱ' => '亃', 'ܲ' => '亄', 'ܳ' => '亶', 'ܴ' => '傽', 'ܵ' => '傿', 'ܶ' => '僆', 'ܷ' => '傮', 'ܸ' => '僄', 'ܹ' => '僊', 'ܺ' => '傴', 'ܻ' => '僈', 'ܼ' => '僂', 'ܽ' => '傰', 'ܾ' => '僁', 'ܿ' => '傺', '' => '傱', '' => '僋', '' => '僉', '' => '傶', '' => '傸', '' => '凗', '' => '剺', '' => '剸', '' => '剻', '' => '剼', '' => '嗃', '' => '嗛', '' => '嗌', '' => '嗐', '' => '嗋', '' => '嗊', '' => '嗝', '' => '嗀', '' => '嗔', '' => '嗄', '' => '嗩', '' => '喿', '' => '嗒', '' => '喍', '' => '嗏', '' => '嗕', '' => '嗢', '' => '嗖', '' => '嗈', '' => '嗲', '' => '嗍', '' => '嗙', '' => '嗂', '' => '圔', '' => '塓', '' => '塨', '' => '塤', '' => '塏', '' => '塍', '' => '塉', '' => '塯', '' => '塕', '' => '塎', '' => '塝', '' => '塙', '' => '塥', '' => '塛', '' => '堽', '' => '塣', '' => '塱', '' => '壼', '' => '嫇', '' => '嫄', '' => '嫋', '' => '媺', '' => '媸', '' => '媱', '' => '媵', '' => '媰', '' => '媿', '' => '嫈', '' => '媻', '' => '嫆', '@' => '媷', 'A' => '嫀', 'B' => '嫊', 'C' => '媴', 'D' => '媶', 'E' => '嫍', 'F' => '媹', 'G' => '媐', 'H' => '寖', 'I' => '寘', 'J' => '寙', 'K' => '尟', 'L' => '尳', 'M' => '嵱', 'N' => '嵣', 'O' => '嵊', 'P' => '嵥', 'Q' => '嵲', 'R' => '嵬', 'S' => '嵞', 'T' => '嵨', 'U' => '嵧', 'V' => '嵢', 'W' => '巰', 'X' => '幏', 'Y' => '幎', 'Z' => '幊', '[' => '幍', '\\' => '幋', ']' => '廅', '^' => '廌', '_' => '廆', '`' => '廋', 'a' => '廇', 'b' => '彀', 'c' => '徯', 'd' => '徭', 'e' => '惷', 'f' => '慉', 'g' => '慊', 'h' => '愫', 'i' => '慅', 'j' => '愶', 'k' => '愲', 'l' => '愮', 'm' => '慆', 'n' => '愯', 'o' => '慏', 'p' => '愩', 'q' => '慀', 'r' => '戠', 's' => '酨', 't' => '戣', 'u' => '戥', 'v' => '戤', 'w' => '揅', 'x' => '揱', 'y' => '揫', 'z' => '搐', '{' => '搒', '|' => '搉', '}' => '搠', '~' => '搤', 'ݡ' => '搳', 'ݢ' => '摃', 'ݣ' => '搟', 'ݤ' => '搕', 'ݥ' => '搘', 'ݦ' => '搹', 'ݧ' => '搷', 'ݨ' => '搢', 'ݩ' => '搣', 'ݪ' => '搌', 'ݫ' => '搦', 'ݬ' => '搰', 'ݭ' => '搨', 'ݮ' => '摁', 'ݯ' => '搵', 'ݰ' => '搯', 'ݱ' => '搊', 'ݲ' => '搚', 'ݳ' => '摀', 'ݴ' => '搥', 'ݵ' => '搧', 'ݶ' => '搋', 'ݷ' => '揧', 'ݸ' => '搛', 'ݹ' => '搮', 'ݺ' => '搡', 'ݻ' => '搎', 'ݼ' => '敯', 'ݽ' => '斒', 'ݾ' => '旓', 'ݿ' => '暆', '' => '暌', '' => '暕', '' => '暐', '' => '暋', '' => '暊', '' => '暙', '' => '暔', '' => '晸', '' => '朠', '' => '楦', '' => '楟', '' => '椸', '' => '楎', '' => '楢', '' => '楱', '' => '椿', '' => '楅', '' => '楪', '' => '椹', '' => '楂', '' => '楗', '' => '楙', '' => '楺', '' => '楈', '' => '楉', '' => '椵', '' => '楬', '' => '椳', '' => '椽', '' => '楥', '' => '棰', '' => '楸', '' => '椴', '' => '楩', '' => '楀', '' => '楯', '' => '楄', '' => '楶', '' => '楘', '' => '楁', '' => '楴', '' => '楌', '' => '椻', '' => '楋', '' => '椷', '' => '楜', '' => '楏', '' => '楑', '' => '椲', '' => '楒', '' => '椯', '' => '楻', '' => '椼', '' => '歆', '' => '歅', '' => '歃', '' => '歂', '' => '歈', '' => '歁', '' => '殛', '' => '嗀', '' => '毻', '' => '毼', '@' => '毹', 'A' => '毷', 'B' => '毸', 'C' => '溛', 'D' => '滖', 'E' => '滈', 'F' => '溏', 'G' => '滀', 'H' => '溟', 'I' => '溓', 'J' => '溔', 'K' => '溠', 'L' => '溱', 'M' => '溹', 'N' => '滆', 'O' => '滒', 'P' => '溽', 'Q' => '滁', 'R' => '溞', 'S' => '滉', 'T' => '溷', 'U' => '溰', 'V' => '滍', 'W' => '溦', 'X' => '滏', 'Y' => '溲', 'Z' => '溾', '[' => '滃', '\\' => '滜', ']' => '滘', '^' => '溙', '_' => '溒', '`' => '溎', 'a' => '溍', 'b' => '溤', 'c' => '溡', 'd' => '溿', 'e' => '溳', 'f' => '滐', 'g' => '滊', 'h' => '溗', 'i' => '溮', 'j' => '溣', 'k' => '煇', 'l' => '煔', 'm' => '煒', 'n' => '煣', 'o' => '煠', 'p' => '煁', 'q' => '煝', 'r' => '煢', 's' => '煲', 't' => '煸', 'u' => '煪', 'v' => '煡', 'w' => '煂', 'x' => '煘', 'y' => '煃', 'z' => '煋', '{' => '煰', '|' => '煟', '}' => '煐', '~' => '煓', 'ޡ' => '煄', 'ޢ' => '煍', 'ޣ' => '煚', 'ޤ' => '牏', 'ޥ' => '犍', 'ަ' => '犌', 'ާ' => '犑', 'ި' => '犐', 'ީ' => '犎', 'ު' => '猼', 'ޫ' => '獂', 'ެ' => '猻', 'ޭ' => '猺', 'ޮ' => '獀', 'ޯ' => '獊', 'ް' => '獉', 'ޱ' => '瑄', '޲' => '瑊', '޳' => '瑋', '޴' => '瑒', '޵' => '瑑', '޶' => '瑗', '޷' => '瑀', '޸' => '瑏', '޹' => '瑐', '޺' => '瑎', '޻' => '瑂', '޼' => '瑆', '޽' => '瑍', '޾' => '瑔', '޿' => '瓡', '' => '瓿', '' => '瓾', '' => '瓽', '' => '甝', '' => '畹', '' => '畷', '' => '榃', '' => '痯', '' => '瘏', '' => '瘃', '' => '痷', '' => '痾', '' => '痼', '' => '痹', '' => '痸', '' => '瘐', '' => '痻', '' => '痶', '' => '痭', '' => '痵', '' => '痽', '' => '皙', '' => '皵', '' => '盝', '' => '睕', '' => '睟', '' => '睠', '' => '睒', '' => '睖', '' => '睚', '' => '睩', '' => '睧', '' => '睔', '' => '睙', '' => '睭', '' => '矠', '' => '碇', '' => '碚', '' => '碔', '' => '碏', '' => '碄', '' => '碕', '' => '碅', '' => '碆', '' => '碡', '' => '碃', '' => '硹', '' => '碙', '' => '碀', '' => '碖', '' => '硻', '' => '祼', '' => '禂', '' => '祽', '' => '祹', '' => '稑', '' => '稘', '' => '稙', '' => '稒', '' => '稗', '' => '稕', '' => '稢', '' => '稓', '@' => '稛', 'A' => '稐', 'B' => '窣', 'C' => '窢', 'D' => '窞', 'E' => '竫', 'F' => '筦', 'G' => '筤', 'H' => '筭', 'I' => '筴', 'J' => '筩', 'K' => '筲', 'L' => '筥', 'M' => '筳', 'N' => '筱', 'O' => '筰', 'P' => '筡', 'Q' => '筸', 'R' => '筶', 'S' => '筣', 'T' => '粲', 'U' => '粴', 'V' => '粯', 'W' => '綈', 'X' => '綆', 'Y' => '綀', 'Z' => '綍', '[' => '絿', '\\' => '綅', ']' => '絺', '^' => '綎', '_' => '絻', '`' => '綃', 'a' => '絼', 'b' => '綌', 'c' => '綔', 'd' => '綄', 'e' => '絽', 'f' => '綒', 'g' => '罭', 'h' => '罫', 'i' => '罧', 'j' => '罨', 'k' => '罬', 'l' => '羦', 'm' => '羥', 'n' => '羧', 'o' => '翛', 'p' => '翜', 'q' => '耡', 'r' => '腤', 's' => '腠', 't' => '腷', 'u' => '腜', 'v' => '腩', 'w' => '腛', 'x' => '腢', 'y' => '腲', 'z' => '朡', '{' => '腞', '|' => '腶', '}' => '腧', '~' => '腯', 'ߡ' => '腄', 'ߢ' => '腡', 'ߣ' => '舝', 'ߤ' => '艉', 'ߥ' => '艄', 'ߦ' => '艀', 'ߧ' => '艂', 'ߨ' => '艅', 'ߩ' => '蓱', 'ߪ' => '萿', '߫' => '葖', '߬' => '葶', '߭' => '葹', '߮' => '蒏', '߯' => '蒍', '߰' => '葥', '߱' => '葑', '߲' => '葀', '߳' => '蒆', 'ߴ' => '葧', 'ߵ' => '萰', '߶' => '葍', '߷' => '葽', '߸' => '葚', '߹' => '葙', 'ߺ' => '葴', '߻' => '葳', '߼' => '葝', '߽' => '蔇', '߾' => '葞', '߿' => '萷', '' => '萺', '' => '萴', '' => '葺', '' => '葃', '' => '葸', '' => '萲', '' => '葅', '' => '萩', '' => '菙', '' => '葋', '' => '萯', '' => '葂', '' => '萭', '' => '葟', '' => '葰', '' => '萹', '' => '葎', '' => '葌', '' => '葒', '' => '葯', '' => '蓅', '' => '蒎', '' => '萻', '' => '葇', '' => '萶', '' => '萳', '' => '葨', '' => '葾', '' => '葄', '' => '萫', '' => '葠', '' => '葔', '' => '葮', '' => '葐', '' => '蜋', '' => '蜄', '' => '蛷', '' => '蜌', '' => '蛺', '' => '蛖', '' => '蛵', '' => '蝍', '' => '蛸', '' => '蜎', '' => '蜉', '' => '蜁', '' => '蛶', '' => '蜍', '' => '蜅', '' => '裖', '' => '裋', '' => '裍', '' => '裎', '' => '裞', '' => '裛', '' => '裚', '' => '裌', '' => '裐', '' => '覅', '' => '覛', '' => '觟', '' => '觥', '' => '觤', '@' => '觡', 'A' => '觠', 'B' => '觢', 'C' => '觜', 'D' => '触', 'E' => '詶', 'F' => '誆', 'G' => '詿', 'H' => '詡', 'I' => '訿', 'J' => '詷', 'K' => '誂', 'L' => '誄', 'M' => '詵', 'N' => '誃', 'O' => '誁', 'P' => '詴', 'Q' => '詺', 'R' => '谼', 'S' => '豋', 'T' => '豊', 'U' => '豥', 'V' => '豤', 'W' => '豦', 'X' => '貆', 'Y' => '貄', 'Z' => '貅', '[' => '賌', '\\' => '赨', ']' => '赩', '^' => '趑', '_' => '趌', '`' => '趎', 'a' => '趏', 'b' => '趍', 'c' => '趓', 'd' => '趔', 'e' => '趐', 'f' => '趒', 'g' => '跰', 'h' => '跠', 'i' => '跬', 'j' => '跱', 'k' => '跮', 'l' => '跐', 'm' => '跩', 'n' => '跣', 'o' => '跢', 'p' => '跧', 'q' => '跲', 'r' => '跫', 's' => '跴', 't' => '輆', 'u' => '軿', 'v' => '輁', 'w' => '輀', 'x' => '輅', 'y' => '輇', 'z' => '輈', '{' => '輂', '|' => '輋', '}' => '遒', '~' => '逿', '' => '遄', '' => '遉', '' => '逽', '' => '鄐', '' => '鄍', '' => '鄏', '' => '鄑', '' => '鄖', '' => '鄔', '' => '鄋', '' => '鄎', '' => '酮', '' => '酯', '' => '鉈', '' => '鉒', '' => '鈰', '' => '鈺', '' => '鉦', '' => '鈳', '' => '鉥', '' => '鉞', '' => '銃', '' => '鈮', '' => '鉊', '' => '鉆', '' => '鉭', '' => '鉬', '' => '鉏', '' => '鉠', '' => '鉧', '' => '鉯', '' => '鈶', '' => '鉡', '' => '鉰', '' => '鈱', '' => '鉔', '' => '鉣', '' => '鉐', '' => '鉲', '' => '鉎', '' => '鉓', '' => '鉌', '' => '鉖', '' => '鈲', '' => '閟', '' => '閜', '' => '閞', '' => '閛', '' => '隒', '' => '隓', '' => '隑', '' => '隗', '' => '雎', '' => '雺', '' => '雽', '' => '雸', '' => '雵', '' => '靳', '' => '靷', '' => '靸', '' => '靲', '' => '頏', '' => '頍', '' => '頎', '' => '颬', '' => '飶', '' => '飹', '' => '馯', '' => '馲', '' => '馰', '' => '馵', '' => '骭', '' => '骫', '' => '魛', '' => '鳪', '' => '鳭', '' => '鳧', '' => '麀', '' => '黽', '' => '僦', '' => '僔', '' => '僗', '' => '僨', '' => '僳', '' => '僛', '' => '僪', '' => '僝', '' => '僤', '' => '僓', '' => '僬', '' => '僰', '' => '僯', '' => '僣', '' => '僠', '@' => '凘', 'A' => '劀', 'B' => '劁', 'C' => '勩', 'D' => '勫', 'E' => '匰', 'F' => '厬', 'G' => '嘧', 'H' => '嘕', 'I' => '嘌', 'J' => '嘒', 'K' => '嗼', 'L' => '嘏', 'M' => '嘜', 'N' => '嘁', 'O' => '嘓', 'P' => '嘂', 'Q' => '嗺', 'R' => '嘝', 'S' => '嘄', 'T' => '嗿', 'U' => '嗹', 'V' => '墉', 'W' => '塼', 'X' => '墐', 'Y' => '墘', 'Z' => '墆', '[' => '墁', '\\' => '塿', ']' => '塴', '^' => '墋', '_' => '塺', '`' => '墇', 'a' => '墑', 'b' => '墎', 'c' => '塶', 'd' => '墂', 'e' => '墈', 'f' => '塻', 'g' => '墔', 'h' => '墏', 'i' => '壾', 'j' => '奫', 'k' => '嫜', 'l' => '嫮', 'm' => '嫥', 'n' => '嫕', 'o' => '嫪', 'p' => '嫚', 'q' => '嫭', 'r' => '嫫', 's' => '嫳', 't' => '嫢', 'u' => '嫠', 'v' => '嫛', 'w' => '嫬', 'x' => '嫞', 'y' => '嫝', 'z' => '嫙', '{' => '嫨', '|' => '嫟', '}' => '孷', '~' => '寠', '' => '寣', '' => '屣', '' => '嶂', '' => '嶀', '' => '嵽', '' => '嶆', '' => '嵺', '' => '嶁', '' => '嵷', '' => '嶊', '' => '嶉', '' => '嶈', '' => '嵾', '' => '嵼', '' => '嶍', '' => '嵹', '' => '嵿', '' => '幘', '' => '幙', '' => '幓', '' => '廘', '' => '廑', '' => '廗', '' => '廎', '' => '廜', '' => '廕', '' => '廙', '' => '廒', '' => '廔', '' => '彄', '' => '彃', '' => '彯', '' => '徶', '' => '愬', '' => '愨', '' => '慁', '' => '慞', '' => '慱', '' => '慳', '' => '慒', '' => '慓', '' => '慲', '' => '慬', '' => '憀', '' => '慴', '' => '慔', '' => '慺', '' => '慛', '' => '慥', '' => '愻', '' => '慪', '' => '慡', '' => '慖', '' => '戩', '' => '戧', '' => '戫', '' => '搫', '' => '摍', '' => '摛', '' => '摝', '' => '摴', '' => '摶', '' => '摲', '' => '摳', '' => '摽', '' => '摵', '' => '摦', '' => '撦', '' => '摎', '' => '撂', '' => '摞', '' => '摜', '' => '摋', '' => '摓', '' => '摠', '' => '摐', '' => '摿', '' => '搿', '' => '摬', '' => '摫', '' => '摙', '' => '摥', '' => '摷', '' => '敳', '' => '斠', '' => '暡', '' => '暠', '' => '暟', '' => '朅', '' => '朄', '' => '朢', '' => '榱', '' => '榶', '' => '槉', '@' => '榠', 'A' => '槎', 'B' => '榖', 'C' => '榰', 'D' => '榬', 'E' => '榼', 'F' => '榑', 'G' => '榙', 'H' => '榎', 'I' => '榧', 'J' => '榍', 'K' => '榩', 'L' => '榾', 'M' => '榯', 'N' => '榿', 'O' => '槄', 'P' => '榽', 'Q' => '榤', 'R' => '槔', 'S' => '榹', 'T' => '槊', 'U' => '榚', 'V' => '槏', 'W' => '榳', 'X' => '榓', 'Y' => '榪', 'Z' => '榡', '[' => '榞', '\\' => '槙', ']' => '榗', '^' => '榐', '_' => '槂', '`' => '榵', 'a' => '榥', 'b' => '槆', 'c' => '歊', 'd' => '歍', 'e' => '歋', 'f' => '殞', 'g' => '殟', 'h' => '殠', 'i' => '毃', 'j' => '毄', 'k' => '毾', 'l' => '滎', 'm' => '滵', 'n' => '滱', 'o' => '漃', 'p' => '漥', 'q' => '滸', 'r' => '漷', 's' => '滻', 't' => '漮', 'u' => '漉', 'v' => '潎', 'w' => '漙', 'x' => '漚', 'y' => '漧', 'z' => '漘', '{' => '漻', '|' => '漒', '}' => '滭', '~' => '漊', '' => '漶', '' => '潳', '' => '滹', '' => '滮', '' => '漭', '' => '潀', '' => '漰', '' => '漼', '' => '漵', '' => '滫', '' => '漇', '' => '漎', '' => '潃', '' => '漅', '' => '滽', '' => '滶', '' => '漹', '' => '漜', '' => '滼', '' => '漺', '' => '漟', '' => '漍', '' => '漞', '' => '漈', '' => '漡', '' => '熇', '' => '熐', '' => '熉', '' => '熀', '' => '熅', '' => '熂', '' => '熏', '' => '煻', '' => '熆', '' => '熁', '' => '熗', '' => '牄', '' => '牓', '' => '犗', '' => '犕', '' => '犓', '' => '獃', '' => '獍', '' => '獑', '' => '獌', '' => '瑢', '' => '瑳', '' => '瑱', '' => '瑵', '' => '瑲', '' => '瑧', '' => '瑮', '' => '甀', '' => '甂', '' => '甃', '' => '畽', '' => '疐', '' => '瘖', '' => '瘈', '' => '瘌', '' => '瘕', '' => '瘑', '' => '瘊', '' => '瘔', '' => '皸', '' => '瞁', '' => '睼', '' => '瞅', '' => '瞂', '' => '睮', '' => '瞀', '' => '睯', '' => '睾', '' => '瞃', '' => '碲', '' => '碪', '' => '碴', '' => '碭', '' => '碨', '' => '硾', '' => '碫', '' => '碞', '' => '碥', '' => '碠', '' => '碬', '' => '碢', '' => '碤', '' => '禘', '' => '禊', '' => '禋', '' => '禖', '' => '禕', '' => '禔', '' => '禓', '@' => '禗', 'A' => '禈', 'B' => '禒', 'C' => '禐', 'D' => '稫', 'E' => '穊', 'F' => '稰', 'G' => '稯', 'H' => '稨', 'I' => '稦', 'J' => '窨', 'K' => '窫', 'L' => '窬', 'M' => '竮', 'N' => '箈', 'O' => '箜', 'P' => '箊', 'Q' => '箑', 'R' => '箐', 'S' => '箖', 'T' => '箍', 'U' => '箌', 'V' => '箛', 'W' => '箎', 'X' => '箅', 'Y' => '箘', 'Z' => '劄', '[' => '箙', '\\' => '箤', ']' => '箂', '^' => '粻', '_' => '粿', '`' => '粼', 'a' => '粺', 'b' => '綧', 'c' => '綷', 'd' => '緂', 'e' => '綣', 'f' => '綪', 'g' => '緁', 'h' => '緀', 'i' => '緅', 'j' => '綝', 'k' => '緎', 'l' => '緄', 'm' => '緆', 'n' => '緋', 'o' => '緌', 'p' => '綯', 'q' => '綹', 'r' => '綖', 's' => '綼', 't' => '綟', 'u' => '綦', 'v' => '綮', 'w' => '綩', 'x' => '綡', 'y' => '緉', 'z' => '罳', '{' => '翢', '|' => '翣', '}' => '翥', '~' => '翞', '' => '耤', '' => '聝', '' => '聜', '' => '膉', '' => '膆', '' => '膃', '' => '膇', '' => '膍', '' => '膌', '' => '膋', '' => '舕', '' => '蒗', '' => '蒤', '' => '蒡', '' => '蒟', '' => '蒺', '' => '蓎', '' => '蓂', '' => '蒬', '' => '蒮', '' => '蒫', '' => '蒹', '' => '蒴', '' => '蓁', '' => '蓍', '' => '蒪', '' => '蒚', '' => '蒱', '' => '蓐', '' => '蒝', '' => '蒧', '' => '蒻', '' => '蒢', '' => '蒔', '' => '蓇', '' => '蓌', '' => '蒛', '' => '蒩', '' => '蒯', '' => '蒨', '' => '蓖', '' => '蒘', '' => '蒶', '' => '蓏', '' => '蒠', '' => '蓗', '' => '蓔', '' => '蓒', '' => '蓛', '' => '蒰', '' => '蒑', '' => '虡', '' => '蜳', '' => '蜣', '' => '蜨', '' => '蝫', '' => '蝀', '' => '蜮', '' => '蜞', '' => '蜡', '' => '蜙', '' => '蜛', '' => '蝃', '' => '蜬', '' => '蝁', '' => '蜾', '' => '蝆', '' => '蜠', '' => '蜲', '' => '蜪', '' => '蜭', '' => '蜼', '' => '蜒', '' => '蜺', '' => '蜱', '' => '蜵', '' => '蝂', '' => '蜦', '' => '蜧', '' => '蜸', '' => '蜤', '' => '蜚', '' => '蜰', '' => '蜑', '' => '裷', '' => '裧', '' => '裱', '' => '裲', '' => '裺', '' => '裾', '' => '裮', '' => '裼', '' => '裶', '' => '裻', '@' => '裰', 'A' => '裬', 'B' => '裫', 'C' => '覝', 'D' => '覡', 'E' => '覟', 'F' => '覞', 'G' => '觩', 'H' => '觫', 'I' => '觨', 'J' => '誫', 'K' => '誙', 'L' => '誋', 'M' => '誒', 'N' => '誏', 'O' => '誖', 'P' => '谽', 'Q' => '豨', 'R' => '豩', 'S' => '賕', 'T' => '賏', 'U' => '賗', 'V' => '趖', 'W' => '踉', 'X' => '踂', 'Y' => '跿', 'Z' => '踍', '[' => '跽', '\\' => '踊', ']' => '踃', '^' => '踇', '_' => '踆', '`' => '踅', 'a' => '跾', 'b' => '踀', 'c' => '踄', 'd' => '輐', 'e' => '輑', 'f' => '輎', 'g' => '輍', 'h' => '鄣', 'i' => '鄜', 'j' => '鄠', 'k' => '鄢', 'l' => '鄟', 'm' => '鄝', 'n' => '鄚', 'o' => '鄤', 'p' => '鄡', 'q' => '鄛', 'r' => '酺', 's' => '酲', 't' => '酹', 'u' => '酳', 'v' => '銥', 'w' => '銤', 'x' => '鉶', 'y' => '銛', 'z' => '鉺', '{' => '銠', '|' => '銔', '}' => '銪', '~' => '銍', '' => '銦', '' => '銚', '' => '銫', '' => '鉹', '' => '銗', '' => '鉿', '' => '銣', '' => '鋮', '' => '銎', '' => '銂', '' => '銕', '' => '銢', '' => '鉽', '' => '銈', '' => '銡', '' => '銊', '' => '銆', '' => '銌', '' => '銙', '' => '銧', '' => '鉾', '' => '銇', '' => '銩', '' => '銝', '' => '銋', '' => '鈭', '' => '隞', '' => '隡', '' => '雿', '' => '靘', '' => '靽', '' => '靺', '' => '靾', '' => '鞃', '' => '鞀', '' => '鞂', '' => '靻', '' => '鞄', '' => '鞁', '' => '靿', '' => '韎', '' => '韍', '' => '頖', '' => '颭', '' => '颮', '' => '餂', '' => '餀', '' => '餇', '' => '馝', '' => '馜', '' => '駃', '' => '馹', '' => '馻', '' => '馺', '' => '駂', '' => '馽', '' => '駇', '' => '骱', '' => '髣', '' => '髧', '' => '鬾', '' => '鬿', '' => '魠', '' => '魡', '' => '魟', '' => '鳱', '' => '鳲', '' => '鳵', '' => '麧', '' => '僿', '' => '儃', '' => '儰', '' => '僸', '' => '儆', '' => '儇', '' => '僶', '' => '僾', '' => '儋', '' => '儌', '' => '僽', '' => '儊', '' => '劋', '' => '劌', '' => '勱', '' => '勯', '' => '噈', '' => '噂', '' => '噌', '' => '嘵', '' => '噁', '' => '噊', '' => '噉', '' => '噆', '' => '噘', '@' => '噚', 'A' => '噀', 'B' => '嘳', 'C' => '嘽', 'D' => '嘬', 'E' => '嘾', 'F' => '嘸', 'G' => '嘪', 'H' => '嘺', 'I' => '圚', 'J' => '墫', 'K' => '墝', 'L' => '墱', 'M' => '墠', 'N' => '墣', 'O' => '墯', 'P' => '墬', 'Q' => '墥', 'R' => '墡', 'S' => '壿', 'T' => '嫿', 'U' => '嫴', 'V' => '嫽', 'W' => '嫷', 'X' => '嫶', 'Y' => '嬃', 'Z' => '嫸', '[' => '嬂', '\\' => '嫹', ']' => '嬁', '^' => '嬇', '_' => '嬅', '`' => '嬏', 'a' => '屧', 'b' => '嶙', 'c' => '嶗', 'd' => '嶟', 'e' => '嶒', 'f' => '嶢', 'g' => '嶓', 'h' => '嶕', 'i' => '嶠', 'j' => '嶜', 'k' => '嶡', 'l' => '嶚', 'm' => '嶞', 'n' => '幩', 'o' => '幝', 'p' => '幠', 'q' => '幜', 'r' => '緳', 's' => '廛', 't' => '廞', 'u' => '廡', 'v' => '彉', 'w' => '徲', 'x' => '憋', 'y' => '憃', 'z' => '慹', '{' => '憱', '|' => '憰', '}' => '憢', '~' => '憉', '' => '憛', '' => '憓', '' => '憯', '' => '憭', '' => '憟', '' => '憒', '' => '憪', '' => '憡', '' => '憍', '' => '慦', '' => '憳', '' => '戭', '' => '摮', '' => '摰', '' => '撖', '' => '撠', '' => '撅', '' => '撗', '' => '撜', '' => '撏', '' => '撋', '' => '撊', '' => '撌', '' => '撣', '' => '撟', '' => '摨', '' => '撱', '' => '撘', '' => '敶', '' => '敺', '' => '敹', '' => '敻', '' => '斲', '' => '斳', '' => '暵', '' => '暰', '' => '暩', '' => '暲', '' => '暷', '' => '暪', '' => '暯', '' => '樀', '' => '樆', '' => '樗', '' => '槥', '' => '槸', '' => '樕', '' => '槱', '' => '槤', '' => '樠', '' => '槿', '' => '槬', '' => '槢', '' => '樛', '' => '樝', '' => '槾', '' => '樧', '' => '槲', '' => '槮', '' => '樔', '' => '槷', '' => '槧', '' => '橀', '' => '樈', '' => '槦', '' => '槻', '' => '樍', '' => '槼', '' => '槫', '' => '樉', '' => '樄', '' => '樘', '' => '樥', '' => '樏', '' => '槶', '' => '樦', '' => '樇', '' => '槴', '' => '樖', '' => '歑', '' => '殥', '' => '殣', '' => '殢', '' => '殦', '' => '氁', '' => '氀', '' => '毿', '' => '氂', '' => '潁', '' => '漦', '' => '潾', '' => '澇', '' => '濆', '' => '澒', '@' => '澍', 'A' => '澉', 'B' => '澌', 'C' => '潢', 'D' => '潏', 'E' => '澅', 'F' => '潚', 'G' => '澖', 'H' => '潶', 'I' => '潬', 'J' => '澂', 'K' => '潕', 'L' => '潲', 'M' => '潒', 'N' => '潐', 'O' => '潗', 'P' => '澔', 'Q' => '澓', 'R' => '潝', 'S' => '漀', 'T' => '潡', 'U' => '潫', 'V' => '潽', 'W' => '潧', 'X' => '澐', 'Y' => '潓', 'Z' => '澋', '[' => '潩', '\\' => '潿', ']' => '澕', '^' => '潣', '_' => '潷', '`' => '潪', 'a' => '潻', 'b' => '熲', 'c' => '熯', 'd' => '熛', 'e' => '熰', 'f' => '熠', 'g' => '熚', 'h' => '熩', 'i' => '熵', 'j' => '熝', 'k' => '熥', 'l' => '熞', 'm' => '熤', 'n' => '熡', 'o' => '熪', 'p' => '熜', 'q' => '熧', 'r' => '熳', 's' => '犘', 't' => '犚', 'u' => '獘', 'v' => '獒', 'w' => '獞', 'x' => '獟', 'y' => '獠', 'z' => '獝', '{' => '獛', '|' => '獡', '}' => '獚', '~' => '獙', '' => '獢', '' => '璇', '' => '璉', '' => '璊', '' => '璆', '' => '璁', '' => '瑽', '' => '璅', '' => '璈', '' => '瑼', '' => '瑹', '' => '甈', '' => '甇', '' => '畾', '' => '瘥', '' => '瘞', '' => '瘙', '' => '瘝', '' => '瘜', '' => '瘣', '' => '瘚', '' => '瘨', '' => '瘛', '' => '皜', '' => '皝', '' => '皞', '' => '皛', '' => '瞍', '' => '瞏', '' => '瞉', '' => '瞈', '' => '磍', '' => '碻', '' => '磏', '' => '磌', '' => '磑', '' => '磎', '' => '磔', '' => '磈', '' => '磃', '' => '磄', '' => '磉', '' => '禚', '' => '禡', '' => '禠', '' => '禜', '' => '禢', '' => '禛', '' => '歶', '' => '稹', '' => '窲', '' => '窴', '' => '窳', '' => '箷', '' => '篋', '' => '箾', '' => '箬', '' => '篎', '' => '箯', '' => '箹', '' => '篊', '' => '箵', '' => '糅', '' => '糈', '' => '糌', '' => '糋', '' => '緷', '' => '緛', '' => '緪', '' => '緧', '' => '緗', '' => '緡', '' => '縃', '' => '緺', '' => '緦', '' => '緶', '' => '緱', '' => '緰', '' => '緮', '' => '緟', '' => '罶', '' => '羬', '' => '羰', '' => '羭', '' => '翭', '' => '翫', '' => '翪', '' => '翬', '' => '翦', '' => '翨', '' => '聤', '' => '聧', '' => '膣', '' => '膟', '@' => '膞', 'A' => '膕', 'B' => '膢', 'C' => '膙', 'D' => '膗', 'E' => '舖', 'F' => '艏', 'G' => '艓', 'H' => '艒', 'I' => '艐', 'J' => '艎', 'K' => '艑', 'L' => '蔤', 'M' => '蔻', 'N' => '蔏', 'O' => '蔀', 'P' => '蔩', 'Q' => '蔎', 'R' => '蔉', 'S' => '蔍', 'T' => '蔟', 'U' => '蔊', 'V' => '蔧', 'W' => '蔜', 'X' => '蓻', 'Y' => '蔫', 'Z' => '蓺', '[' => '蔈', '\\' => '蔌', ']' => '蓴', '^' => '蔪', '_' => '蓲', '`' => '蔕', 'a' => '蓷', 'b' => '蓫', 'c' => '蓳', 'd' => '蓼', 'e' => '蔒', 'f' => '蓪', 'g' => '蓩', 'h' => '蔖', 'i' => '蓾', 'j' => '蔨', 'k' => '蔝', 'l' => '蔮', 'm' => '蔂', 'n' => '蓽', 'o' => '蔞', 'p' => '蓶', 'q' => '蔱', 'r' => '蔦', 's' => '蓧', 't' => '蓨', 'u' => '蓰', 'v' => '蓯', 'w' => '蓹', 'x' => '蔘', 'y' => '蔠', 'z' => '蔰', '{' => '蔋', '|' => '蔙', '}' => '蔯', '~' => '虢', '' => '蝖', '' => '蝣', '' => '蝤', '' => '蝷', '' => '蟡', '' => '蝳', '' => '蝘', '' => '蝔', '' => '蝛', '' => '蝒', '' => '蝡', '' => '蝚', '' => '蝑', '' => '蝞', '' => '蝭', '' => '蝪', '' => '蝐', '' => '蝎', '' => '蝟', '' => '蝝', '' => '蝯', '' => '蝬', '' => '蝺', '' => '蝮', '' => '蝜', '' => '蝥', '' => '蝏', '' => '蝻', '' => '蝵', '' => '蝢', '' => '蝧', '' => '蝩', '' => '衚', '' => '褅', '' => '褌', '' => '褔', '' => '褋', '' => '褗', '' => '褘', '' => '褙', '' => '褆', '' => '褖', '' => '褑', '' => '褎', '' => '褉', '' => '覢', '' => '覤', '' => '覣', '' => '觭', '' => '觰', '' => '觬', '' => '諏', '' => '諆', '' => '誸', '' => '諓', '' => '諑', '' => '諔', '' => '諕', '' => '誻', '' => '諗', '' => '誾', '' => '諀', '' => '諅', '' => '諘', '' => '諃', '' => '誺', '' => '誽', '' => '諙', '' => '谾', '' => '豍', '' => '貏', '' => '賥', '' => '賟', '' => '賙', '' => '賨', '' => '賚', '' => '賝', '' => '賧', '' => '趠', '' => '趜', '' => '趡', '' => '趛', '' => '踠', '' => '踣', '' => '踥', '' => '踤', '' => '踮', '' => '踕', '' => '踛', '' => '踖', '' => '踑', '' => '踙', '' => '踦', '' => '踧', '@' => '踔', 'A' => '踒', 'B' => '踘', 'C' => '踓', 'D' => '踜', 'E' => '踗', 'F' => '踚', 'G' => '輬', 'H' => '輤', 'I' => '輘', 'J' => '輚', 'K' => '輠', 'L' => '輣', 'M' => '輖', 'N' => '輗', 'O' => '遳', 'P' => '遰', 'Q' => '遯', 'R' => '遧', 'S' => '遫', 'T' => '鄯', 'U' => '鄫', 'V' => '鄩', 'W' => '鄪', 'X' => '鄲', 'Y' => '鄦', 'Z' => '鄮', '[' => '醅', '\\' => '醆', ']' => '醊', '^' => '醁', '_' => '醂', '`' => '醄', 'a' => '醀', 'b' => '鋐', 'c' => '鋃', 'd' => '鋄', 'e' => '鋀', 'f' => '鋙', 'g' => '銶', 'h' => '鋏', 'i' => '鋱', 'j' => '鋟', 'k' => '鋘', 'l' => '鋩', 'm' => '鋗', 'n' => '鋝', 'o' => '鋌', 'p' => '鋯', 'q' => '鋂', 'r' => '鋨', 's' => '鋊', 't' => '鋈', 'u' => '鋎', 'v' => '鋦', 'w' => '鋍', 'x' => '鋕', 'y' => '鋉', 'z' => '鋠', '{' => '鋞', '|' => '鋧', '}' => '鋑', '~' => '鋓', '' => '銵', '' => '鋡', '' => '鋆', '' => '銴', '' => '镼', '' => '閬', '' => '閫', '' => '閮', '' => '閰', '' => '隤', '' => '隢', '' => '雓', '' => '霅', '' => '霈', '' => '霂', '' => '靚', '' => '鞊', '' => '鞎', '' => '鞈', '' => '韐', '' => '韏', '' => '頞', '' => '頝', '' => '頦', '' => '頩', '' => '頨', '' => '頠', '' => '頛', '' => '頧', '' => '颲', '' => '餈', '' => '飺', '' => '餑', '' => '餔', '' => '餖', '' => '餗', '' => '餕', '' => '駜', '' => '駍', '' => '駏', '' => '駓', '' => '駔', '' => '駎', '' => '駉', '' => '駖', '' => '駘', '' => '駋', '' => '駗', '' => '駌', '' => '骳', '' => '髬', '' => '髫', '' => '髳', '' => '髲', '' => '髱', '' => '魆', '' => '魃', '' => '魧', '' => '魴', '' => '魱', '' => '魦', '' => '魶', '' => '魵', '' => '魰', '' => '魨', '' => '魤', '' => '魬', '' => '鳼', '' => '鳺', '' => '鳽', '' => '鳿', '' => '鳷', '' => '鴇', '' => '鴀', '' => '鳹', '' => '鳻', '' => '鴈', '' => '鴅', '' => '鴄', '' => '麃', '' => '黓', '' => '鼏', '' => '鼐', '' => '儜', '' => '儓', '' => '儗', '' => '儚', '' => '儑', '' => '凞', '' => '匴', '' => '叡', '' => '噰', '' => '噠', '' => '噮', '@' => '噳', 'A' => '噦', 'B' => '噣', 'C' => '噭', 'D' => '噲', 'E' => '噞', 'F' => '噷', 'G' => '圜', 'H' => '圛', 'I' => '壈', 'J' => '墽', 'K' => '壉', 'L' => '墿', 'M' => '墺', 'N' => '壂', 'O' => '墼', 'P' => '壆', 'Q' => '嬗', 'R' => '嬙', 'S' => '嬛', 'T' => '嬡', 'U' => '嬔', 'V' => '嬓', 'W' => '嬐', 'X' => '嬖', 'Y' => '嬨', 'Z' => '嬚', '[' => '嬠', '\\' => '嬞', ']' => '寯', '^' => '嶬', '_' => '嶱', '`' => '嶩', 'a' => '嶧', 'b' => '嶵', 'c' => '嶰', 'd' => '嶮', 'e' => '嶪', 'f' => '嶨', 'g' => '嶲', 'h' => '嶭', 'i' => '嶯', 'j' => '嶴', 'k' => '幧', 'l' => '幨', 'm' => '幦', 'n' => '幯', 'o' => '廩', 'p' => '廧', 'q' => '廦', 'r' => '廨', 's' => '廥', 't' => '彋', 'u' => '徼', 'v' => '憝', 'w' => '憨', 'x' => '憖', 'y' => '懅', 'z' => '憴', '{' => '懆', '|' => '懁', '}' => '懌', '~' => '憺', '' => '憿', '' => '憸', '' => '憌', '' => '擗', '' => '擖', '' => '擐', '' => '擏', '' => '擉', '' => '撽', '' => '撉', '' => '擃', '' => '擛', '' => '擳', '' => '擙', '' => '攳', '' => '敿', '' => '敼', '' => '斢', '' => '曈', '' => '暾', '' => '曀', '' => '曊', '' => '曋', '' => '曏', '' => '暽', '' => '暻', '' => '暺', '' => '曌', '' => '朣', '' => '樴', '' => '橦', '' => '橉', '' => '橧', '' => '樲', '' => '橨', '' => '樾', '' => '橝', '' => '橭', '' => '橶', '' => '橛', '' => '橑', '' => '樨', '' => '橚', '' => '樻', '' => '樿', '' => '橁', '' => '橪', '' => '橤', '' => '橐', '' => '橏', '' => '橔', '' => '橯', '' => '橩', '' => '橠', '' => '樼', '' => '橞', '' => '橖', '' => '橕', '' => '橍', '' => '橎', '' => '橆', '' => '歕', '' => '歔', '' => '歖', '' => '殧', '' => '殪', '' => '殫', '' => '毈', '' => '毇', '' => '氄', '' => '氃', '' => '氆', '' => '澭', '' => '濋', '' => '澣', '' => '濇', '' => '澼', '' => '濎', '' => '濈', '' => '潞', '' => '濄', '' => '澽', '' => '澞', '' => '濊', '' => '澨', '' => '瀄', '' => '澥', '' => '澮', '' => '澺', '' => '澬', '' => '澪', '' => '濏', '' => '澿', '' => '澸', '@' => '澢', 'A' => '濉', 'B' => '澫', 'C' => '濍', 'D' => '澯', 'E' => '澲', 'F' => '澰', 'G' => '燅', 'H' => '燂', 'I' => '熿', 'J' => '熸', 'K' => '燖', 'L' => '燀', 'M' => '燁', 'N' => '燋', 'O' => '燔', 'P' => '燊', 'Q' => '燇', 'R' => '燏', 'S' => '熽', 'T' => '燘', 'U' => '熼', 'V' => '燆', 'W' => '燚', 'X' => '燛', 'Y' => '犝', 'Z' => '犞', '[' => '獩', '\\' => '獦', ']' => '獧', '^' => '獬', '_' => '獥', '`' => '獫', 'a' => '獪', 'b' => '瑿', 'c' => '璚', 'd' => '璠', 'e' => '璔', 'f' => '璒', 'g' => '璕', 'h' => '璡', 'i' => '甋', 'j' => '疀', 'k' => '瘯', 'l' => '瘭', 'm' => '瘱', 'n' => '瘽', 'o' => '瘳', 'p' => '瘼', 'q' => '瘵', 'r' => '瘲', 's' => '瘰', 't' => '皻', 'u' => '盦', 'v' => '瞚', 'w' => '瞝', 'x' => '瞡', 'y' => '瞜', 'z' => '瞛', '{' => '瞢', '|' => '瞣', '}' => '瞕', '~' => '瞙', '' => '瞗', '' => '磝', '' => '磩', '' => '磥', '' => '磪', '' => '磞', '' => '磣', '' => '磛', '' => '磡', '' => '磢', '' => '磭', '' => '磟', '' => '磠', '' => '禤', '' => '穄', '' => '穈', '' => '穇', '' => '窶', '' => '窸', '' => '窵', '' => '窱', '' => '窷', '' => '篞', '' => '篣', '' => '篧', '' => '篝', '' => '篕', '' => '篥', '' => '篚', '' => '篨', '' => '篹', '' => '篔', '' => '篪', '' => '篢', '' => '篜', '' => '篫', '' => '篘', '' => '篟', '' => '糒', '' => '糔', '' => '糗', '' => '糐', '' => '糑', '' => '縒', '' => '縡', '' => '縗', '' => '縌', '' => '縟', '' => '縠', '' => '縓', '' => '縎', '' => '縜', '' => '縕', '' => '縚', '' => '縢', '' => '縋', '' => '縏', '' => '縖', '' => '縍', '' => '縔', '' => '縥', '' => '縤', '' => '罃', '' => '罻', '' => '罼', '' => '罺', '' => '羱', '' => '翯', '' => '耪', '' => '耩', '' => '聬', '' => '膱', '' => '膦', '' => '膮', '' => '膹', '' => '膵', '' => '膫', '' => '膰', '' => '膬', '' => '膴', '' => '膲', '' => '膷', '' => '膧', '' => '臲', '' => '艕', '' => '艖', '' => '艗', '' => '蕖', '' => '蕅', '' => '蕫', '' => '蕍', '' => '蕓', '' => '蕡', '' => '蕘', '@' => '蕀', 'A' => '蕆', 'B' => '蕤', 'C' => '蕁', 'D' => '蕢', 'E' => '蕄', 'F' => '蕑', 'G' => '蕇', 'H' => '蕣', 'I' => '蔾', 'J' => '蕛', 'K' => '蕱', 'L' => '蕎', 'M' => '蕮', 'N' => '蕵', 'O' => '蕕', 'P' => '蕧', 'Q' => '蕠', 'R' => '薌', 'S' => '蕦', 'T' => '蕝', 'U' => '蕔', 'V' => '蕥', 'W' => '蕬', 'X' => '虣', 'Y' => '虥', 'Z' => '虤', '[' => '螛', '\\' => '螏', ']' => '螗', '^' => '螓', '_' => '螒', '`' => '螈', 'a' => '螁', 'b' => '螖', 'c' => '螘', 'd' => '蝹', 'e' => '螇', 'f' => '螣', 'g' => '螅', 'h' => '螐', 'i' => '螑', 'j' => '螝', 'k' => '螄', 'l' => '螔', 'm' => '螜', 'n' => '螚', 'o' => '螉', 'p' => '褞', 'q' => '褦', 'r' => '褰', 's' => '褭', 't' => '褮', 'u' => '褧', 'v' => '褱', 'w' => '褢', 'x' => '褩', 'y' => '褣', 'z' => '褯', '{' => '褬', '|' => '褟', '}' => '觱', '~' => '諠', '' => '諢', '' => '諲', '' => '諴', '' => '諵', '' => '諝', '' => '謔', '' => '諤', '' => '諟', '' => '諰', '' => '諈', '' => '諞', '' => '諡', '' => '諨', '' => '諿', '' => '諯', '' => '諻', '' => '貑', '' => '貒', '' => '貐', '' => '賵', '' => '賮', '' => '賱', '' => '賰', '' => '賳', '' => '赬', '' => '赮', '' => '趥', '' => '趧', '' => '踳', '' => '踾', '' => '踸', '' => '蹀', '' => '蹅', '' => '踶', '' => '踼', '' => '踽', '' => '蹁', '' => '踰', '' => '踿', '' => '躽', '' => '輶', '' => '輮', '' => '輵', '' => '輲', '' => '輹', '' => '輷', '' => '輴', '' => '遶', '' => '遹', '' => '遻', '' => '邆', '' => '郺', '' => '鄳', '' => '鄵', '' => '鄶', '' => '醓', '' => '醐', '' => '醑', '' => '醍', '' => '醏', '' => '錧', '' => '錞', '' => '錈', '' => '錟', '' => '錆', '' => '錏', '' => '鍺', '' => '錸', '' => '錼', '' => '錛', '' => '錣', '' => '錒', '' => '錁', '' => '鍆', '' => '錭', '' => '錎', '' => '錍', '' => '鋋', '' => '錝', '' => '鋺', '' => '錥', '' => '錓', '' => '鋹', '' => '鋷', '' => '錴', '' => '錂', '' => '錤', '' => '鋿', '' => '錩', '' => '錹', '' => '錵', '' => '錪', '' => '錔', '' => '錌', '@' => '錋', 'A' => '鋾', 'B' => '錉', 'C' => '錀', 'D' => '鋻', 'E' => '錖', 'F' => '閼', 'G' => '闍', 'H' => '閾', 'I' => '閹', 'J' => '閺', 'K' => '閶', 'L' => '閿', 'M' => '閵', 'N' => '閽', 'O' => '隩', 'P' => '雔', 'Q' => '霋', 'R' => '霒', 'S' => '霐', 'T' => '鞙', 'U' => '鞗', 'V' => '鞔', 'W' => '韰', 'X' => '韸', 'Y' => '頵', 'Z' => '頯', '[' => '頲', '\\' => '餤', ']' => '餟', '^' => '餧', '_' => '餩', '`' => '馞', 'a' => '駮', 'b' => '駬', 'c' => '駥', 'd' => '駤', 'e' => '駰', 'f' => '駣', 'g' => '駪', 'h' => '駩', 'i' => '駧', 'j' => '骹', 'k' => '骿', 'l' => '骴', 'm' => '骻', 'n' => '髶', 'o' => '髺', 'p' => '髹', 'q' => '髷', 'r' => '鬳', 's' => '鮀', 't' => '鮅', 'u' => '鮇', 'v' => '魼', 'w' => '魾', 'x' => '魻', 'y' => '鮂', 'z' => '鮓', '{' => '鮒', '|' => '鮐', '}' => '魺', '~' => '鮕', '' => '魽', '' => '鮈', '' => '鴥', '' => '鴗', '' => '鴠', '' => '鴞', '' => '鴔', '' => '鴩', '' => '鴝', '' => '鴘', '' => '鴢', '' => '鴐', '' => '鴙', '' => '鴟', '' => '麈', '' => '麆', '' => '麇', '' => '麮', '' => '麭', '' => '黕', '' => '黖', '' => '黺', '' => '鼒', '' => '鼽', '' => '儦', '' => '儥', '' => '儢', '' => '儤', '' => '儠', '' => '儩', '' => '勴', '' => '嚓', '' => '嚌', '' => '嚍', '' => '嚆', '' => '嚄', '' => '嚃', '' => '噾', '' => '嚂', '' => '噿', '' => '嚁', '' => '壖', '' => '壔', '' => '壏', '' => '壒', '' => '嬭', '' => '嬥', '' => '嬲', '' => '嬣', '' => '嬬', '' => '嬧', '' => '嬦', '' => '嬯', '' => '嬮', '' => '孻', '' => '寱', '' => '寲', '' => '嶷', '' => '幬', '' => '幪', '' => '徾', '' => '徻', '' => '懃', '' => '憵', '' => '憼', '' => '懧', '' => '懠', '' => '懥', '' => '懤', '' => '懨', '' => '懞', '' => '擯', '' => '擩', '' => '擣', '' => '擫', '' => '擤', '' => '擨', '' => '斁', '' => '斀', '' => '斶', '' => '旚', '' => '曒', '' => '檍', '' => '檖', '' => '檁', '' => '檥', '' => '檉', '' => '檟', '' => '檛', '' => '檡', '' => '檞', '' => '檇', '' => '檓', '' => '檎', '@' => '檕', 'A' => '檃', 'B' => '檨', 'C' => '檤', 'D' => '檑', 'E' => '橿', 'F' => '檦', 'G' => '檚', 'H' => '檅', 'I' => '檌', 'J' => '檒', 'K' => '歛', 'L' => '殭', 'M' => '氉', 'N' => '濌', 'O' => '澩', 'P' => '濴', 'Q' => '濔', 'R' => '濣', 'S' => '濜', 'T' => '濭', 'U' => '濧', 'V' => '濦', 'W' => '濞', 'X' => '濲', 'Y' => '濝', 'Z' => '濢', '[' => '濨', '\\' => '燡', ']' => '燱', '^' => '燨', '_' => '燲', '`' => '燤', 'a' => '燰', 'b' => '燢', 'c' => '獳', 'd' => '獮', 'e' => '獯', 'f' => '璗', 'g' => '璲', 'h' => '璫', 'i' => '璐', 'j' => '璪', 'k' => '璭', 'l' => '璱', 'm' => '璥', 'n' => '璯', 'o' => '甐', 'p' => '甑', 'q' => '甒', 'r' => '甏', 's' => '疄', 't' => '癃', 'u' => '癈', 'v' => '癉', 'w' => '癇', 'x' => '皤', 'y' => '盩', 'z' => '瞵', '{' => '瞫', '|' => '瞲', '}' => '瞷', '~' => '瞶', '' => '瞴', '' => '瞱', '' => '瞨', '' => '矰', '' => '磳', '' => '磽', '' => '礂', '' => '磻', '' => '磼', '' => '磲', '' => '礅', '' => '磹', '' => '磾', '' => '礄', '' => '禫', '' => '禨', '' => '穜', '' => '穛', '' => '穖', '' => '穘', '' => '穔', '' => '穚', '' => '窾', '' => '竀', '' => '竁', '' => '簅', '' => '簏', '' => '篲', '' => '簀', '' => '篿', '' => '篻', '' => '簎', '' => '篴', '' => '簋', '' => '篳', '' => '簂', '' => '簉', '' => '簃', '' => '簁', '' => '篸', '' => '篽', '' => '簆', '' => '篰', '' => '篱', '' => '簐', '' => '簊', '' => '糨', '' => '縭', '' => '縼', '' => '繂', '' => '縳', '' => '顈', '' => '縸', '' => '縪', '' => '繉', '' => '繀', '' => '繇', '' => '縩', '' => '繌', '' => '縰', '' => '縻', '' => '縶', '' => '繄', '' => '縺', '' => '罅', '' => '罿', '' => '罾', '' => '罽', '' => '翴', '' => '翲', '' => '耬', '' => '膻', '' => '臄', '' => '臌', '' => '臊', '' => '臅', '' => '臇', '' => '膼', '' => '臩', '' => '艛', '' => '艚', '' => '艜', '' => '薃', '' => '薀', '' => '薏', '' => '薧', '' => '薕', '' => '薠', '' => '薋', '' => '薣', '' => '蕻', '' => '薤', '' => '薚', '' => '薞', '@' => '蕷', 'A' => '蕼', 'B' => '薉', 'C' => '薡', 'D' => '蕺', 'E' => '蕸', 'F' => '蕗', 'G' => '薎', 'H' => '薖', 'I' => '薆', 'J' => '薍', 'K' => '薙', 'L' => '薝', 'M' => '薁', 'N' => '薢', 'O' => '薂', 'P' => '薈', 'Q' => '薅', 'R' => '蕹', 'S' => '蕶', 'T' => '薘', 'U' => '薐', 'V' => '薟', 'W' => '虨', 'X' => '螾', 'Y' => '螪', 'Z' => '螭', '[' => '蟅', '\\' => '螰', ']' => '螬', '^' => '螹', '_' => '螵', '`' => '螼', 'a' => '螮', 'b' => '蟉', 'c' => '蟃', 'd' => '蟂', 'e' => '蟌', 'f' => '螷', 'g' => '螯', 'h' => '蟄', 'i' => '蟊', 'j' => '螴', 'k' => '螶', 'l' => '螿', 'm' => '螸', 'n' => '螽', 'o' => '蟞', 'p' => '螲', 'q' => '褵', 'r' => '褳', 's' => '褼', 't' => '褾', 'u' => '襁', 'v' => '襒', 'w' => '褷', 'x' => '襂', 'y' => '覭', 'z' => '覯', '{' => '覮', '|' => '觲', '}' => '觳', '~' => '謞', '' => '謘', '' => '謖', '' => '謑', '' => '謅', '' => '謋', '' => '謢', '' => '謏', '' => '謒', '' => '謕', '' => '謇', '' => '謍', '' => '謈', '' => '謆', '' => '謜', '' => '謓', '' => '謚', '' => '豏', '' => '豰', '' => '豲', '' => '豱', '' => '豯', '' => '貕', '' => '貔', '' => '賹', '' => '赯', '' => '蹎', '' => '蹍', '' => '蹓', '' => '蹐', '' => '蹌', '' => '蹇', '' => '轃', '' => '轀', '' => '邅', '' => '遾', '' => '鄸', '' => '醚', '' => '醢', '' => '醛', '' => '醙', '' => '醟', '' => '醡', '' => '醝', '' => '醠', '' => '鎡', '' => '鎃', '' => '鎯', '' => '鍤', '' => '鍖', '' => '鍇', '' => '鍼', '' => '鍘', '' => '鍜', '' => '鍶', '' => '鍉', '' => '鍐', '' => '鍑', '' => '鍠', '' => '鍭', '' => '鎏', '' => '鍌', '' => '鍪', '' => '鍹', '' => '鍗', '' => '鍕', '' => '鍒', '' => '鍏', '' => '鍱', '' => '鍷', '' => '鍻', '' => '鍡', '' => '鍞', '' => '鍣', '' => '鍧', '' => '鎀', '' => '鍎', '' => '鍙', '' => '闇', '' => '闀', '' => '闉', '' => '闃', '' => '闅', '' => '閷', '' => '隮', '' => '隰', '' => '隬', '' => '霠', '' => '霟', '' => '霘', '' => '霝', '' => '霙', '' => '鞚', '' => '鞡', '' => '鞜', '@' => '鞞', 'A' => '鞝', 'B' => '韕', 'C' => '韔', 'D' => '韱', 'E' => '顁', 'F' => '顄', 'G' => '顊', 'H' => '顉', 'I' => '顅', 'J' => '顃', 'K' => '餥', 'L' => '餫', 'M' => '餬', 'N' => '餪', 'O' => '餳', 'P' => '餲', 'Q' => '餯', 'R' => '餭', 'S' => '餱', 'T' => '餰', 'U' => '馘', 'V' => '馣', 'W' => '馡', 'X' => '騂', 'Y' => '駺', 'Z' => '駴', '[' => '駷', '\\' => '駹', ']' => '駸', '^' => '駶', '_' => '駻', '`' => '駽', 'a' => '駾', 'b' => '駼', 'c' => '騃', 'd' => '骾', 'e' => '髾', 'f' => '髽', 'g' => '鬁', 'h' => '髼', 'i' => '魈', 'j' => '鮚', 'k' => '鮨', 'l' => '鮞', 'm' => '鮛', 'n' => '鮦', 'o' => '鮡', 'p' => '鮥', 'q' => '鮤', 'r' => '鮆', 's' => '鮢', 't' => '鮠', 'u' => '鮯', 'v' => '鴳', 'w' => '鵁', 'x' => '鵧', 'y' => '鴶', 'z' => '鴮', '{' => '鴯', '|' => '鴱', '}' => '鴸', '~' => '鴰', '' => '鵅', '' => '鵂', '' => '鵃', '' => '鴾', '' => '鴷', '' => '鵀', '' => '鴽', '' => '翵', '' => '鴭', '' => '麊', '' => '麉', '' => '麍', '' => '麰', '' => '黈', '' => '黚', '' => '黻', '' => '黿', '' => '鼤', '' => '鼣', '' => '鼢', '' => '齔', '' => '龠', '' => '儱', '' => '儭', '' => '儮', '' => '嚘', '' => '嚜', '' => '嚗', '' => '嚚', '' => '嚝', '' => '嚙', '' => '奰', '' => '嬼', '' => '屩', '' => '屪', '' => '巀', '' => '幭', '' => '幮', '' => '懘', '' => '懟', '' => '懭', '' => '懮', '' => '懱', '' => '懪', '' => '懰', '' => '懫', '' => '懖', '' => '懩', '' => '擿', '' => '攄', '' => '擽', '' => '擸', '' => '攁', '' => '攃', '' => '擼', '' => '斔', '' => '旛', '' => '曚', '' => '曛', '' => '曘', '' => '櫅', '' => '檹', '' => '檽', '' => '櫡', '' => '櫆', '' => '檺', '' => '檶', '' => '檷', '' => '櫇', '' => '檴', '' => '檭', '' => '歞', '' => '毉', '' => '氋', '' => '瀇', '' => '瀌', '' => '瀍', '' => '瀁', '' => '瀅', '' => '瀔', '' => '瀎', '' => '濿', '' => '瀀', '' => '濻', '' => '瀦', '' => '濼', '' => '濷', '' => '瀊', '' => '爁', '' => '燿', '' => '燹', '' => '爃', '' => '燽', '' => '獶', '@' => '璸', 'A' => '瓀', 'B' => '璵', 'C' => '瓁', 'D' => '璾', 'E' => '璶', 'F' => '璻', 'G' => '瓂', 'H' => '甔', 'I' => '甓', 'J' => '癜', 'K' => '癤', 'L' => '癙', 'M' => '癐', 'N' => '癓', 'O' => '癗', 'P' => '癚', 'Q' => '皦', 'R' => '皽', 'S' => '盬', 'T' => '矂', 'U' => '瞺', 'V' => '磿', 'W' => '礌', 'X' => '礓', 'Y' => '礔', 'Z' => '礉', '[' => '礐', '\\' => '礒', ']' => '礑', '^' => '禭', '_' => '禬', '`' => '穟', 'a' => '簜', 'b' => '簩', 'c' => '簙', 'd' => '簠', 'e' => '簟', 'f' => '簭', 'g' => '簝', 'h' => '簦', 'i' => '簨', 'j' => '簢', 'k' => '簥', 'l' => '簰', 'm' => '繜', 'n' => '繐', 'o' => '繖', 'p' => '繣', 'q' => '繘', 'r' => '繢', 's' => '繟', 't' => '繑', 'u' => '繠', 'v' => '繗', 'w' => '繓', 'x' => '羵', 'y' => '羳', 'z' => '翷', '{' => '翸', '|' => '聵', '}' => '臑', '~' => '臒', '' => '臐', '' => '艟', '' => '艞', '' => '薴', '' => '藆', '' => '藀', '' => '藃', '' => '藂', '' => '薳', '' => '薵', '' => '薽', '' => '藇', '' => '藄', '' => '薿', '' => '藋', '' => '藎', '' => '藈', '' => '藅', '' => '薱', '' => '薶', '' => '藒', '' => '蘤', '' => '薸', '' => '薷', '' => '薾', '' => '虩', '' => '蟧', '' => '蟦', '' => '蟢', '' => '蟛', '' => '蟫', '' => '蟪', '' => '蟥', '' => '蟟', '' => '蟳', '' => '蟤', '' => '蟔', '' => '蟜', '' => '蟓', '' => '蟭', '' => '蟘', '' => '蟣', '' => '螤', '' => '蟗', '' => '蟙', '' => '蠁', '' => '蟴', '' => '蟨', '' => '蟝', '' => '襓', '' => '襋', '' => '襏', '' => '襌', '' => '襆', '' => '襐', '' => '襑', '' => '襉', '' => '謪', '' => '謧', '' => '謣', '' => '謳', '' => '謰', '' => '謵', '' => '譇', '' => '謯', '' => '謼', '' => '謾', '' => '謱', '' => '謥', '' => '謷', '' => '謦', '' => '謶', '' => '謮', '' => '謤', '' => '謻', '' => '謽', '' => '謺', '' => '豂', '' => '豵', '' => '貙', '' => '貘', '' => '貗', '' => '賾', '' => '贄', '' => '贂', '' => '贀', '' => '蹜', '' => '蹢', '' => '蹠', '' => '蹗', '' => '蹖', '' => '蹞', '' => '蹥', '' => '蹧', '@' => '蹛', 'A' => '蹚', 'B' => '蹡', 'C' => '蹝', 'D' => '蹩', 'E' => '蹔', 'F' => '轆', 'G' => '轇', 'H' => '轈', 'I' => '轋', 'J' => '鄨', 'K' => '鄺', 'L' => '鄻', 'M' => '鄾', 'N' => '醨', 'O' => '醥', 'P' => '醧', 'Q' => '醯', 'R' => '醪', 'S' => '鎵', 'T' => '鎌', 'U' => '鎒', 'V' => '鎷', 'W' => '鎛', 'X' => '鎝', 'Y' => '鎉', 'Z' => '鎧', '[' => '鎎', '\\' => '鎪', ']' => '鎞', '^' => '鎦', '_' => '鎕', '`' => '鎈', 'a' => '鎙', 'b' => '鎟', 'c' => '鎍', 'd' => '鎱', 'e' => '鎑', 'f' => '鎲', 'g' => '鎤', 'h' => '鎨', 'i' => '鎴', 'j' => '鎣', 'k' => '鎥', 'l' => '闒', 'm' => '闓', 'n' => '闑', 'o' => '隳', 'p' => '雗', 'q' => '雚', 'r' => '巂', 's' => '雟', 't' => '雘', 'u' => '雝', 'v' => '霣', 'w' => '霢', 'x' => '霥', 'y' => '鞬', 'z' => '鞮', '{' => '鞨', '|' => '鞫', '}' => '鞤', '~' => '鞪', '' => '鞢', '' => '鞥', '' => '韗', '' => '韙', '' => '韖', '' => '韘', '' => '韺', '' => '顐', '' => '顑', '' => '顒', '' => '颸', '' => '饁', '' => '餼', '' => '餺', '' => '騏', '' => '騋', '' => '騉', '' => '騍', '' => '騄', '' => '騑', '' => '騊', '' => '騅', '' => '騇', '' => '騆', '' => '髀', '' => '髜', '' => '鬈', '' => '鬄', '' => '鬅', '' => '鬩', '' => '鬵', '' => '魊', '' => '魌', '' => '魋', '' => '鯇', '' => '鯆', '' => '鯃', '' => '鮿', '' => '鯁', '' => '鮵', '' => '鮸', '' => '鯓', '' => '鮶', '' => '鯄', '' => '鮹', '' => '鮽', '' => '鵜', '' => '鵓', '' => '鵏', '' => '鵊', '' => '鵛', '' => '鵋', '' => '鵙', '' => '鵖', '' => '鵌', '' => '鵗', '' => '鵒', '' => '鵔', '' => '鵟', '' => '鵘', '' => '鵚', '' => '麎', '' => '麌', '' => '黟', '' => '鼁', '' => '鼀', '' => '鼖', '' => '鼥', '' => '鼫', '' => '鼪', '' => '鼩', '' => '鼨', '' => '齌', '' => '齕', '' => '儴', '' => '儵', '' => '劖', '' => '勷', '' => '厴', '' => '嚫', '' => '嚭', '' => '嚦', '' => '嚧', '' => '嚪', '' => '嚬', '' => '壚', '' => '壝', '' => '壛', '' => '夒', '' => '嬽', '' => '嬾', '' => '嬿', '' => '巃', '' => '幰', '@' => '徿', 'A' => '懻', 'B' => '攇', 'C' => '攐', 'D' => '攍', 'E' => '攉', 'F' => '攌', 'G' => '攎', 'H' => '斄', 'I' => '旞', 'J' => '旝', 'K' => '曞', 'L' => '櫧', 'M' => '櫠', 'N' => '櫌', 'O' => '櫑', 'P' => '櫙', 'Q' => '櫋', 'R' => '櫟', 'S' => '櫜', 'T' => '櫐', 'U' => '櫫', 'V' => '櫏', 'W' => '櫍', 'X' => '櫞', 'Y' => '歠', 'Z' => '殰', '[' => '氌', '\\' => '瀙', ']' => '瀧', '^' => '瀠', '_' => '瀖', '`' => '瀫', 'a' => '瀡', 'b' => '瀢', 'c' => '瀣', 'd' => '瀩', 'e' => '瀗', 'f' => '瀤', 'g' => '瀜', 'h' => '瀪', 'i' => '爌', 'j' => '爊', 'k' => '爇', 'l' => '爂', 'm' => '爅', 'n' => '犥', 'o' => '犦', 'p' => '犤', 'q' => '犣', 'r' => '犡', 's' => '瓋', 't' => '瓅', 'u' => '璷', 'v' => '瓃', 'w' => '甖', 'x' => '癠', 'y' => '矉', 'z' => '矊', '{' => '矄', '|' => '矱', '}' => '礝', '~' => '礛', '' => '礡', '' => '礜', '' => '礗', '' => '礞', '' => '禰', '' => '穧', '' => '穨', '' => '簳', '' => '簼', '' => '簹', '' => '簬', '' => '簻', '' => '糬', '' => '糪', '' => '繶', '' => '繵', '' => '繸', '' => '繰', '' => '繷', '' => '繯', '' => '繺', '' => '繲', '' => '繴', '' => '繨', '' => '罋', '' => '罊', '' => '羃', '' => '羆', '' => '羷', '' => '翽', '' => '翾', '' => '聸', '' => '臗', '' => '臕', '' => '艤', '' => '艡', '' => '艣', '' => '藫', '' => '藱', '' => '藭', '' => '藙', '' => '藡', '' => '藨', '' => '藚', '' => '藗', '' => '藬', '' => '藲', '' => '藸', '' => '藘', '' => '藟', '' => '藣', '' => '藜', '' => '藑', '' => '藰', '' => '藦', '' => '藯', '' => '藞', '' => '藢', '' => '蠀', '' => '蟺', '' => '蠃', '' => '蟶', '' => '蟷', '' => '蠉', '' => '蠌', '' => '蠋', '' => '蠆', '' => '蟼', '' => '蠈', '' => '蟿', '' => '蠊', '' => '蠂', '' => '襢', '' => '襚', '' => '襛', '' => '襗', '' => '襡', '' => '襜', '' => '襘', '' => '襝', '' => '襙', '' => '覈', '' => '覷', '' => '覶', '' => '觶', '' => '譐', '' => '譈', '' => '譊', '' => '譀', '' => '譓', '' => '譖', '' => '譔', '' => '譋', '' => '譕', '@' => '譑', 'A' => '譂', 'B' => '譒', 'C' => '譗', 'D' => '豃', 'E' => '豷', 'F' => '豶', 'G' => '貚', 'H' => '贆', 'I' => '贇', 'J' => '贉', 'K' => '趬', 'L' => '趪', 'M' => '趭', 'N' => '趫', 'O' => '蹭', 'P' => '蹸', 'Q' => '蹳', 'R' => '蹪', 'S' => '蹯', 'T' => '蹻', 'U' => '軂', 'V' => '轒', 'W' => '轑', 'X' => '轏', 'Y' => '轐', 'Z' => '轓', '[' => '辴', '\\' => '酀', ']' => '鄿', '^' => '醰', '_' => '醭', '`' => '鏞', 'a' => '鏇', 'b' => '鏏', 'c' => '鏂', 'd' => '鏚', 'e' => '鏐', 'f' => '鏹', 'g' => '鏬', 'h' => '鏌', 'i' => '鏙', 'j' => '鎩', 'k' => '鏦', 'l' => '鏊', 'm' => '鏔', 'n' => '鏮', 'o' => '鏣', 'p' => '鏕', 'q' => '鏄', 'r' => '鏎', 's' => '鏀', 't' => '鏒', 'u' => '鏧', 'v' => '镽', 'w' => '闚', 'x' => '闛', 'y' => '雡', 'z' => '霩', '{' => '霫', '|' => '霬', '}' => '霨', '~' => '霦', '' => '鞳', '' => '鞷', '' => '鞶', '' => '韝', '' => '韞', '' => '韟', '' => '顜', '' => '顙', '' => '顝', '' => '顗', '' => '颿', '' => '颽', '' => '颻', '' => '颾', '' => '饈', '' => '饇', '' => '饃', '' => '馦', '' => '馧', '' => '騚', '' => '騕', '' => '騥', '' => '騝', '' => '騤', '' => '騛', '' => '騢', '' => '騠', '' => '騧', '' => '騣', '' => '騞', '' => '騜', '' => '騔', '' => '髂', '' => '鬋', '' => '鬊', '' => '鬎', '' => '鬌', '' => '鬷', '' => '鯪', '' => '鯫', '' => '鯠', '' => '鯞', '' => '鯤', '' => '鯦', '' => '鯢', '' => '鯰', '' => '鯔', '' => '鯗', '' => '鯬', '' => '鯜', '' => '鯙', '' => '鯥', '' => '鯕', '' => '鯡', '' => '鯚', '' => '鵷', '' => '鶁', '' => '鶊', '' => '鶄', '' => '鶈', '' => '鵱', '' => '鶀', '' => '鵸', '' => '鶆', '' => '鶋', '' => '鶌', '' => '鵽', '' => '鵫', '' => '鵴', '' => '鵵', '' => '鵰', '' => '鵩', '' => '鶅', '' => '鵳', '' => '鵻', '' => '鶂', '' => '鵯', '' => '鵹', '' => '鵿', '' => '鶇', '' => '鵨', '' => '麔', '' => '麑', '' => '黀', '' => '黼', '' => '鼭', '' => '齀', '' => '齁', '' => '齍', '' => '齖', '' => '齗', '' => '齘', '' => '匷', '' => '嚲', '@' => '嚵', 'A' => '嚳', 'B' => '壣', 'C' => '孅', 'D' => '巆', 'E' => '巇', 'F' => '廮', 'G' => '廯', 'H' => '忀', 'I' => '忁', 'J' => '懹', 'K' => '攗', 'L' => '攖', 'M' => '攕', 'N' => '攓', 'O' => '旟', 'P' => '曨', 'Q' => '曣', 'R' => '曤', 'S' => '櫳', 'T' => '櫰', 'U' => '櫪', 'V' => '櫨', 'W' => '櫹', 'X' => '櫱', 'Y' => '櫮', 'Z' => '櫯', '[' => '瀼', '\\' => '瀵', ']' => '瀯', '^' => '瀷', '_' => '瀴', '`' => '瀱', 'a' => '灂', 'b' => '瀸', 'c' => '瀿', 'd' => '瀺', 'e' => '瀹', 'f' => '灀', 'g' => '瀻', 'h' => '瀳', 'i' => '灁', 'j' => '爓', 'k' => '爔', 'l' => '犨', 'm' => '獽', 'n' => '獼', 'o' => '璺', 'p' => '皫', 'q' => '皪', 'r' => '皾', 's' => '盭', 't' => '矌', 'u' => '矎', 'v' => '矏', 'w' => '矍', 'x' => '矲', 'y' => '礥', 'z' => '礣', '{' => '礧', '|' => '礨', '}' => '礤', '~' => '礩', '' => '禲', '' => '穮', '' => '穬', '' => '穭', '' => '竷', '' => '籉', '' => '籈', '' => '籊', '' => '籇', '' => '籅', '' => '糮', '' => '繻', '' => '繾', '' => '纁', '' => '纀', '' => '羺', '' => '翿', '' => '聹', '' => '臛', '' => '臙', '' => '舋', '' => '艨', '' => '艩', '' => '蘢', '' => '藿', '' => '蘁', '' => '藾', '' => '蘛', '' => '蘀', '' => '藶', '' => '蘄', '' => '蘉', '' => '蘅', '' => '蘌', '' => '藽', '' => '蠙', '' => '蠐', '' => '蠑', '' => '蠗', '' => '蠓', '' => '蠖', '' => '襣', '' => '襦', '' => '覹', '' => '觷', '' => '譠', '' => '譪', '' => '譝', '' => '譨', '' => '譣', '' => '譥', '' => '譧', '' => '譭', '' => '趮', '' => '躆', '' => '躈', '' => '躄', '' => '轙', '' => '轖', '' => '轗', '' => '轕', '' => '轘', '' => '轚', '' => '邍', '' => '酃', '' => '酁', '' => '醷', '' => '醵', '' => '醲', '' => '醳', '' => '鐋', '' => '鐓', '' => '鏻', '' => '鐠', '' => '鐏', '' => '鐔', '' => '鏾', '' => '鐕', '' => '鐐', '' => '鐨', '' => '鐙', '' => '鐍', '' => '鏵', '' => '鐀', '' => '鏷', '' => '鐇', '' => '鐎', '' => '鐖', '' => '鐒', '' => '鏺', '' => '鐉', '' => '鏸', '' => '鐊', '' => '鏿', '@' => '鏼', 'A' => '鐌', 'B' => '鏶', 'C' => '鐑', 'D' => '鐆', 'E' => '闞', 'F' => '闠', 'G' => '闟', 'H' => '霮', 'I' => '霯', 'J' => '鞹', 'K' => '鞻', 'L' => '韽', 'M' => '韾', 'N' => '顠', 'O' => '顢', 'P' => '顣', 'Q' => '顟', 'R' => '飁', 'S' => '飂', 'T' => '饐', 'U' => '饎', 'V' => '饙', 'W' => '饌', 'X' => '饋', 'Y' => '饓', 'Z' => '騲', '[' => '騴', '\\' => '騱', ']' => '騬', '^' => '騪', '_' => '騶', '`' => '騩', 'a' => '騮', 'b' => '騸', 'c' => '騭', 'd' => '髇', 'e' => '髊', 'f' => '髆', 'g' => '鬐', 'h' => '鬒', 'i' => '鬑', 'j' => '鰋', 'k' => '鰈', 'l' => '鯷', 'm' => '鰅', 'n' => '鰒', 'o' => '鯸', 'p' => '鱀', 'q' => '鰇', 'r' => '鰎', 's' => '鰆', 't' => '鰗', 'u' => '鰔', 'v' => '鰉', 'w' => '鶟', 'x' => '鶙', 'y' => '鶤', 'z' => '鶝', '{' => '鶒', '|' => '鶘', '}' => '鶐', '~' => '鶛', '' => '鶠', '' => '鶔', '' => '鶜', '' => '鶪', '' => '鶗', '' => '鶡', '' => '鶚', '' => '鶢', '' => '鶨', '' => '鶞', '' => '鶣', '' => '鶿', '' => '鶩', '' => '鶖', '' => '鶦', '' => '鶧', '' => '麙', '' => '麛', '' => '麚', '' => '黥', '' => '黤', '' => '黧', '' => '黦', '' => '鼰', '' => '鼮', '' => '齛', '' => '齠', '' => '齞', '' => '齝', '' => '齙', '' => '龑', '' => '儺', '' => '儹', '' => '劘', '' => '劗', '' => '囃', '' => '嚽', '' => '嚾', '' => '孈', '' => '孇', '' => '巋', '' => '巏', '' => '廱', '' => '懽', '' => '攛', '' => '欂', '' => '櫼', '' => '欃', '' => '櫸', '' => '欀', '' => '灃', '' => '灄', '' => '灊', '' => '灈', '' => '灉', '' => '灅', '' => '灆', '' => '爝', '' => '爚', '' => '爙', '' => '獾', '' => '甗', '' => '癪', '' => '矐', '' => '礭', '' => '礱', '' => '礯', '' => '籔', '' => '籓', '' => '糲', '' => '纊', '' => '纇', '' => '纈', '' => '纋', '' => '纆', '' => '纍', '' => '罍', '' => '羻', '' => '耰', '' => '臝', '' => '蘘', '' => '蘪', '' => '蘦', '' => '蘟', '' => '蘣', '' => '蘜', '' => '蘙', '' => '蘧', '' => '蘮', '' => '蘡', '' => '蘠', '' => '蘩', '' => '蘞', '' => '蘥', '@' => '蠩', 'A' => '蠝', 'B' => '蠛', 'C' => '蠠', 'D' => '蠤', 'E' => '蠜', 'F' => '蠫', 'G' => '衊', 'H' => '襭', 'I' => '襩', 'J' => '襮', 'K' => '襫', 'L' => '觺', 'M' => '譹', 'N' => '譸', 'O' => '譅', 'P' => '譺', 'Q' => '譻', 'R' => '贐', 'S' => '贔', 'T' => '趯', 'U' => '躎', 'V' => '躌', 'W' => '轞', 'X' => '轛', 'Y' => '轝', 'Z' => '酆', '[' => '酄', '\\' => '酅', ']' => '醹', '^' => '鐿', '_' => '鐻', '`' => '鐶', 'a' => '鐩', 'b' => '鐽', 'c' => '鐼', 'd' => '鐰', 'e' => '鐹', 'f' => '鐪', 'g' => '鐷', 'h' => '鐬', 'i' => '鑀', 'j' => '鐱', 'k' => '闥', 'l' => '闤', 'm' => '闣', 'n' => '霵', 'o' => '霺', 'p' => '鞿', 'q' => '韡', 'r' => '顤', 's' => '飉', 't' => '飆', 'u' => '飀', 'v' => '饘', 'w' => '饖', 'x' => '騹', 'y' => '騽', 'z' => '驆', '{' => '驄', '|' => '驂', '}' => '驁', '~' => '騺', '' => '騿', '' => '髍', '' => '鬕', '' => '鬗', '' => '鬘', '' => '鬖', '' => '鬺', '' => '魒', '' => '鰫', '' => '鰝', '' => '鰜', '' => '鰬', '' => '鰣', '' => '鰨', '' => '鰩', '' => '鰤', '' => '鰡', '' => '鶷', '' => '鶶', '' => '鶼', '' => '鷁', '' => '鷇', '' => '鷊', '' => '鷏', '' => '鶾', '' => '鷅', '' => '鷃', '' => '鶻', '' => '鶵', '' => '鷎', '' => '鶹', '' => '鶺', '' => '鶬', '' => '鷈', '' => '鶱', '' => '鶭', '' => '鷌', '' => '鶳', '' => '鷍', '' => '鶲', '' => '鹺', '' => '麜', '' => '黫', '' => '黮', '' => '黭', '' => '鼛', '' => '鼘', '' => '鼚', '' => '鼱', '' => '齎', '' => '齥', '' => '齤', '' => '龒', '' => '亹', '' => '囆', '' => '囅', '' => '囋', '' => '奱', '' => '孋', '' => '孌', '' => '巕', '' => '巑', '' => '廲', '' => '攡', '' => '攠', '' => '攦', '' => '攢', '' => '欋', '' => '欈', '' => '欉', '' => '氍', '' => '灕', '' => '灖', '' => '灗', '' => '灒', '' => '爞', '' => '爟', '' => '犩', '' => '獿', '' => '瓘', '' => '瓕', '' => '瓙', '' => '瓗', '' => '癭', '' => '皭', '' => '礵', '' => '禴', '' => '穰', '' => '穱', '' => '籗', '' => '籜', '' => '籙', '' => '籛', '' => '籚', '@' => '糴', 'A' => '糱', 'B' => '纑', 'C' => '罏', 'D' => '羇', 'E' => '臞', 'F' => '艫', 'G' => '蘴', 'H' => '蘵', 'I' => '蘳', 'J' => '蘬', 'K' => '蘲', 'L' => '蘶', 'M' => '蠬', 'N' => '蠨', 'O' => '蠦', 'P' => '蠪', 'Q' => '蠥', 'R' => '襱', 'S' => '覿', 'T' => '覾', 'U' => '觻', 'V' => '譾', 'W' => '讄', 'X' => '讂', 'Y' => '讆', 'Z' => '讅', '[' => '譿', '\\' => '贕', ']' => '躕', '^' => '躔', '_' => '躚', '`' => '躒', 'a' => '躐', 'b' => '躖', 'c' => '躗', 'd' => '轠', 'e' => '轢', 'f' => '酇', 'g' => '鑌', 'h' => '鑐', 'i' => '鑊', 'j' => '鑋', 'k' => '鑏', 'l' => '鑇', 'm' => '鑅', 'n' => '鑈', 'o' => '鑉', 'p' => '鑆', 'q' => '霿', 'r' => '韣', 's' => '顪', 't' => '顩', 'u' => '飋', 'v' => '饔', 'w' => '饛', 'x' => '驎', 'y' => '驓', 'z' => '驔', '{' => '驌', '|' => '驏', '}' => '驈', '~' => '驊', '' => '驉', '' => '驒', '' => '驐', '' => '髐', '' => '鬙', '' => '鬫', '' => '鬻', '' => '魖', '' => '魕', '' => '鱆', '' => '鱈', '' => '鰿', '' => '鱄', '' => '鰹', '' => '鰳', '' => '鱁', '' => '鰼', '' => '鰷', '' => '鰴', '' => '鰲', '' => '鰽', '' => '鰶', '' => '鷛', '' => '鷒', '' => '鷞', '' => '鷚', '' => '鷋', '' => '鷐', '' => '鷜', '' => '鷑', '' => '鷟', '' => '鷩', '' => '鷙', '' => '鷘', '' => '鷖', '' => '鷵', '' => '鷕', '' => '鷝', '' => '麶', '' => '黰', '' => '鼵', '' => '鼳', '' => '鼲', '' => '齂', '' => '齫', '' => '龕', '' => '龢', '' => '儽', '' => '劙', '' => '壨', '' => '壧', '' => '奲', '' => '孍', '' => '巘', '' => '蠯', '' => '彏', '' => '戁', '' => '戃', '' => '戄', '' => '攩', '' => '攥', '' => '斖', '' => '曫', '' => '欑', '' => '欒', '' => '欏', '' => '毊', '' => '灛', '' => '灚', '' => '爢', '' => '玂', '' => '玁', '' => '玃', '' => '癰', '' => '矔', '' => '籧', '' => '籦', '' => '纕', '' => '艬', '' => '蘺', '' => '虀', '' => '蘹', '' => '蘼', '' => '蘱', '' => '蘻', '' => '蘾', '' => '蠰', '' => '蠲', '' => '蠮', '' => '蠳', '' => '襶', '' => '襴', '' => '襳', '' => '觾', '@' => '讌', 'A' => '讎', 'B' => '讋', 'C' => '讈', 'D' => '豅', 'E' => '贙', 'F' => '躘', 'G' => '轤', 'H' => '轣', 'I' => '醼', 'J' => '鑢', 'K' => '鑕', 'L' => '鑝', 'M' => '鑗', 'N' => '鑞', 'O' => '韄', 'P' => '韅', 'Q' => '頀', 'R' => '驖', 'S' => '驙', 'T' => '鬞', 'U' => '鬟', 'V' => '鬠', 'W' => '鱒', 'X' => '鱘', 'Y' => '鱐', 'Z' => '鱊', '[' => '鱍', '\\' => '鱋', ']' => '鱕', '^' => '鱙', '_' => '鱌', '`' => '鱎', 'a' => '鷻', 'b' => '鷷', 'c' => '鷯', 'd' => '鷣', 'e' => '鷫', 'f' => '鷸', 'g' => '鷤', 'h' => '鷶', 'i' => '鷡', 'j' => '鷮', 'k' => '鷦', 'l' => '鷲', 'm' => '鷰', 'n' => '鷢', 'o' => '鷬', 'p' => '鷴', 'q' => '鷳', 'r' => '鷨', 's' => '鷭', 't' => '黂', 'u' => '黐', 'v' => '黲', 'w' => '黳', 'x' => '鼆', 'y' => '鼜', 'z' => '鼸', '{' => '鼷', '|' => '鼶', '}' => '齃', '~' => '齏', '' => '齱', '' => '齰', '' => '齮', '' => '齯', '' => '囓', '' => '囍', '' => '孎', '' => '屭', '' => '攭', '' => '曭', '' => '曮', '' => '欓', '' => '灟', '' => '灡', '' => '灝', '' => '灠', '' => '爣', '' => '瓛', '' => '瓥', '' => '矕', '' => '礸', '' => '禷', '' => '禶', '' => '籪', '' => '纗', '' => '羉', '' => '艭', '' => '虃', '' => '蠸', '' => '蠷', '' => '蠵', '' => '衋', '' => '讔', '' => '讕', '' => '躞', '' => '躟', '' => '躠', '' => '躝', '' => '醾', '' => '醽', '' => '釂', '' => '鑫', '' => '鑨', '' => '鑩', '' => '雥', '' => '靆', '' => '靃', '' => '靇', '' => '韇', '' => '韥', '' => '驞', '' => '髕', '' => '魙', '' => '鱣', '' => '鱧', '' => '鱦', '' => '鱢', '' => '鱞', '' => '鱠', '' => '鸂', '' => '鷾', '' => '鸇', '' => '鸃', '' => '鸆', '' => '鸅', '' => '鸀', '' => '鸁', '' => '鸉', '' => '鷿', '' => '鷽', '' => '鸄', '' => '麠', '' => '鼞', '' => '齆', '' => '齴', '' => '齵', '' => '齶', '' => '囔', '' => '攮', '' => '斸', '' => '欘', '' => '欙', '' => '欗', '' => '欚', '' => '灢', '' => '爦', '' => '犪', '' => '矘', '' => '矙', '' => '礹', '' => '籩', '' => '籫', '' => '糶', '' => '纚', '@' => '纘', 'A' => '纛', 'B' => '纙', 'C' => '臠', 'D' => '臡', 'E' => '虆', 'F' => '虇', 'G' => '虈', 'H' => '襹', 'I' => '襺', 'J' => '襼', 'K' => '襻', 'L' => '觿', 'M' => '讘', 'N' => '讙', 'O' => '躥', 'P' => '躤', 'Q' => '躣', 'R' => '鑮', 'S' => '鑭', 'T' => '鑯', 'U' => '鑱', 'V' => '鑳', 'W' => '靉', 'X' => '顲', 'Y' => '饟', 'Z' => '鱨', '[' => '鱮', '\\' => '鱭', ']' => '鸋', '^' => '鸍', '_' => '鸐', '`' => '鸏', 'a' => '鸒', 'b' => '鸑', 'c' => '麡', 'd' => '黵', 'e' => '鼉', 'f' => '齇', 'g' => '齸', 'h' => '齻', 'i' => '齺', 'j' => '齹', 'k' => '圞', 'l' => '灦', 'm' => '籯', 'n' => '蠼', 'o' => '趲', 'p' => '躦', 'q' => '釃', 'r' => '鑴', 's' => '鑸', 't' => '鑶', 'u' => '鑵', 'v' => '驠', 'w' => '鱴', 'x' => '鱳', 'y' => '鱱', 'z' => '鱵', '{' => '鸔', '|' => '鸓', '}' => '黶', '~' => '鼊', '' => '龤', '' => '灨', '' => '灥', '' => '糷', '' => '虪', '' => '蠾', '' => '蠽', '' => '蠿', '' => '讞', '' => '貜', '' => '躩', '' => '軉', '' => '靋', '' => '顳', '' => '顴', '' => '飌', '' => '饡', '' => '馫', '' => '驤', '' => '驦', '' => '驧', '' => '鬤', '' => '鸕', '' => '鸗', '' => '齈', '' => '戇', '' => '欞', '' => '爧', '' => '虌', '' => '躨', '' => '钂', '' => '钀', '' => '钁', '' => '驩', '' => '驨', '' => '鬮', '' => '鸙', '' => '爩', '' => '虋', '' => '讟', '' => '钃', '' => '鱹', '' => '麷', '' => '癵', '' => '驫', '' => '鱺', '' => '鸝', '' => '灩', '' => '灪', '' => '麤', '' => '齾', '' => '齉', '' => '龘', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp932.php000064400000405717150432043200015437 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '。', '' => '「', '' => '」', '' => '、', '' => '・', '' => 'ヲ', '' => 'ァ', '' => 'ィ', '' => 'ゥ', '' => 'ェ', '' => 'ォ', '' => 'ャ', '' => 'ュ', '' => 'ョ', '' => 'ッ', '' => 'ー', '' => 'ア', '' => 'イ', '' => 'ウ', '' => 'エ', '' => 'オ', '' => 'カ', '' => 'キ', '' => 'ク', '' => 'ケ', '' => 'コ', '' => 'サ', '' => 'シ', '' => 'ス', '' => 'セ', '' => 'ソ', '' => 'タ', '' => 'チ', '' => 'ツ', '' => 'テ', '' => 'ト', '' => 'ナ', '' => 'ニ', '' => 'ヌ', '' => 'ネ', '' => 'ノ', '' => 'ハ', '' => 'ヒ', '' => 'フ', '' => 'ヘ', '' => 'ホ', '' => 'マ', '' => 'ミ', '' => 'ム', '' => 'メ', '' => 'モ', '' => 'ヤ', '' => 'ユ', '' => 'ヨ', '' => 'ラ', '' => 'リ', '' => 'ル', '' => 'レ', '' => 'ロ', '' => 'ワ', '' => 'ン', '' => '゙', '' => '゚', '@' => ' ', 'A' => '、', 'B' => '。', 'C' => ',', 'D' => '.', 'E' => '・', 'F' => ':', 'G' => ';', 'H' => '?', 'I' => '!', 'J' => '゛', 'K' => '゜', 'L' => '´', 'M' => '`', 'N' => '¨', 'O' => '^', 'P' => ' ̄', 'Q' => '_', 'R' => 'ヽ', 'S' => 'ヾ', 'T' => 'ゝ', 'U' => 'ゞ', 'V' => '〃', 'W' => '仝', 'X' => '々', 'Y' => '〆', 'Z' => '〇', '[' => 'ー', '\\' => '―', ']' => '‐', '^' => '/', '_' => '\', '`' => '~', 'a' => '∥', 'b' => '|', 'c' => '…', 'd' => '‥', 'e' => '‘', 'f' => '’', 'g' => '“', 'h' => '”', 'i' => '(', 'j' => ')', 'k' => '〔', 'l' => '〕', 'm' => '[', 'n' => ']', 'o' => '{', 'p' => '}', 'q' => '〈', 'r' => '〉', 's' => '《', 't' => '》', 'u' => '「', 'v' => '」', 'w' => '『', 'x' => '』', 'y' => '【', 'z' => '】', '{' => '+', '|' => '-', '}' => '±', '~' => '×', '' => '÷', '' => '=', '' => '≠', '' => '<', '' => '>', '' => '≦', '' => '≧', '' => '∞', '' => '∴', '' => '♂', '' => '♀', '' => '°', '' => '′', '' => '″', '' => '℃', '' => '¥', '' => '$', '' => '¢', '' => '£', '' => '%', '' => '#', '' => '&', '' => '*', '' => '@', '' => '§', '' => '☆', '' => '★', '' => '○', '' => '●', '' => '◎', '' => '◇', '' => '◆', '' => '□', '' => '■', '' => '△', '' => '▲', '' => '▽', '' => '▼', '' => '※', '' => '〒', '' => '→', '' => '←', '' => '↑', '' => '↓', '' => '〓', '' => '∈', '' => '∋', '' => '⊆', '' => '⊇', '' => '⊂', '' => '⊃', '' => '∪', '' => '∩', '' => '∧', '' => '∨', '' => '¬', '' => '⇒', '' => '⇔', '' => '∀', '' => '∃', '' => '∠', '' => '⊥', '' => '⌒', '' => '∂', '' => '∇', '' => '≡', '' => '≒', '' => '≪', '' => '≫', '' => '√', '' => '∽', '' => '∝', '' => '∵', '' => '∫', '' => '∬', '' => 'Å', '' => '‰', '' => '♯', '' => '♭', '' => '♪', '' => '†', '' => '‡', '' => '¶', '' => '◯', 'O' => '0', 'P' => '1', 'Q' => '2', 'R' => '3', 'S' => '4', 'T' => '5', 'U' => '6', 'V' => '7', 'W' => '8', 'X' => '9', '`' => 'A', 'a' => 'B', 'b' => 'C', 'c' => 'D', 'd' => 'E', 'e' => 'F', 'f' => 'G', 'g' => 'H', 'h' => 'I', 'i' => 'J', 'j' => 'K', 'k' => 'L', 'l' => 'M', 'm' => 'N', 'n' => 'O', 'o' => 'P', 'p' => 'Q', 'q' => 'R', 'r' => 'S', 's' => 'T', 't' => 'U', 'u' => 'V', 'v' => 'W', 'w' => 'X', 'x' => 'Y', 'y' => 'Z', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => 'ぁ', '' => 'あ', '' => 'ぃ', '' => 'い', '' => 'ぅ', '' => 'う', '' => 'ぇ', '' => 'え', '' => 'ぉ', '' => 'お', '' => 'か', '' => 'が', '' => 'き', '' => 'ぎ', '' => 'く', '' => 'ぐ', '' => 'け', '' => 'げ', '' => 'こ', '' => 'ご', '' => 'さ', '' => 'ざ', '' => 'し', '' => 'じ', '' => 'す', '' => 'ず', '' => 'せ', '' => 'ぜ', '' => 'そ', '' => 'ぞ', '' => 'た', '' => 'だ', '' => 'ち', '' => 'ぢ', '' => 'っ', '' => 'つ', '' => 'づ', '' => 'て', '' => 'で', '' => 'と', '' => 'ど', '' => 'な', '' => 'に', '' => 'ぬ', '' => 'ね', '' => 'の', '' => 'は', '' => 'ば', '' => 'ぱ', '' => 'ひ', '' => 'び', '' => 'ぴ', '' => 'ふ', '' => 'ぶ', '' => 'ぷ', '' => 'へ', '' => 'べ', '' => 'ぺ', '' => 'ほ', '' => 'ぼ', '' => 'ぽ', '' => 'ま', '' => 'み', '' => 'む', '' => 'め', '' => 'も', '' => 'ゃ', '' => 'や', '' => 'ゅ', '' => 'ゆ', '' => 'ょ', '' => 'よ', '' => 'ら', '' => 'り', '' => 'る', '' => 'れ', '' => 'ろ', '' => 'ゎ', '' => 'わ', '' => 'ゐ', '' => 'ゑ', '' => 'を', '' => 'ん', '@' => 'ァ', 'A' => 'ア', 'B' => 'ィ', 'C' => 'イ', 'D' => 'ゥ', 'E' => 'ウ', 'F' => 'ェ', 'G' => 'エ', 'H' => 'ォ', 'I' => 'オ', 'J' => 'カ', 'K' => 'ガ', 'L' => 'キ', 'M' => 'ギ', 'N' => 'ク', 'O' => 'グ', 'P' => 'ケ', 'Q' => 'ゲ', 'R' => 'コ', 'S' => 'ゴ', 'T' => 'サ', 'U' => 'ザ', 'V' => 'シ', 'W' => 'ジ', 'X' => 'ス', 'Y' => 'ズ', 'Z' => 'セ', '[' => 'ゼ', '\\' => 'ソ', ']' => 'ゾ', '^' => 'タ', '_' => 'ダ', '`' => 'チ', 'a' => 'ヂ', 'b' => 'ッ', 'c' => 'ツ', 'd' => 'ヅ', 'e' => 'テ', 'f' => 'デ', 'g' => 'ト', 'h' => 'ド', 'i' => 'ナ', 'j' => 'ニ', 'k' => 'ヌ', 'l' => 'ネ', 'm' => 'ノ', 'n' => 'ハ', 'o' => 'バ', 'p' => 'パ', 'q' => 'ヒ', 'r' => 'ビ', 's' => 'ピ', 't' => 'フ', 'u' => 'ブ', 'v' => 'プ', 'w' => 'ヘ', 'x' => 'ベ', 'y' => 'ペ', 'z' => 'ホ', '{' => 'ボ', '|' => 'ポ', '}' => 'マ', '~' => 'ミ', '' => 'ム', '' => 'メ', '' => 'モ', '' => 'ャ', '' => 'ヤ', '' => 'ュ', '' => 'ユ', '' => 'ョ', '' => 'ヨ', '' => 'ラ', '' => 'リ', '' => 'ル', '' => 'レ', '' => 'ロ', '' => 'ヮ', '' => 'ワ', '' => 'ヰ', '' => 'ヱ', '' => 'ヲ', '' => 'ン', '' => 'ヴ', '' => 'ヵ', '' => 'ヶ', '' => 'Α', '' => 'Β', '' => 'Γ', '' => 'Δ', '' => 'Ε', '' => 'Ζ', '' => 'Η', '' => 'Θ', '' => 'Ι', '' => 'Κ', '' => 'Λ', '' => 'Μ', '' => 'Ν', '' => 'Ξ', '' => 'Ο', '' => 'Π', '' => 'Ρ', '' => 'Σ', '' => 'Τ', '' => 'Υ', '' => 'Φ', '' => 'Χ', '' => 'Ψ', '' => 'Ω', '' => 'α', '' => 'β', '' => 'γ', '' => 'δ', '' => 'ε', '' => 'ζ', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'σ', '' => 'τ', '' => 'υ', '' => 'φ', '' => 'χ', '' => 'ψ', '' => 'ω', '@' => 'А', 'A' => 'Б', 'B' => 'В', 'C' => 'Г', 'D' => 'Д', 'E' => 'Е', 'F' => 'Ё', 'G' => 'Ж', 'H' => 'З', 'I' => 'И', 'J' => 'Й', 'K' => 'К', 'L' => 'Л', 'M' => 'М', 'N' => 'Н', 'O' => 'О', 'P' => 'П', 'Q' => 'Р', 'R' => 'С', 'S' => 'Т', 'T' => 'У', 'U' => 'Ф', 'V' => 'Х', 'W' => 'Ц', 'X' => 'Ч', 'Y' => 'Ш', 'Z' => 'Щ', '[' => 'Ъ', '\\' => 'Ы', ']' => 'Ь', '^' => 'Э', '_' => 'Ю', '`' => 'Я', 'p' => 'а', 'q' => 'б', 'r' => 'в', 's' => 'г', 't' => 'д', 'u' => 'е', 'v' => 'ё', 'w' => 'ж', 'x' => 'з', 'y' => 'и', 'z' => 'й', '{' => 'к', '|' => 'л', '}' => 'м', '~' => 'н', '' => 'о', '' => 'п', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ф', '' => 'х', '' => 'ц', '' => 'ч', '' => 'ш', '' => 'щ', '' => 'ъ', '' => 'ы', '' => 'ь', '' => 'э', '' => 'ю', '' => 'я', '' => '─', '' => '│', '' => '┌', '' => '┐', '' => '┘', '' => '└', '' => '├', '' => '┬', '' => '┤', '' => '┴', '' => '┼', '' => '━', '' => '┃', '' => '┏', '' => '┓', '' => '┛', '' => '┗', '' => '┣', '' => '┳', '' => '┫', '' => '┻', '' => '╋', '' => '┠', '' => '┯', '' => '┨', '' => '┷', '' => '┿', '' => '┝', '' => '┰', '' => '┥', '' => '┸', '' => '╂', '@' => '①', 'A' => '②', 'B' => '③', 'C' => '④', 'D' => '⑤', 'E' => '⑥', 'F' => '⑦', 'G' => '⑧', 'H' => '⑨', 'I' => '⑩', 'J' => '⑪', 'K' => '⑫', 'L' => '⑬', 'M' => '⑭', 'N' => '⑮', 'O' => '⑯', 'P' => '⑰', 'Q' => '⑱', 'R' => '⑲', 'S' => '⑳', 'T' => 'Ⅰ', 'U' => 'Ⅱ', 'V' => 'Ⅲ', 'W' => 'Ⅳ', 'X' => 'Ⅴ', 'Y' => 'Ⅵ', 'Z' => 'Ⅶ', '[' => 'Ⅷ', '\\' => 'Ⅸ', ']' => 'Ⅹ', '_' => '㍉', '`' => '㌔', 'a' => '㌢', 'b' => '㍍', 'c' => '㌘', 'd' => '㌧', 'e' => '㌃', 'f' => '㌶', 'g' => '㍑', 'h' => '㍗', 'i' => '㌍', 'j' => '㌦', 'k' => '㌣', 'l' => '㌫', 'm' => '㍊', 'n' => '㌻', 'o' => '㎜', 'p' => '㎝', 'q' => '㎞', 'r' => '㎎', 's' => '㎏', 't' => '㏄', 'u' => '㎡', '~' => '㍻', '' => '〝', '' => '〟', '' => '№', '' => '㏍', '' => '℡', '' => '㊤', '' => '㊥', '' => '㊦', '' => '㊧', '' => '㊨', '' => '㈱', '' => '㈲', '' => '㈹', '' => '㍾', '' => '㍽', '' => '㍼', '' => '≒', '' => '≡', '' => '∫', '' => '∮', '' => '∑', '' => '√', '' => '⊥', '' => '∠', '' => '∟', '' => '⊿', '' => '∵', '' => '∩', '' => '∪', '' => '亜', '' => '唖', '' => '娃', '' => '阿', '' => '哀', '' => '愛', '' => '挨', '' => '姶', '' => '逢', '' => '葵', '' => '茜', '' => '穐', '' => '悪', '' => '握', '' => '渥', '' => '旭', '' => '葦', '' => '芦', '' => '鯵', '' => '梓', '' => '圧', '' => '斡', '' => '扱', '' => '宛', '' => '姐', '' => '虻', '' => '飴', '' => '絢', '' => '綾', '' => '鮎', '' => '或', '' => '粟', '' => '袷', '' => '安', '' => '庵', '' => '按', '' => '暗', '' => '案', '' => '闇', '' => '鞍', '' => '杏', '' => '以', '' => '伊', '' => '位', '' => '依', '' => '偉', '' => '囲', '' => '夷', '' => '委', '' => '威', '' => '尉', '' => '惟', '' => '意', '' => '慰', '' => '易', '' => '椅', '' => '為', '' => '畏', '' => '異', '' => '移', '' => '維', '' => '緯', '' => '胃', '' => '萎', '' => '衣', '' => '謂', '' => '違', '' => '遺', '' => '医', '' => '井', '' => '亥', '' => '域', '' => '育', '' => '郁', '' => '磯', '' => '一', '' => '壱', '' => '溢', '' => '逸', '' => '稲', '' => '茨', '' => '芋', '' => '鰯', '' => '允', '' => '印', '' => '咽', '' => '員', '' => '因', '' => '姻', '' => '引', '' => '飲', '' => '淫', '' => '胤', '' => '蔭', '@' => '院', 'A' => '陰', 'B' => '隠', 'C' => '韻', 'D' => '吋', 'E' => '右', 'F' => '宇', 'G' => '烏', 'H' => '羽', 'I' => '迂', 'J' => '雨', 'K' => '卯', 'L' => '鵜', 'M' => '窺', 'N' => '丑', 'O' => '碓', 'P' => '臼', 'Q' => '渦', 'R' => '嘘', 'S' => '唄', 'T' => '欝', 'U' => '蔚', 'V' => '鰻', 'W' => '姥', 'X' => '厩', 'Y' => '浦', 'Z' => '瓜', '[' => '閏', '\\' => '噂', ']' => '云', '^' => '運', '_' => '雲', '`' => '荏', 'a' => '餌', 'b' => '叡', 'c' => '営', 'd' => '嬰', 'e' => '影', 'f' => '映', 'g' => '曳', 'h' => '栄', 'i' => '永', 'j' => '泳', 'k' => '洩', 'l' => '瑛', 'm' => '盈', 'n' => '穎', 'o' => '頴', 'p' => '英', 'q' => '衛', 'r' => '詠', 's' => '鋭', 't' => '液', 'u' => '疫', 'v' => '益', 'w' => '駅', 'x' => '悦', 'y' => '謁', 'z' => '越', '{' => '閲', '|' => '榎', '}' => '厭', '~' => '円', '' => '園', '' => '堰', '' => '奄', '' => '宴', '' => '延', '' => '怨', '' => '掩', '' => '援', '' => '沿', '' => '演', '' => '炎', '' => '焔', '' => '煙', '' => '燕', '' => '猿', '' => '縁', '' => '艶', '' => '苑', '' => '薗', '' => '遠', '' => '鉛', '' => '鴛', '' => '塩', '' => '於', '' => '汚', '' => '甥', '' => '凹', '' => '央', '' => '奥', '' => '往', '' => '応', '' => '押', '' => '旺', '' => '横', '' => '欧', '' => '殴', '' => '王', '' => '翁', '' => '襖', '' => '鴬', '' => '鴎', '' => '黄', '' => '岡', '' => '沖', '' => '荻', '' => '億', '' => '屋', '' => '憶', '' => '臆', '' => '桶', '' => '牡', '' => '乙', '' => '俺', '' => '卸', '' => '恩', '' => '温', '' => '穏', '' => '音', '' => '下', '' => '化', '' => '仮', '' => '何', '' => '伽', '' => '価', '' => '佳', '' => '加', '' => '可', '' => '嘉', '' => '夏', '' => '嫁', '' => '家', '' => '寡', '' => '科', '' => '暇', '' => '果', '' => '架', '' => '歌', '' => '河', '' => '火', '' => '珂', '' => '禍', '' => '禾', '' => '稼', '' => '箇', '' => '花', '' => '苛', '' => '茄', '' => '荷', '' => '華', '' => '菓', '' => '蝦', '' => '課', '' => '嘩', '' => '貨', '' => '迦', '' => '過', '' => '霞', '' => '蚊', '' => '俄', '' => '峨', '' => '我', '' => '牙', '' => '画', '' => '臥', '' => '芽', '' => '蛾', '' => '賀', '' => '雅', '' => '餓', '' => '駕', '' => '介', '' => '会', '' => '解', '' => '回', '' => '塊', '' => '壊', '' => '廻', '' => '快', '' => '怪', '' => '悔', '' => '恢', '' => '懐', '' => '戒', '' => '拐', '' => '改', '@' => '魁', 'A' => '晦', 'B' => '械', 'C' => '海', 'D' => '灰', 'E' => '界', 'F' => '皆', 'G' => '絵', 'H' => '芥', 'I' => '蟹', 'J' => '開', 'K' => '階', 'L' => '貝', 'M' => '凱', 'N' => '劾', 'O' => '外', 'P' => '咳', 'Q' => '害', 'R' => '崖', 'S' => '慨', 'T' => '概', 'U' => '涯', 'V' => '碍', 'W' => '蓋', 'X' => '街', 'Y' => '該', 'Z' => '鎧', '[' => '骸', '\\' => '浬', ']' => '馨', '^' => '蛙', '_' => '垣', '`' => '柿', 'a' => '蛎', 'b' => '鈎', 'c' => '劃', 'd' => '嚇', 'e' => '各', 'f' => '廓', 'g' => '拡', 'h' => '撹', 'i' => '格', 'j' => '核', 'k' => '殻', 'l' => '獲', 'm' => '確', 'n' => '穫', 'o' => '覚', 'p' => '角', 'q' => '赫', 'r' => '較', 's' => '郭', 't' => '閣', 'u' => '隔', 'v' => '革', 'w' => '学', 'x' => '岳', 'y' => '楽', 'z' => '額', '{' => '顎', '|' => '掛', '}' => '笠', '~' => '樫', '' => '橿', '' => '梶', '' => '鰍', '' => '潟', '' => '割', '' => '喝', '' => '恰', '' => '括', '' => '活', '' => '渇', '' => '滑', '' => '葛', '' => '褐', '' => '轄', '' => '且', '' => '鰹', '' => '叶', '' => '椛', '' => '樺', '' => '鞄', '' => '株', '' => '兜', '' => '竃', '' => '蒲', '' => '釜', '' => '鎌', '' => '噛', '' => '鴨', '' => '栢', '' => '茅', '' => '萱', '' => '粥', '' => '刈', '' => '苅', '' => '瓦', '' => '乾', '' => '侃', '' => '冠', '' => '寒', '' => '刊', '' => '勘', '' => '勧', '' => '巻', '' => '喚', '' => '堪', '' => '姦', '' => '完', '' => '官', '' => '寛', '' => '干', '' => '幹', '' => '患', '' => '感', '' => '慣', '' => '憾', '' => '換', '' => '敢', '' => '柑', '' => '桓', '' => '棺', '' => '款', '' => '歓', '' => '汗', '' => '漢', '' => '澗', '' => '潅', '' => '環', '' => '甘', '' => '監', '' => '看', '' => '竿', '' => '管', '' => '簡', '' => '緩', '' => '缶', '' => '翰', '' => '肝', '' => '艦', '' => '莞', '' => '観', '' => '諌', '' => '貫', '' => '還', '' => '鑑', '' => '間', '' => '閑', '' => '関', '' => '陥', '' => '韓', '' => '館', '' => '舘', '' => '丸', '' => '含', '' => '岸', '' => '巌', '' => '玩', '' => '癌', '' => '眼', '' => '岩', '' => '翫', '' => '贋', '' => '雁', '' => '頑', '' => '顔', '' => '願', '' => '企', '' => '伎', '' => '危', '' => '喜', '' => '器', '' => '基', '' => '奇', '' => '嬉', '' => '寄', '' => '岐', '' => '希', '' => '幾', '' => '忌', '' => '揮', '' => '机', '' => '旗', '' => '既', '' => '期', '' => '棋', '' => '棄', '@' => '機', 'A' => '帰', 'B' => '毅', 'C' => '気', 'D' => '汽', 'E' => '畿', 'F' => '祈', 'G' => '季', 'H' => '稀', 'I' => '紀', 'J' => '徽', 'K' => '規', 'L' => '記', 'M' => '貴', 'N' => '起', 'O' => '軌', 'P' => '輝', 'Q' => '飢', 'R' => '騎', 'S' => '鬼', 'T' => '亀', 'U' => '偽', 'V' => '儀', 'W' => '妓', 'X' => '宜', 'Y' => '戯', 'Z' => '技', '[' => '擬', '\\' => '欺', ']' => '犠', '^' => '疑', '_' => '祇', '`' => '義', 'a' => '蟻', 'b' => '誼', 'c' => '議', 'd' => '掬', 'e' => '菊', 'f' => '鞠', 'g' => '吉', 'h' => '吃', 'i' => '喫', 'j' => '桔', 'k' => '橘', 'l' => '詰', 'm' => '砧', 'n' => '杵', 'o' => '黍', 'p' => '却', 'q' => '客', 'r' => '脚', 's' => '虐', 't' => '逆', 'u' => '丘', 'v' => '久', 'w' => '仇', 'x' => '休', 'y' => '及', 'z' => '吸', '{' => '宮', '|' => '弓', '}' => '急', '~' => '救', '' => '朽', '' => '求', '' => '汲', '' => '泣', '' => '灸', '' => '球', '' => '究', '' => '窮', '' => '笈', '' => '級', '' => '糾', '' => '給', '' => '旧', '' => '牛', '' => '去', '' => '居', '' => '巨', '' => '拒', '' => '拠', '' => '挙', '' => '渠', '' => '虚', '' => '許', '' => '距', '' => '鋸', '' => '漁', '' => '禦', '' => '魚', '' => '亨', '' => '享', '' => '京', '' => '供', '' => '侠', '' => '僑', '' => '兇', '' => '競', '' => '共', '' => '凶', '' => '協', '' => '匡', '' => '卿', '' => '叫', '' => '喬', '' => '境', '' => '峡', '' => '強', '' => '彊', '' => '怯', '' => '恐', '' => '恭', '' => '挟', '' => '教', '' => '橋', '' => '況', '' => '狂', '' => '狭', '' => '矯', '' => '胸', '' => '脅', '' => '興', '' => '蕎', '' => '郷', '' => '鏡', '' => '響', '' => '饗', '' => '驚', '' => '仰', '' => '凝', '' => '尭', '' => '暁', '' => '業', '' => '局', '' => '曲', '' => '極', '' => '玉', '' => '桐', '' => '粁', '' => '僅', '' => '勤', '' => '均', '' => '巾', '' => '錦', '' => '斤', '' => '欣', '' => '欽', '' => '琴', '' => '禁', '' => '禽', '' => '筋', '' => '緊', '' => '芹', '' => '菌', '' => '衿', '' => '襟', '' => '謹', '' => '近', '' => '金', '' => '吟', '' => '銀', '' => '九', '' => '倶', '' => '句', '' => '区', '' => '狗', '' => '玖', '' => '矩', '' => '苦', '' => '躯', '' => '駆', '' => '駈', '' => '駒', '' => '具', '' => '愚', '' => '虞', '' => '喰', '' => '空', '' => '偶', '' => '寓', '' => '遇', '' => '隅', '' => '串', '' => '櫛', '' => '釧', '' => '屑', '' => '屈', '@' => '掘', 'A' => '窟', 'B' => '沓', 'C' => '靴', 'D' => '轡', 'E' => '窪', 'F' => '熊', 'G' => '隈', 'H' => '粂', 'I' => '栗', 'J' => '繰', 'K' => '桑', 'L' => '鍬', 'M' => '勲', 'N' => '君', 'O' => '薫', 'P' => '訓', 'Q' => '群', 'R' => '軍', 'S' => '郡', 'T' => '卦', 'U' => '袈', 'V' => '祁', 'W' => '係', 'X' => '傾', 'Y' => '刑', 'Z' => '兄', '[' => '啓', '\\' => '圭', ']' => '珪', '^' => '型', '_' => '契', '`' => '形', 'a' => '径', 'b' => '恵', 'c' => '慶', 'd' => '慧', 'e' => '憩', 'f' => '掲', 'g' => '携', 'h' => '敬', 'i' => '景', 'j' => '桂', 'k' => '渓', 'l' => '畦', 'm' => '稽', 'n' => '系', 'o' => '経', 'p' => '継', 'q' => '繋', 'r' => '罫', 's' => '茎', 't' => '荊', 'u' => '蛍', 'v' => '計', 'w' => '詣', 'x' => '警', 'y' => '軽', 'z' => '頚', '{' => '鶏', '|' => '芸', '}' => '迎', '~' => '鯨', '' => '劇', '' => '戟', '' => '撃', '' => '激', '' => '隙', '' => '桁', '' => '傑', '' => '欠', '' => '決', '' => '潔', '' => '穴', '' => '結', '' => '血', '' => '訣', '' => '月', '' => '件', '' => '倹', '' => '倦', '' => '健', '' => '兼', '' => '券', '' => '剣', '' => '喧', '' => '圏', '' => '堅', '' => '嫌', '' => '建', '' => '憲', '' => '懸', '' => '拳', '' => '捲', '' => '検', '' => '権', '' => '牽', '' => '犬', '' => '献', '' => '研', '' => '硯', '' => '絹', '' => '県', '' => '肩', '' => '見', '' => '謙', '' => '賢', '' => '軒', '' => '遣', '' => '鍵', '' => '険', '' => '顕', '' => '験', '' => '鹸', '' => '元', '' => '原', '' => '厳', '' => '幻', '' => '弦', '' => '減', '' => '源', '' => '玄', '' => '現', '' => '絃', '' => '舷', '' => '言', '' => '諺', '' => '限', '' => '乎', '' => '個', '' => '古', '' => '呼', '' => '固', '' => '姑', '' => '孤', '' => '己', '' => '庫', '' => '弧', '' => '戸', '' => '故', '' => '枯', '' => '湖', '' => '狐', '' => '糊', '' => '袴', '' => '股', '' => '胡', '' => '菰', '' => '虎', '' => '誇', '' => '跨', '' => '鈷', '' => '雇', '' => '顧', '' => '鼓', '' => '五', '' => '互', '' => '伍', '' => '午', '' => '呉', '' => '吾', '' => '娯', '' => '後', '' => '御', '' => '悟', '' => '梧', '' => '檎', '' => '瑚', '' => '碁', '' => '語', '' => '誤', '' => '護', '' => '醐', '' => '乞', '' => '鯉', '' => '交', '' => '佼', '' => '侯', '' => '候', '' => '倖', '' => '光', '' => '公', '' => '功', '' => '効', '' => '勾', '' => '厚', '' => '口', '' => '向', '@' => '后', 'A' => '喉', 'B' => '坑', 'C' => '垢', 'D' => '好', 'E' => '孔', 'F' => '孝', 'G' => '宏', 'H' => '工', 'I' => '巧', 'J' => '巷', 'K' => '幸', 'L' => '広', 'M' => '庚', 'N' => '康', 'O' => '弘', 'P' => '恒', 'Q' => '慌', 'R' => '抗', 'S' => '拘', 'T' => '控', 'U' => '攻', 'V' => '昂', 'W' => '晃', 'X' => '更', 'Y' => '杭', 'Z' => '校', '[' => '梗', '\\' => '構', ']' => '江', '^' => '洪', '_' => '浩', '`' => '港', 'a' => '溝', 'b' => '甲', 'c' => '皇', 'd' => '硬', 'e' => '稿', 'f' => '糠', 'g' => '紅', 'h' => '紘', 'i' => '絞', 'j' => '綱', 'k' => '耕', 'l' => '考', 'm' => '肯', 'n' => '肱', 'o' => '腔', 'p' => '膏', 'q' => '航', 'r' => '荒', 's' => '行', 't' => '衡', 'u' => '講', 'v' => '貢', 'w' => '購', 'x' => '郊', 'y' => '酵', 'z' => '鉱', '{' => '砿', '|' => '鋼', '}' => '閤', '~' => '降', '' => '項', '' => '香', '' => '高', '' => '鴻', '' => '剛', '' => '劫', '' => '号', '' => '合', '' => '壕', '' => '拷', '' => '濠', '' => '豪', '' => '轟', '' => '麹', '' => '克', '' => '刻', '' => '告', '' => '国', '' => '穀', '' => '酷', '' => '鵠', '' => '黒', '' => '獄', '' => '漉', '' => '腰', '' => '甑', '' => '忽', '' => '惚', '' => '骨', '' => '狛', '' => '込', '' => '此', '' => '頃', '' => '今', '' => '困', '' => '坤', '' => '墾', '' => '婚', '' => '恨', '' => '懇', '' => '昏', '' => '昆', '' => '根', '' => '梱', '' => '混', '' => '痕', '' => '紺', '' => '艮', '' => '魂', '' => '些', '' => '佐', '' => '叉', '' => '唆', '' => '嵯', '' => '左', '' => '差', '' => '査', '' => '沙', '' => '瑳', '' => '砂', '' => '詐', '' => '鎖', '' => '裟', '' => '坐', '' => '座', '' => '挫', '' => '債', '' => '催', '' => '再', '' => '最', '' => '哉', '' => '塞', '' => '妻', '' => '宰', '' => '彩', '' => '才', '' => '採', '' => '栽', '' => '歳', '' => '済', '' => '災', '' => '采', '' => '犀', '' => '砕', '' => '砦', '' => '祭', '' => '斎', '' => '細', '' => '菜', '' => '裁', '' => '載', '' => '際', '' => '剤', '' => '在', '' => '材', '' => '罪', '' => '財', '' => '冴', '' => '坂', '' => '阪', '' => '堺', '' => '榊', '' => '肴', '' => '咲', '' => '崎', '' => '埼', '' => '碕', '' => '鷺', '' => '作', '' => '削', '' => '咋', '' => '搾', '' => '昨', '' => '朔', '' => '柵', '' => '窄', '' => '策', '' => '索', '' => '錯', '' => '桜', '' => '鮭', '' => '笹', '' => '匙', '' => '冊', '' => '刷', '@' => '察', 'A' => '拶', 'B' => '撮', 'C' => '擦', 'D' => '札', 'E' => '殺', 'F' => '薩', 'G' => '雑', 'H' => '皐', 'I' => '鯖', 'J' => '捌', 'K' => '錆', 'L' => '鮫', 'M' => '皿', 'N' => '晒', 'O' => '三', 'P' => '傘', 'Q' => '参', 'R' => '山', 'S' => '惨', 'T' => '撒', 'U' => '散', 'V' => '桟', 'W' => '燦', 'X' => '珊', 'Y' => '産', 'Z' => '算', '[' => '纂', '\\' => '蚕', ']' => '讃', '^' => '賛', '_' => '酸', '`' => '餐', 'a' => '斬', 'b' => '暫', 'c' => '残', 'd' => '仕', 'e' => '仔', 'f' => '伺', 'g' => '使', 'h' => '刺', 'i' => '司', 'j' => '史', 'k' => '嗣', 'l' => '四', 'm' => '士', 'n' => '始', 'o' => '姉', 'p' => '姿', 'q' => '子', 'r' => '屍', 's' => '市', 't' => '師', 'u' => '志', 'v' => '思', 'w' => '指', 'x' => '支', 'y' => '孜', 'z' => '斯', '{' => '施', '|' => '旨', '}' => '枝', '~' => '止', '' => '死', '' => '氏', '' => '獅', '' => '祉', '' => '私', '' => '糸', '' => '紙', '' => '紫', '' => '肢', '' => '脂', '' => '至', '' => '視', '' => '詞', '' => '詩', '' => '試', '' => '誌', '' => '諮', '' => '資', '' => '賜', '' => '雌', '' => '飼', '' => '歯', '' => '事', '' => '似', '' => '侍', '' => '児', '' => '字', '' => '寺', '' => '慈', '' => '持', '' => '時', '' => '次', '' => '滋', '' => '治', '' => '爾', '' => '璽', '' => '痔', '' => '磁', '' => '示', '' => '而', '' => '耳', '' => '自', '' => '蒔', '' => '辞', '' => '汐', '' => '鹿', '' => '式', '' => '識', '' => '鴫', '' => '竺', '' => '軸', '' => '宍', '' => '雫', '' => '七', '' => '叱', '' => '執', '' => '失', '' => '嫉', '' => '室', '' => '悉', '' => '湿', '' => '漆', '' => '疾', '' => '質', '' => '実', '' => '蔀', '' => '篠', '' => '偲', '' => '柴', '' => '芝', '' => '屡', '' => '蕊', '' => '縞', '' => '舎', '' => '写', '' => '射', '' => '捨', '' => '赦', '' => '斜', '' => '煮', '' => '社', '' => '紗', '' => '者', '' => '謝', '' => '車', '' => '遮', '' => '蛇', '' => '邪', '' => '借', '' => '勺', '' => '尺', '' => '杓', '' => '灼', '' => '爵', '' => '酌', '' => '釈', '' => '錫', '' => '若', '' => '寂', '' => '弱', '' => '惹', '' => '主', '' => '取', '' => '守', '' => '手', '' => '朱', '' => '殊', '' => '狩', '' => '珠', '' => '種', '' => '腫', '' => '趣', '' => '酒', '' => '首', '' => '儒', '' => '受', '' => '呪', '' => '寿', '' => '授', '' => '樹', '' => '綬', '' => '需', '' => '囚', '' => '収', '' => '周', '@' => '宗', 'A' => '就', 'B' => '州', 'C' => '修', 'D' => '愁', 'E' => '拾', 'F' => '洲', 'G' => '秀', 'H' => '秋', 'I' => '終', 'J' => '繍', 'K' => '習', 'L' => '臭', 'M' => '舟', 'N' => '蒐', 'O' => '衆', 'P' => '襲', 'Q' => '讐', 'R' => '蹴', 'S' => '輯', 'T' => '週', 'U' => '酋', 'V' => '酬', 'W' => '集', 'X' => '醜', 'Y' => '什', 'Z' => '住', '[' => '充', '\\' => '十', ']' => '従', '^' => '戎', '_' => '柔', '`' => '汁', 'a' => '渋', 'b' => '獣', 'c' => '縦', 'd' => '重', 'e' => '銃', 'f' => '叔', 'g' => '夙', 'h' => '宿', 'i' => '淑', 'j' => '祝', 'k' => '縮', 'l' => '粛', 'm' => '塾', 'n' => '熟', 'o' => '出', 'p' => '術', 'q' => '述', 'r' => '俊', 's' => '峻', 't' => '春', 'u' => '瞬', 'v' => '竣', 'w' => '舜', 'x' => '駿', 'y' => '准', 'z' => '循', '{' => '旬', '|' => '楯', '}' => '殉', '~' => '淳', '' => '準', '' => '潤', '' => '盾', '' => '純', '' => '巡', '' => '遵', '' => '醇', '' => '順', '' => '処', '' => '初', '' => '所', '' => '暑', '' => '曙', '' => '渚', '' => '庶', '' => '緒', '' => '署', '' => '書', '' => '薯', '' => '藷', '' => '諸', '' => '助', '' => '叙', '' => '女', '' => '序', '' => '徐', '' => '恕', '' => '鋤', '' => '除', '' => '傷', '' => '償', '' => '勝', '' => '匠', '' => '升', '' => '召', '' => '哨', '' => '商', '' => '唱', '' => '嘗', '' => '奨', '' => '妾', '' => '娼', '' => '宵', '' => '将', '' => '小', '' => '少', '' => '尚', '' => '庄', '' => '床', '' => '廠', '' => '彰', '' => '承', '' => '抄', '' => '招', '' => '掌', '' => '捷', '' => '昇', '' => '昌', '' => '昭', '' => '晶', '' => '松', '' => '梢', '' => '樟', '' => '樵', '' => '沼', '' => '消', '' => '渉', '' => '湘', '' => '焼', '' => '焦', '' => '照', '' => '症', '' => '省', '' => '硝', '' => '礁', '' => '祥', '' => '称', '' => '章', '' => '笑', '' => '粧', '' => '紹', '' => '肖', '' => '菖', '' => '蒋', '' => '蕉', '' => '衝', '' => '裳', '' => '訟', '' => '証', '' => '詔', '' => '詳', '' => '象', '' => '賞', '' => '醤', '' => '鉦', '' => '鍾', '' => '鐘', '' => '障', '' => '鞘', '' => '上', '' => '丈', '' => '丞', '' => '乗', '' => '冗', '' => '剰', '' => '城', '' => '場', '' => '壌', '' => '嬢', '' => '常', '' => '情', '' => '擾', '' => '条', '' => '杖', '' => '浄', '' => '状', '' => '畳', '' => '穣', '' => '蒸', '' => '譲', '' => '醸', '' => '錠', '' => '嘱', '' => '埴', '' => '飾', '@' => '拭', 'A' => '植', 'B' => '殖', 'C' => '燭', 'D' => '織', 'E' => '職', 'F' => '色', 'G' => '触', 'H' => '食', 'I' => '蝕', 'J' => '辱', 'K' => '尻', 'L' => '伸', 'M' => '信', 'N' => '侵', 'O' => '唇', 'P' => '娠', 'Q' => '寝', 'R' => '審', 'S' => '心', 'T' => '慎', 'U' => '振', 'V' => '新', 'W' => '晋', 'X' => '森', 'Y' => '榛', 'Z' => '浸', '[' => '深', '\\' => '申', ']' => '疹', '^' => '真', '_' => '神', '`' => '秦', 'a' => '紳', 'b' => '臣', 'c' => '芯', 'd' => '薪', 'e' => '親', 'f' => '診', 'g' => '身', 'h' => '辛', 'i' => '進', 'j' => '針', 'k' => '震', 'l' => '人', 'm' => '仁', 'n' => '刃', 'o' => '塵', 'p' => '壬', 'q' => '尋', 'r' => '甚', 's' => '尽', 't' => '腎', 'u' => '訊', 'v' => '迅', 'w' => '陣', 'x' => '靭', 'y' => '笥', 'z' => '諏', '{' => '須', '|' => '酢', '}' => '図', '~' => '厨', '' => '逗', '' => '吹', '' => '垂', '' => '帥', '' => '推', '' => '水', '' => '炊', '' => '睡', '' => '粋', '' => '翠', '' => '衰', '' => '遂', '' => '酔', '' => '錐', '' => '錘', '' => '随', '' => '瑞', '' => '髄', '' => '崇', '' => '嵩', '' => '数', '' => '枢', '' => '趨', '' => '雛', '' => '据', '' => '杉', '' => '椙', '' => '菅', '' => '頗', '' => '雀', '' => '裾', '' => '澄', '' => '摺', '' => '寸', '' => '世', '' => '瀬', '' => '畝', '' => '是', '' => '凄', '' => '制', '' => '勢', '' => '姓', '' => '征', '' => '性', '' => '成', '' => '政', '' => '整', '' => '星', '' => '晴', '' => '棲', '' => '栖', '' => '正', '' => '清', '' => '牲', '' => '生', '' => '盛', '' => '精', '' => '聖', '' => '声', '' => '製', '' => '西', '' => '誠', '' => '誓', '' => '請', '' => '逝', '' => '醒', '' => '青', '' => '静', '' => '斉', '' => '税', '' => '脆', '' => '隻', '' => '席', '' => '惜', '' => '戚', '' => '斥', '' => '昔', '' => '析', '' => '石', '' => '積', '' => '籍', '' => '績', '' => '脊', '' => '責', '' => '赤', '' => '跡', '' => '蹟', '' => '碩', '' => '切', '' => '拙', '' => '接', '' => '摂', '' => '折', '' => '設', '' => '窃', '' => '節', '' => '説', '' => '雪', '' => '絶', '' => '舌', '' => '蝉', '' => '仙', '' => '先', '' => '千', '' => '占', '' => '宣', '' => '専', '' => '尖', '' => '川', '' => '戦', '' => '扇', '' => '撰', '' => '栓', '' => '栴', '' => '泉', '' => '浅', '' => '洗', '' => '染', '' => '潜', '' => '煎', '' => '煽', '' => '旋', '' => '穿', '' => '箭', '' => '線', '@' => '繊', 'A' => '羨', 'B' => '腺', 'C' => '舛', 'D' => '船', 'E' => '薦', 'F' => '詮', 'G' => '賎', 'H' => '践', 'I' => '選', 'J' => '遷', 'K' => '銭', 'L' => '銑', 'M' => '閃', 'N' => '鮮', 'O' => '前', 'P' => '善', 'Q' => '漸', 'R' => '然', 'S' => '全', 'T' => '禅', 'U' => '繕', 'V' => '膳', 'W' => '糎', 'X' => '噌', 'Y' => '塑', 'Z' => '岨', '[' => '措', '\\' => '曾', ']' => '曽', '^' => '楚', '_' => '狙', '`' => '疏', 'a' => '疎', 'b' => '礎', 'c' => '祖', 'd' => '租', 'e' => '粗', 'f' => '素', 'g' => '組', 'h' => '蘇', 'i' => '訴', 'j' => '阻', 'k' => '遡', 'l' => '鼠', 'm' => '僧', 'n' => '創', 'o' => '双', 'p' => '叢', 'q' => '倉', 'r' => '喪', 's' => '壮', 't' => '奏', 'u' => '爽', 'v' => '宋', 'w' => '層', 'x' => '匝', 'y' => '惣', 'z' => '想', '{' => '捜', '|' => '掃', '}' => '挿', '~' => '掻', '' => '操', '' => '早', '' => '曹', '' => '巣', '' => '槍', '' => '槽', '' => '漕', '' => '燥', '' => '争', '' => '痩', '' => '相', '' => '窓', '' => '糟', '' => '総', '' => '綜', '' => '聡', '' => '草', '' => '荘', '' => '葬', '' => '蒼', '' => '藻', '' => '装', '' => '走', '' => '送', '' => '遭', '' => '鎗', '' => '霜', '' => '騒', '' => '像', '' => '増', '' => '憎', '' => '臓', '' => '蔵', '' => '贈', '' => '造', '' => '促', '' => '側', '' => '則', '' => '即', '' => '息', '' => '捉', '' => '束', '' => '測', '' => '足', '' => '速', '' => '俗', '' => '属', '' => '賊', '' => '族', '' => '続', '' => '卒', '' => '袖', '' => '其', '' => '揃', '' => '存', '' => '孫', '' => '尊', '' => '損', '' => '村', '' => '遜', '' => '他', '' => '多', '' => '太', '' => '汰', '' => '詑', '' => '唾', '' => '堕', '' => '妥', '' => '惰', '' => '打', '' => '柁', '' => '舵', '' => '楕', '' => '陀', '' => '駄', '' => '騨', '' => '体', '' => '堆', '' => '対', '' => '耐', '' => '岱', '' => '帯', '' => '待', '' => '怠', '' => '態', '' => '戴', '' => '替', '' => '泰', '' => '滞', '' => '胎', '' => '腿', '' => '苔', '' => '袋', '' => '貸', '' => '退', '' => '逮', '' => '隊', '' => '黛', '' => '鯛', '' => '代', '' => '台', '' => '大', '' => '第', '' => '醍', '' => '題', '' => '鷹', '' => '滝', '' => '瀧', '' => '卓', '' => '啄', '' => '宅', '' => '托', '' => '択', '' => '拓', '' => '沢', '' => '濯', '' => '琢', '' => '託', '' => '鐸', '' => '濁', '' => '諾', '' => '茸', '' => '凧', '' => '蛸', '' => '只', '@' => '叩', 'A' => '但', 'B' => '達', 'C' => '辰', 'D' => '奪', 'E' => '脱', 'F' => '巽', 'G' => '竪', 'H' => '辿', 'I' => '棚', 'J' => '谷', 'K' => '狸', 'L' => '鱈', 'M' => '樽', 'N' => '誰', 'O' => '丹', 'P' => '単', 'Q' => '嘆', 'R' => '坦', 'S' => '担', 'T' => '探', 'U' => '旦', 'V' => '歎', 'W' => '淡', 'X' => '湛', 'Y' => '炭', 'Z' => '短', '[' => '端', '\\' => '箪', ']' => '綻', '^' => '耽', '_' => '胆', '`' => '蛋', 'a' => '誕', 'b' => '鍛', 'c' => '団', 'd' => '壇', 'e' => '弾', 'f' => '断', 'g' => '暖', 'h' => '檀', 'i' => '段', 'j' => '男', 'k' => '談', 'l' => '値', 'm' => '知', 'n' => '地', 'o' => '弛', 'p' => '恥', 'q' => '智', 'r' => '池', 's' => '痴', 't' => '稚', 'u' => '置', 'v' => '致', 'w' => '蜘', 'x' => '遅', 'y' => '馳', 'z' => '築', '{' => '畜', '|' => '竹', '}' => '筑', '~' => '蓄', '' => '逐', '' => '秩', '' => '窒', '' => '茶', '' => '嫡', '' => '着', '' => '中', '' => '仲', '' => '宙', '' => '忠', '' => '抽', '' => '昼', '' => '柱', '' => '注', '' => '虫', '' => '衷', '' => '註', '' => '酎', '' => '鋳', '' => '駐', '' => '樗', '' => '瀦', '' => '猪', '' => '苧', '' => '著', '' => '貯', '' => '丁', '' => '兆', '' => '凋', '' => '喋', '' => '寵', '' => '帖', '' => '帳', '' => '庁', '' => '弔', '' => '張', '' => '彫', '' => '徴', '' => '懲', '' => '挑', '' => '暢', '' => '朝', '' => '潮', '' => '牒', '' => '町', '' => '眺', '' => '聴', '' => '脹', '' => '腸', '' => '蝶', '' => '調', '' => '諜', '' => '超', '' => '跳', '' => '銚', '' => '長', '' => '頂', '' => '鳥', '' => '勅', '' => '捗', '' => '直', '' => '朕', '' => '沈', '' => '珍', '' => '賃', '' => '鎮', '' => '陳', '' => '津', '' => '墜', '' => '椎', '' => '槌', '' => '追', '' => '鎚', '' => '痛', '' => '通', '' => '塚', '' => '栂', '' => '掴', '' => '槻', '' => '佃', '' => '漬', '' => '柘', '' => '辻', '' => '蔦', '' => '綴', '' => '鍔', '' => '椿', '' => '潰', '' => '坪', '' => '壷', '' => '嬬', '' => '紬', '' => '爪', '' => '吊', '' => '釣', '' => '鶴', '' => '亭', '' => '低', '' => '停', '' => '偵', '' => '剃', '' => '貞', '' => '呈', '' => '堤', '' => '定', '' => '帝', '' => '底', '' => '庭', '' => '廷', '' => '弟', '' => '悌', '' => '抵', '' => '挺', '' => '提', '' => '梯', '' => '汀', '' => '碇', '' => '禎', '' => '程', '' => '締', '' => '艇', '' => '訂', '' => '諦', '' => '蹄', '' => '逓', '@' => '邸', 'A' => '鄭', 'B' => '釘', 'C' => '鼎', 'D' => '泥', 'E' => '摘', 'F' => '擢', 'G' => '敵', 'H' => '滴', 'I' => '的', 'J' => '笛', 'K' => '適', 'L' => '鏑', 'M' => '溺', 'N' => '哲', 'O' => '徹', 'P' => '撤', 'Q' => '轍', 'R' => '迭', 'S' => '鉄', 'T' => '典', 'U' => '填', 'V' => '天', 'W' => '展', 'X' => '店', 'Y' => '添', 'Z' => '纏', '[' => '甜', '\\' => '貼', ']' => '転', '^' => '顛', '_' => '点', '`' => '伝', 'a' => '殿', 'b' => '澱', 'c' => '田', 'd' => '電', 'e' => '兎', 'f' => '吐', 'g' => '堵', 'h' => '塗', 'i' => '妬', 'j' => '屠', 'k' => '徒', 'l' => '斗', 'm' => '杜', 'n' => '渡', 'o' => '登', 'p' => '菟', 'q' => '賭', 'r' => '途', 's' => '都', 't' => '鍍', 'u' => '砥', 'v' => '砺', 'w' => '努', 'x' => '度', 'y' => '土', 'z' => '奴', '{' => '怒', '|' => '倒', '}' => '党', '~' => '冬', '' => '凍', '' => '刀', '' => '唐', '' => '塔', '' => '塘', '' => '套', '' => '宕', '' => '島', '' => '嶋', '' => '悼', '' => '投', '' => '搭', '' => '東', '' => '桃', '' => '梼', '' => '棟', '' => '盗', '' => '淘', '' => '湯', '' => '涛', '' => '灯', '' => '燈', '' => '当', '' => '痘', '' => '祷', '' => '等', '' => '答', '' => '筒', '' => '糖', '' => '統', '' => '到', '' => '董', '' => '蕩', '' => '藤', '' => '討', '' => '謄', '' => '豆', '' => '踏', '' => '逃', '' => '透', '' => '鐙', '' => '陶', '' => '頭', '' => '騰', '' => '闘', '' => '働', '' => '動', '' => '同', '' => '堂', '' => '導', '' => '憧', '' => '撞', '' => '洞', '' => '瞳', '' => '童', '' => '胴', '' => '萄', '' => '道', '' => '銅', '' => '峠', '' => '鴇', '' => '匿', '' => '得', '' => '徳', '' => '涜', '' => '特', '' => '督', '' => '禿', '' => '篤', '' => '毒', '' => '独', '' => '読', '' => '栃', '' => '橡', '' => '凸', '' => '突', '' => '椴', '' => '届', '' => '鳶', '' => '苫', '' => '寅', '' => '酉', '' => '瀞', '' => '噸', '' => '屯', '' => '惇', '' => '敦', '' => '沌', '' => '豚', '' => '遁', '' => '頓', '' => '呑', '' => '曇', '' => '鈍', '' => '奈', '' => '那', '' => '内', '' => '乍', '' => '凪', '' => '薙', '' => '謎', '' => '灘', '' => '捺', '' => '鍋', '' => '楢', '' => '馴', '' => '縄', '' => '畷', '' => '南', '' => '楠', '' => '軟', '' => '難', '' => '汝', '' => '二', '' => '尼', '' => '弐', '' => '迩', '' => '匂', '' => '賑', '' => '肉', '' => '虹', '' => '廿', '' => '日', '' => '乳', '' => '入', '@' => '如', 'A' => '尿', 'B' => '韮', 'C' => '任', 'D' => '妊', 'E' => '忍', 'F' => '認', 'G' => '濡', 'H' => '禰', 'I' => '祢', 'J' => '寧', 'K' => '葱', 'L' => '猫', 'M' => '熱', 'N' => '年', 'O' => '念', 'P' => '捻', 'Q' => '撚', 'R' => '燃', 'S' => '粘', 'T' => '乃', 'U' => '廼', 'V' => '之', 'W' => '埜', 'X' => '嚢', 'Y' => '悩', 'Z' => '濃', '[' => '納', '\\' => '能', ']' => '脳', '^' => '膿', '_' => '農', '`' => '覗', 'a' => '蚤', 'b' => '巴', 'c' => '把', 'd' => '播', 'e' => '覇', 'f' => '杷', 'g' => '波', 'h' => '派', 'i' => '琶', 'j' => '破', 'k' => '婆', 'l' => '罵', 'm' => '芭', 'n' => '馬', 'o' => '俳', 'p' => '廃', 'q' => '拝', 'r' => '排', 's' => '敗', 't' => '杯', 'u' => '盃', 'v' => '牌', 'w' => '背', 'x' => '肺', 'y' => '輩', 'z' => '配', '{' => '倍', '|' => '培', '}' => '媒', '~' => '梅', '' => '楳', '' => '煤', '' => '狽', '' => '買', '' => '売', '' => '賠', '' => '陪', '' => '這', '' => '蝿', '' => '秤', '' => '矧', '' => '萩', '' => '伯', '' => '剥', '' => '博', '' => '拍', '' => '柏', '' => '泊', '' => '白', '' => '箔', '' => '粕', '' => '舶', '' => '薄', '' => '迫', '' => '曝', '' => '漠', '' => '爆', '' => '縛', '' => '莫', '' => '駁', '' => '麦', '' => '函', '' => '箱', '' => '硲', '' => '箸', '' => '肇', '' => '筈', '' => '櫨', '' => '幡', '' => '肌', '' => '畑', '' => '畠', '' => '八', '' => '鉢', '' => '溌', '' => '発', '' => '醗', '' => '髪', '' => '伐', '' => '罰', '' => '抜', '' => '筏', '' => '閥', '' => '鳩', '' => '噺', '' => '塙', '' => '蛤', '' => '隼', '' => '伴', '' => '判', '' => '半', '' => '反', '' => '叛', '' => '帆', '' => '搬', '' => '斑', '' => '板', '' => '氾', '' => '汎', '' => '版', '' => '犯', '' => '班', '' => '畔', '' => '繁', '' => '般', '' => '藩', '' => '販', '' => '範', '' => '釆', '' => '煩', '' => '頒', '' => '飯', '' => '挽', '' => '晩', '' => '番', '' => '盤', '' => '磐', '' => '蕃', '' => '蛮', '' => '匪', '' => '卑', '' => '否', '' => '妃', '' => '庇', '' => '彼', '' => '悲', '' => '扉', '' => '批', '' => '披', '' => '斐', '' => '比', '' => '泌', '' => '疲', '' => '皮', '' => '碑', '' => '秘', '' => '緋', '' => '罷', '' => '肥', '' => '被', '' => '誹', '' => '費', '' => '避', '' => '非', '' => '飛', '' => '樋', '' => '簸', '' => '備', '' => '尾', '' => '微', '' => '枇', '' => '毘', '' => '琵', '' => '眉', '' => '美', '@' => '鼻', 'A' => '柊', 'B' => '稗', 'C' => '匹', 'D' => '疋', 'E' => '髭', 'F' => '彦', 'G' => '膝', 'H' => '菱', 'I' => '肘', 'J' => '弼', 'K' => '必', 'L' => '畢', 'M' => '筆', 'N' => '逼', 'O' => '桧', 'P' => '姫', 'Q' => '媛', 'R' => '紐', 'S' => '百', 'T' => '謬', 'U' => '俵', 'V' => '彪', 'W' => '標', 'X' => '氷', 'Y' => '漂', 'Z' => '瓢', '[' => '票', '\\' => '表', ']' => '評', '^' => '豹', '_' => '廟', '`' => '描', 'a' => '病', 'b' => '秒', 'c' => '苗', 'd' => '錨', 'e' => '鋲', 'f' => '蒜', 'g' => '蛭', 'h' => '鰭', 'i' => '品', 'j' => '彬', 'k' => '斌', 'l' => '浜', 'm' => '瀕', 'n' => '貧', 'o' => '賓', 'p' => '頻', 'q' => '敏', 'r' => '瓶', 's' => '不', 't' => '付', 'u' => '埠', 'v' => '夫', 'w' => '婦', 'x' => '富', 'y' => '冨', 'z' => '布', '{' => '府', '|' => '怖', '}' => '扶', '~' => '敷', '' => '斧', '' => '普', '' => '浮', '' => '父', '' => '符', '' => '腐', '' => '膚', '' => '芙', '' => '譜', '' => '負', '' => '賦', '' => '赴', '' => '阜', '' => '附', '' => '侮', '' => '撫', '' => '武', '' => '舞', '' => '葡', '' => '蕪', '' => '部', '' => '封', '' => '楓', '' => '風', '' => '葺', '' => '蕗', '' => '伏', '' => '副', '' => '復', '' => '幅', '' => '服', '' => '福', '' => '腹', '' => '複', '' => '覆', '' => '淵', '' => '弗', '' => '払', '' => '沸', '' => '仏', '' => '物', '' => '鮒', '' => '分', '' => '吻', '' => '噴', '' => '墳', '' => '憤', '' => '扮', '' => '焚', '' => '奮', '' => '粉', '' => '糞', '' => '紛', '' => '雰', '' => '文', '' => '聞', '' => '丙', '' => '併', '' => '兵', '' => '塀', '' => '幣', '' => '平', '' => '弊', '' => '柄', '' => '並', '' => '蔽', '' => '閉', '' => '陛', '' => '米', '' => '頁', '' => '僻', '' => '壁', '' => '癖', '' => '碧', '' => '別', '' => '瞥', '' => '蔑', '' => '箆', '' => '偏', '' => '変', '' => '片', '' => '篇', '' => '編', '' => '辺', '' => '返', '' => '遍', '' => '便', '' => '勉', '' => '娩', '' => '弁', '' => '鞭', '' => '保', '' => '舗', '' => '鋪', '' => '圃', '' => '捕', '' => '歩', '' => '甫', '' => '補', '' => '輔', '' => '穂', '' => '募', '' => '墓', '' => '慕', '' => '戊', '' => '暮', '' => '母', '' => '簿', '' => '菩', '' => '倣', '' => '俸', '' => '包', '' => '呆', '' => '報', '' => '奉', '' => '宝', '' => '峰', '' => '峯', '' => '崩', '' => '庖', '' => '抱', '' => '捧', '' => '放', '' => '方', '' => '朋', '@' => '法', 'A' => '泡', 'B' => '烹', 'C' => '砲', 'D' => '縫', 'E' => '胞', 'F' => '芳', 'G' => '萌', 'H' => '蓬', 'I' => '蜂', 'J' => '褒', 'K' => '訪', 'L' => '豊', 'M' => '邦', 'N' => '鋒', 'O' => '飽', 'P' => '鳳', 'Q' => '鵬', 'R' => '乏', 'S' => '亡', 'T' => '傍', 'U' => '剖', 'V' => '坊', 'W' => '妨', 'X' => '帽', 'Y' => '忘', 'Z' => '忙', '[' => '房', '\\' => '暴', ']' => '望', '^' => '某', '_' => '棒', '`' => '冒', 'a' => '紡', 'b' => '肪', 'c' => '膨', 'd' => '謀', 'e' => '貌', 'f' => '貿', 'g' => '鉾', 'h' => '防', 'i' => '吠', 'j' => '頬', 'k' => '北', 'l' => '僕', 'm' => '卜', 'n' => '墨', 'o' => '撲', 'p' => '朴', 'q' => '牧', 'r' => '睦', 's' => '穆', 't' => '釦', 'u' => '勃', 'v' => '没', 'w' => '殆', 'x' => '堀', 'y' => '幌', 'z' => '奔', '{' => '本', '|' => '翻', '}' => '凡', '~' => '盆', '' => '摩', '' => '磨', '' => '魔', '' => '麻', '' => '埋', '' => '妹', '' => '昧', '' => '枚', '' => '毎', '' => '哩', '' => '槙', '' => '幕', '' => '膜', '' => '枕', '' => '鮪', '' => '柾', '' => '鱒', '' => '桝', '' => '亦', '' => '俣', '' => '又', '' => '抹', '' => '末', '' => '沫', '' => '迄', '' => '侭', '' => '繭', '' => '麿', '' => '万', '' => '慢', '' => '満', '' => '漫', '' => '蔓', '' => '味', '' => '未', '' => '魅', '' => '巳', '' => '箕', '' => '岬', '' => '密', '' => '蜜', '' => '湊', '' => '蓑', '' => '稔', '' => '脈', '' => '妙', '' => '粍', '' => '民', '' => '眠', '' => '務', '' => '夢', '' => '無', '' => '牟', '' => '矛', '' => '霧', '' => '鵡', '' => '椋', '' => '婿', '' => '娘', '' => '冥', '' => '名', '' => '命', '' => '明', '' => '盟', '' => '迷', '' => '銘', '' => '鳴', '' => '姪', '' => '牝', '' => '滅', '' => '免', '' => '棉', '' => '綿', '' => '緬', '' => '面', '' => '麺', '' => '摸', '' => '模', '' => '茂', '' => '妄', '' => '孟', '' => '毛', '' => '猛', '' => '盲', '' => '網', '' => '耗', '' => '蒙', '' => '儲', '' => '木', '' => '黙', '' => '目', '' => '杢', '' => '勿', '' => '餅', '' => '尤', '' => '戻', '' => '籾', '' => '貰', '' => '問', '' => '悶', '' => '紋', '' => '門', '' => '匁', '' => '也', '' => '冶', '' => '夜', '' => '爺', '' => '耶', '' => '野', '' => '弥', '' => '矢', '' => '厄', '' => '役', '' => '約', '' => '薬', '' => '訳', '' => '躍', '' => '靖', '' => '柳', '' => '薮', '' => '鑓', '' => '愉', '' => '愈', '' => '油', '' => '癒', '@' => '諭', 'A' => '輸', 'B' => '唯', 'C' => '佑', 'D' => '優', 'E' => '勇', 'F' => '友', 'G' => '宥', 'H' => '幽', 'I' => '悠', 'J' => '憂', 'K' => '揖', 'L' => '有', 'M' => '柚', 'N' => '湧', 'O' => '涌', 'P' => '猶', 'Q' => '猷', 'R' => '由', 'S' => '祐', 'T' => '裕', 'U' => '誘', 'V' => '遊', 'W' => '邑', 'X' => '郵', 'Y' => '雄', 'Z' => '融', '[' => '夕', '\\' => '予', ']' => '余', '^' => '与', '_' => '誉', '`' => '輿', 'a' => '預', 'b' => '傭', 'c' => '幼', 'd' => '妖', 'e' => '容', 'f' => '庸', 'g' => '揚', 'h' => '揺', 'i' => '擁', 'j' => '曜', 'k' => '楊', 'l' => '様', 'm' => '洋', 'n' => '溶', 'o' => '熔', 'p' => '用', 'q' => '窯', 'r' => '羊', 's' => '耀', 't' => '葉', 'u' => '蓉', 'v' => '要', 'w' => '謡', 'x' => '踊', 'y' => '遥', 'z' => '陽', '{' => '養', '|' => '慾', '}' => '抑', '~' => '欲', '' => '沃', '' => '浴', '' => '翌', '' => '翼', '' => '淀', '' => '羅', '' => '螺', '' => '裸', '' => '来', '' => '莱', '' => '頼', '' => '雷', '' => '洛', '' => '絡', '' => '落', '' => '酪', '' => '乱', '' => '卵', '' => '嵐', '' => '欄', '' => '濫', '' => '藍', '' => '蘭', '' => '覧', '' => '利', '' => '吏', '' => '履', '' => '李', '' => '梨', '' => '理', '' => '璃', '' => '痢', '' => '裏', '' => '裡', '' => '里', '' => '離', '' => '陸', '' => '律', '' => '率', '' => '立', '' => '葎', '' => '掠', '' => '略', '' => '劉', '' => '流', '' => '溜', '' => '琉', '' => '留', '' => '硫', '' => '粒', '' => '隆', '' => '竜', '' => '龍', '' => '侶', '' => '慮', '' => '旅', '' => '虜', '' => '了', '' => '亮', '' => '僚', '' => '両', '' => '凌', '' => '寮', '' => '料', '' => '梁', '' => '涼', '' => '猟', '' => '療', '' => '瞭', '' => '稜', '' => '糧', '' => '良', '' => '諒', '' => '遼', '' => '量', '' => '陵', '' => '領', '' => '力', '' => '緑', '' => '倫', '' => '厘', '' => '林', '' => '淋', '' => '燐', '' => '琳', '' => '臨', '' => '輪', '' => '隣', '' => '鱗', '' => '麟', '' => '瑠', '' => '塁', '' => '涙', '' => '累', '' => '類', '' => '令', '' => '伶', '' => '例', '' => '冷', '' => '励', '' => '嶺', '' => '怜', '' => '玲', '' => '礼', '' => '苓', '' => '鈴', '' => '隷', '' => '零', '' => '霊', '' => '麗', '' => '齢', '' => '暦', '' => '歴', '' => '列', '' => '劣', '' => '烈', '' => '裂', '' => '廉', '' => '恋', '' => '憐', '' => '漣', '' => '煉', '' => '簾', '' => '練', '' => '聯', '@' => '蓮', 'A' => '連', 'B' => '錬', 'C' => '呂', 'D' => '魯', 'E' => '櫓', 'F' => '炉', 'G' => '賂', 'H' => '路', 'I' => '露', 'J' => '労', 'K' => '婁', 'L' => '廊', 'M' => '弄', 'N' => '朗', 'O' => '楼', 'P' => '榔', 'Q' => '浪', 'R' => '漏', 'S' => '牢', 'T' => '狼', 'U' => '篭', 'V' => '老', 'W' => '聾', 'X' => '蝋', 'Y' => '郎', 'Z' => '六', '[' => '麓', '\\' => '禄', ']' => '肋', '^' => '録', '_' => '論', '`' => '倭', 'a' => '和', 'b' => '話', 'c' => '歪', 'd' => '賄', 'e' => '脇', 'f' => '惑', 'g' => '枠', 'h' => '鷲', 'i' => '亙', 'j' => '亘', 'k' => '鰐', 'l' => '詫', 'm' => '藁', 'n' => '蕨', 'o' => '椀', 'p' => '湾', 'q' => '碗', 'r' => '腕', '' => '弌', '' => '丐', '' => '丕', '' => '个', '' => '丱', '' => '丶', '' => '丼', '' => '丿', '' => '乂', '' => '乖', '' => '乘', '' => '亂', '' => '亅', '' => '豫', '' => '亊', '' => '舒', '' => '弍', '' => '于', '' => '亞', '' => '亟', '' => '亠', '' => '亢', '' => '亰', '' => '亳', '' => '亶', '' => '从', '' => '仍', '' => '仄', '' => '仆', '' => '仂', '' => '仗', '' => '仞', '' => '仭', '' => '仟', '' => '价', '' => '伉', '' => '佚', '' => '估', '' => '佛', '' => '佝', '' => '佗', '' => '佇', '' => '佶', '' => '侈', '' => '侏', '' => '侘', '' => '佻', '' => '佩', '' => '佰', '' => '侑', '' => '佯', '' => '來', '' => '侖', '' => '儘', '' => '俔', '' => '俟', '' => '俎', '' => '俘', '' => '俛', '' => '俑', '' => '俚', '' => '俐', '' => '俤', '' => '俥', '' => '倚', '' => '倨', '' => '倔', '' => '倪', '' => '倥', '' => '倅', '' => '伜', '' => '俶', '' => '倡', '' => '倩', '' => '倬', '' => '俾', '' => '俯', '' => '們', '' => '倆', '' => '偃', '' => '假', '' => '會', '' => '偕', '' => '偐', '' => '偈', '' => '做', '' => '偖', '' => '偬', '' => '偸', '' => '傀', '' => '傚', '' => '傅', '' => '傴', '' => '傲', '@' => '僉', 'A' => '僊', 'B' => '傳', 'C' => '僂', 'D' => '僖', 'E' => '僞', 'F' => '僥', 'G' => '僭', 'H' => '僣', 'I' => '僮', 'J' => '價', 'K' => '僵', 'L' => '儉', 'M' => '儁', 'N' => '儂', 'O' => '儖', 'P' => '儕', 'Q' => '儔', 'R' => '儚', 'S' => '儡', 'T' => '儺', 'U' => '儷', 'V' => '儼', 'W' => '儻', 'X' => '儿', 'Y' => '兀', 'Z' => '兒', '[' => '兌', '\\' => '兔', ']' => '兢', '^' => '竸', '_' => '兩', '`' => '兪', 'a' => '兮', 'b' => '冀', 'c' => '冂', 'd' => '囘', 'e' => '册', 'f' => '冉', 'g' => '冏', 'h' => '冑', 'i' => '冓', 'j' => '冕', 'k' => '冖', 'l' => '冤', 'm' => '冦', 'n' => '冢', 'o' => '冩', 'p' => '冪', 'q' => '冫', 'r' => '决', 's' => '冱', 't' => '冲', 'u' => '冰', 'v' => '况', 'w' => '冽', 'x' => '凅', 'y' => '凉', 'z' => '凛', '{' => '几', '|' => '處', '}' => '凩', '~' => '凭', '' => '凰', '' => '凵', '' => '凾', '' => '刄', '' => '刋', '' => '刔', '' => '刎', '' => '刧', '' => '刪', '' => '刮', '' => '刳', '' => '刹', '' => '剏', '' => '剄', '' => '剋', '' => '剌', '' => '剞', '' => '剔', '' => '剪', '' => '剴', '' => '剩', '' => '剳', '' => '剿', '' => '剽', '' => '劍', '' => '劔', '' => '劒', '' => '剱', '' => '劈', '' => '劑', '' => '辨', '' => '辧', '' => '劬', '' => '劭', '' => '劼', '' => '劵', '' => '勁', '' => '勍', '' => '勗', '' => '勞', '' => '勣', '' => '勦', '' => '飭', '' => '勠', '' => '勳', '' => '勵', '' => '勸', '' => '勹', '' => '匆', '' => '匈', '' => '甸', '' => '匍', '' => '匐', '' => '匏', '' => '匕', '' => '匚', '' => '匣', '' => '匯', '' => '匱', '' => '匳', '' => '匸', '' => '區', '' => '卆', '' => '卅', '' => '丗', '' => '卉', '' => '卍', '' => '凖', '' => '卞', '' => '卩', '' => '卮', '' => '夘', '' => '卻', '' => '卷', '' => '厂', '' => '厖', '' => '厠', '' => '厦', '' => '厥', '' => '厮', '' => '厰', '' => '厶', '' => '參', '' => '簒', '' => '雙', '' => '叟', '' => '曼', '' => '燮', '' => '叮', '' => '叨', '' => '叭', '' => '叺', '' => '吁', '' => '吽', '' => '呀', '' => '听', '' => '吭', '' => '吼', '' => '吮', '' => '吶', '' => '吩', '' => '吝', '' => '呎', '' => '咏', '' => '呵', '' => '咎', '' => '呟', '' => '呱', '' => '呷', '' => '呰', '' => '咒', '' => '呻', '' => '咀', '' => '呶', '' => '咄', '' => '咐', '' => '咆', '' => '哇', '' => '咢', '' => '咸', '' => '咥', '' => '咬', '' => '哄', '' => '哈', '' => '咨', '@' => '咫', 'A' => '哂', 'B' => '咤', 'C' => '咾', 'D' => '咼', 'E' => '哘', 'F' => '哥', 'G' => '哦', 'H' => '唏', 'I' => '唔', 'J' => '哽', 'K' => '哮', 'L' => '哭', 'M' => '哺', 'N' => '哢', 'O' => '唹', 'P' => '啀', 'Q' => '啣', 'R' => '啌', 'S' => '售', 'T' => '啜', 'U' => '啅', 'V' => '啖', 'W' => '啗', 'X' => '唸', 'Y' => '唳', 'Z' => '啝', '[' => '喙', '\\' => '喀', ']' => '咯', '^' => '喊', '_' => '喟', '`' => '啻', 'a' => '啾', 'b' => '喘', 'c' => '喞', 'd' => '單', 'e' => '啼', 'f' => '喃', 'g' => '喩', 'h' => '喇', 'i' => '喨', 'j' => '嗚', 'k' => '嗅', 'l' => '嗟', 'm' => '嗄', 'n' => '嗜', 'o' => '嗤', 'p' => '嗔', 'q' => '嘔', 'r' => '嗷', 's' => '嘖', 't' => '嗾', 'u' => '嗽', 'v' => '嘛', 'w' => '嗹', 'x' => '噎', 'y' => '噐', 'z' => '營', '{' => '嘴', '|' => '嘶', '}' => '嘲', '~' => '嘸', '' => '噫', '' => '噤', '' => '嘯', '' => '噬', '' => '噪', '' => '嚆', '' => '嚀', '' => '嚊', '' => '嚠', '' => '嚔', '' => '嚏', '' => '嚥', '' => '嚮', '' => '嚶', '' => '嚴', '' => '囂', '' => '嚼', '' => '囁', '' => '囃', '' => '囀', '' => '囈', '' => '囎', '' => '囑', '' => '囓', '' => '囗', '' => '囮', '' => '囹', '' => '圀', '' => '囿', '' => '圄', '' => '圉', '' => '圈', '' => '國', '' => '圍', '' => '圓', '' => '團', '' => '圖', '' => '嗇', '' => '圜', '' => '圦', '' => '圷', '' => '圸', '' => '坎', '' => '圻', '' => '址', '' => '坏', '' => '坩', '' => '埀', '' => '垈', '' => '坡', '' => '坿', '' => '垉', '' => '垓', '' => '垠', '' => '垳', '' => '垤', '' => '垪', '' => '垰', '' => '埃', '' => '埆', '' => '埔', '' => '埒', '' => '埓', '' => '堊', '' => '埖', '' => '埣', '' => '堋', '' => '堙', '' => '堝', '' => '塲', '' => '堡', '' => '塢', '' => '塋', '' => '塰', '' => '毀', '' => '塒', '' => '堽', '' => '塹', '' => '墅', '' => '墹', '' => '墟', '' => '墫', '' => '墺', '' => '壞', '' => '墻', '' => '墸', '' => '墮', '' => '壅', '' => '壓', '' => '壑', '' => '壗', '' => '壙', '' => '壘', '' => '壥', '' => '壜', '' => '壤', '' => '壟', '' => '壯', '' => '壺', '' => '壹', '' => '壻', '' => '壼', '' => '壽', '' => '夂', '' => '夊', '' => '夐', '' => '夛', '' => '梦', '' => '夥', '' => '夬', '' => '夭', '' => '夲', '' => '夸', '' => '夾', '' => '竒', '' => '奕', '' => '奐', '' => '奎', '' => '奚', '' => '奘', '' => '奢', '' => '奠', '' => '奧', '' => '奬', '' => '奩', '@' => '奸', 'A' => '妁', 'B' => '妝', 'C' => '佞', 'D' => '侫', 'E' => '妣', 'F' => '妲', 'G' => '姆', 'H' => '姨', 'I' => '姜', 'J' => '妍', 'K' => '姙', 'L' => '姚', 'M' => '娥', 'N' => '娟', 'O' => '娑', 'P' => '娜', 'Q' => '娉', 'R' => '娚', 'S' => '婀', 'T' => '婬', 'U' => '婉', 'V' => '娵', 'W' => '娶', 'X' => '婢', 'Y' => '婪', 'Z' => '媚', '[' => '媼', '\\' => '媾', ']' => '嫋', '^' => '嫂', '_' => '媽', '`' => '嫣', 'a' => '嫗', 'b' => '嫦', 'c' => '嫩', 'd' => '嫖', 'e' => '嫺', 'f' => '嫻', 'g' => '嬌', 'h' => '嬋', 'i' => '嬖', 'j' => '嬲', 'k' => '嫐', 'l' => '嬪', 'm' => '嬶', 'n' => '嬾', 'o' => '孃', 'p' => '孅', 'q' => '孀', 'r' => '孑', 's' => '孕', 't' => '孚', 'u' => '孛', 'v' => '孥', 'w' => '孩', 'x' => '孰', 'y' => '孳', 'z' => '孵', '{' => '學', '|' => '斈', '}' => '孺', '~' => '宀', '' => '它', '' => '宦', '' => '宸', '' => '寃', '' => '寇', '' => '寉', '' => '寔', '' => '寐', '' => '寤', '' => '實', '' => '寢', '' => '寞', '' => '寥', '' => '寫', '' => '寰', '' => '寶', '' => '寳', '' => '尅', '' => '將', '' => '專', '' => '對', '' => '尓', '' => '尠', '' => '尢', '' => '尨', '' => '尸', '' => '尹', '' => '屁', '' => '屆', '' => '屎', '' => '屓', '' => '屐', '' => '屏', '' => '孱', '' => '屬', '' => '屮', '' => '乢', '' => '屶', '' => '屹', '' => '岌', '' => '岑', '' => '岔', '' => '妛', '' => '岫', '' => '岻', '' => '岶', '' => '岼', '' => '岷', '' => '峅', '' => '岾', '' => '峇', '' => '峙', '' => '峩', '' => '峽', '' => '峺', '' => '峭', '' => '嶌', '' => '峪', '' => '崋', '' => '崕', '' => '崗', '' => '嵜', '' => '崟', '' => '崛', '' => '崑', '' => '崔', '' => '崢', '' => '崚', '' => '崙', '' => '崘', '' => '嵌', '' => '嵒', '' => '嵎', '' => '嵋', '' => '嵬', '' => '嵳', '' => '嵶', '' => '嶇', '' => '嶄', '' => '嶂', '' => '嶢', '' => '嶝', '' => '嶬', '' => '嶮', '' => '嶽', '' => '嶐', '' => '嶷', '' => '嶼', '' => '巉', '' => '巍', '' => '巓', '' => '巒', '' => '巖', '' => '巛', '' => '巫', '' => '已', '' => '巵', '' => '帋', '' => '帚', '' => '帙', '' => '帑', '' => '帛', '' => '帶', '' => '帷', '' => '幄', '' => '幃', '' => '幀', '' => '幎', '' => '幗', '' => '幔', '' => '幟', '' => '幢', '' => '幤', '' => '幇', '' => '幵', '' => '并', '' => '幺', '' => '麼', '' => '广', '' => '庠', '' => '廁', '' => '廂', '' => '廈', '' => '廐', '' => '廏', '@' => '廖', 'A' => '廣', 'B' => '廝', 'C' => '廚', 'D' => '廛', 'E' => '廢', 'F' => '廡', 'G' => '廨', 'H' => '廩', 'I' => '廬', 'J' => '廱', 'K' => '廳', 'L' => '廰', 'M' => '廴', 'N' => '廸', 'O' => '廾', 'P' => '弃', 'Q' => '弉', 'R' => '彝', 'S' => '彜', 'T' => '弋', 'U' => '弑', 'V' => '弖', 'W' => '弩', 'X' => '弭', 'Y' => '弸', 'Z' => '彁', '[' => '彈', '\\' => '彌', ']' => '彎', '^' => '弯', '_' => '彑', '`' => '彖', 'a' => '彗', 'b' => '彙', 'c' => '彡', 'd' => '彭', 'e' => '彳', 'f' => '彷', 'g' => '徃', 'h' => '徂', 'i' => '彿', 'j' => '徊', 'k' => '很', 'l' => '徑', 'm' => '徇', 'n' => '從', 'o' => '徙', 'p' => '徘', 'q' => '徠', 'r' => '徨', 's' => '徭', 't' => '徼', 'u' => '忖', 'v' => '忻', 'w' => '忤', 'x' => '忸', 'y' => '忱', 'z' => '忝', '{' => '悳', '|' => '忿', '}' => '怡', '~' => '恠', '' => '怙', '' => '怐', '' => '怩', '' => '怎', '' => '怱', '' => '怛', '' => '怕', '' => '怫', '' => '怦', '' => '怏', '' => '怺', '' => '恚', '' => '恁', '' => '恪', '' => '恷', '' => '恟', '' => '恊', '' => '恆', '' => '恍', '' => '恣', '' => '恃', '' => '恤', '' => '恂', '' => '恬', '' => '恫', '' => '恙', '' => '悁', '' => '悍', '' => '惧', '' => '悃', '' => '悚', '' => '悄', '' => '悛', '' => '悖', '' => '悗', '' => '悒', '' => '悧', '' => '悋', '' => '惡', '' => '悸', '' => '惠', '' => '惓', '' => '悴', '' => '忰', '' => '悽', '' => '惆', '' => '悵', '' => '惘', '' => '慍', '' => '愕', '' => '愆', '' => '惶', '' => '惷', '' => '愀', '' => '惴', '' => '惺', '' => '愃', '' => '愡', '' => '惻', '' => '惱', '' => '愍', '' => '愎', '' => '慇', '' => '愾', '' => '愨', '' => '愧', '' => '慊', '' => '愿', '' => '愼', '' => '愬', '' => '愴', '' => '愽', '' => '慂', '' => '慄', '' => '慳', '' => '慷', '' => '慘', '' => '慙', '' => '慚', '' => '慫', '' => '慴', '' => '慯', '' => '慥', '' => '慱', '' => '慟', '' => '慝', '' => '慓', '' => '慵', '' => '憙', '' => '憖', '' => '憇', '' => '憬', '' => '憔', '' => '憚', '' => '憊', '' => '憑', '' => '憫', '' => '憮', '' => '懌', '' => '懊', '' => '應', '' => '懷', '' => '懈', '' => '懃', '' => '懆', '' => '憺', '' => '懋', '' => '罹', '' => '懍', '' => '懦', '' => '懣', '' => '懶', '' => '懺', '' => '懴', '' => '懿', '' => '懽', '' => '懼', '' => '懾', '' => '戀', '' => '戈', '' => '戉', '' => '戍', '' => '戌', '' => '戔', '' => '戛', '@' => '戞', 'A' => '戡', 'B' => '截', 'C' => '戮', 'D' => '戰', 'E' => '戲', 'F' => '戳', 'G' => '扁', 'H' => '扎', 'I' => '扞', 'J' => '扣', 'K' => '扛', 'L' => '扠', 'M' => '扨', 'N' => '扼', 'O' => '抂', 'P' => '抉', 'Q' => '找', 'R' => '抒', 'S' => '抓', 'T' => '抖', 'U' => '拔', 'V' => '抃', 'W' => '抔', 'X' => '拗', 'Y' => '拑', 'Z' => '抻', '[' => '拏', '\\' => '拿', ']' => '拆', '^' => '擔', '_' => '拈', '`' => '拜', 'a' => '拌', 'b' => '拊', 'c' => '拂', 'd' => '拇', 'e' => '抛', 'f' => '拉', 'g' => '挌', 'h' => '拮', 'i' => '拱', 'j' => '挧', 'k' => '挂', 'l' => '挈', 'm' => '拯', 'n' => '拵', 'o' => '捐', 'p' => '挾', 'q' => '捍', 'r' => '搜', 's' => '捏', 't' => '掖', 'u' => '掎', 'v' => '掀', 'w' => '掫', 'x' => '捶', 'y' => '掣', 'z' => '掏', '{' => '掉', '|' => '掟', '}' => '掵', '~' => '捫', '' => '捩', '' => '掾', '' => '揩', '' => '揀', '' => '揆', '' => '揣', '' => '揉', '' => '插', '' => '揶', '' => '揄', '' => '搖', '' => '搴', '' => '搆', '' => '搓', '' => '搦', '' => '搶', '' => '攝', '' => '搗', '' => '搨', '' => '搏', '' => '摧', '' => '摯', '' => '摶', '' => '摎', '' => '攪', '' => '撕', '' => '撓', '' => '撥', '' => '撩', '' => '撈', '' => '撼', '' => '據', '' => '擒', '' => '擅', '' => '擇', '' => '撻', '' => '擘', '' => '擂', '' => '擱', '' => '擧', '' => '舉', '' => '擠', '' => '擡', '' => '抬', '' => '擣', '' => '擯', '' => '攬', '' => '擶', '' => '擴', '' => '擲', '' => '擺', '' => '攀', '' => '擽', '' => '攘', '' => '攜', '' => '攅', '' => '攤', '' => '攣', '' => '攫', '' => '攴', '' => '攵', '' => '攷', '' => '收', '' => '攸', '' => '畋', '' => '效', '' => '敖', '' => '敕', '' => '敍', '' => '敘', '' => '敞', '' => '敝', '' => '敲', '' => '數', '' => '斂', '' => '斃', '' => '變', '' => '斛', '' => '斟', '' => '斫', '' => '斷', '' => '旃', '' => '旆', '' => '旁', '' => '旄', '' => '旌', '' => '旒', '' => '旛', '' => '旙', '' => '无', '' => '旡', '' => '旱', '' => '杲', '' => '昊', '' => '昃', '' => '旻', '' => '杳', '' => '昵', '' => '昶', '' => '昴', '' => '昜', '' => '晏', '' => '晄', '' => '晉', '' => '晁', '' => '晞', '' => '晝', '' => '晤', '' => '晧', '' => '晨', '' => '晟', '' => '晢', '' => '晰', '' => '暃', '' => '暈', '' => '暎', '' => '暉', '' => '暄', '' => '暘', '' => '暝', '' => '曁', '' => '暹', '' => '曉', '' => '暾', '' => '暼', '@' => '曄', 'A' => '暸', 'B' => '曖', 'C' => '曚', 'D' => '曠', 'E' => '昿', 'F' => '曦', 'G' => '曩', 'H' => '曰', 'I' => '曵', 'J' => '曷', 'K' => '朏', 'L' => '朖', 'M' => '朞', 'N' => '朦', 'O' => '朧', 'P' => '霸', 'Q' => '朮', 'R' => '朿', 'S' => '朶', 'T' => '杁', 'U' => '朸', 'V' => '朷', 'W' => '杆', 'X' => '杞', 'Y' => '杠', 'Z' => '杙', '[' => '杣', '\\' => '杤', ']' => '枉', '^' => '杰', '_' => '枩', '`' => '杼', 'a' => '杪', 'b' => '枌', 'c' => '枋', 'd' => '枦', 'e' => '枡', 'f' => '枅', 'g' => '枷', 'h' => '柯', 'i' => '枴', 'j' => '柬', 'k' => '枳', 'l' => '柩', 'm' => '枸', 'n' => '柤', 'o' => '柞', 'p' => '柝', 'q' => '柢', 'r' => '柮', 's' => '枹', 't' => '柎', 'u' => '柆', 'v' => '柧', 'w' => '檜', 'x' => '栞', 'y' => '框', 'z' => '栩', '{' => '桀', '|' => '桍', '}' => '栲', '~' => '桎', '' => '梳', '' => '栫', '' => '桙', '' => '档', '' => '桷', '' => '桿', '' => '梟', '' => '梏', '' => '梭', '' => '梔', '' => '條', '' => '梛', '' => '梃', '' => '檮', '' => '梹', '' => '桴', '' => '梵', '' => '梠', '' => '梺', '' => '椏', '' => '梍', '' => '桾', '' => '椁', '' => '棊', '' => '椈', '' => '棘', '' => '椢', '' => '椦', '' => '棡', '' => '椌', '' => '棍', '' => '棔', '' => '棧', '' => '棕', '' => '椶', '' => '椒', '' => '椄', '' => '棗', '' => '棣', '' => '椥', '' => '棹', '' => '棠', '' => '棯', '' => '椨', '' => '椪', '' => '椚', '' => '椣', '' => '椡', '' => '棆', '' => '楹', '' => '楷', '' => '楜', '' => '楸', '' => '楫', '' => '楔', '' => '楾', '' => '楮', '' => '椹', '' => '楴', '' => '椽', '' => '楙', '' => '椰', '' => '楡', '' => '楞', '' => '楝', '' => '榁', '' => '楪', '' => '榲', '' => '榮', '' => '槐', '' => '榿', '' => '槁', '' => '槓', '' => '榾', '' => '槎', '' => '寨', '' => '槊', '' => '槝', '' => '榻', '' => '槃', '' => '榧', '' => '樮', '' => '榑', '' => '榠', '' => '榜', '' => '榕', '' => '榴', '' => '槞', '' => '槨', '' => '樂', '' => '樛', '' => '槿', '' => '權', '' => '槹', '' => '槲', '' => '槧', '' => '樅', '' => '榱', '' => '樞', '' => '槭', '' => '樔', '' => '槫', '' => '樊', '' => '樒', '' => '櫁', '' => '樣', '' => '樓', '' => '橄', '' => '樌', '' => '橲', '' => '樶', '' => '橸', '' => '橇', '' => '橢', '' => '橙', '' => '橦', '' => '橈', '' => '樸', '' => '樢', '' => '檐', '' => '檍', '' => '檠', '' => '檄', '' => '檢', '' => '檣', '@' => '檗', 'A' => '蘗', 'B' => '檻', 'C' => '櫃', 'D' => '櫂', 'E' => '檸', 'F' => '檳', 'G' => '檬', 'H' => '櫞', 'I' => '櫑', 'J' => '櫟', 'K' => '檪', 'L' => '櫚', 'M' => '櫪', 'N' => '櫻', 'O' => '欅', 'P' => '蘖', 'Q' => '櫺', 'R' => '欒', 'S' => '欖', 'T' => '鬱', 'U' => '欟', 'V' => '欸', 'W' => '欷', 'X' => '盜', 'Y' => '欹', 'Z' => '飮', '[' => '歇', '\\' => '歃', ']' => '歉', '^' => '歐', '_' => '歙', '`' => '歔', 'a' => '歛', 'b' => '歟', 'c' => '歡', 'd' => '歸', 'e' => '歹', 'f' => '歿', 'g' => '殀', 'h' => '殄', 'i' => '殃', 'j' => '殍', 'k' => '殘', 'l' => '殕', 'm' => '殞', 'n' => '殤', 'o' => '殪', 'p' => '殫', 'q' => '殯', 'r' => '殲', 's' => '殱', 't' => '殳', 'u' => '殷', 'v' => '殼', 'w' => '毆', 'x' => '毋', 'y' => '毓', 'z' => '毟', '{' => '毬', '|' => '毫', '}' => '毳', '~' => '毯', '' => '麾', '' => '氈', '' => '氓', '' => '气', '' => '氛', '' => '氤', '' => '氣', '' => '汞', '' => '汕', '' => '汢', '' => '汪', '' => '沂', '' => '沍', '' => '沚', '' => '沁', '' => '沛', '' => '汾', '' => '汨', '' => '汳', '' => '沒', '' => '沐', '' => '泄', '' => '泱', '' => '泓', '' => '沽', '' => '泗', '' => '泅', '' => '泝', '' => '沮', '' => '沱', '' => '沾', '' => '沺', '' => '泛', '' => '泯', '' => '泙', '' => '泪', '' => '洟', '' => '衍', '' => '洶', '' => '洫', '' => '洽', '' => '洸', '' => '洙', '' => '洵', '' => '洳', '' => '洒', '' => '洌', '' => '浣', '' => '涓', '' => '浤', '' => '浚', '' => '浹', '' => '浙', '' => '涎', '' => '涕', '' => '濤', '' => '涅', '' => '淹', '' => '渕', '' => '渊', '' => '涵', '' => '淇', '' => '淦', '' => '涸', '' => '淆', '' => '淬', '' => '淞', '' => '淌', '' => '淨', '' => '淒', '' => '淅', '' => '淺', '' => '淙', '' => '淤', '' => '淕', '' => '淪', '' => '淮', '' => '渭', '' => '湮', '' => '渮', '' => '渙', '' => '湲', '' => '湟', '' => '渾', '' => '渣', '' => '湫', '' => '渫', '' => '湶', '' => '湍', '' => '渟', '' => '湃', '' => '渺', '' => '湎', '' => '渤', '' => '滿', '' => '渝', '' => '游', '' => '溂', '' => '溪', '' => '溘', '' => '滉', '' => '溷', '' => '滓', '' => '溽', '' => '溯', '' => '滄', '' => '溲', '' => '滔', '' => '滕', '' => '溏', '' => '溥', '' => '滂', '' => '溟', '' => '潁', '' => '漑', '' => '灌', '' => '滬', '' => '滸', '' => '滾', '' => '漿', '' => '滲', '' => '漱', '' => '滯', '' => '漲', '' => '滌', '@' => '漾', 'A' => '漓', 'B' => '滷', 'C' => '澆', 'D' => '潺', 'E' => '潸', 'F' => '澁', 'G' => '澀', 'H' => '潯', 'I' => '潛', 'J' => '濳', 'K' => '潭', 'L' => '澂', 'M' => '潼', 'N' => '潘', 'O' => '澎', 'P' => '澑', 'Q' => '濂', 'R' => '潦', 'S' => '澳', 'T' => '澣', 'U' => '澡', 'V' => '澤', 'W' => '澹', 'X' => '濆', 'Y' => '澪', 'Z' => '濟', '[' => '濕', '\\' => '濬', ']' => '濔', '^' => '濘', '_' => '濱', '`' => '濮', 'a' => '濛', 'b' => '瀉', 'c' => '瀋', 'd' => '濺', 'e' => '瀑', 'f' => '瀁', 'g' => '瀏', 'h' => '濾', 'i' => '瀛', 'j' => '瀚', 'k' => '潴', 'l' => '瀝', 'm' => '瀘', 'n' => '瀟', 'o' => '瀰', 'p' => '瀾', 'q' => '瀲', 'r' => '灑', 's' => '灣', 't' => '炙', 'u' => '炒', 'v' => '炯', 'w' => '烱', 'x' => '炬', 'y' => '炸', 'z' => '炳', '{' => '炮', '|' => '烟', '}' => '烋', '~' => '烝', '' => '烙', '' => '焉', '' => '烽', '' => '焜', '' => '焙', '' => '煥', '' => '煕', '' => '熈', '' => '煦', '' => '煢', '' => '煌', '' => '煖', '' => '煬', '' => '熏', '' => '燻', '' => '熄', '' => '熕', '' => '熨', '' => '熬', '' => '燗', '' => '熹', '' => '熾', '' => '燒', '' => '燉', '' => '燔', '' => '燎', '' => '燠', '' => '燬', '' => '燧', '' => '燵', '' => '燼', '' => '燹', '' => '燿', '' => '爍', '' => '爐', '' => '爛', '' => '爨', '' => '爭', '' => '爬', '' => '爰', '' => '爲', '' => '爻', '' => '爼', '' => '爿', '' => '牀', '' => '牆', '' => '牋', '' => '牘', '' => '牴', '' => '牾', '' => '犂', '' => '犁', '' => '犇', '' => '犒', '' => '犖', '' => '犢', '' => '犧', '' => '犹', '' => '犲', '' => '狃', '' => '狆', '' => '狄', '' => '狎', '' => '狒', '' => '狢', '' => '狠', '' => '狡', '' => '狹', '' => '狷', '' => '倏', '' => '猗', '' => '猊', '' => '猜', '' => '猖', '' => '猝', '' => '猴', '' => '猯', '' => '猩', '' => '猥', '' => '猾', '' => '獎', '' => '獏', '' => '默', '' => '獗', '' => '獪', '' => '獨', '' => '獰', '' => '獸', '' => '獵', '' => '獻', '' => '獺', '' => '珈', '' => '玳', '' => '珎', '' => '玻', '' => '珀', '' => '珥', '' => '珮', '' => '珞', '' => '璢', '' => '琅', '' => '瑯', '' => '琥', '' => '珸', '' => '琲', '' => '琺', '' => '瑕', '' => '琿', '' => '瑟', '' => '瑙', '' => '瑁', '' => '瑜', '' => '瑩', '' => '瑰', '' => '瑣', '' => '瑪', '' => '瑶', '' => '瑾', '' => '璋', '' => '璞', '' => '璧', '' => '瓊', '' => '瓏', '' => '瓔', '' => '珱', '@' => '瓠', 'A' => '瓣', 'B' => '瓧', 'C' => '瓩', 'D' => '瓮', 'E' => '瓲', 'F' => '瓰', 'G' => '瓱', 'H' => '瓸', 'I' => '瓷', 'J' => '甄', 'K' => '甃', 'L' => '甅', 'M' => '甌', 'N' => '甎', 'O' => '甍', 'P' => '甕', 'Q' => '甓', 'R' => '甞', 'S' => '甦', 'T' => '甬', 'U' => '甼', 'V' => '畄', 'W' => '畍', 'X' => '畊', 'Y' => '畉', 'Z' => '畛', '[' => '畆', '\\' => '畚', ']' => '畩', '^' => '畤', '_' => '畧', '`' => '畫', 'a' => '畭', 'b' => '畸', 'c' => '當', 'd' => '疆', 'e' => '疇', 'f' => '畴', 'g' => '疊', 'h' => '疉', 'i' => '疂', 'j' => '疔', 'k' => '疚', 'l' => '疝', 'm' => '疥', 'n' => '疣', 'o' => '痂', 'p' => '疳', 'q' => '痃', 'r' => '疵', 's' => '疽', 't' => '疸', 'u' => '疼', 'v' => '疱', 'w' => '痍', 'x' => '痊', 'y' => '痒', 'z' => '痙', '{' => '痣', '|' => '痞', '}' => '痾', '~' => '痿', '' => '痼', '' => '瘁', '' => '痰', '' => '痺', '' => '痲', '' => '痳', '' => '瘋', '' => '瘍', '' => '瘉', '' => '瘟', '' => '瘧', '' => '瘠', '' => '瘡', '' => '瘢', '' => '瘤', '' => '瘴', '' => '瘰', '' => '瘻', '' => '癇', '' => '癈', '' => '癆', '' => '癜', '' => '癘', '' => '癡', '' => '癢', '' => '癨', '' => '癩', '' => '癪', '' => '癧', '' => '癬', '' => '癰', '' => '癲', '' => '癶', '' => '癸', '' => '發', '' => '皀', '' => '皃', '' => '皈', '' => '皋', '' => '皎', '' => '皖', '' => '皓', '' => '皙', '' => '皚', '' => '皰', '' => '皴', '' => '皸', '' => '皹', '' => '皺', '' => '盂', '' => '盍', '' => '盖', '' => '盒', '' => '盞', '' => '盡', '' => '盥', '' => '盧', '' => '盪', '' => '蘯', '' => '盻', '' => '眈', '' => '眇', '' => '眄', '' => '眩', '' => '眤', '' => '眞', '' => '眥', '' => '眦', '' => '眛', '' => '眷', '' => '眸', '' => '睇', '' => '睚', '' => '睨', '' => '睫', '' => '睛', '' => '睥', '' => '睿', '' => '睾', '' => '睹', '' => '瞎', '' => '瞋', '' => '瞑', '' => '瞠', '' => '瞞', '' => '瞰', '' => '瞶', '' => '瞹', '' => '瞿', '' => '瞼', '' => '瞽', '' => '瞻', '' => '矇', '' => '矍', '' => '矗', '' => '矚', '' => '矜', '' => '矣', '' => '矮', '' => '矼', '' => '砌', '' => '砒', '' => '礦', '' => '砠', '' => '礪', '' => '硅', '' => '碎', '' => '硴', '' => '碆', '' => '硼', '' => '碚', '' => '碌', '' => '碣', '' => '碵', '' => '碪', '' => '碯', '' => '磑', '' => '磆', '' => '磋', '' => '磔', '' => '碾', '' => '碼', '' => '磅', '' => '磊', '' => '磬', '@' => '磧', 'A' => '磚', 'B' => '磽', 'C' => '磴', 'D' => '礇', 'E' => '礒', 'F' => '礑', 'G' => '礙', 'H' => '礬', 'I' => '礫', 'J' => '祀', 'K' => '祠', 'L' => '祗', 'M' => '祟', 'N' => '祚', 'O' => '祕', 'P' => '祓', 'Q' => '祺', 'R' => '祿', 'S' => '禊', 'T' => '禝', 'U' => '禧', 'V' => '齋', 'W' => '禪', 'X' => '禮', 'Y' => '禳', 'Z' => '禹', '[' => '禺', '\\' => '秉', ']' => '秕', '^' => '秧', '_' => '秬', '`' => '秡', 'a' => '秣', 'b' => '稈', 'c' => '稍', 'd' => '稘', 'e' => '稙', 'f' => '稠', 'g' => '稟', 'h' => '禀', 'i' => '稱', 'j' => '稻', 'k' => '稾', 'l' => '稷', 'm' => '穃', 'n' => '穗', 'o' => '穉', 'p' => '穡', 'q' => '穢', 'r' => '穩', 's' => '龝', 't' => '穰', 'u' => '穹', 'v' => '穽', 'w' => '窈', 'x' => '窗', 'y' => '窕', 'z' => '窘', '{' => '窖', '|' => '窩', '}' => '竈', '~' => '窰', '' => '窶', '' => '竅', '' => '竄', '' => '窿', '' => '邃', '' => '竇', '' => '竊', '' => '竍', '' => '竏', '' => '竕', '' => '竓', '' => '站', '' => '竚', '' => '竝', '' => '竡', '' => '竢', '' => '竦', '' => '竭', '' => '竰', '' => '笂', '' => '笏', '' => '笊', '' => '笆', '' => '笳', '' => '笘', '' => '笙', '' => '笞', '' => '笵', '' => '笨', '' => '笶', '' => '筐', '' => '筺', '' => '笄', '' => '筍', '' => '笋', '' => '筌', '' => '筅', '' => '筵', '' => '筥', '' => '筴', '' => '筧', '' => '筰', '' => '筱', '' => '筬', '' => '筮', '' => '箝', '' => '箘', '' => '箟', '' => '箍', '' => '箜', '' => '箚', '' => '箋', '' => '箒', '' => '箏', '' => '筝', '' => '箙', '' => '篋', '' => '篁', '' => '篌', '' => '篏', '' => '箴', '' => '篆', '' => '篝', '' => '篩', '' => '簑', '' => '簔', '' => '篦', '' => '篥', '' => '籠', '' => '簀', '' => '簇', '' => '簓', '' => '篳', '' => '篷', '' => '簗', '' => '簍', '' => '篶', '' => '簣', '' => '簧', '' => '簪', '' => '簟', '' => '簷', '' => '簫', '' => '簽', '' => '籌', '' => '籃', '' => '籔', '' => '籏', '' => '籀', '' => '籐', '' => '籘', '' => '籟', '' => '籤', '' => '籖', '' => '籥', '' => '籬', '' => '籵', '' => '粃', '' => '粐', '' => '粤', '' => '粭', '' => '粢', '' => '粫', '' => '粡', '' => '粨', '' => '粳', '' => '粲', '' => '粱', '' => '粮', '' => '粹', '' => '粽', '' => '糀', '' => '糅', '' => '糂', '' => '糘', '' => '糒', '' => '糜', '' => '糢', '' => '鬻', '' => '糯', '' => '糲', '' => '糴', '' => '糶', '' => '糺', '' => '紆', '@' => '紂', 'A' => '紜', 'B' => '紕', 'C' => '紊', 'D' => '絅', 'E' => '絋', 'F' => '紮', 'G' => '紲', 'H' => '紿', 'I' => '紵', 'J' => '絆', 'K' => '絳', 'L' => '絖', 'M' => '絎', 'N' => '絲', 'O' => '絨', 'P' => '絮', 'Q' => '絏', 'R' => '絣', 'S' => '經', 'T' => '綉', 'U' => '絛', 'V' => '綏', 'W' => '絽', 'X' => '綛', 'Y' => '綺', 'Z' => '綮', '[' => '綣', '\\' => '綵', ']' => '緇', '^' => '綽', '_' => '綫', '`' => '總', 'a' => '綢', 'b' => '綯', 'c' => '緜', 'd' => '綸', 'e' => '綟', 'f' => '綰', 'g' => '緘', 'h' => '緝', 'i' => '緤', 'j' => '緞', 'k' => '緻', 'l' => '緲', 'm' => '緡', 'n' => '縅', 'o' => '縊', 'p' => '縣', 'q' => '縡', 'r' => '縒', 's' => '縱', 't' => '縟', 'u' => '縉', 'v' => '縋', 'w' => '縢', 'x' => '繆', 'y' => '繦', 'z' => '縻', '{' => '縵', '|' => '縹', '}' => '繃', '~' => '縷', '' => '縲', '' => '縺', '' => '繧', '' => '繝', '' => '繖', '' => '繞', '' => '繙', '' => '繚', '' => '繹', '' => '繪', '' => '繩', '' => '繼', '' => '繻', '' => '纃', '' => '緕', '' => '繽', '' => '辮', '' => '繿', '' => '纈', '' => '纉', '' => '續', '' => '纒', '' => '纐', '' => '纓', '' => '纔', '' => '纖', '' => '纎', '' => '纛', '' => '纜', '' => '缸', '' => '缺', '' => '罅', '' => '罌', '' => '罍', '' => '罎', '' => '罐', '' => '网', '' => '罕', '' => '罔', '' => '罘', '' => '罟', '' => '罠', '' => '罨', '' => '罩', '' => '罧', '' => '罸', '' => '羂', '' => '羆', '' => '羃', '' => '羈', '' => '羇', '' => '羌', '' => '羔', '' => '羞', '' => '羝', '' => '羚', '' => '羣', '' => '羯', '' => '羲', '' => '羹', '' => '羮', '' => '羶', '' => '羸', '' => '譱', '' => '翅', '' => '翆', '' => '翊', '' => '翕', '' => '翔', '' => '翡', '' => '翦', '' => '翩', '' => '翳', '' => '翹', '' => '飜', '' => '耆', '' => '耄', '' => '耋', '' => '耒', '' => '耘', '' => '耙', '' => '耜', '' => '耡', '' => '耨', '' => '耿', '' => '耻', '' => '聊', '' => '聆', '' => '聒', '' => '聘', '' => '聚', '' => '聟', '' => '聢', '' => '聨', '' => '聳', '' => '聲', '' => '聰', '' => '聶', '' => '聹', '' => '聽', '' => '聿', '' => '肄', '' => '肆', '' => '肅', '' => '肛', '' => '肓', '' => '肚', '' => '肭', '' => '冐', '' => '肬', '' => '胛', '' => '胥', '' => '胙', '' => '胝', '' => '胄', '' => '胚', '' => '胖', '' => '脉', '' => '胯', '' => '胱', '' => '脛', '' => '脩', '' => '脣', '' => '脯', '' => '腋', '@' => '隋', 'A' => '腆', 'B' => '脾', 'C' => '腓', 'D' => '腑', 'E' => '胼', 'F' => '腱', 'G' => '腮', 'H' => '腥', 'I' => '腦', 'J' => '腴', 'K' => '膃', 'L' => '膈', 'M' => '膊', 'N' => '膀', 'O' => '膂', 'P' => '膠', 'Q' => '膕', 'R' => '膤', 'S' => '膣', 'T' => '腟', 'U' => '膓', 'V' => '膩', 'W' => '膰', 'X' => '膵', 'Y' => '膾', 'Z' => '膸', '[' => '膽', '\\' => '臀', ']' => '臂', '^' => '膺', '_' => '臉', '`' => '臍', 'a' => '臑', 'b' => '臙', 'c' => '臘', 'd' => '臈', 'e' => '臚', 'f' => '臟', 'g' => '臠', 'h' => '臧', 'i' => '臺', 'j' => '臻', 'k' => '臾', 'l' => '舁', 'm' => '舂', 'n' => '舅', 'o' => '與', 'p' => '舊', 'q' => '舍', 'r' => '舐', 's' => '舖', 't' => '舩', 'u' => '舫', 'v' => '舸', 'w' => '舳', 'x' => '艀', 'y' => '艙', 'z' => '艘', '{' => '艝', '|' => '艚', '}' => '艟', '~' => '艤', '' => '艢', '' => '艨', '' => '艪', '' => '艫', '' => '舮', '' => '艱', '' => '艷', '' => '艸', '' => '艾', '' => '芍', '' => '芒', '' => '芫', '' => '芟', '' => '芻', '' => '芬', '' => '苡', '' => '苣', '' => '苟', '' => '苒', '' => '苴', '' => '苳', '' => '苺', '' => '莓', '' => '范', '' => '苻', '' => '苹', '' => '苞', '' => '茆', '' => '苜', '' => '茉', '' => '苙', '' => '茵', '' => '茴', '' => '茖', '' => '茲', '' => '茱', '' => '荀', '' => '茹', '' => '荐', '' => '荅', '' => '茯', '' => '茫', '' => '茗', '' => '茘', '' => '莅', '' => '莚', '' => '莪', '' => '莟', '' => '莢', '' => '莖', '' => '茣', '' => '莎', '' => '莇', '' => '莊', '' => '荼', '' => '莵', '' => '荳', '' => '荵', '' => '莠', '' => '莉', '' => '莨', '' => '菴', '' => '萓', '' => '菫', '' => '菎', '' => '菽', '' => '萃', '' => '菘', '' => '萋', '' => '菁', '' => '菷', '' => '萇', '' => '菠', '' => '菲', '' => '萍', '' => '萢', '' => '萠', '' => '莽', '' => '萸', '' => '蔆', '' => '菻', '' => '葭', '' => '萪', '' => '萼', '' => '蕚', '' => '蒄', '' => '葷', '' => '葫', '' => '蒭', '' => '葮', '' => '蒂', '' => '葩', '' => '葆', '' => '萬', '' => '葯', '' => '葹', '' => '萵', '' => '蓊', '' => '葢', '' => '蒹', '' => '蒿', '' => '蒟', '' => '蓙', '' => '蓍', '' => '蒻', '' => '蓚', '' => '蓐', '' => '蓁', '' => '蓆', '' => '蓖', '' => '蒡', '' => '蔡', '' => '蓿', '' => '蓴', '' => '蔗', '' => '蔘', '' => '蔬', '' => '蔟', '' => '蔕', '' => '蔔', '' => '蓼', '' => '蕀', '' => '蕣', '' => '蕘', '' => '蕈', '@' => '蕁', 'A' => '蘂', 'B' => '蕋', 'C' => '蕕', 'D' => '薀', 'E' => '薤', 'F' => '薈', 'G' => '薑', 'H' => '薊', 'I' => '薨', 'J' => '蕭', 'K' => '薔', 'L' => '薛', 'M' => '藪', 'N' => '薇', 'O' => '薜', 'P' => '蕷', 'Q' => '蕾', 'R' => '薐', 'S' => '藉', 'T' => '薺', 'U' => '藏', 'V' => '薹', 'W' => '藐', 'X' => '藕', 'Y' => '藝', 'Z' => '藥', '[' => '藜', '\\' => '藹', ']' => '蘊', '^' => '蘓', '_' => '蘋', '`' => '藾', 'a' => '藺', 'b' => '蘆', 'c' => '蘢', 'd' => '蘚', 'e' => '蘰', 'f' => '蘿', 'g' => '虍', 'h' => '乕', 'i' => '虔', 'j' => '號', 'k' => '虧', 'l' => '虱', 'm' => '蚓', 'n' => '蚣', 'o' => '蚩', 'p' => '蚪', 'q' => '蚋', 'r' => '蚌', 's' => '蚶', 't' => '蚯', 'u' => '蛄', 'v' => '蛆', 'w' => '蚰', 'x' => '蛉', 'y' => '蠣', 'z' => '蚫', '{' => '蛔', '|' => '蛞', '}' => '蛩', '~' => '蛬', '' => '蛟', '' => '蛛', '' => '蛯', '' => '蜒', '' => '蜆', '' => '蜈', '' => '蜀', '' => '蜃', '' => '蛻', '' => '蜑', '' => '蜉', '' => '蜍', '' => '蛹', '' => '蜊', '' => '蜴', '' => '蜿', '' => '蜷', '' => '蜻', '' => '蜥', '' => '蜩', '' => '蜚', '' => '蝠', '' => '蝟', '' => '蝸', '' => '蝌', '' => '蝎', '' => '蝴', '' => '蝗', '' => '蝨', '' => '蝮', '' => '蝙', '' => '蝓', '' => '蝣', '' => '蝪', '' => '蠅', '' => '螢', '' => '螟', '' => '螂', '' => '螯', '' => '蟋', '' => '螽', '' => '蟀', '' => '蟐', '' => '雖', '' => '螫', '' => '蟄', '' => '螳', '' => '蟇', '' => '蟆', '' => '螻', '' => '蟯', '' => '蟲', '' => '蟠', '' => '蠏', '' => '蠍', '' => '蟾', '' => '蟶', '' => '蟷', '' => '蠎', '' => '蟒', '' => '蠑', '' => '蠖', '' => '蠕', '' => '蠢', '' => '蠡', '' => '蠱', '' => '蠶', '' => '蠹', '' => '蠧', '' => '蠻', '' => '衄', '' => '衂', '' => '衒', '' => '衙', '' => '衞', '' => '衢', '' => '衫', '' => '袁', '' => '衾', '' => '袞', '' => '衵', '' => '衽', '' => '袵', '' => '衲', '' => '袂', '' => '袗', '' => '袒', '' => '袮', '' => '袙', '' => '袢', '' => '袍', '' => '袤', '' => '袰', '' => '袿', '' => '袱', '' => '裃', '' => '裄', '' => '裔', '' => '裘', '' => '裙', '' => '裝', '' => '裹', '' => '褂', '' => '裼', '' => '裴', '' => '裨', '' => '裲', '' => '褄', '' => '褌', '' => '褊', '' => '褓', '' => '襃', '' => '褞', '' => '褥', '' => '褪', '' => '褫', '' => '襁', '' => '襄', '' => '褻', '' => '褶', '' => '褸', '' => '襌', '' => '褝', '' => '襠', '' => '襞', '@' => '襦', 'A' => '襤', 'B' => '襭', 'C' => '襪', 'D' => '襯', 'E' => '襴', 'F' => '襷', 'G' => '襾', 'H' => '覃', 'I' => '覈', 'J' => '覊', 'K' => '覓', 'L' => '覘', 'M' => '覡', 'N' => '覩', 'O' => '覦', 'P' => '覬', 'Q' => '覯', 'R' => '覲', 'S' => '覺', 'T' => '覽', 'U' => '覿', 'V' => '觀', 'W' => '觚', 'X' => '觜', 'Y' => '觝', 'Z' => '觧', '[' => '觴', '\\' => '觸', ']' => '訃', '^' => '訖', '_' => '訐', '`' => '訌', 'a' => '訛', 'b' => '訝', 'c' => '訥', 'd' => '訶', 'e' => '詁', 'f' => '詛', 'g' => '詒', 'h' => '詆', 'i' => '詈', 'j' => '詼', 'k' => '詭', 'l' => '詬', 'm' => '詢', 'n' => '誅', 'o' => '誂', 'p' => '誄', 'q' => '誨', 'r' => '誡', 's' => '誑', 't' => '誥', 'u' => '誦', 'v' => '誚', 'w' => '誣', 'x' => '諄', 'y' => '諍', 'z' => '諂', '{' => '諚', '|' => '諫', '}' => '諳', '~' => '諧', '' => '諤', '' => '諱', '' => '謔', '' => '諠', '' => '諢', '' => '諷', '' => '諞', '' => '諛', '' => '謌', '' => '謇', '' => '謚', '' => '諡', '' => '謖', '' => '謐', '' => '謗', '' => '謠', '' => '謳', '' => '鞫', '' => '謦', '' => '謫', '' => '謾', '' => '謨', '' => '譁', '' => '譌', '' => '譏', '' => '譎', '' => '證', '' => '譖', '' => '譛', '' => '譚', '' => '譫', '' => '譟', '' => '譬', '' => '譯', '' => '譴', '' => '譽', '' => '讀', '' => '讌', '' => '讎', '' => '讒', '' => '讓', '' => '讖', '' => '讙', '' => '讚', '' => '谺', '' => '豁', '' => '谿', '' => '豈', '' => '豌', '' => '豎', '' => '豐', '' => '豕', '' => '豢', '' => '豬', '' => '豸', '' => '豺', '' => '貂', '' => '貉', '' => '貅', '' => '貊', '' => '貍', '' => '貎', '' => '貔', '' => '豼', '' => '貘', '' => '戝', '' => '貭', '' => '貪', '' => '貽', '' => '貲', '' => '貳', '' => '貮', '' => '貶', '' => '賈', '' => '賁', '' => '賤', '' => '賣', '' => '賚', '' => '賽', '' => '賺', '' => '賻', '' => '贄', '' => '贅', '' => '贊', '' => '贇', '' => '贏', '' => '贍', '' => '贐', '' => '齎', '' => '贓', '' => '賍', '' => '贔', '' => '贖', '' => '赧', '' => '赭', '' => '赱', '' => '赳', '' => '趁', '' => '趙', '' => '跂', '' => '趾', '' => '趺', '' => '跏', '' => '跚', '' => '跖', '' => '跌', '' => '跛', '' => '跋', '' => '跪', '' => '跫', '' => '跟', '' => '跣', '' => '跼', '' => '踈', '' => '踉', '' => '跿', '' => '踝', '' => '踞', '' => '踐', '' => '踟', '' => '蹂', '' => '踵', '' => '踰', '' => '踴', '' => '蹊', '@' => '蹇', 'A' => '蹉', 'B' => '蹌', 'C' => '蹐', 'D' => '蹈', 'E' => '蹙', 'F' => '蹤', 'G' => '蹠', 'H' => '踪', 'I' => '蹣', 'J' => '蹕', 'K' => '蹶', 'L' => '蹲', 'M' => '蹼', 'N' => '躁', 'O' => '躇', 'P' => '躅', 'Q' => '躄', 'R' => '躋', 'S' => '躊', 'T' => '躓', 'U' => '躑', 'V' => '躔', 'W' => '躙', 'X' => '躪', 'Y' => '躡', 'Z' => '躬', '[' => '躰', '\\' => '軆', ']' => '躱', '^' => '躾', '_' => '軅', '`' => '軈', 'a' => '軋', 'b' => '軛', 'c' => '軣', 'd' => '軼', 'e' => '軻', 'f' => '軫', 'g' => '軾', 'h' => '輊', 'i' => '輅', 'j' => '輕', 'k' => '輒', 'l' => '輙', 'm' => '輓', 'n' => '輜', 'o' => '輟', 'p' => '輛', 'q' => '輌', 'r' => '輦', 's' => '輳', 't' => '輻', 'u' => '輹', 'v' => '轅', 'w' => '轂', 'x' => '輾', 'y' => '轌', 'z' => '轉', '{' => '轆', '|' => '轎', '}' => '轗', '~' => '轜', '' => '轢', '' => '轣', '' => '轤', '' => '辜', '' => '辟', '' => '辣', '' => '辭', '' => '辯', '' => '辷', '' => '迚', '' => '迥', '' => '迢', '' => '迪', '' => '迯', '' => '邇', '' => '迴', '' => '逅', '' => '迹', '' => '迺', '' => '逑', '' => '逕', '' => '逡', '' => '逍', '' => '逞', '' => '逖', '' => '逋', '' => '逧', '' => '逶', '' => '逵', '' => '逹', '' => '迸', '' => '遏', '' => '遐', '' => '遑', '' => '遒', '' => '逎', '' => '遉', '' => '逾', '' => '遖', '' => '遘', '' => '遞', '' => '遨', '' => '遯', '' => '遶', '' => '隨', '' => '遲', '' => '邂', '' => '遽', '' => '邁', '' => '邀', '' => '邊', '' => '邉', '' => '邏', '' => '邨', '' => '邯', '' => '邱', '' => '邵', '' => '郢', '' => '郤', '' => '扈', '' => '郛', '' => '鄂', '' => '鄒', '' => '鄙', '' => '鄲', '' => '鄰', '' => '酊', '' => '酖', '' => '酘', '' => '酣', '' => '酥', '' => '酩', '' => '酳', '' => '酲', '' => '醋', '' => '醉', '' => '醂', '' => '醢', '' => '醫', '' => '醯', '' => '醪', '' => '醵', '' => '醴', '' => '醺', '' => '釀', '' => '釁', '' => '釉', '' => '釋', '' => '釐', '' => '釖', '' => '釟', '' => '釡', '' => '釛', '' => '釼', '' => '釵', '' => '釶', '' => '鈞', '' => '釿', '' => '鈔', '' => '鈬', '' => '鈕', '' => '鈑', '' => '鉞', '' => '鉗', '' => '鉅', '' => '鉉', '' => '鉤', '' => '鉈', '' => '銕', '' => '鈿', '' => '鉋', '' => '鉐', '' => '銜', '' => '銖', '' => '銓', '' => '銛', '' => '鉚', '' => '鋏', '' => '銹', '' => '銷', '' => '鋩', '' => '錏', '' => '鋺', '' => '鍄', '' => '錮', '@' => '錙', 'A' => '錢', 'B' => '錚', 'C' => '錣', 'D' => '錺', 'E' => '錵', 'F' => '錻', 'G' => '鍜', 'H' => '鍠', 'I' => '鍼', 'J' => '鍮', 'K' => '鍖', 'L' => '鎰', 'M' => '鎬', 'N' => '鎭', 'O' => '鎔', 'P' => '鎹', 'Q' => '鏖', 'R' => '鏗', 'S' => '鏨', 'T' => '鏥', 'U' => '鏘', 'V' => '鏃', 'W' => '鏝', 'X' => '鏐', 'Y' => '鏈', 'Z' => '鏤', '[' => '鐚', '\\' => '鐔', ']' => '鐓', '^' => '鐃', '_' => '鐇', '`' => '鐐', 'a' => '鐶', 'b' => '鐫', 'c' => '鐵', 'd' => '鐡', 'e' => '鐺', 'f' => '鑁', 'g' => '鑒', 'h' => '鑄', 'i' => '鑛', 'j' => '鑠', 'k' => '鑢', 'l' => '鑞', 'm' => '鑪', 'n' => '鈩', 'o' => '鑰', 'p' => '鑵', 'q' => '鑷', 'r' => '鑽', 's' => '鑚', 't' => '鑼', 'u' => '鑾', 'v' => '钁', 'w' => '鑿', 'x' => '閂', 'y' => '閇', 'z' => '閊', '{' => '閔', '|' => '閖', '}' => '閘', '~' => '閙', '' => '閠', '' => '閨', '' => '閧', '' => '閭', '' => '閼', '' => '閻', '' => '閹', '' => '閾', '' => '闊', '' => '濶', '' => '闃', '' => '闍', '' => '闌', '' => '闕', '' => '闔', '' => '闖', '' => '關', '' => '闡', '' => '闥', '' => '闢', '' => '阡', '' => '阨', '' => '阮', '' => '阯', '' => '陂', '' => '陌', '' => '陏', '' => '陋', '' => '陷', '' => '陜', '' => '陞', '' => '陝', '' => '陟', '' => '陦', '' => '陲', '' => '陬', '' => '隍', '' => '隘', '' => '隕', '' => '隗', '' => '險', '' => '隧', '' => '隱', '' => '隲', '' => '隰', '' => '隴', '' => '隶', '' => '隸', '' => '隹', '' => '雎', '' => '雋', '' => '雉', '' => '雍', '' => '襍', '' => '雜', '' => '霍', '' => '雕', '' => '雹', '' => '霄', '' => '霆', '' => '霈', '' => '霓', '' => '霎', '' => '霑', '' => '霏', '' => '霖', '' => '霙', '' => '霤', '' => '霪', '' => '霰', '' => '霹', '' => '霽', '' => '霾', '' => '靄', '' => '靆', '' => '靈', '' => '靂', '' => '靉', '' => '靜', '' => '靠', '' => '靤', '' => '靦', '' => '靨', '' => '勒', '' => '靫', '' => '靱', '' => '靹', '' => '鞅', '' => '靼', '' => '鞁', '' => '靺', '' => '鞆', '' => '鞋', '' => '鞏', '' => '鞐', '' => '鞜', '' => '鞨', '' => '鞦', '' => '鞣', '' => '鞳', '' => '鞴', '' => '韃', '' => '韆', '' => '韈', '' => '韋', '' => '韜', '' => '韭', '' => '齏', '' => '韲', '' => '竟', '' => '韶', '' => '韵', '' => '頏', '' => '頌', '' => '頸', '' => '頤', '' => '頡', '' => '頷', '' => '頽', '' => '顆', '' => '顏', '' => '顋', '' => '顫', '' => '顯', '' => '顰', '@' => '顱', 'A' => '顴', 'B' => '顳', 'C' => '颪', 'D' => '颯', 'E' => '颱', 'F' => '颶', 'G' => '飄', 'H' => '飃', 'I' => '飆', 'J' => '飩', 'K' => '飫', 'L' => '餃', 'M' => '餉', 'N' => '餒', 'O' => '餔', 'P' => '餘', 'Q' => '餡', 'R' => '餝', 'S' => '餞', 'T' => '餤', 'U' => '餠', 'V' => '餬', 'W' => '餮', 'X' => '餽', 'Y' => '餾', 'Z' => '饂', '[' => '饉', '\\' => '饅', ']' => '饐', '^' => '饋', '_' => '饑', '`' => '饒', 'a' => '饌', 'b' => '饕', 'c' => '馗', 'd' => '馘', 'e' => '馥', 'f' => '馭', 'g' => '馮', 'h' => '馼', 'i' => '駟', 'j' => '駛', 'k' => '駝', 'l' => '駘', 'm' => '駑', 'n' => '駭', 'o' => '駮', 'p' => '駱', 'q' => '駲', 'r' => '駻', 's' => '駸', 't' => '騁', 'u' => '騏', 'v' => '騅', 'w' => '駢', 'x' => '騙', 'y' => '騫', 'z' => '騷', '{' => '驅', '|' => '驂', '}' => '驀', '~' => '驃', '' => '騾', '' => '驕', '' => '驍', '' => '驛', '' => '驗', '' => '驟', '' => '驢', '' => '驥', '' => '驤', '' => '驩', '' => '驫', '' => '驪', '' => '骭', '' => '骰', '' => '骼', '' => '髀', '' => '髏', '' => '髑', '' => '髓', '' => '體', '' => '髞', '' => '髟', '' => '髢', '' => '髣', '' => '髦', '' => '髯', '' => '髫', '' => '髮', '' => '髴', '' => '髱', '' => '髷', '' => '髻', '' => '鬆', '' => '鬘', '' => '鬚', '' => '鬟', '' => '鬢', '' => '鬣', '' => '鬥', '' => '鬧', '' => '鬨', '' => '鬩', '' => '鬪', '' => '鬮', '' => '鬯', '' => '鬲', '' => '魄', '' => '魃', '' => '魏', '' => '魍', '' => '魎', '' => '魑', '' => '魘', '' => '魴', '' => '鮓', '' => '鮃', '' => '鮑', '' => '鮖', '' => '鮗', '' => '鮟', '' => '鮠', '' => '鮨', '' => '鮴', '' => '鯀', '' => '鯊', '' => '鮹', '' => '鯆', '' => '鯏', '' => '鯑', '' => '鯒', '' => '鯣', '' => '鯢', '' => '鯤', '' => '鯔', '' => '鯡', '' => '鰺', '' => '鯲', '' => '鯱', '' => '鯰', '' => '鰕', '' => '鰔', '' => '鰉', '' => '鰓', '' => '鰌', '' => '鰆', '' => '鰈', '' => '鰒', '' => '鰊', '' => '鰄', '' => '鰮', '' => '鰛', '' => '鰥', '' => '鰤', '' => '鰡', '' => '鰰', '' => '鱇', '' => '鰲', '' => '鱆', '' => '鰾', '' => '鱚', '' => '鱠', '' => '鱧', '' => '鱶', '' => '鱸', '' => '鳧', '' => '鳬', '' => '鳰', '' => '鴉', '' => '鴈', '' => '鳫', '' => '鴃', '' => '鴆', '' => '鴪', '' => '鴦', '' => '鶯', '' => '鴣', '' => '鴟', '' => '鵄', '' => '鴕', '' => '鴒', '' => '鵁', '' => '鴿', '' => '鴾', '' => '鵆', '' => '鵈', '@' => '鵝', 'A' => '鵞', 'B' => '鵤', 'C' => '鵑', 'D' => '鵐', 'E' => '鵙', 'F' => '鵲', 'G' => '鶉', 'H' => '鶇', 'I' => '鶫', 'J' => '鵯', 'K' => '鵺', 'L' => '鶚', 'M' => '鶤', 'N' => '鶩', 'O' => '鶲', 'P' => '鷄', 'Q' => '鷁', 'R' => '鶻', 'S' => '鶸', 'T' => '鶺', 'U' => '鷆', 'V' => '鷏', 'W' => '鷂', 'X' => '鷙', 'Y' => '鷓', 'Z' => '鷸', '[' => '鷦', '\\' => '鷭', ']' => '鷯', '^' => '鷽', '_' => '鸚', '`' => '鸛', 'a' => '鸞', 'b' => '鹵', 'c' => '鹹', 'd' => '鹽', 'e' => '麁', 'f' => '麈', 'g' => '麋', 'h' => '麌', 'i' => '麒', 'j' => '麕', 'k' => '麑', 'l' => '麝', 'm' => '麥', 'n' => '麩', 'o' => '麸', 'p' => '麪', 'q' => '麭', 'r' => '靡', 's' => '黌', 't' => '黎', 'u' => '黏', 'v' => '黐', 'w' => '黔', 'x' => '黜', 'y' => '點', 'z' => '黝', '{' => '黠', '|' => '黥', '}' => '黨', '~' => '黯', '' => '黴', '' => '黶', '' => '黷', '' => '黹', '' => '黻', '' => '黼', '' => '黽', '' => '鼇', '' => '鼈', '' => '皷', '' => '鼕', '' => '鼡', '' => '鼬', '' => '鼾', '' => '齊', '' => '齒', '' => '齔', '' => '齣', '' => '齟', '' => '齠', '' => '齡', '' => '齦', '' => '齧', '' => '齬', '' => '齪', '' => '齷', '' => '齲', '' => '齶', '' => '龕', '' => '龜', '' => '龠', '' => '堯', '' => '槇', '' => '遙', '' => '瑤', '' => '凜', '' => '熙', '@' => '纊', 'A' => '褜', 'B' => '鍈', 'C' => '銈', 'D' => '蓜', 'E' => '俉', 'F' => '炻', 'G' => '昱', 'H' => '棈', 'I' => '鋹', 'J' => '曻', 'K' => '彅', 'L' => '丨', 'M' => '仡', 'N' => '仼', 'O' => '伀', 'P' => '伃', 'Q' => '伹', 'R' => '佖', 'S' => '侒', 'T' => '侊', 'U' => '侚', 'V' => '侔', 'W' => '俍', 'X' => '偀', 'Y' => '倢', 'Z' => '俿', '[' => '倞', '\\' => '偆', ']' => '偰', '^' => '偂', '_' => '傔', '`' => '僴', 'a' => '僘', 'b' => '兊', 'c' => '兤', 'd' => '冝', 'e' => '冾', 'f' => '凬', 'g' => '刕', 'h' => '劜', 'i' => '劦', 'j' => '勀', 'k' => '勛', 'l' => '匀', 'm' => '匇', 'n' => '匤', 'o' => '卲', 'p' => '厓', 'q' => '厲', 'r' => '叝', 's' => '﨎', 't' => '咜', 'u' => '咊', 'v' => '咩', 'w' => '哿', 'x' => '喆', 'y' => '坙', 'z' => '坥', '{' => '垬', '|' => '埈', '}' => '埇', '~' => '﨏', '' => '塚', '' => '增', '' => '墲', '' => '夋', '' => '奓', '' => '奛', '' => '奝', '' => '奣', '' => '妤', '' => '妺', '' => '孖', '' => '寀', '' => '甯', '' => '寘', '' => '寬', '' => '尞', '' => '岦', '' => '岺', '' => '峵', '' => '崧', '' => '嵓', '' => '﨑', '' => '嵂', '' => '嵭', '' => '嶸', '' => '嶹', '' => '巐', '' => '弡', '' => '弴', '' => '彧', '' => '德', '' => '忞', '' => '恝', '' => '悅', '' => '悊', '' => '惞', '' => '惕', '' => '愠', '' => '惲', '' => '愑', '' => '愷', '' => '愰', '' => '憘', '' => '戓', '' => '抦', '' => '揵', '' => '摠', '' => '撝', '' => '擎', '' => '敎', '' => '昀', '' => '昕', '' => '昻', '' => '昉', '' => '昮', '' => '昞', '' => '昤', '' => '晥', '' => '晗', '' => '晙', '' => '晴', '' => '晳', '' => '暙', '' => '暠', '' => '暲', '' => '暿', '' => '曺', '' => '朎', '' => '朗', '' => '杦', '' => '枻', '' => '桒', '' => '柀', '' => '栁', '' => '桄', '' => '棏', '' => '﨓', '' => '楨', '' => '﨔', '' => '榘', '' => '槢', '' => '樰', '' => '橫', '' => '橆', '' => '橳', '' => '橾', '' => '櫢', '' => '櫤', '' => '毖', '' => '氿', '' => '汜', '' => '沆', '' => '汯', '' => '泚', '' => '洄', '' => '涇', '' => '浯', '' => '涖', '' => '涬', '' => '淏', '' => '淸', '' => '淲', '' => '淼', '' => '渹', '' => '湜', '' => '渧', '' => '渼', '' => '溿', '' => '澈', '' => '澵', '' => '濵', '' => '瀅', '' => '瀇', '' => '瀨', '' => '炅', '' => '炫', '' => '焏', '' => '焄', '' => '煜', '' => '煆', '' => '煇', '' => '凞', '' => '燁', '' => '燾', '' => '犱', '@' => '犾', 'A' => '猤', 'B' => '猪', 'C' => '獷', 'D' => '玽', 'E' => '珉', 'F' => '珖', 'G' => '珣', 'H' => '珒', 'I' => '琇', 'J' => '珵', 'K' => '琦', 'L' => '琪', 'M' => '琩', 'N' => '琮', 'O' => '瑢', 'P' => '璉', 'Q' => '璟', 'R' => '甁', 'S' => '畯', 'T' => '皂', 'U' => '皜', 'V' => '皞', 'W' => '皛', 'X' => '皦', 'Y' => '益', 'Z' => '睆', '[' => '劯', '\\' => '砡', ']' => '硎', '^' => '硤', '_' => '硺', '`' => '礰', 'a' => '礼', 'b' => '神', 'c' => '祥', 'd' => '禔', 'e' => '福', 'f' => '禛', 'g' => '竑', 'h' => '竧', 'i' => '靖', 'j' => '竫', 'k' => '箞', 'l' => '精', 'm' => '絈', 'n' => '絜', 'o' => '綷', 'p' => '綠', 'q' => '緖', 'r' => '繒', 's' => '罇', 't' => '羡', 'u' => '羽', 'v' => '茁', 'w' => '荢', 'x' => '荿', 'y' => '菇', 'z' => '菶', '{' => '葈', '|' => '蒴', '}' => '蕓', '~' => '蕙', '' => '蕫', '' => '﨟', '' => '薰', '' => '蘒', '' => '﨡', '' => '蠇', '' => '裵', '' => '訒', '' => '訷', '' => '詹', '' => '誧', '' => '誾', '' => '諟', '' => '諸', '' => '諶', '' => '譓', '' => '譿', '' => '賰', '' => '賴', '' => '贒', '' => '赶', '' => '﨣', '' => '軏', '' => '﨤', '' => '逸', '' => '遧', '' => '郞', '' => '都', '' => '鄕', '' => '鄧', '' => '釚', '' => '釗', '' => '釞', '' => '釭', '' => '釮', '' => '釤', '' => '釥', '' => '鈆', '' => '鈐', '' => '鈊', '' => '鈺', '' => '鉀', '' => '鈼', '' => '鉎', '' => '鉙', '' => '鉑', '' => '鈹', '' => '鉧', '' => '銧', '' => '鉷', '' => '鉸', '' => '鋧', '' => '鋗', '' => '鋙', '' => '鋐', '' => '﨧', '' => '鋕', '' => '鋠', '' => '鋓', '' => '錥', '' => '錡', '' => '鋻', '' => '﨨', '' => '錞', '' => '鋿', '' => '錝', '' => '錂', '' => '鍰', '' => '鍗', '' => '鎤', '' => '鏆', '' => '鏞', '' => '鏸', '' => '鐱', '' => '鑅', '' => '鑈', '' => '閒', '' => '隆', '' => '﨩', '' => '隝', '' => '隯', '' => '霳', '' => '霻', '' => '靃', '' => '靍', '' => '靏', '' => '靑', '' => '靕', '' => '顗', '' => '顥', '' => '飯', '' => '飼', '' => '餧', '' => '館', '' => '馞', '' => '驎', '' => '髙', '' => '髜', '' => '魵', '' => '魲', '' => '鮏', '' => '鮱', '' => '鮻', '' => '鰀', '' => '鵰', '' => '鵫', '' => '鶴', '' => '鸙', '' => '黑', '' => 'ⅰ', '' => 'ⅱ', '' => 'ⅲ', '' => 'ⅳ', '' => 'ⅴ', '' => 'ⅵ', '' => 'ⅶ', '' => 'ⅷ', '' => 'ⅸ', '' => 'ⅹ', '' => '¬', '' => '¦', '' => ''', '' => '"', '@' => 'ⅰ', 'A' => 'ⅱ', 'B' => 'ⅲ', 'C' => 'ⅳ', 'D' => 'ⅴ', 'E' => 'ⅵ', 'F' => 'ⅶ', 'G' => 'ⅷ', 'H' => 'ⅸ', 'I' => 'ⅹ', 'J' => 'Ⅰ', 'K' => 'Ⅱ', 'L' => 'Ⅲ', 'M' => 'Ⅳ', 'N' => 'Ⅴ', 'O' => 'Ⅵ', 'P' => 'Ⅶ', 'Q' => 'Ⅷ', 'R' => 'Ⅸ', 'S' => 'Ⅹ', 'T' => '¬', 'U' => '¦', 'V' => ''', 'W' => '"', 'X' => '㈱', 'Y' => '№', 'Z' => '℡', '[' => '∵', '\\' => '纊', ']' => '褜', '^' => '鍈', '_' => '銈', '`' => '蓜', 'a' => '俉', 'b' => '炻', 'c' => '昱', 'd' => '棈', 'e' => '鋹', 'f' => '曻', 'g' => '彅', 'h' => '丨', 'i' => '仡', 'j' => '仼', 'k' => '伀', 'l' => '伃', 'm' => '伹', 'n' => '佖', 'o' => '侒', 'p' => '侊', 'q' => '侚', 'r' => '侔', 's' => '俍', 't' => '偀', 'u' => '倢', 'v' => '俿', 'w' => '倞', 'x' => '偆', 'y' => '偰', 'z' => '偂', '{' => '傔', '|' => '僴', '}' => '僘', '~' => '兊', '' => '兤', '' => '冝', '' => '冾', '' => '凬', '' => '刕', '' => '劜', '' => '劦', '' => '勀', '' => '勛', '' => '匀', '' => '匇', '' => '匤', '' => '卲', '' => '厓', '' => '厲', '' => '叝', '' => '﨎', '' => '咜', '' => '咊', '' => '咩', '' => '哿', '' => '喆', '' => '坙', '' => '坥', '' => '垬', '' => '埈', '' => '埇', '' => '﨏', '' => '塚', '' => '增', '' => '墲', '' => '夋', '' => '奓', '' => '奛', '' => '奝', '' => '奣', '' => '妤', '' => '妺', '' => '孖', '' => '寀', '' => '甯', '' => '寘', '' => '寬', '' => '尞', '' => '岦', '' => '岺', '' => '峵', '' => '崧', '' => '嵓', '' => '﨑', '' => '嵂', '' => '嵭', '' => '嶸', '' => '嶹', '' => '巐', '' => '弡', '' => '弴', '' => '彧', '' => '德', '' => '忞', '' => '恝', '' => '悅', '' => '悊', '' => '惞', '' => '惕', '' => '愠', '' => '惲', '' => '愑', '' => '愷', '' => '愰', '' => '憘', '' => '戓', '' => '抦', '' => '揵', '' => '摠', '' => '撝', '' => '擎', '' => '敎', '' => '昀', '' => '昕', '' => '昻', '' => '昉', '' => '昮', '' => '昞', '' => '昤', '' => '晥', '' => '晗', '' => '晙', '' => '晴', '' => '晳', '' => '暙', '' => '暠', '' => '暲', '' => '暿', '' => '曺', '' => '朎', '' => '朗', '' => '杦', '' => '枻', '' => '桒', '' => '柀', '' => '栁', '' => '桄', '' => '棏', '' => '﨓', '' => '楨', '' => '﨔', '' => '榘', '' => '槢', '' => '樰', '' => '橫', '' => '橆', '' => '橳', '' => '橾', '' => '櫢', '' => '櫤', '' => '毖', '' => '氿', '' => '汜', '' => '沆', '' => '汯', '' => '泚', '' => '洄', '' => '涇', '' => '浯', '@' => '涖', 'A' => '涬', 'B' => '淏', 'C' => '淸', 'D' => '淲', 'E' => '淼', 'F' => '渹', 'G' => '湜', 'H' => '渧', 'I' => '渼', 'J' => '溿', 'K' => '澈', 'L' => '澵', 'M' => '濵', 'N' => '瀅', 'O' => '瀇', 'P' => '瀨', 'Q' => '炅', 'R' => '炫', 'S' => '焏', 'T' => '焄', 'U' => '煜', 'V' => '煆', 'W' => '煇', 'X' => '凞', 'Y' => '燁', 'Z' => '燾', '[' => '犱', '\\' => '犾', ']' => '猤', '^' => '猪', '_' => '獷', '`' => '玽', 'a' => '珉', 'b' => '珖', 'c' => '珣', 'd' => '珒', 'e' => '琇', 'f' => '珵', 'g' => '琦', 'h' => '琪', 'i' => '琩', 'j' => '琮', 'k' => '瑢', 'l' => '璉', 'm' => '璟', 'n' => '甁', 'o' => '畯', 'p' => '皂', 'q' => '皜', 'r' => '皞', 's' => '皛', 't' => '皦', 'u' => '益', 'v' => '睆', 'w' => '劯', 'x' => '砡', 'y' => '硎', 'z' => '硤', '{' => '硺', '|' => '礰', '}' => '礼', '~' => '神', '' => '祥', '' => '禔', '' => '福', '' => '禛', '' => '竑', '' => '竧', '' => '靖', '' => '竫', '' => '箞', '' => '精', '' => '絈', '' => '絜', '' => '綷', '' => '綠', '' => '緖', '' => '繒', '' => '罇', '' => '羡', '' => '羽', '' => '茁', '' => '荢', '' => '荿', '' => '菇', '' => '菶', '' => '葈', '' => '蒴', '' => '蕓', '' => '蕙', '' => '蕫', '' => '﨟', '' => '薰', '' => '蘒', '' => '﨡', '' => '蠇', '' => '裵', '' => '訒', '' => '訷', '' => '詹', '' => '誧', '' => '誾', '' => '諟', '' => '諸', '' => '諶', '' => '譓', '' => '譿', '' => '賰', '' => '賴', '' => '贒', '' => '赶', '' => '﨣', '' => '軏', '' => '﨤', '' => '逸', '' => '遧', '' => '郞', '' => '都', '' => '鄕', '' => '鄧', '' => '釚', '' => '釗', '' => '釞', '' => '釭', '' => '釮', '' => '釤', '' => '釥', '' => '鈆', '' => '鈐', '' => '鈊', '' => '鈺', '' => '鉀', '' => '鈼', '' => '鉎', '' => '鉙', '' => '鉑', '' => '鈹', '' => '鉧', '' => '銧', '' => '鉷', '' => '鉸', '' => '鋧', '' => '鋗', '' => '鋙', '' => '鋐', '' => '﨧', '' => '鋕', '' => '鋠', '' => '鋓', '' => '錥', '' => '錡', '' => '鋻', '' => '﨨', '' => '錞', '' => '鋿', '' => '錝', '' => '錂', '' => '鍰', '' => '鍗', '' => '鎤', '' => '鏆', '' => '鏞', '' => '鏸', '' => '鐱', '' => '鑅', '' => '鑈', '' => '閒', '' => '隆', '' => '﨩', '' => '隝', '' => '隯', '' => '霳', '' => '霻', '' => '靃', '' => '靍', '' => '靏', '' => '靑', '' => '靕', '' => '顗', '' => '顥', '' => '飯', '' => '飼', '' => '餧', '' => '館', '' => '馞', '' => '驎', '' => '髙', '@' => '髜', 'A' => '魵', 'B' => '魲', 'C' => '鮏', 'D' => '鮱', 'E' => '鮻', 'F' => '鰀', 'G' => '鵰', 'H' => '鵫', 'I' => '鶴', 'J' => '鸙', 'K' => '黑', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/translit.php000064400000220763150432043200015471 0ustar00 'μ', '¼' => ' 1⁄4 ', '½' => ' 1⁄2 ', '¾' => ' 3⁄4 ', 'IJ' => 'IJ', 'ij' => 'ij', 'Ŀ' => 'L·', 'ŀ' => 'l·', 'ʼn' => 'ʼn', 'ſ' => 's', 'DŽ' => 'DŽ', 'Dž' => 'Dž', 'dž' => 'dž', 'LJ' => 'LJ', 'Lj' => 'Lj', 'lj' => 'lj', 'NJ' => 'NJ', 'Nj' => 'Nj', 'nj' => 'nj', 'DZ' => 'DZ', 'Dz' => 'Dz', 'dz' => 'dz', 'ϐ' => 'β', 'ϑ' => 'θ', 'ϒ' => 'Υ', 'ϕ' => 'φ', 'ϖ' => 'π', 'ϰ' => 'κ', 'ϱ' => 'ρ', 'ϲ' => 'ς', 'ϴ' => 'Θ', 'ϵ' => 'ε', 'Ϲ' => 'Σ', 'և' => 'եւ', 'ٵ' => 'اٴ', 'ٶ' => 'وٴ', 'ٷ' => 'ۇٴ', 'ٸ' => 'يٴ', 'ำ' => 'ํา', 'ຳ' => 'ໍາ', 'ໜ' => 'ຫນ', 'ໝ' => 'ຫມ', 'ཷ' => 'ྲཱྀ', 'ཹ' => 'ླཱྀ', 'ẚ' => 'aʾ', '․' => '.', '‥' => '..', '…' => '...', '″' => '′′', '‴' => '′′′', '‶' => '‵‵', '‷' => '‵‵‵', '‼' => '!!', '⁇' => '??', '⁈' => '?!', '⁉' => '!?', '⁗' => '′′′′', '₨' => 'Rs', '℀' => 'a/c', '℁' => 'a/s', 'ℂ' => 'C', '℃' => '°C', '℅' => 'c/o', '℆' => 'c/u', 'ℇ' => 'Ɛ', '℉' => '°F', 'ℊ' => 'g', 'ℋ' => 'H', 'ℌ' => 'H', 'ℍ' => 'H', 'ℎ' => 'h', 'ℏ' => 'ħ', 'ℐ' => 'I', 'ℑ' => 'I', 'ℒ' => 'L', 'ℓ' => 'l', 'ℕ' => 'N', '№' => 'No', 'ℙ' => 'P', 'ℚ' => 'Q', 'ℛ' => 'R', 'ℜ' => 'R', 'ℝ' => 'R', '℡' => 'TEL', 'ℤ' => 'Z', 'ℨ' => 'Z', 'ℬ' => 'B', 'ℭ' => 'C', 'ℯ' => 'e', 'ℰ' => 'E', 'ℱ' => 'F', 'ℳ' => 'M', 'ℴ' => 'o', 'ℵ' => 'א', 'ℶ' => 'ב', 'ℷ' => 'ג', 'ℸ' => 'ד', 'ℹ' => 'i', '℻' => 'FAX', 'ℼ' => 'π', 'ℽ' => 'γ', 'ℾ' => 'Γ', 'ℿ' => 'Π', '⅀' => '∑', 'ⅅ' => 'D', 'ⅆ' => 'd', 'ⅇ' => 'e', 'ⅈ' => 'i', 'ⅉ' => 'j', '⅐' => ' 1⁄7 ', '⅑' => ' 1⁄9 ', '⅒' => ' 1⁄10 ', '⅓' => ' 1⁄3 ', '⅔' => ' 2⁄3 ', '⅕' => ' 1⁄5 ', '⅖' => ' 2⁄5 ', '⅗' => ' 3⁄5 ', '⅘' => ' 4⁄5 ', '⅙' => ' 1⁄6 ', '⅚' => ' 5⁄6 ', '⅛' => ' 1⁄8 ', '⅜' => ' 3⁄8 ', '⅝' => ' 5⁄8 ', '⅞' => ' 7⁄8 ', '⅟' => ' 1⁄ ', 'Ⅰ' => 'I', 'Ⅱ' => 'II', 'Ⅲ' => 'III', 'Ⅳ' => 'IV', 'Ⅴ' => 'V', 'Ⅵ' => 'VI', 'Ⅶ' => 'VII', 'Ⅷ' => 'VIII', 'Ⅸ' => 'IX', 'Ⅹ' => 'X', 'Ⅺ' => 'XI', 'Ⅻ' => 'XII', 'Ⅼ' => 'L', 'Ⅽ' => 'C', 'Ⅾ' => 'D', 'Ⅿ' => 'M', 'ⅰ' => 'i', 'ⅱ' => 'ii', 'ⅲ' => 'iii', 'ⅳ' => 'iv', 'ⅴ' => 'v', 'ⅵ' => 'vi', 'ⅶ' => 'vii', 'ⅷ' => 'viii', 'ⅸ' => 'ix', 'ⅹ' => 'x', 'ⅺ' => 'xi', 'ⅻ' => 'xii', 'ⅼ' => 'l', 'ⅽ' => 'c', 'ⅾ' => 'd', 'ⅿ' => 'm', '↉' => ' 0⁄3 ', '∬' => '∫∫', '∭' => '∫∫∫', '∯' => '∮∮', '∰' => '∮∮∮', '①' => '(1)', '②' => '(2)', '③' => '(3)', '④' => '(4)', '⑤' => '(5)', '⑥' => '(6)', '⑦' => '(7)', '⑧' => '(8)', '⑨' => '(9)', '⑩' => '(10)', '⑪' => '(11)', '⑫' => '(12)', '⑬' => '(13)', '⑭' => '(14)', '⑮' => '(15)', '⑯' => '(16)', '⑰' => '(17)', '⑱' => '(18)', '⑲' => '(19)', '⑳' => '(20)', '⑴' => '(1)', '⑵' => '(2)', '⑶' => '(3)', '⑷' => '(4)', '⑸' => '(5)', '⑹' => '(6)', '⑺' => '(7)', '⑻' => '(8)', '⑼' => '(9)', '⑽' => '(10)', '⑾' => '(11)', '⑿' => '(12)', '⒀' => '(13)', '⒁' => '(14)', '⒂' => '(15)', '⒃' => '(16)', '⒄' => '(17)', '⒅' => '(18)', '⒆' => '(19)', '⒇' => '(20)', '⒈' => '1.', '⒉' => '2.', '⒊' => '3.', '⒋' => '4.', '⒌' => '5.', '⒍' => '6.', '⒎' => '7.', '⒏' => '8.', '⒐' => '9.', '⒑' => '10.', '⒒' => '11.', '⒓' => '12.', '⒔' => '13.', '⒕' => '14.', '⒖' => '15.', '⒗' => '16.', '⒘' => '17.', '⒙' => '18.', '⒚' => '19.', '⒛' => '20.', '⒜' => '(a)', '⒝' => '(b)', '⒞' => '(c)', '⒟' => '(d)', '⒠' => '(e)', '⒡' => '(f)', '⒢' => '(g)', '⒣' => '(h)', '⒤' => '(i)', '⒥' => '(j)', '⒦' => '(k)', '⒧' => '(l)', '⒨' => '(m)', '⒩' => '(n)', '⒪' => '(o)', '⒫' => '(p)', '⒬' => '(q)', '⒭' => '(r)', '⒮' => '(s)', '⒯' => '(t)', '⒰' => '(u)', '⒱' => '(v)', '⒲' => '(w)', '⒳' => '(x)', '⒴' => '(y)', '⒵' => '(z)', 'Ⓐ' => '(A)', 'Ⓑ' => '(B)', 'Ⓒ' => '(C)', 'Ⓓ' => '(D)', 'Ⓔ' => '(E)', 'Ⓕ' => '(F)', 'Ⓖ' => '(G)', 'Ⓗ' => '(H)', 'Ⓘ' => '(I)', 'Ⓙ' => '(J)', 'Ⓚ' => '(K)', 'Ⓛ' => '(L)', 'Ⓜ' => '(M)', 'Ⓝ' => '(N)', 'Ⓞ' => '(O)', 'Ⓟ' => '(P)', 'Ⓠ' => '(Q)', 'Ⓡ' => '(R)', 'Ⓢ' => '(S)', 'Ⓣ' => '(T)', 'Ⓤ' => '(U)', 'Ⓥ' => '(V)', 'Ⓦ' => '(W)', 'Ⓧ' => '(X)', 'Ⓨ' => '(Y)', 'Ⓩ' => '(Z)', 'ⓐ' => '(a)', 'ⓑ' => '(b)', 'ⓒ' => '(c)', 'ⓓ' => '(d)', 'ⓔ' => '(e)', 'ⓕ' => '(f)', 'ⓖ' => '(g)', 'ⓗ' => '(h)', 'ⓘ' => '(i)', 'ⓙ' => '(j)', 'ⓚ' => '(k)', 'ⓛ' => '(l)', 'ⓜ' => '(m)', 'ⓝ' => '(n)', 'ⓞ' => '(o)', 'ⓟ' => '(p)', 'ⓠ' => '(q)', 'ⓡ' => '(r)', 'ⓢ' => '(s)', 'ⓣ' => '(t)', 'ⓤ' => '(u)', 'ⓥ' => '(v)', 'ⓦ' => '(w)', 'ⓧ' => '(x)', 'ⓨ' => '(y)', 'ⓩ' => '(z)', '⓪' => '(0)', '⨌' => '∫∫∫∫', '⩴' => '::=', '⩵' => '==', '⩶' => '===', '⺟' => '母', '⻳' => '龟', '⼀' => '一', '⼁' => '丨', '⼂' => '丶', '⼃' => '丿', '⼄' => '乙', '⼅' => '亅', '⼆' => '二', '⼇' => '亠', '⼈' => '人', '⼉' => '儿', '⼊' => '入', '⼋' => '八', '⼌' => '冂', '⼍' => '冖', '⼎' => '冫', '⼏' => '几', '⼐' => '凵', '⼑' => '刀', '⼒' => '力', '⼓' => '勹', '⼔' => '匕', '⼕' => '匚', '⼖' => '匸', '⼗' => '十', '⼘' => '卜', '⼙' => '卩', '⼚' => '厂', '⼛' => '厶', '⼜' => '又', '⼝' => '口', '⼞' => '囗', '⼟' => '土', '⼠' => '士', '⼡' => '夂', '⼢' => '夊', '⼣' => '夕', '⼤' => '大', '⼥' => '女', '⼦' => '子', '⼧' => '宀', '⼨' => '寸', '⼩' => '小', '⼪' => '尢', '⼫' => '尸', '⼬' => '屮', '⼭' => '山', '⼮' => '巛', '⼯' => '工', '⼰' => '己', '⼱' => '巾', '⼲' => '干', '⼳' => '幺', '⼴' => '广', '⼵' => '廴', '⼶' => '廾', '⼷' => '弋', '⼸' => '弓', '⼹' => '彐', '⼺' => '彡', '⼻' => '彳', '⼼' => '心', '⼽' => '戈', '⼾' => '戶', '⼿' => '手', '⽀' => '支', '⽁' => '攴', '⽂' => '文', '⽃' => '斗', '⽄' => '斤', '⽅' => '方', '⽆' => '无', '⽇' => '日', '⽈' => '曰', '⽉' => '月', '⽊' => '木', '⽋' => '欠', '⽌' => '止', '⽍' => '歹', '⽎' => '殳', '⽏' => '毋', '⽐' => '比', '⽑' => '毛', '⽒' => '氏', '⽓' => '气', '⽔' => '水', '⽕' => '火', '⽖' => '爪', '⽗' => '父', '⽘' => '爻', '⽙' => '爿', '⽚' => '片', '⽛' => '牙', '⽜' => '牛', '⽝' => '犬', '⽞' => '玄', '⽟' => '玉', '⽠' => '瓜', '⽡' => '瓦', '⽢' => '甘', '⽣' => '生', '⽤' => '用', '⽥' => '田', '⽦' => '疋', '⽧' => '疒', '⽨' => '癶', '⽩' => '白', '⽪' => '皮', '⽫' => '皿', '⽬' => '目', '⽭' => '矛', '⽮' => '矢', '⽯' => '石', '⽰' => '示', '⽱' => '禸', '⽲' => '禾', '⽳' => '穴', '⽴' => '立', '⽵' => '竹', '⽶' => '米', '⽷' => '糸', '⽸' => '缶', '⽹' => '网', '⽺' => '羊', '⽻' => '羽', '⽼' => '老', '⽽' => '而', '⽾' => '耒', '⽿' => '耳', '⾀' => '聿', '⾁' => '肉', '⾂' => '臣', '⾃' => '自', '⾄' => '至', '⾅' => '臼', '⾆' => '舌', '⾇' => '舛', '⾈' => '舟', '⾉' => '艮', '⾊' => '色', '⾋' => '艸', '⾌' => '虍', '⾍' => '虫', '⾎' => '血', '⾏' => '行', '⾐' => '衣', '⾑' => '襾', '⾒' => '見', '⾓' => '角', '⾔' => '言', '⾕' => '谷', '⾖' => '豆', '⾗' => '豕', '⾘' => '豸', '⾙' => '貝', '⾚' => '赤', '⾛' => '走', '⾜' => '足', '⾝' => '身', '⾞' => '車', '⾟' => '辛', '⾠' => '辰', '⾡' => '辵', '⾢' => '邑', '⾣' => '酉', '⾤' => '釆', '⾥' => '里', '⾦' => '金', '⾧' => '長', '⾨' => '門', '⾩' => '阜', '⾪' => '隶', '⾫' => '隹', '⾬' => '雨', '⾭' => '靑', '⾮' => '非', '⾯' => '面', '⾰' => '革', '⾱' => '韋', '⾲' => '韭', '⾳' => '音', '⾴' => '頁', '⾵' => '風', '⾶' => '飛', '⾷' => '食', '⾸' => '首', '⾹' => '香', '⾺' => '馬', '⾻' => '骨', '⾼' => '高', '⾽' => '髟', '⾾' => '鬥', '⾿' => '鬯', '⿀' => '鬲', '⿁' => '鬼', '⿂' => '魚', '⿃' => '鳥', '⿄' => '鹵', '⿅' => '鹿', '⿆' => '麥', '⿇' => '麻', '⿈' => '黃', '⿉' => '黍', '⿊' => '黑', '⿋' => '黹', '⿌' => '黽', '⿍' => '鼎', '⿎' => '鼓', '⿏' => '鼠', '⿐' => '鼻', '⿑' => '齊', '⿒' => '齒', '⿓' => '龍', '⿔' => '龜', '⿕' => '龠', ' ' => ' ', '〶' => '〒', '〸' => '十', '〹' => '卄', '〺' => '卅', 'ㄱ' => 'ᄀ', 'ㄲ' => 'ᄁ', 'ㄳ' => 'ᆪ', 'ㄴ' => 'ᄂ', 'ㄵ' => 'ᆬ', 'ㄶ' => 'ᆭ', 'ㄷ' => 'ᄃ', 'ㄸ' => 'ᄄ', 'ㄹ' => 'ᄅ', 'ㄺ' => 'ᆰ', 'ㄻ' => 'ᆱ', 'ㄼ' => 'ᆲ', 'ㄽ' => 'ᆳ', 'ㄾ' => 'ᆴ', 'ㄿ' => 'ᆵ', 'ㅀ' => 'ᄚ', 'ㅁ' => 'ᄆ', 'ㅂ' => 'ᄇ', 'ㅃ' => 'ᄈ', 'ㅄ' => 'ᄡ', 'ㅅ' => 'ᄉ', 'ㅆ' => 'ᄊ', 'ㅇ' => 'ᄋ', 'ㅈ' => 'ᄌ', 'ㅉ' => 'ᄍ', 'ㅊ' => 'ᄎ', 'ㅋ' => 'ᄏ', 'ㅌ' => 'ᄐ', 'ㅍ' => 'ᄑ', 'ㅎ' => 'ᄒ', 'ㅏ' => 'ᅡ', 'ㅐ' => 'ᅢ', 'ㅑ' => 'ᅣ', 'ㅒ' => 'ᅤ', 'ㅓ' => 'ᅥ', 'ㅔ' => 'ᅦ', 'ㅕ' => 'ᅧ', 'ㅖ' => 'ᅨ', 'ㅗ' => 'ᅩ', 'ㅘ' => 'ᅪ', 'ㅙ' => 'ᅫ', 'ㅚ' => 'ᅬ', 'ㅛ' => 'ᅭ', 'ㅜ' => 'ᅮ', 'ㅝ' => 'ᅯ', 'ㅞ' => 'ᅰ', 'ㅟ' => 'ᅱ', 'ㅠ' => 'ᅲ', 'ㅡ' => 'ᅳ', 'ㅢ' => 'ᅴ', 'ㅣ' => 'ᅵ', 'ㅤ' => 'ᅠ', 'ㅥ' => 'ᄔ', 'ㅦ' => 'ᄕ', 'ㅧ' => 'ᇇ', 'ㅨ' => 'ᇈ', 'ㅩ' => 'ᇌ', 'ㅪ' => 'ᇎ', 'ㅫ' => 'ᇓ', 'ㅬ' => 'ᇗ', 'ㅭ' => 'ᇙ', 'ㅮ' => 'ᄜ', 'ㅯ' => 'ᇝ', 'ㅰ' => 'ᇟ', 'ㅱ' => 'ᄝ', 'ㅲ' => 'ᄞ', 'ㅳ' => 'ᄠ', 'ㅴ' => 'ᄢ', 'ㅵ' => 'ᄣ', 'ㅶ' => 'ᄧ', 'ㅷ' => 'ᄩ', 'ㅸ' => 'ᄫ', 'ㅹ' => 'ᄬ', 'ㅺ' => 'ᄭ', 'ㅻ' => 'ᄮ', 'ㅼ' => 'ᄯ', 'ㅽ' => 'ᄲ', 'ㅾ' => 'ᄶ', 'ㅿ' => 'ᅀ', 'ㆀ' => 'ᅇ', 'ㆁ' => 'ᅌ', 'ㆂ' => 'ᇱ', 'ㆃ' => 'ᇲ', 'ㆄ' => 'ᅗ', 'ㆅ' => 'ᅘ', 'ㆆ' => 'ᅙ', 'ㆇ' => 'ᆄ', 'ㆈ' => 'ᆅ', 'ㆉ' => 'ᆈ', 'ㆊ' => 'ᆑ', 'ㆋ' => 'ᆒ', 'ㆌ' => 'ᆔ', 'ㆍ' => 'ᆞ', 'ㆎ' => 'ᆡ', '㈀' => '(ᄀ)', '㈁' => '(ᄂ)', '㈂' => '(ᄃ)', '㈃' => '(ᄅ)', '㈄' => '(ᄆ)', '㈅' => '(ᄇ)', '㈆' => '(ᄉ)', '㈇' => '(ᄋ)', '㈈' => '(ᄌ)', '㈉' => '(ᄎ)', '㈊' => '(ᄏ)', '㈋' => '(ᄐ)', '㈌' => '(ᄑ)', '㈍' => '(ᄒ)', '㈎' => '(가)', '㈏' => '(나)', '㈐' => '(다)', '㈑' => '(라)', '㈒' => '(마)', '㈓' => '(바)', '㈔' => '(사)', '㈕' => '(아)', '㈖' => '(자)', '㈗' => '(차)', '㈘' => '(카)', '㈙' => '(타)', '㈚' => '(파)', '㈛' => '(하)', '㈜' => '(주)', '㈝' => '(오전)', '㈞' => '(오후)', '㈠' => '(一)', '㈡' => '(二)', '㈢' => '(三)', '㈣' => '(四)', '㈤' => '(五)', '㈥' => '(六)', '㈦' => '(七)', '㈧' => '(八)', '㈨' => '(九)', '㈩' => '(十)', '㈪' => '(月)', '㈫' => '(火)', '㈬' => '(水)', '㈭' => '(木)', '㈮' => '(金)', '㈯' => '(土)', '㈰' => '(日)', '㈱' => '(株)', '㈲' => '(有)', '㈳' => '(社)', '㈴' => '(名)', '㈵' => '(特)', '㈶' => '(財)', '㈷' => '(祝)', '㈸' => '(労)', '㈹' => '(代)', '㈺' => '(呼)', '㈻' => '(学)', '㈼' => '(監)', '㈽' => '(企)', '㈾' => '(資)', '㈿' => '(協)', '㉀' => '(祭)', '㉁' => '(休)', '㉂' => '(自)', '㉃' => '(至)', '㉄' => '(問)', '㉅' => '(幼)', '㉆' => '(文)', '㉇' => '(箏)', '㉐' => 'PTE', '㉑' => '(21)', '㉒' => '(22)', '㉓' => '(23)', '㉔' => '(24)', '㉕' => '(25)', '㉖' => '(26)', '㉗' => '(27)', '㉘' => '(28)', '㉙' => '(29)', '㉚' => '(30)', '㉛' => '(31)', '㉜' => '(32)', '㉝' => '(33)', '㉞' => '(34)', '㉟' => '(35)', '㉠' => '(ᄀ)', '㉡' => '(ᄂ)', '㉢' => '(ᄃ)', '㉣' => '(ᄅ)', '㉤' => '(ᄆ)', '㉥' => '(ᄇ)', '㉦' => '(ᄉ)', '㉧' => '(ᄋ)', '㉨' => '(ᄌ)', '㉩' => '(ᄎ)', '㉪' => '(ᄏ)', '㉫' => '(ᄐ)', '㉬' => '(ᄑ)', '㉭' => '(ᄒ)', '㉮' => '(가)', '㉯' => '(나)', '㉰' => '(다)', '㉱' => '(라)', '㉲' => '(마)', '㉳' => '(바)', '㉴' => '(사)', '㉵' => '(아)', '㉶' => '(자)', '㉷' => '(차)', '㉸' => '(카)', '㉹' => '(타)', '㉺' => '(파)', '㉻' => '(하)', '㉼' => '(참고)', '㉽' => '(주의)', '㉾' => '(우)', '㊀' => '(一)', '㊁' => '(二)', '㊂' => '(三)', '㊃' => '(四)', '㊄' => '(五)', '㊅' => '(六)', '㊆' => '(七)', '㊇' => '(八)', '㊈' => '(九)', '㊉' => '(十)', '㊊' => '(月)', '㊋' => '(火)', '㊌' => '(水)', '㊍' => '(木)', '㊎' => '(金)', '㊏' => '(土)', '㊐' => '(日)', '㊑' => '(株)', '㊒' => '(有)', '㊓' => '(社)', '㊔' => '(名)', '㊕' => '(特)', '㊖' => '(財)', '㊗' => '(祝)', '㊘' => '(労)', '㊙' => '(秘)', '㊚' => '(男)', '㊛' => '(女)', '㊜' => '(適)', '㊝' => '(優)', '㊞' => '(印)', '㊟' => '(注)', '㊠' => '(項)', '㊡' => '(休)', '㊢' => '(写)', '㊣' => '(正)', '㊤' => '(上)', '㊥' => '(中)', '㊦' => '(下)', '㊧' => '(左)', '㊨' => '(右)', '㊩' => '(医)', '㊪' => '(宗)', '㊫' => '(学)', '㊬' => '(監)', '㊭' => '(企)', '㊮' => '(資)', '㊯' => '(協)', '㊰' => '(夜)', '㊱' => '(36)', '㊲' => '(37)', '㊳' => '(38)', '㊴' => '(39)', '㊵' => '(40)', '㊶' => '(41)', '㊷' => '(42)', '㊸' => '(43)', '㊹' => '(44)', '㊺' => '(45)', '㊻' => '(46)', '㊼' => '(47)', '㊽' => '(48)', '㊾' => '(49)', '㊿' => '(50)', '㋀' => '1月', '㋁' => '2月', '㋂' => '3月', '㋃' => '4月', '㋄' => '5月', '㋅' => '6月', '㋆' => '7月', '㋇' => '8月', '㋈' => '9月', '㋉' => '10月', '㋊' => '11月', '㋋' => '12月', '㋌' => 'Hg', '㋍' => 'erg', '㋎' => 'eV', '㋏' => 'LTD', '㋐' => '(ア)', '㋑' => '(イ)', '㋒' => '(ウ)', '㋓' => '(エ)', '㋔' => '(オ)', '㋕' => '(カ)', '㋖' => '(キ)', '㋗' => '(ク)', '㋘' => '(ケ)', '㋙' => '(コ)', '㋚' => '(サ)', '㋛' => '(シ)', '㋜' => '(ス)', '㋝' => '(セ)', '㋞' => '(ソ)', '㋟' => '(タ)', '㋠' => '(チ)', '㋡' => '(ツ)', '㋢' => '(テ)', '㋣' => '(ト)', '㋤' => '(ナ)', '㋥' => '(ニ)', '㋦' => '(ヌ)', '㋧' => '(ネ)', '㋨' => '(ノ)', '㋩' => '(ハ)', '㋪' => '(ヒ)', '㋫' => '(フ)', '㋬' => '(ヘ)', '㋭' => '(ホ)', '㋮' => '(マ)', '㋯' => '(ミ)', '㋰' => '(ム)', '㋱' => '(メ)', '㋲' => '(モ)', '㋳' => '(ヤ)', '㋴' => '(ユ)', '㋵' => '(ヨ)', '㋶' => '(ラ)', '㋷' => '(リ)', '㋸' => '(ル)', '㋹' => '(レ)', '㋺' => '(ロ)', '㋻' => '(ワ)', '㋼' => '(ヰ)', '㋽' => '(ヱ)', '㋾' => '(ヲ)', '㋿' => '令和', '㌀' => 'アパート', '㌁' => 'アルファ', '㌂' => 'アンペア', '㌃' => 'アール', '㌄' => 'イニング', '㌅' => 'インチ', '㌆' => 'ウォン', '㌇' => 'エスクード', '㌈' => 'エーカー', '㌉' => 'オンス', '㌊' => 'オーム', '㌋' => 'カイリ', '㌌' => 'カラット', '㌍' => 'カロリー', '㌎' => 'ガロン', '㌏' => 'ガンマ', '㌐' => 'ギガ', '㌑' => 'ギニー', '㌒' => 'キュリー', '㌓' => 'ギルダー', '㌔' => 'キロ', '㌕' => 'キログラム', '㌖' => 'キロメートル', '㌗' => 'キロワット', '㌘' => 'グラム', '㌙' => 'グラムトン', '㌚' => 'クルゼイロ', '㌛' => 'クローネ', '㌜' => 'ケース', '㌝' => 'コルナ', '㌞' => 'コーポ', '㌟' => 'サイクル', '㌠' => 'サンチーム', '㌡' => 'シリング', '㌢' => 'センチ', '㌣' => 'セント', '㌤' => 'ダース', '㌥' => 'デシ', '㌦' => 'ドル', '㌧' => 'トン', '㌨' => 'ナノ', '㌩' => 'ノット', '㌪' => 'ハイツ', '㌫' => 'パーセント', '㌬' => 'パーツ', '㌭' => 'バーレル', '㌮' => 'ピアストル', '㌯' => 'ピクル', '㌰' => 'ピコ', '㌱' => 'ビル', '㌲' => 'ファラッド', '㌳' => 'フィート', '㌴' => 'ブッシェル', '㌵' => 'フラン', '㌶' => 'ヘクタール', '㌷' => 'ペソ', '㌸' => 'ペニヒ', '㌹' => 'ヘルツ', '㌺' => 'ペンス', '㌻' => 'ページ', '㌼' => 'ベータ', '㌽' => 'ポイント', '㌾' => 'ボルト', '㌿' => 'ホン', '㍀' => 'ポンド', '㍁' => 'ホール', '㍂' => 'ホーン', '㍃' => 'マイクロ', '㍄' => 'マイル', '㍅' => 'マッハ', '㍆' => 'マルク', '㍇' => 'マンション', '㍈' => 'ミクロン', '㍉' => 'ミリ', '㍊' => 'ミリバール', '㍋' => 'メガ', '㍌' => 'メガトン', '㍍' => 'メートル', '㍎' => 'ヤード', '㍏' => 'ヤール', '㍐' => 'ユアン', '㍑' => 'リットル', '㍒' => 'リラ', '㍓' => 'ルピー', '㍔' => 'ルーブル', '㍕' => 'レム', '㍖' => 'レントゲン', '㍗' => 'ワット', '㍘' => '0点', '㍙' => '1点', '㍚' => '2点', '㍛' => '3点', '㍜' => '4点', '㍝' => '5点', '㍞' => '6点', '㍟' => '7点', '㍠' => '8点', '㍡' => '9点', '㍢' => '10点', '㍣' => '11点', '㍤' => '12点', '㍥' => '13点', '㍦' => '14点', '㍧' => '15点', '㍨' => '16点', '㍩' => '17点', '㍪' => '18点', '㍫' => '19点', '㍬' => '20点', '㍭' => '21点', '㍮' => '22点', '㍯' => '23点', '㍰' => '24点', '㍱' => 'hPa', '㍲' => 'da', '㍳' => 'AU', '㍴' => 'bar', '㍵' => 'oV', '㍶' => 'pc', '㍷' => 'dm', '㍸' => 'dm²', '㍹' => 'dm³', '㍺' => 'IU', '㍻' => '平成', '㍼' => '昭和', '㍽' => '大正', '㍾' => '明治', '㍿' => '株式会社', '㎀' => 'pA', '㎁' => 'nA', '㎂' => 'μA', '㎃' => 'mA', '㎄' => 'kA', '㎅' => 'KB', '㎆' => 'MB', '㎇' => 'GB', '㎈' => 'cal', '㎉' => 'kcal', '㎊' => 'pF', '㎋' => 'nF', '㎌' => 'μF', '㎍' => 'μg', '㎎' => 'mg', '㎏' => 'kg', '㎐' => 'Hz', '㎑' => 'kHz', '㎒' => 'MHz', '㎓' => 'GHz', '㎔' => 'THz', '㎕' => 'μℓ', '㎖' => 'mℓ', '㎗' => 'dℓ', '㎘' => 'kℓ', '㎙' => 'fm', '㎚' => 'nm', '㎛' => 'μm', '㎜' => 'mm', '㎝' => 'cm', '㎞' => 'km', '㎟' => 'mm²', '㎠' => 'cm²', '㎡' => 'm²', '㎢' => 'km²', '㎣' => 'mm³', '㎤' => 'cm³', '㎥' => 'm³', '㎦' => 'km³', '㎧' => 'm∕s', '㎨' => 'm∕s²', '㎩' => 'Pa', '㎪' => 'kPa', '㎫' => 'MPa', '㎬' => 'GPa', '㎭' => 'rad', '㎮' => 'rad∕s', '㎯' => 'rad∕s²', '㎰' => 'ps', '㎱' => 'ns', '㎲' => 'μs', '㎳' => 'ms', '㎴' => 'pV', '㎵' => 'nV', '㎶' => 'μV', '㎷' => 'mV', '㎸' => 'kV', '㎹' => 'MV', '㎺' => 'pW', '㎻' => 'nW', '㎼' => 'μW', '㎽' => 'mW', '㎾' => 'kW', '㎿' => 'MW', '㏀' => 'kΩ', '㏁' => 'MΩ', '㏂' => 'a.m.', '㏃' => 'Bq', '㏄' => 'cc', '㏅' => 'cd', '㏆' => 'C∕kg', '㏇' => 'Co.', '㏈' => 'dB', '㏉' => 'Gy', '㏊' => 'ha', '㏋' => 'HP', '㏌' => 'in', '㏍' => 'KK', '㏎' => 'KM', '㏏' => 'kt', '㏐' => 'lm', '㏑' => 'ln', '㏒' => 'log', '㏓' => 'lx', '㏔' => 'mb', '㏕' => 'mil', '㏖' => 'mol', '㏗' => 'PH', '㏘' => 'p.m.', '㏙' => 'PPM', '㏚' => 'PR', '㏛' => 'sr', '㏜' => 'Sv', '㏝' => 'Wb', '㏞' => 'V∕m', '㏟' => 'A∕m', '㏠' => '1日', '㏡' => '2日', '㏢' => '3日', '㏣' => '4日', '㏤' => '5日', '㏥' => '6日', '㏦' => '7日', '㏧' => '8日', '㏨' => '9日', '㏩' => '10日', '㏪' => '11日', '㏫' => '12日', '㏬' => '13日', '㏭' => '14日', '㏮' => '15日', '㏯' => '16日', '㏰' => '17日', '㏱' => '18日', '㏲' => '19日', '㏳' => '20日', '㏴' => '21日', '㏵' => '22日', '㏶' => '23日', '㏷' => '24日', '㏸' => '25日', '㏹' => '26日', '㏺' => '27日', '㏻' => '28日', '㏼' => '29日', '㏽' => '30日', '㏾' => '31日', '㏿' => 'gal', '豈' => '豈', '更' => '更', '車' => '車', '賈' => '賈', '滑' => '滑', '串' => '串', '句' => '句', '龜' => '龜', '龜' => '龜', '契' => '契', '金' => '金', '喇' => '喇', '奈' => '奈', '懶' => '懶', '癩' => '癩', '羅' => '羅', '蘿' => '蘿', '螺' => '螺', '裸' => '裸', '邏' => '邏', '樂' => '樂', '洛' => '洛', '烙' => '烙', '珞' => '珞', '落' => '落', '酪' => '酪', '駱' => '駱', '亂' => '亂', '卵' => '卵', '欄' => '欄', '爛' => '爛', '蘭' => '蘭', '鸞' => '鸞', '嵐' => '嵐', '濫' => '濫', '藍' => '藍', '襤' => '襤', '拉' => '拉', '臘' => '臘', '蠟' => '蠟', '廊' => '廊', '朗' => '朗', '浪' => '浪', '狼' => '狼', '郎' => '郎', '來' => '來', '冷' => '冷', '勞' => '勞', '擄' => '擄', '櫓' => '櫓', '爐' => '爐', '盧' => '盧', '老' => '老', '蘆' => '蘆', '虜' => '虜', '路' => '路', '露' => '露', '魯' => '魯', '鷺' => '鷺', '碌' => '碌', '祿' => '祿', '綠' => '綠', '菉' => '菉', '錄' => '錄', '鹿' => '鹿', '論' => '論', '壟' => '壟', '弄' => '弄', '籠' => '籠', '聾' => '聾', '牢' => '牢', '磊' => '磊', '賂' => '賂', '雷' => '雷', '壘' => '壘', '屢' => '屢', '樓' => '樓', '淚' => '淚', '漏' => '漏', '累' => '累', '縷' => '縷', '陋' => '陋', '勒' => '勒', '肋' => '肋', '凜' => '凜', '凌' => '凌', '稜' => '稜', '綾' => '綾', '菱' => '菱', '陵' => '陵', '讀' => '讀', '拏' => '拏', '樂' => '樂', '諾' => '諾', '丹' => '丹', '寧' => '寧', '怒' => '怒', '率' => '率', '異' => '異', '北' => '北', '磻' => '磻', '便' => '便', '復' => '復', '不' => '不', '泌' => '泌', '數' => '數', '索' => '索', '參' => '參', '塞' => '塞', '省' => '省', '葉' => '葉', '說' => '說', '殺' => '殺', '辰' => '辰', '沈' => '沈', '拾' => '拾', '若' => '若', '掠' => '掠', '略' => '略', '亮' => '亮', '兩' => '兩', '凉' => '凉', '梁' => '梁', '糧' => '糧', '良' => '良', '諒' => '諒', '量' => '量', '勵' => '勵', '呂' => '呂', '女' => '女', '廬' => '廬', '旅' => '旅', '濾' => '濾', '礪' => '礪', '閭' => '閭', '驪' => '驪', '麗' => '麗', '黎' => '黎', '力' => '力', '曆' => '曆', '歷' => '歷', '轢' => '轢', '年' => '年', '憐' => '憐', '戀' => '戀', '撚' => '撚', '漣' => '漣', '煉' => '煉', '璉' => '璉', '秊' => '秊', '練' => '練', '聯' => '聯', '輦' => '輦', '蓮' => '蓮', '連' => '連', '鍊' => '鍊', '列' => '列', '劣' => '劣', '咽' => '咽', '烈' => '烈', '裂' => '裂', '說' => '說', '廉' => '廉', '念' => '念', '捻' => '捻', '殮' => '殮', '簾' => '簾', '獵' => '獵', '令' => '令', '囹' => '囹', '寧' => '寧', '嶺' => '嶺', '怜' => '怜', '玲' => '玲', '瑩' => '瑩', '羚' => '羚', '聆' => '聆', '鈴' => '鈴', '零' => '零', '靈' => '靈', '領' => '領', '例' => '例', '禮' => '禮', '醴' => '醴', '隸' => '隸', '惡' => '惡', '了' => '了', '僚' => '僚', '寮' => '寮', '尿' => '尿', '料' => '料', '樂' => '樂', '燎' => '燎', '療' => '療', '蓼' => '蓼', '遼' => '遼', '龍' => '龍', '暈' => '暈', '阮' => '阮', '劉' => '劉', '杻' => '杻', '柳' => '柳', '流' => '流', '溜' => '溜', '琉' => '琉', '留' => '留', '硫' => '硫', '紐' => '紐', '類' => '類', '六' => '六', '戮' => '戮', '陸' => '陸', '倫' => '倫', '崙' => '崙', '淪' => '淪', '輪' => '輪', '律' => '律', '慄' => '慄', '栗' => '栗', '率' => '率', '隆' => '隆', '利' => '利', '吏' => '吏', '履' => '履', '易' => '易', '李' => '李', '梨' => '梨', '泥' => '泥', '理' => '理', '痢' => '痢', '罹' => '罹', '裏' => '裏', '裡' => '裡', '里' => '里', '離' => '離', '匿' => '匿', '溺' => '溺', '吝' => '吝', '燐' => '燐', '璘' => '璘', '藺' => '藺', '隣' => '隣', '鱗' => '鱗', '麟' => '麟', '林' => '林', '淋' => '淋', '臨' => '臨', '立' => '立', '笠' => '笠', '粒' => '粒', '狀' => '狀', '炙' => '炙', '識' => '識', '什' => '什', '茶' => '茶', '刺' => '刺', '切' => '切', '度' => '度', '拓' => '拓', '糖' => '糖', '宅' => '宅', '洞' => '洞', '暴' => '暴', '輻' => '輻', '行' => '行', '降' => '降', '見' => '見', '廓' => '廓', '兀' => '兀', '嗀' => '嗀', '﨎' => '' . "\0" . '', '﨏' => '' . "\0" . '', '塚' => '塚', '﨑' => '' . "\0" . '', '晴' => '晴', '﨓' => '' . "\0" . '', '﨔' => '' . "\0" . '', '凞' => '凞', '猪' => '猪', '益' => '益', '礼' => '礼', '神' => '神', '祥' => '祥', '福' => '福', '靖' => '靖', '精' => '精', '羽' => '羽', '﨟' => '' . "\0" . '', '蘒' => '蘒', '﨡' => '' . "\0" . '', '諸' => '諸', '﨣' => '' . "\0" . '', '﨤' => '' . "\0" . '', '逸' => '逸', '都' => '都', '﨧' => '' . "\0" . '', '﨨' => '' . "\0" . '', '﨩' => '' . "\0" . '', '飯' => '飯', '飼' => '飼', '館' => '館', '鶴' => '鶴', '郞' => '郞', '隷' => '隷', '侮' => '侮', '僧' => '僧', '免' => '免', '勉' => '勉', '勤' => '勤', '卑' => '卑', '喝' => '喝', '嘆' => '嘆', '器' => '器', '塀' => '塀', '墨' => '墨', '層' => '層', '屮' => '屮', '悔' => '悔', '慨' => '慨', '憎' => '憎', '懲' => '懲', '敏' => '敏', '既' => '既', '暑' => '暑', '梅' => '梅', '海' => '海', '渚' => '渚', '漢' => '漢', '煮' => '煮', '爫' => '爫', '琢' => '琢', '碑' => '碑', '社' => '社', '祉' => '祉', '祈' => '祈', '祐' => '祐', '祖' => '祖', '祝' => '祝', '禍' => '禍', '禎' => '禎', '穀' => '穀', '突' => '突', '節' => '節', '練' => '練', '縉' => '縉', '繁' => '繁', '署' => '署', '者' => '者', '臭' => '臭', '艹' => '艹', '艹' => '艹', '著' => '著', '褐' => '褐', '視' => '視', '謁' => '謁', '謹' => '謹', '賓' => '賓', '贈' => '贈', '辶' => '辶', '逸' => '逸', '難' => '難', '響' => '響', '頻' => '頻', '恵' => '恵', '𤋮' => '𤋮', '舘' => '舘', '並' => '並', '况' => '况', '全' => '全', '侀' => '侀', '充' => '充', '冀' => '冀', '勇' => '勇', '勺' => '勺', '喝' => '喝', '啕' => '啕', '喙' => '喙', '嗢' => '嗢', '塚' => '塚', '墳' => '墳', '奄' => '奄', '奔' => '奔', '婢' => '婢', '嬨' => '嬨', '廒' => '廒', '廙' => '廙', '彩' => '彩', '徭' => '徭', '惘' => '惘', '慎' => '慎', '愈' => '愈', '憎' => '憎', '慠' => '慠', '懲' => '懲', '戴' => '戴', '揄' => '揄', '搜' => '搜', '摒' => '摒', '敖' => '敖', '晴' => '晴', '朗' => '朗', '望' => '望', '杖' => '杖', '歹' => '歹', '殺' => '殺', '流' => '流', '滛' => '滛', '滋' => '滋', '漢' => '漢', '瀞' => '瀞', '煮' => '煮', '瞧' => '瞧', '爵' => '爵', '犯' => '犯', '猪' => '猪', '瑱' => '瑱', '甆' => '甆', '画' => '画', '瘝' => '瘝', '瘟' => '瘟', '益' => '益', '盛' => '盛', '直' => '直', '睊' => '睊', '着' => '着', '磌' => '磌', '窱' => '窱', '節' => '節', '类' => '类', '絛' => '絛', '練' => '練', '缾' => '缾', '者' => '者', '荒' => '荒', '華' => '華', '蝹' => '蝹', '襁' => '襁', '覆' => '覆', '視' => '視', '調' => '調', '諸' => '諸', '請' => '請', '謁' => '謁', '諾' => '諾', '諭' => '諭', '謹' => '謹', '變' => '變', '贈' => '贈', '輸' => '輸', '遲' => '遲', '醙' => '醙', '鉶' => '鉶', '陼' => '陼', '難' => '難', '靖' => '靖', '韛' => '韛', '響' => '響', '頋' => '頋', '頻' => '頻', '鬒' => '鬒', '龜' => '龜', '𢡊' => '𢡊', '𢡄' => '𢡄', '𣏕' => '𣏕', '㮝' => '㮝', '䀘' => '䀘', '䀹' => '䀹', '𥉉' => '𥉉', '𥳐' => '𥳐', '𧻓' => '𧻓', '齃' => '齃', '龎' => '龎', 'ff' => 'ff', 'fi' => 'fi', 'fl' => 'fl', 'ffi' => 'ffi', 'ffl' => 'ffl', 'ſt' => 'ſt', 'st' => 'st', 'ﬓ' => 'մն', 'ﬔ' => 'մե', 'ﬕ' => 'մի', 'ﬖ' => 'վն', 'ﬗ' => 'մխ', 'ﬠ' => 'ע', 'ﬡ' => 'א', 'ﬢ' => 'ד', 'ﬣ' => 'ה', 'ﬤ' => 'כ', 'ﬥ' => 'ל', 'ﬦ' => 'ם', 'ﬧ' => 'ר', 'ﬨ' => 'ת', '﬩' => '+', 'ﭏ' => 'אל', '﹉' => '‾', '﹊' => '‾', '﹋' => '‾', '﹌' => '‾', '﹍' => '_', '﹎' => '_', '﹏' => '_', '﹐' => ',', '﹑' => '、', '﹒' => '.', '﹔' => ';', '﹕' => ':', '﹖' => '?', '﹗' => '!', '﹘' => '—', '﹙' => '(', '﹚' => ')', '﹛' => '{', '﹜' => '}', '﹝' => '〔', '﹞' => '〕', '﹟' => '#', '﹠' => '&', '﹡' => '*', '﹢' => '+', '﹣' => '-', '﹤' => '<', '﹥' => '>', '﹦' => '=', '﹨' => '\\', '﹩' => '$', '﹪' => '%', '﹫' => '@', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', ''' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '⦅' => '⦅', '⦆' => '⦆', '。' => '。', '「' => '「', '」' => '」', '、' => '、', '・' => '・', 'ヲ' => 'ヲ', 'ァ' => 'ァ', 'ィ' => 'ィ', 'ゥ' => 'ゥ', 'ェ' => 'ェ', 'ォ' => 'ォ', 'ャ' => 'ャ', 'ュ' => 'ュ', 'ョ' => 'ョ', 'ッ' => 'ッ', 'ー' => 'ー', 'ア' => 'ア', 'イ' => 'イ', 'ウ' => 'ウ', 'エ' => 'エ', 'オ' => 'オ', 'カ' => 'カ', 'キ' => 'キ', 'ク' => 'ク', 'ケ' => 'ケ', 'コ' => 'コ', 'サ' => 'サ', 'シ' => 'シ', 'ス' => 'ス', 'セ' => 'セ', 'ソ' => 'ソ', 'タ' => 'タ', 'チ' => 'チ', 'ツ' => 'ツ', 'テ' => 'テ', 'ト' => 'ト', 'ナ' => 'ナ', 'ニ' => 'ニ', 'ヌ' => 'ヌ', 'ネ' => 'ネ', 'ノ' => 'ノ', 'ハ' => 'ハ', 'ヒ' => 'ヒ', 'フ' => 'フ', 'ヘ' => 'ヘ', 'ホ' => 'ホ', 'マ' => 'マ', 'ミ' => 'ミ', 'ム' => 'ム', 'メ' => 'メ', 'モ' => 'モ', 'ヤ' => 'ヤ', 'ユ' => 'ユ', 'ヨ' => 'ヨ', 'ラ' => 'ラ', 'リ' => 'リ', 'ル' => 'ル', 'レ' => 'レ', 'ロ' => 'ロ', 'ワ' => 'ワ', 'ン' => 'ン', '゙' => '゙', '゚' => '゚', 'ᅠ' => 'ㅤ', 'ᄀ' => 'ㄱ', 'ᄁ' => 'ㄲ', 'ᆪ' => 'ㄳ', 'ᄂ' => 'ㄴ', 'ᆬ' => 'ㄵ', 'ᆭ' => 'ㄶ', 'ᄃ' => 'ㄷ', 'ᄄ' => 'ㄸ', 'ᄅ' => 'ㄹ', 'ᆰ' => 'ㄺ', 'ᆱ' => 'ㄻ', 'ᆲ' => 'ㄼ', 'ᆳ' => 'ㄽ', 'ᆴ' => 'ㄾ', 'ᆵ' => 'ㄿ', 'ᄚ' => 'ㅀ', 'ᄆ' => 'ㅁ', 'ᄇ' => 'ㅂ', 'ᄈ' => 'ㅃ', 'ᄡ' => 'ㅄ', 'ᄉ' => 'ㅅ', 'ᄊ' => 'ㅆ', 'ᄋ' => 'ㅇ', 'ᄌ' => 'ㅈ', 'ᄍ' => 'ㅉ', 'ᄎ' => 'ㅊ', 'ᄏ' => 'ㅋ', 'ᄐ' => 'ㅌ', 'ᄑ' => 'ㅍ', 'ᄒ' => 'ㅎ', 'ᅡ' => 'ㅏ', 'ᅢ' => 'ㅐ', 'ᅣ' => 'ㅑ', 'ᅤ' => 'ㅒ', 'ᅥ' => 'ㅓ', 'ᅦ' => 'ㅔ', 'ᅧ' => 'ㅕ', 'ᅨ' => 'ㅖ', 'ᅩ' => 'ㅗ', 'ᅪ' => 'ㅘ', 'ᅫ' => 'ㅙ', 'ᅬ' => 'ㅚ', 'ᅭ' => 'ㅛ', 'ᅮ' => 'ㅜ', 'ᅯ' => 'ㅝ', 'ᅰ' => 'ㅞ', 'ᅱ' => 'ㅟ', 'ᅲ' => 'ㅠ', 'ᅳ' => 'ㅡ', 'ᅴ' => 'ㅢ', 'ᅵ' => 'ㅣ', '¢' => '¢', '£' => '£', '¬' => '¬', ' ̄' => '¯', '¦' => '¦', '¥' => '¥', '₩' => '₩', '│' => '│', '←' => '←', '↑' => '↑', '→' => '→', '↓' => '↓', '■' => '■', '○' => '○', '𝐀' => 'A', '𝐁' => 'B', '𝐂' => 'C', '𝐃' => 'D', '𝐄' => 'E', '𝐅' => 'F', '𝐆' => 'G', '𝐇' => 'H', '𝐈' => 'I', '𝐉' => 'J', '𝐊' => 'K', '𝐋' => 'L', '𝐌' => 'M', '𝐍' => 'N', '𝐎' => 'O', '𝐏' => 'P', '𝐐' => 'Q', '𝐑' => 'R', '𝐒' => 'S', '𝐓' => 'T', '𝐔' => 'U', '𝐕' => 'V', '𝐖' => 'W', '𝐗' => 'X', '𝐘' => 'Y', '𝐙' => 'Z', '𝐚' => 'a', '𝐛' => 'b', '𝐜' => 'c', '𝐝' => 'd', '𝐞' => 'e', '𝐟' => 'f', '𝐠' => 'g', '𝐡' => 'h', '𝐢' => 'i', '𝐣' => 'j', '𝐤' => 'k', '𝐥' => 'l', '𝐦' => 'm', '𝐧' => 'n', '𝐨' => 'o', '𝐩' => 'p', '𝐪' => 'q', '𝐫' => 'r', '𝐬' => 's', '𝐭' => 't', '𝐮' => 'u', '𝐯' => 'v', '𝐰' => 'w', '𝐱' => 'x', '𝐲' => 'y', '𝐳' => 'z', '𝐴' => 'A', '𝐵' => 'B', '𝐶' => 'C', '𝐷' => 'D', '𝐸' => 'E', '𝐹' => 'F', '𝐺' => 'G', '𝐻' => 'H', '𝐼' => 'I', '𝐽' => 'J', '𝐾' => 'K', '𝐿' => 'L', '𝑀' => 'M', '𝑁' => 'N', '𝑂' => 'O', '𝑃' => 'P', '𝑄' => 'Q', '𝑅' => 'R', '𝑆' => 'S', '𝑇' => 'T', '𝑈' => 'U', '𝑉' => 'V', '𝑊' => 'W', '𝑋' => 'X', '𝑌' => 'Y', '𝑍' => 'Z', '𝑎' => 'a', '𝑏' => 'b', '𝑐' => 'c', '𝑑' => 'd', '𝑒' => 'e', '𝑓' => 'f', '𝑔' => 'g', '𝑖' => 'i', '𝑗' => 'j', '𝑘' => 'k', '𝑙' => 'l', '𝑚' => 'm', '𝑛' => 'n', '𝑜' => 'o', '𝑝' => 'p', '𝑞' => 'q', '𝑟' => 'r', '𝑠' => 's', '𝑡' => 't', '𝑢' => 'u', '𝑣' => 'v', '𝑤' => 'w', '𝑥' => 'x', '𝑦' => 'y', '𝑧' => 'z', '𝑨' => 'A', '𝑩' => 'B', '𝑪' => 'C', '𝑫' => 'D', '𝑬' => 'E', '𝑭' => 'F', '𝑮' => 'G', '𝑯' => 'H', '𝑰' => 'I', '𝑱' => 'J', '𝑲' => 'K', '𝑳' => 'L', '𝑴' => 'M', '𝑵' => 'N', '𝑶' => 'O', '𝑷' => 'P', '𝑸' => 'Q', '𝑹' => 'R', '𝑺' => 'S', '𝑻' => 'T', '𝑼' => 'U', '𝑽' => 'V', '𝑾' => 'W', '𝑿' => 'X', '𝒀' => 'Y', '𝒁' => 'Z', '𝒂' => 'a', '𝒃' => 'b', '𝒄' => 'c', '𝒅' => 'd', '𝒆' => 'e', '𝒇' => 'f', '𝒈' => 'g', '𝒉' => 'h', '𝒊' => 'i', '𝒋' => 'j', '𝒌' => 'k', '𝒍' => 'l', '𝒎' => 'm', '𝒏' => 'n', '𝒐' => 'o', '𝒑' => 'p', '𝒒' => 'q', '𝒓' => 'r', '𝒔' => 's', '𝒕' => 't', '𝒖' => 'u', '𝒗' => 'v', '𝒘' => 'w', '𝒙' => 'x', '𝒚' => 'y', '𝒛' => 'z', '𝒜' => 'A', '𝒞' => 'C', '𝒟' => 'D', '𝒢' => 'G', '𝒥' => 'J', '𝒦' => 'K', '𝒩' => 'N', '𝒪' => 'O', '𝒫' => 'P', '𝒬' => 'Q', '𝒮' => 'S', '𝒯' => 'T', '𝒰' => 'U', '𝒱' => 'V', '𝒲' => 'W', '𝒳' => 'X', '𝒴' => 'Y', '𝒵' => 'Z', '𝒶' => 'a', '𝒷' => 'b', '𝒸' => 'c', '𝒹' => 'd', '𝒻' => 'f', '𝒽' => 'h', '𝒾' => 'i', '𝒿' => 'j', '𝓀' => 'k', '𝓁' => 'l', '𝓂' => 'm', '𝓃' => 'n', '𝓅' => 'p', '𝓆' => 'q', '𝓇' => 'r', '𝓈' => 's', '𝓉' => 't', '𝓊' => 'u', '𝓋' => 'v', '𝓌' => 'w', '𝓍' => 'x', '𝓎' => 'y', '𝓏' => 'z', '𝓐' => 'A', '𝓑' => 'B', '𝓒' => 'C', '𝓓' => 'D', '𝓔' => 'E', '𝓕' => 'F', '𝓖' => 'G', '𝓗' => 'H', '𝓘' => 'I', '𝓙' => 'J', '𝓚' => 'K', '𝓛' => 'L', '𝓜' => 'M', '𝓝' => 'N', '𝓞' => 'O', '𝓟' => 'P', '𝓠' => 'Q', '𝓡' => 'R', '𝓢' => 'S', '𝓣' => 'T', '𝓤' => 'U', '𝓥' => 'V', '𝓦' => 'W', '𝓧' => 'X', '𝓨' => 'Y', '𝓩' => 'Z', '𝓪' => 'a', '𝓫' => 'b', '𝓬' => 'c', '𝓭' => 'd', '𝓮' => 'e', '𝓯' => 'f', '𝓰' => 'g', '𝓱' => 'h', '𝓲' => 'i', '𝓳' => 'j', '𝓴' => 'k', '𝓵' => 'l', '𝓶' => 'm', '𝓷' => 'n', '𝓸' => 'o', '𝓹' => 'p', '𝓺' => 'q', '𝓻' => 'r', '𝓼' => 's', '𝓽' => 't', '𝓾' => 'u', '𝓿' => 'v', '𝔀' => 'w', '𝔁' => 'x', '𝔂' => 'y', '𝔃' => 'z', '𝔄' => 'A', '𝔅' => 'B', '𝔇' => 'D', '𝔈' => 'E', '𝔉' => 'F', '𝔊' => 'G', '𝔍' => 'J', '𝔎' => 'K', '𝔏' => 'L', '𝔐' => 'M', '𝔑' => 'N', '𝔒' => 'O', '𝔓' => 'P', '𝔔' => 'Q', '𝔖' => 'S', '𝔗' => 'T', '𝔘' => 'U', '𝔙' => 'V', '𝔚' => 'W', '𝔛' => 'X', '𝔜' => 'Y', '𝔞' => 'a', '𝔟' => 'b', '𝔠' => 'c', '𝔡' => 'd', '𝔢' => 'e', '𝔣' => 'f', '𝔤' => 'g', '𝔥' => 'h', '𝔦' => 'i', '𝔧' => 'j', '𝔨' => 'k', '𝔩' => 'l', '𝔪' => 'm', '𝔫' => 'n', '𝔬' => 'o', '𝔭' => 'p', '𝔮' => 'q', '𝔯' => 'r', '𝔰' => 's', '𝔱' => 't', '𝔲' => 'u', '𝔳' => 'v', '𝔴' => 'w', '𝔵' => 'x', '𝔶' => 'y', '𝔷' => 'z', '𝔸' => 'A', '𝔹' => 'B', '𝔻' => 'D', '𝔼' => 'E', '𝔽' => 'F', '𝔾' => 'G', '𝕀' => 'I', '𝕁' => 'J', '𝕂' => 'K', '𝕃' => 'L', '𝕄' => 'M', '𝕆' => 'O', '𝕊' => 'S', '𝕋' => 'T', '𝕌' => 'U', '𝕍' => 'V', '𝕎' => 'W', '𝕏' => 'X', '𝕐' => 'Y', '𝕒' => 'a', '𝕓' => 'b', '𝕔' => 'c', '𝕕' => 'd', '𝕖' => 'e', '𝕗' => 'f', '𝕘' => 'g', '𝕙' => 'h', '𝕚' => 'i', '𝕛' => 'j', '𝕜' => 'k', '𝕝' => 'l', '𝕞' => 'm', '𝕟' => 'n', '𝕠' => 'o', '𝕡' => 'p', '𝕢' => 'q', '𝕣' => 'r', '𝕤' => 's', '𝕥' => 't', '𝕦' => 'u', '𝕧' => 'v', '𝕨' => 'w', '𝕩' => 'x', '𝕪' => 'y', '𝕫' => 'z', '𝕬' => 'A', '𝕭' => 'B', '𝕮' => 'C', '𝕯' => 'D', '𝕰' => 'E', '𝕱' => 'F', '𝕲' => 'G', '𝕳' => 'H', '𝕴' => 'I', '𝕵' => 'J', '𝕶' => 'K', '𝕷' => 'L', '𝕸' => 'M', '𝕹' => 'N', '𝕺' => 'O', '𝕻' => 'P', '𝕼' => 'Q', '𝕽' => 'R', '𝕾' => 'S', '𝕿' => 'T', '𝖀' => 'U', '𝖁' => 'V', '𝖂' => 'W', '𝖃' => 'X', '𝖄' => 'Y', '𝖅' => 'Z', '𝖆' => 'a', '𝖇' => 'b', '𝖈' => 'c', '𝖉' => 'd', '𝖊' => 'e', '𝖋' => 'f', '𝖌' => 'g', '𝖍' => 'h', '𝖎' => 'i', '𝖏' => 'j', '𝖐' => 'k', '𝖑' => 'l', '𝖒' => 'm', '𝖓' => 'n', '𝖔' => 'o', '𝖕' => 'p', '𝖖' => 'q', '𝖗' => 'r', '𝖘' => 's', '𝖙' => 't', '𝖚' => 'u', '𝖛' => 'v', '𝖜' => 'w', '𝖝' => 'x', '𝖞' => 'y', '𝖟' => 'z', '𝖠' => 'A', '𝖡' => 'B', '𝖢' => 'C', '𝖣' => 'D', '𝖤' => 'E', '𝖥' => 'F', '𝖦' => 'G', '𝖧' => 'H', '𝖨' => 'I', '𝖩' => 'J', '𝖪' => 'K', '𝖫' => 'L', '𝖬' => 'M', '𝖭' => 'N', '𝖮' => 'O', '𝖯' => 'P', '𝖰' => 'Q', '𝖱' => 'R', '𝖲' => 'S', '𝖳' => 'T', '𝖴' => 'U', '𝖵' => 'V', '𝖶' => 'W', '𝖷' => 'X', '𝖸' => 'Y', '𝖹' => 'Z', '𝖺' => 'a', '𝖻' => 'b', '𝖼' => 'c', '𝖽' => 'd', '𝖾' => 'e', '𝖿' => 'f', '𝗀' => 'g', '𝗁' => 'h', '𝗂' => 'i', '𝗃' => 'j', '𝗄' => 'k', '𝗅' => 'l', '𝗆' => 'm', '𝗇' => 'n', '𝗈' => 'o', '𝗉' => 'p', '𝗊' => 'q', '𝗋' => 'r', '𝗌' => 's', '𝗍' => 't', '𝗎' => 'u', '𝗏' => 'v', '𝗐' => 'w', '𝗑' => 'x', '𝗒' => 'y', '𝗓' => 'z', '𝗔' => 'A', '𝗕' => 'B', '𝗖' => 'C', '𝗗' => 'D', '𝗘' => 'E', '𝗙' => 'F', '𝗚' => 'G', '𝗛' => 'H', '𝗜' => 'I', '𝗝' => 'J', '𝗞' => 'K', '𝗟' => 'L', '𝗠' => 'M', '𝗡' => 'N', '𝗢' => 'O', '𝗣' => 'P', '𝗤' => 'Q', '𝗥' => 'R', '𝗦' => 'S', '𝗧' => 'T', '𝗨' => 'U', '𝗩' => 'V', '𝗪' => 'W', '𝗫' => 'X', '𝗬' => 'Y', '𝗭' => 'Z', '𝗮' => 'a', '𝗯' => 'b', '𝗰' => 'c', '𝗱' => 'd', '𝗲' => 'e', '𝗳' => 'f', '𝗴' => 'g', '𝗵' => 'h', '𝗶' => 'i', '𝗷' => 'j', '𝗸' => 'k', '𝗹' => 'l', '𝗺' => 'm', '𝗻' => 'n', '𝗼' => 'o', '𝗽' => 'p', '𝗾' => 'q', '𝗿' => 'r', '𝘀' => 's', '𝘁' => 't', '𝘂' => 'u', '𝘃' => 'v', '𝘄' => 'w', '𝘅' => 'x', '𝘆' => 'y', '𝘇' => 'z', '𝘈' => 'A', '𝘉' => 'B', '𝘊' => 'C', '𝘋' => 'D', '𝘌' => 'E', '𝘍' => 'F', '𝘎' => 'G', '𝘏' => 'H', '𝘐' => 'I', '𝘑' => 'J', '𝘒' => 'K', '𝘓' => 'L', '𝘔' => 'M', '𝘕' => 'N', '𝘖' => 'O', '𝘗' => 'P', '𝘘' => 'Q', '𝘙' => 'R', '𝘚' => 'S', '𝘛' => 'T', '𝘜' => 'U', '𝘝' => 'V', '𝘞' => 'W', '𝘟' => 'X', '𝘠' => 'Y', '𝘡' => 'Z', '𝘢' => 'a', '𝘣' => 'b', '𝘤' => 'c', '𝘥' => 'd', '𝘦' => 'e', '𝘧' => 'f', '𝘨' => 'g', '𝘩' => 'h', '𝘪' => 'i', '𝘫' => 'j', '𝘬' => 'k', '𝘭' => 'l', '𝘮' => 'm', '𝘯' => 'n', '𝘰' => 'o', '𝘱' => 'p', '𝘲' => 'q', '𝘳' => 'r', '𝘴' => 's', '𝘵' => 't', '𝘶' => 'u', '𝘷' => 'v', '𝘸' => 'w', '𝘹' => 'x', '𝘺' => 'y', '𝘻' => 'z', '𝘼' => 'A', '𝘽' => 'B', '𝘾' => 'C', '𝘿' => 'D', '𝙀' => 'E', '𝙁' => 'F', '𝙂' => 'G', '𝙃' => 'H', '𝙄' => 'I', '𝙅' => 'J', '𝙆' => 'K', '𝙇' => 'L', '𝙈' => 'M', '𝙉' => 'N', '𝙊' => 'O', '𝙋' => 'P', '𝙌' => 'Q', '𝙍' => 'R', '𝙎' => 'S', '𝙏' => 'T', '𝙐' => 'U', '𝙑' => 'V', '𝙒' => 'W', '𝙓' => 'X', '𝙔' => 'Y', '𝙕' => 'Z', '𝙖' => 'a', '𝙗' => 'b', '𝙘' => 'c', '𝙙' => 'd', '𝙚' => 'e', '𝙛' => 'f', '𝙜' => 'g', '𝙝' => 'h', '𝙞' => 'i', '𝙟' => 'j', '𝙠' => 'k', '𝙡' => 'l', '𝙢' => 'm', '𝙣' => 'n', '𝙤' => 'o', '𝙥' => 'p', '𝙦' => 'q', '𝙧' => 'r', '𝙨' => 's', '𝙩' => 't', '𝙪' => 'u', '𝙫' => 'v', '𝙬' => 'w', '𝙭' => 'x', '𝙮' => 'y', '𝙯' => 'z', '𝙰' => 'A', '𝙱' => 'B', '𝙲' => 'C', '𝙳' => 'D', '𝙴' => 'E', '𝙵' => 'F', '𝙶' => 'G', '𝙷' => 'H', '𝙸' => 'I', '𝙹' => 'J', '𝙺' => 'K', '𝙻' => 'L', '𝙼' => 'M', '𝙽' => 'N', '𝙾' => 'O', '𝙿' => 'P', '𝚀' => 'Q', '𝚁' => 'R', '𝚂' => 'S', '𝚃' => 'T', '𝚄' => 'U', '𝚅' => 'V', '𝚆' => 'W', '𝚇' => 'X', '𝚈' => 'Y', '𝚉' => 'Z', '𝚊' => 'a', '𝚋' => 'b', '𝚌' => 'c', '𝚍' => 'd', '𝚎' => 'e', '𝚏' => 'f', '𝚐' => 'g', '𝚑' => 'h', '𝚒' => 'i', '𝚓' => 'j', '𝚔' => 'k', '𝚕' => 'l', '𝚖' => 'm', '𝚗' => 'n', '𝚘' => 'o', '𝚙' => 'p', '𝚚' => 'q', '𝚛' => 'r', '𝚜' => 's', '𝚝' => 't', '𝚞' => 'u', '𝚟' => 'v', '𝚠' => 'w', '𝚡' => 'x', '𝚢' => 'y', '𝚣' => 'z', '𝚤' => 'ı', '𝚥' => 'ȷ', '𝚨' => 'Α', '𝚩' => 'Β', '𝚪' => 'Γ', '𝚫' => 'Δ', '𝚬' => 'Ε', '𝚭' => 'Ζ', '𝚮' => 'Η', '𝚯' => 'Θ', '𝚰' => 'Ι', '𝚱' => 'Κ', '𝚲' => 'Λ', '𝚳' => 'Μ', '𝚴' => 'Ν', '𝚵' => 'Ξ', '𝚶' => 'Ο', '𝚷' => 'Π', '𝚸' => 'Ρ', '𝚹' => 'ϴ', '𝚺' => 'Σ', '𝚻' => 'Τ', '𝚼' => 'Υ', '𝚽' => 'Φ', '𝚾' => 'Χ', '𝚿' => 'Ψ', '𝛀' => 'Ω', '𝛁' => '∇', '𝛂' => 'α', '𝛃' => 'β', '𝛄' => 'γ', '𝛅' => 'δ', '𝛆' => 'ε', '𝛇' => 'ζ', '𝛈' => 'η', '𝛉' => 'θ', '𝛊' => 'ι', '𝛋' => 'κ', '𝛌' => 'λ', '𝛍' => 'μ', '𝛎' => 'ν', '𝛏' => 'ξ', '𝛐' => 'ο', '𝛑' => 'π', '𝛒' => 'ρ', '𝛓' => 'ς', '𝛔' => 'σ', '𝛕' => 'τ', '𝛖' => 'υ', '𝛗' => 'φ', '𝛘' => 'χ', '𝛙' => 'ψ', '𝛚' => 'ω', '𝛛' => '∂', '𝛜' => 'ϵ', '𝛝' => 'ϑ', '𝛞' => 'ϰ', '𝛟' => 'ϕ', '𝛠' => 'ϱ', '𝛡' => 'ϖ', '𝛢' => 'Α', '𝛣' => 'Β', '𝛤' => 'Γ', '𝛥' => 'Δ', '𝛦' => 'Ε', '𝛧' => 'Ζ', '𝛨' => 'Η', '𝛩' => 'Θ', '𝛪' => 'Ι', '𝛫' => 'Κ', '𝛬' => 'Λ', '𝛭' => 'Μ', '𝛮' => 'Ν', '𝛯' => 'Ξ', '𝛰' => 'Ο', '𝛱' => 'Π', '𝛲' => 'Ρ', '𝛳' => 'ϴ', '𝛴' => 'Σ', '𝛵' => 'Τ', '𝛶' => 'Υ', '𝛷' => 'Φ', '𝛸' => 'Χ', '𝛹' => 'Ψ', '𝛺' => 'Ω', '𝛻' => '∇', '𝛼' => 'α', '𝛽' => 'β', '𝛾' => 'γ', '𝛿' => 'δ', '𝜀' => 'ε', '𝜁' => 'ζ', '𝜂' => 'η', '𝜃' => 'θ', '𝜄' => 'ι', '𝜅' => 'κ', '𝜆' => 'λ', '𝜇' => 'μ', '𝜈' => 'ν', '𝜉' => 'ξ', '𝜊' => 'ο', '𝜋' => 'π', '𝜌' => 'ρ', '𝜍' => 'ς', '𝜎' => 'σ', '𝜏' => 'τ', '𝜐' => 'υ', '𝜑' => 'φ', '𝜒' => 'χ', '𝜓' => 'ψ', '𝜔' => 'ω', '𝜕' => '∂', '𝜖' => 'ϵ', '𝜗' => 'ϑ', '𝜘' => 'ϰ', '𝜙' => 'ϕ', '𝜚' => 'ϱ', '𝜛' => 'ϖ', '𝜜' => 'Α', '𝜝' => 'Β', '𝜞' => 'Γ', '𝜟' => 'Δ', '𝜠' => 'Ε', '𝜡' => 'Ζ', '𝜢' => 'Η', '𝜣' => 'Θ', '𝜤' => 'Ι', '𝜥' => 'Κ', '𝜦' => 'Λ', '𝜧' => 'Μ', '𝜨' => 'Ν', '𝜩' => 'Ξ', '𝜪' => 'Ο', '𝜫' => 'Π', '𝜬' => 'Ρ', '𝜭' => 'ϴ', '𝜮' => 'Σ', '𝜯' => 'Τ', '𝜰' => 'Υ', '𝜱' => 'Φ', '𝜲' => 'Χ', '𝜳' => 'Ψ', '𝜴' => 'Ω', '𝜵' => '∇', '𝜶' => 'α', '𝜷' => 'β', '𝜸' => 'γ', '𝜹' => 'δ', '𝜺' => 'ε', '𝜻' => 'ζ', '𝜼' => 'η', '𝜽' => 'θ', '𝜾' => 'ι', '𝜿' => 'κ', '𝝀' => 'λ', '𝝁' => 'μ', '𝝂' => 'ν', '𝝃' => 'ξ', '𝝄' => 'ο', '𝝅' => 'π', '𝝆' => 'ρ', '𝝇' => 'ς', '𝝈' => 'σ', '𝝉' => 'τ', '𝝊' => 'υ', '𝝋' => 'φ', '𝝌' => 'χ', '𝝍' => 'ψ', '𝝎' => 'ω', '𝝏' => '∂', '𝝐' => 'ϵ', '𝝑' => 'ϑ', '𝝒' => 'ϰ', '𝝓' => 'ϕ', '𝝔' => 'ϱ', '𝝕' => 'ϖ', '𝝖' => 'Α', '𝝗' => 'Β', '𝝘' => 'Γ', '𝝙' => 'Δ', '𝝚' => 'Ε', '𝝛' => 'Ζ', '𝝜' => 'Η', '𝝝' => 'Θ', '𝝞' => 'Ι', '𝝟' => 'Κ', '𝝠' => 'Λ', '𝝡' => 'Μ', '𝝢' => 'Ν', '𝝣' => 'Ξ', '𝝤' => 'Ο', '𝝥' => 'Π', '𝝦' => 'Ρ', '𝝧' => 'ϴ', '𝝨' => 'Σ', '𝝩' => 'Τ', '𝝪' => 'Υ', '𝝫' => 'Φ', '𝝬' => 'Χ', '𝝭' => 'Ψ', '𝝮' => 'Ω', '𝝯' => '∇', '𝝰' => 'α', '𝝱' => 'β', '𝝲' => 'γ', '𝝳' => 'δ', '𝝴' => 'ε', '𝝵' => 'ζ', '𝝶' => 'η', '𝝷' => 'θ', '𝝸' => 'ι', '𝝹' => 'κ', '𝝺' => 'λ', '𝝻' => 'μ', '𝝼' => 'ν', '𝝽' => 'ξ', '𝝾' => 'ο', '𝝿' => 'π', '𝞀' => 'ρ', '𝞁' => 'ς', '𝞂' => 'σ', '𝞃' => 'τ', '𝞄' => 'υ', '𝞅' => 'φ', '𝞆' => 'χ', '𝞇' => 'ψ', '𝞈' => 'ω', '𝞉' => '∂', '𝞊' => 'ϵ', '𝞋' => 'ϑ', '𝞌' => 'ϰ', '𝞍' => 'ϕ', '𝞎' => 'ϱ', '𝞏' => 'ϖ', '𝞐' => 'Α', '𝞑' => 'Β', '𝞒' => 'Γ', '𝞓' => 'Δ', '𝞔' => 'Ε', '𝞕' => 'Ζ', '𝞖' => 'Η', '𝞗' => 'Θ', '𝞘' => 'Ι', '𝞙' => 'Κ', '𝞚' => 'Λ', '𝞛' => 'Μ', '𝞜' => 'Ν', '𝞝' => 'Ξ', '𝞞' => 'Ο', '𝞟' => 'Π', '𝞠' => 'Ρ', '𝞡' => 'ϴ', '𝞢' => 'Σ', '𝞣' => 'Τ', '𝞤' => 'Υ', '𝞥' => 'Φ', '𝞦' => 'Χ', '𝞧' => 'Ψ', '𝞨' => 'Ω', '𝞩' => '∇', '𝞪' => 'α', '𝞫' => 'β', '𝞬' => 'γ', '𝞭' => 'δ', '𝞮' => 'ε', '𝞯' => 'ζ', '𝞰' => 'η', '𝞱' => 'θ', '𝞲' => 'ι', '𝞳' => 'κ', '𝞴' => 'λ', '𝞵' => 'μ', '𝞶' => 'ν', '𝞷' => 'ξ', '𝞸' => 'ο', '𝞹' => 'π', '𝞺' => 'ρ', '𝞻' => 'ς', '𝞼' => 'σ', '𝞽' => 'τ', '𝞾' => 'υ', '𝞿' => 'φ', '𝟀' => 'χ', '𝟁' => 'ψ', '𝟂' => 'ω', '𝟃' => '∂', '𝟄' => 'ϵ', '𝟅' => 'ϑ', '𝟆' => 'ϰ', '𝟇' => 'ϕ', '𝟈' => 'ϱ', '𝟉' => 'ϖ', '𝟊' => 'Ϝ', '𝟋' => 'ϝ', '𝟎' => '0', '𝟏' => '1', '𝟐' => '2', '𝟑' => '3', '𝟒' => '4', '𝟓' => '5', '𝟔' => '6', '𝟕' => '7', '𝟖' => '8', '𝟗' => '9', '𝟘' => '0', '𝟙' => '1', '𝟚' => '2', '𝟛' => '3', '𝟜' => '4', '𝟝' => '5', '𝟞' => '6', '𝟟' => '7', '𝟠' => '8', '𝟡' => '9', '𝟢' => '0', '𝟣' => '1', '𝟤' => '2', '𝟥' => '3', '𝟦' => '4', '𝟧' => '5', '𝟨' => '6', '𝟩' => '7', '𝟪' => '8', '𝟫' => '9', '𝟬' => '0', '𝟭' => '1', '𝟮' => '2', '𝟯' => '3', '𝟰' => '4', '𝟱' => '5', '𝟲' => '6', '𝟳' => '7', '𝟴' => '8', '𝟵' => '9', '𝟶' => '0', '𝟷' => '1', '𝟸' => '2', '𝟹' => '3', '𝟺' => '4', '𝟻' => '5', '𝟼' => '6', '𝟽' => '7', '𝟾' => '8', '𝟿' => '9', '𞸀' => 'ا', '𞸁' => 'ب', '𞸂' => 'ج', '𞸃' => 'د', '𞸅' => 'و', '𞸆' => 'ز', '𞸇' => 'ح', '𞸈' => 'ط', '𞸉' => 'ي', '𞸊' => 'ك', '𞸋' => 'ل', '𞸌' => 'م', '𞸍' => 'ن', '𞸎' => 'س', '𞸏' => 'ع', '𞸐' => 'ف', '𞸑' => 'ص', '𞸒' => 'ق', '𞸓' => 'ر', '𞸔' => 'ش', '𞸕' => 'ت', '𞸖' => 'ث', '𞸗' => 'خ', '𞸘' => 'ذ', '𞸙' => 'ض', '𞸚' => 'ظ', '𞸛' => 'غ', '𞸜' => 'ٮ', '𞸝' => 'ں', '𞸞' => 'ڡ', '𞸟' => 'ٯ', '𞸡' => 'ب', '𞸢' => 'ج', '𞸤' => 'ه', '𞸧' => 'ح', '𞸩' => 'ي', '𞸪' => 'ك', '𞸫' => 'ل', '𞸬' => 'م', '𞸭' => 'ن', '𞸮' => 'س', '𞸯' => 'ع', '𞸰' => 'ف', '𞸱' => 'ص', '𞸲' => 'ق', '𞸴' => 'ش', '𞸵' => 'ت', '𞸶' => 'ث', '𞸷' => 'خ', '𞸹' => 'ض', '𞸻' => 'غ', '𞹂' => 'ج', '𞹇' => 'ح', '𞹉' => 'ي', '𞹋' => 'ل', '𞹍' => 'ن', '𞹎' => 'س', '𞹏' => 'ع', '𞹑' => 'ص', '𞹒' => 'ق', '𞹔' => 'ش', '𞹗' => 'خ', '𞹙' => 'ض', '𞹛' => 'غ', '𞹝' => 'ں', '𞹟' => 'ٯ', '𞹡' => 'ب', '𞹢' => 'ج', '𞹤' => 'ه', '𞹧' => 'ح', '𞹨' => 'ط', '𞹩' => 'ي', '𞹪' => 'ك', '𞹬' => 'م', '𞹭' => 'ن', '𞹮' => 'س', '𞹯' => 'ع', '𞹰' => 'ف', '𞹱' => 'ص', '𞹲' => 'ق', '𞹴' => 'ش', '𞹵' => 'ت', '𞹶' => 'ث', '𞹷' => 'خ', '𞹹' => 'ض', '𞹺' => 'ظ', '𞹻' => 'غ', '𞹼' => 'ٮ', '𞹾' => 'ڡ', '𞺀' => 'ا', '𞺁' => 'ب', '𞺂' => 'ج', '𞺃' => 'د', '𞺄' => 'ه', '𞺅' => 'و', '𞺆' => 'ز', '𞺇' => 'ح', '𞺈' => 'ط', '𞺉' => 'ي', '𞺋' => 'ل', '𞺌' => 'م', '𞺍' => 'ن', '𞺎' => 'س', '𞺏' => 'ع', '𞺐' => 'ف', '𞺑' => 'ص', '𞺒' => 'ق', '𞺓' => 'ر', '𞺔' => 'ش', '𞺕' => 'ت', '𞺖' => 'ث', '𞺗' => 'خ', '𞺘' => 'ذ', '𞺙' => 'ض', '𞺚' => 'ظ', '𞺛' => 'غ', '𞺡' => 'ب', '𞺢' => 'ج', '𞺣' => 'د', '𞺥' => 'و', '𞺦' => 'ز', '𞺧' => 'ح', '𞺨' => 'ط', '𞺩' => 'ي', '𞺫' => 'ل', '𞺬' => 'م', '𞺭' => 'ن', '𞺮' => 'س', '𞺯' => 'ع', '𞺰' => 'ف', '𞺱' => 'ص', '𞺲' => 'ق', '𞺳' => 'ر', '𞺴' => 'ش', '𞺵' => 'ت', '𞺶' => 'ث', '𞺷' => 'خ', '𞺸' => 'ذ', '𞺹' => 'ض', '𞺺' => 'ظ', '𞺻' => 'غ', '🄀' => '0.', '🄁' => '0,', '🄂' => '1,', '🄃' => '2,', '🄄' => '3,', '🄅' => '4,', '🄆' => '5,', '🄇' => '6,', '🄈' => '7,', '🄉' => '8,', '🄊' => '9,', '🄐' => '(A)', '🄑' => '(B)', '🄒' => '(C)', '🄓' => '(D)', '🄔' => '(E)', '🄕' => '(F)', '🄖' => '(G)', '🄗' => '(H)', '🄘' => '(I)', '🄙' => '(J)', '🄚' => '(K)', '🄛' => '(L)', '🄜' => '(M)', '🄝' => '(N)', '🄞' => '(O)', '🄟' => '(P)', '🄠' => '(Q)', '🄡' => '(R)', '🄢' => '(S)', '🄣' => '(T)', '🄤' => '(U)', '🄥' => '(V)', '🄦' => '(W)', '🄧' => '(X)', '🄨' => '(Y)', '🄩' => '(Z)', '🄪' => '〔S〕', '🄫' => '(C)', '🄬' => '(R)', '🄭' => '(CD)', '🄮' => '(WZ)', '🄰' => 'A', '🄱' => 'B', '🄲' => 'C', '🄳' => 'D', '🄴' => 'E', '🄵' => 'F', '🄶' => 'G', '🄷' => 'H', '🄸' => 'I', '🄹' => 'J', '🄺' => 'K', '🄻' => 'L', '🄼' => 'M', '🄽' => 'N', '🄾' => 'O', '🄿' => 'P', '🅀' => 'Q', '🅁' => 'R', '🅂' => 'S', '🅃' => 'T', '🅄' => 'U', '🅅' => 'V', '🅆' => 'W', '🅇' => 'X', '🅈' => 'Y', '🅉' => 'Z', '🅊' => 'HV', '🅋' => 'MV', '🅌' => 'SD', '🅍' => 'SS', '🅎' => 'PPV', '🅏' => 'WC', '🆐' => 'DJ', '🈀' => 'ほか', '🈁' => 'ココ', '🈂' => 'サ', '🈐' => '手', '🈑' => '字', '🈒' => '双', '🈓' => 'デ', '🈔' => '二', '🈕' => '多', '🈖' => '解', '🈗' => '天', '🈘' => '交', '🈙' => '映', '🈚' => '無', '🈛' => '料', '🈜' => '前', '🈝' => '後', '🈞' => '再', '🈟' => '新', '🈠' => '初', '🈡' => '終', '🈢' => '生', '🈣' => '販', '🈤' => '声', '🈥' => '吹', '🈦' => '演', '🈧' => '投', '🈨' => '捕', '🈩' => '一', '🈪' => '三', '🈫' => '遊', '🈬' => '左', '🈭' => '中', '🈮' => '右', '🈯' => '指', '🈰' => '走', '🈱' => '打', '🈲' => '禁', '🈳' => '空', '🈴' => '合', '🈵' => '満', '🈶' => '有', '🈷' => '月', '🈸' => '申', '🈹' => '割', '🈺' => '営', '🈻' => '配', '🉀' => '〔本〕', '🉁' => '〔三〕', '🉂' => '〔二〕', '🉃' => '〔安〕', '🉄' => '〔点〕', '🉅' => '〔打〕', '🉆' => '〔盗〕', '🉇' => '〔勝〕', '🉈' => '〔敗〕', '🉐' => '(得)', '🉑' => '(可)', '🯰' => '0', '🯱' => '1', '🯲' => '2', '🯳' => '3', '🯴' => '4', '🯵' => '5', '🯶' => '6', '🯷' => '7', '🯸' => '8', '🯹' => '9', '丽' => '丽', '丸' => '丸', '乁' => '乁', '𠄢' => '𠄢', '你' => '你', '侮' => '侮', '侻' => '侻', '倂' => '倂', '偺' => '偺', '備' => '備', '僧' => '僧', '像' => '像', '㒞' => '㒞', '𠘺' => '𠘺', '免' => '免', '兔' => '兔', '兤' => '兤', '具' => '具', '𠔜' => '𠔜', '㒹' => '㒹', '內' => '內', '再' => '再', '𠕋' => '𠕋', '冗' => '冗', '冤' => '冤', '仌' => '仌', '冬' => '冬', '况' => '况', '𩇟' => '𩇟', '凵' => '凵', '刃' => '刃', '㓟' => '㓟', '刻' => '刻', '剆' => '剆', '割' => '割', '剷' => '剷', '㔕' => '㔕', '勇' => '勇', '勉' => '勉', '勤' => '勤', '勺' => '勺', '包' => '包', '匆' => '匆', '北' => '北', '卉' => '卉', '卑' => '卑', '博' => '博', '即' => '即', '卽' => '卽', '卿' => '卿', '卿' => '卿', '卿' => '卿', '𠨬' => '𠨬', '灰' => '灰', '及' => '及', '叟' => '叟', '𠭣' => '𠭣', '叫' => '叫', '叱' => '叱', '吆' => '吆', '咞' => '咞', '吸' => '吸', '呈' => '呈', '周' => '周', '咢' => '咢', '哶' => '哶', '唐' => '唐', '啓' => '啓', '啣' => '啣', '善' => '善', '善' => '善', '喙' => '喙', '喫' => '喫', '喳' => '喳', '嗂' => '嗂', '圖' => '圖', '嘆' => '嘆', '圗' => '圗', '噑' => '噑', '噴' => '噴', '切' => '切', '壮' => '壮', '城' => '城', '埴' => '埴', '堍' => '堍', '型' => '型', '堲' => '堲', '報' => '報', '墬' => '墬', '𡓤' => '𡓤', '売' => '売', '壷' => '壷', '夆' => '夆', '多' => '多', '夢' => '夢', '奢' => '奢', '𡚨' => '𡚨', '𡛪' => '𡛪', '姬' => '姬', '娛' => '娛', '娧' => '娧', '姘' => '姘', '婦' => '婦', '㛮' => '㛮', '㛼' => '㛼', '嬈' => '嬈', '嬾' => '嬾', '嬾' => '嬾', '𡧈' => '𡧈', '寃' => '寃', '寘' => '寘', '寧' => '寧', '寳' => '寳', '𡬘' => '𡬘', '寿' => '寿', '将' => '将', '当' => '当', '尢' => '尢', '㞁' => '㞁', '屠' => '屠', '屮' => '屮', '峀' => '峀', '岍' => '岍', '𡷤' => '𡷤', '嵃' => '嵃', '𡷦' => '𡷦', '嵮' => '嵮', '嵫' => '嵫', '嵼' => '嵼', '巡' => '巡', '巢' => '巢', '㠯' => '㠯', '巽' => '巽', '帨' => '帨', '帽' => '帽', '幩' => '幩', '㡢' => '㡢', '𢆃' => '𢆃', '㡼' => '㡼', '庰' => '庰', '庳' => '庳', '庶' => '庶', '廊' => '廊', '𪎒' => '𪎒', '廾' => '廾', '𢌱' => '𢌱', '𢌱' => '𢌱', '舁' => '舁', '弢' => '弢', '弢' => '弢', '㣇' => '㣇', '𣊸' => '𣊸', '𦇚' => '𦇚', '形' => '形', '彫' => '彫', '㣣' => '㣣', '徚' => '徚', '忍' => '忍', '志' => '志', '忹' => '忹', '悁' => '悁', '㤺' => '㤺', '㤜' => '㤜', '悔' => '悔', '𢛔' => '𢛔', '惇' => '惇', '慈' => '慈', '慌' => '慌', '慎' => '慎', '慌' => '慌', '慺' => '慺', '憎' => '憎', '憲' => '憲', '憤' => '憤', '憯' => '憯', '懞' => '懞', '懲' => '懲', '懶' => '懶', '成' => '成', '戛' => '戛', '扝' => '扝', '抱' => '抱', '拔' => '拔', '捐' => '捐', '𢬌' => '𢬌', '挽' => '挽', '拼' => '拼', '捨' => '捨', '掃' => '掃', '揤' => '揤', '𢯱' => '𢯱', '搢' => '搢', '揅' => '揅', '掩' => '掩', '㨮' => '㨮', '摩' => '摩', '摾' => '摾', '撝' => '撝', '摷' => '摷', '㩬' => '㩬', '敏' => '敏', '敬' => '敬', '𣀊' => '𣀊', '旣' => '旣', '書' => '書', '晉' => '晉', '㬙' => '㬙', '暑' => '暑', '㬈' => '㬈', '㫤' => '㫤', '冒' => '冒', '冕' => '冕', '最' => '最', '暜' => '暜', '肭' => '肭', '䏙' => '䏙', '朗' => '朗', '望' => '望', '朡' => '朡', '杞' => '杞', '杓' => '杓', '𣏃' => '𣏃', '㭉' => '㭉', '柺' => '柺', '枅' => '枅', '桒' => '桒', '梅' => '梅', '𣑭' => '𣑭', '梎' => '梎', '栟' => '栟', '椔' => '椔', '㮝' => '㮝', '楂' => '楂', '榣' => '榣', '槪' => '槪', '檨' => '檨', '𣚣' => '𣚣', '櫛' => '櫛', '㰘' => '㰘', '次' => '次', '𣢧' => '𣢧', '歔' => '歔', '㱎' => '㱎', '歲' => '歲', '殟' => '殟', '殺' => '殺', '殻' => '殻', '𣪍' => '𣪍', '𡴋' => '𡴋', '𣫺' => '𣫺', '汎' => '汎', '𣲼' => '𣲼', '沿' => '沿', '泍' => '泍', '汧' => '汧', '洖' => '洖', '派' => '派', '海' => '海', '流' => '流', '浩' => '浩', '浸' => '浸', '涅' => '涅', '𣴞' => '𣴞', '洴' => '洴', '港' => '港', '湮' => '湮', '㴳' => '㴳', '滋' => '滋', '滇' => '滇', '𣻑' => '𣻑', '淹' => '淹', '潮' => '潮', '𣽞' => '𣽞', '𣾎' => '𣾎', '濆' => '濆', '瀹' => '瀹', '瀞' => '瀞', '瀛' => '瀛', '㶖' => '㶖', '灊' => '灊', '災' => '災', '灷' => '灷', '炭' => '炭', '𠔥' => '𠔥', '煅' => '煅', '𤉣' => '𤉣', '熜' => '熜', '𤎫' => '𤎫', '爨' => '爨', '爵' => '爵', '牐' => '牐', '𤘈' => '𤘈', '犀' => '犀', '犕' => '犕', '𤜵' => '𤜵', '𤠔' => '𤠔', '獺' => '獺', '王' => '王', '㺬' => '㺬', '玥' => '玥', '㺸' => '㺸', '㺸' => '㺸', '瑇' => '瑇', '瑜' => '瑜', '瑱' => '瑱', '璅' => '璅', '瓊' => '瓊', '㼛' => '㼛', '甤' => '甤', '𤰶' => '𤰶', '甾' => '甾', '𤲒' => '𤲒', '異' => '異', '𢆟' => '𢆟', '瘐' => '瘐', '𤾡' => '𤾡', '𤾸' => '𤾸', '𥁄' => '𥁄', '㿼' => '㿼', '䀈' => '䀈', '直' => '直', '𥃳' => '𥃳', '𥃲' => '𥃲', '𥄙' => '𥄙', '𥄳' => '𥄳', '眞' => '眞', '真' => '真', '真' => '真', '睊' => '睊', '䀹' => '䀹', '瞋' => '瞋', '䁆' => '䁆', '䂖' => '䂖', '𥐝' => '𥐝', '硎' => '硎', '碌' => '碌', '磌' => '磌', '䃣' => '䃣', '𥘦' => '𥘦', '祖' => '祖', '𥚚' => '𥚚', '𥛅' => '𥛅', '福' => '福', '秫' => '秫', '䄯' => '䄯', '穀' => '穀', '穊' => '穊', '穏' => '穏', '𥥼' => '𥥼', '𥪧' => '𥪧', '𥪧' => '𥪧', '竮' => '竮', '䈂' => '䈂', '𥮫' => '𥮫', '篆' => '篆', '築' => '築', '䈧' => '䈧', '𥲀' => '𥲀', '糒' => '糒', '䊠' => '䊠', '糨' => '糨', '糣' => '糣', '紀' => '紀', '𥾆' => '𥾆', '絣' => '絣', '䌁' => '䌁', '緇' => '緇', '縂' => '縂', '繅' => '繅', '䌴' => '䌴', '𦈨' => '𦈨', '𦉇' => '𦉇', '䍙' => '䍙', '𦋙' => '𦋙', '罺' => '罺', '𦌾' => '𦌾', '羕' => '羕', '翺' => '翺', '者' => '者', '𦓚' => '𦓚', '𦔣' => '𦔣', '聠' => '聠', '𦖨' => '𦖨', '聰' => '聰', '𣍟' => '𣍟', '䏕' => '䏕', '育' => '育', '脃' => '脃', '䐋' => '䐋', '脾' => '脾', '媵' => '媵', '𦞧' => '𦞧', '𦞵' => '𦞵', '𣎓' => '𣎓', '𣎜' => '𣎜', '舁' => '舁', '舄' => '舄', '辞' => '辞', '䑫' => '䑫', '芑' => '芑', '芋' => '芋', '芝' => '芝', '劳' => '劳', '花' => '花', '芳' => '芳', '芽' => '芽', '苦' => '苦', '𦬼' => '𦬼', '若' => '若', '茝' => '茝', '荣' => '荣', '莭' => '莭', '茣' => '茣', '莽' => '莽', '菧' => '菧', '著' => '著', '荓' => '荓', '菊' => '菊', '菌' => '菌', '菜' => '菜', '𦰶' => '𦰶', '𦵫' => '𦵫', '𦳕' => '𦳕', '䔫' => '䔫', '蓱' => '蓱', '蓳' => '蓳', '蔖' => '蔖', '𧏊' => '𧏊', '蕤' => '蕤', '𦼬' => '𦼬', '䕝' => '䕝', '䕡' => '䕡', '𦾱' => '𦾱', '𧃒' => '𧃒', '䕫' => '䕫', '虐' => '虐', '虜' => '虜', '虧' => '虧', '虩' => '虩', '蚩' => '蚩', '蚈' => '蚈', '蜎' => '蜎', '蛢' => '蛢', '蝹' => '蝹', '蜨' => '蜨', '蝫' => '蝫', '螆' => '螆', '䗗' => '䗗', '蟡' => '蟡', '蠁' => '蠁', '䗹' => '䗹', '衠' => '衠', '衣' => '衣', '𧙧' => '𧙧', '裗' => '裗', '裞' => '裞', '䘵' => '䘵', '裺' => '裺', '㒻' => '㒻', '𧢮' => '𧢮', '𧥦' => '𧥦', '䚾' => '䚾', '䛇' => '䛇', '誠' => '誠', '諭' => '諭', '變' => '變', '豕' => '豕', '𧲨' => '𧲨', '貫' => '貫', '賁' => '賁', '贛' => '贛', '起' => '起', '𧼯' => '𧼯', '𠠄' => '𠠄', '跋' => '跋', '趼' => '趼', '跰' => '跰', '𠣞' => '𠣞', '軔' => '軔', '輸' => '輸', '𨗒' => '𨗒', '𨗭' => '𨗭', '邔' => '邔', '郱' => '郱', '鄑' => '鄑', '𨜮' => '𨜮', '鄛' => '鄛', '鈸' => '鈸', '鋗' => '鋗', '鋘' => '鋘', '鉼' => '鉼', '鏹' => '鏹', '鐕' => '鐕', '𨯺' => '𨯺', '開' => '開', '䦕' => '䦕', '閷' => '閷', '𨵷' => '𨵷', '䧦' => '䧦', '雃' => '雃', '嶲' => '嶲', '霣' => '霣', '𩅅' => '𩅅', '𩈚' => '𩈚', '䩮' => '䩮', '䩶' => '䩶', '韠' => '韠', '𩐊' => '𩐊', '䪲' => '䪲', '𩒖' => '𩒖', '頋' => '頋', '頋' => '頋', '頩' => '頩', '𩖶' => '𩖶', '飢' => '飢', '䬳' => '䬳', '餩' => '餩', '馧' => '馧', '駂' => '駂', '駾' => '駾', '䯎' => '䯎', '𩬰' => '𩬰', '鬒' => '鬒', '鱀' => '鱀', '鳽' => '鳽', '䳎' => '䳎', '䳭' => '䳭', '鵧' => '鵧', '𪃎' => '𪃎', '䳸' => '䳸', '𪄅' => '𪄅', '𪈎' => '𪈎', '𪊑' => '𪊑', '麻' => '麻', '䵖' => '䵖', '黹' => '黹', '黾' => '黾', '鼅' => '鼅', '鼏' => '鼏', '鼖' => '鼖', '鼻' => '鼻', '𪘀' => '𪘀', 'Æ' => 'AE', 'Ð' => 'D', 'Ø' => 'O', 'Þ' => 'TH', 'ß' => 'ss', 'æ' => 'ae', 'ð' => 'd', 'ø' => 'o', 'þ' => 'th', 'Đ' => 'D', 'đ' => 'd', 'Ħ' => 'H', 'ħ' => 'h', 'ı' => 'i', 'ĸ' => 'q', 'Ł' => 'L', 'ł' => 'l', 'Ŋ' => 'N', 'ŋ' => 'n', 'Œ' => 'OE', 'œ' => 'oe', 'Ŧ' => 'T', 'ŧ' => 't', 'ƀ' => 'b', 'Ɓ' => 'B', 'Ƃ' => 'B', 'ƃ' => 'b', 'Ƈ' => 'C', 'ƈ' => 'c', 'Ɖ' => 'D', 'Ɗ' => 'D', 'Ƌ' => 'D', 'ƌ' => 'd', 'Ɛ' => 'E', 'Ƒ' => 'F', 'ƒ' => 'f', 'Ɠ' => 'G', 'ƕ' => 'hv', 'Ɩ' => 'I', 'Ɨ' => 'I', 'Ƙ' => 'K', 'ƙ' => 'k', 'ƚ' => 'l', 'Ɲ' => 'N', 'ƞ' => 'n', 'Ƣ' => 'OI', 'ƣ' => 'oi', 'Ƥ' => 'P', 'ƥ' => 'p', 'ƫ' => 't', 'Ƭ' => 'T', 'ƭ' => 't', 'Ʈ' => 'T', 'Ʋ' => 'V', 'Ƴ' => 'Y', 'ƴ' => 'y', 'Ƶ' => 'Z', 'ƶ' => 'z', 'Ǥ' => 'G', 'ǥ' => 'g', 'ȡ' => 'd', 'Ȥ' => 'Z', 'ȥ' => 'z', 'ȴ' => 'l', 'ȵ' => 'n', 'ȶ' => 't', 'ȷ' => 'j', 'ȸ' => 'db', 'ȹ' => 'qp', 'Ⱥ' => 'A', 'Ȼ' => 'C', 'ȼ' => 'c', 'Ƚ' => 'L', 'Ⱦ' => 'T', 'ȿ' => 's', 'ɀ' => 'z', 'Ƀ' => 'B', 'Ʉ' => 'U', 'Ɇ' => 'E', 'ɇ' => 'e', 'Ɉ' => 'J', 'ɉ' => 'j', 'Ɍ' => 'R', 'ɍ' => 'r', 'Ɏ' => 'Y', 'ɏ' => 'y', 'ɓ' => 'b', 'ɕ' => 'c', 'ɖ' => 'd', 'ɗ' => 'd', 'ɛ' => 'e', 'ɟ' => 'j', 'ɠ' => 'g', 'ɡ' => 'g', 'ɢ' => 'G', 'ɦ' => 'h', 'ɧ' => 'h', 'ɨ' => 'i', 'ɪ' => 'I', 'ɫ' => 'l', 'ɬ' => 'l', 'ɭ' => 'l', 'ɱ' => 'm', 'ɲ' => 'n', 'ɳ' => 'n', 'ɴ' => 'N', 'ɶ' => 'OE', 'ɼ' => 'r', 'ɽ' => 'r', 'ɾ' => 'r', 'ʀ' => 'R', 'ʂ' => 's', 'ʈ' => 't', 'ʉ' => 'u', 'ʋ' => 'v', 'ʏ' => 'Y', 'ʐ' => 'z', 'ʑ' => 'z', 'ʙ' => 'B', 'ʛ' => 'G', 'ʜ' => 'H', 'ʝ' => 'j', 'ʟ' => 'L', 'ʠ' => 'q', 'ʣ' => 'dz', 'ʥ' => 'dz', 'ʦ' => 'ts', 'ʪ' => 'ls', 'ʫ' => 'lz', 'ᴀ' => 'A', 'ᴁ' => 'AE', 'ᴃ' => 'B', 'ᴄ' => 'C', 'ᴅ' => 'D', 'ᴆ' => 'D', 'ᴇ' => 'E', 'ᴊ' => 'J', 'ᴋ' => 'K', 'ᴌ' => 'L', 'ᴍ' => 'M', 'ᴏ' => 'O', 'ᴘ' => 'P', 'ᴛ' => 'T', 'ᴜ' => 'U', 'ᴠ' => 'V', 'ᴡ' => 'W', 'ᴢ' => 'Z', 'ᵫ' => 'ue', 'ᵬ' => 'b', 'ᵭ' => 'd', 'ᵮ' => 'f', 'ᵯ' => 'm', 'ᵰ' => 'n', 'ᵱ' => 'p', 'ᵲ' => 'r', 'ᵳ' => 'r', 'ᵴ' => 's', 'ᵵ' => 't', 'ᵶ' => 'z', 'ᵺ' => 'th', 'ᵻ' => 'I', 'ᵽ' => 'p', 'ᵾ' => 'U', 'ᶀ' => 'b', 'ᶁ' => 'd', 'ᶂ' => 'f', 'ᶃ' => 'g', 'ᶄ' => 'k', 'ᶅ' => 'l', 'ᶆ' => 'm', 'ᶇ' => 'n', 'ᶈ' => 'p', 'ᶉ' => 'r', 'ᶊ' => 's', 'ᶌ' => 'v', 'ᶍ' => 'x', 'ᶎ' => 'z', 'ᶏ' => 'a', 'ᶑ' => 'd', 'ᶒ' => 'e', 'ᶓ' => 'e', 'ᶖ' => 'i', 'ᶙ' => 'u', 'ẜ' => 's', 'ẝ' => 's', 'ẞ' => 'SS', 'Ỻ' => 'LL', 'ỻ' => 'll', 'Ỽ' => 'V', 'ỽ' => 'v', 'Ỿ' => 'Y', 'ỿ' => 'y', 'Ⱡ' => 'L', 'ⱡ' => 'l', 'Ɫ' => 'L', 'Ᵽ' => 'P', 'Ɽ' => 'R', 'ⱥ' => 'a', 'ⱦ' => 't', 'Ⱨ' => 'H', 'ⱨ' => 'h', 'Ⱪ' => 'K', 'ⱪ' => 'k', 'Ⱬ' => 'Z', 'ⱬ' => 'z', 'Ɱ' => 'M', 'ⱱ' => 'v', 'Ⱳ' => 'W', 'ⱳ' => 'w', 'ⱴ' => 'v', 'ⱸ' => 'e', 'ⱺ' => 'o', 'Ȿ' => 'S', 'Ɀ' => 'Z', 'ꜰ' => 'F', 'ꜱ' => 'S', 'Ꜳ' => 'AA', 'ꜳ' => 'aa', 'Ꜵ' => 'AO', 'ꜵ' => 'ao', 'Ꜷ' => 'AU', 'ꜷ' => 'au', 'Ꜹ' => 'AV', 'ꜹ' => 'av', 'Ꜻ' => 'AV', 'ꜻ' => 'av', 'Ꜽ' => 'AY', 'ꜽ' => 'ay', 'Ꝁ' => 'K', 'ꝁ' => 'k', 'Ꝃ' => 'K', 'ꝃ' => 'k', 'Ꝅ' => 'K', 'ꝅ' => 'k', 'Ꝇ' => 'L', 'ꝇ' => 'l', 'Ꝉ' => 'L', 'ꝉ' => 'l', 'Ꝋ' => 'O', 'ꝋ' => 'o', 'Ꝍ' => 'O', 'ꝍ' => 'o', 'Ꝏ' => 'OO', 'ꝏ' => 'oo', 'Ꝑ' => 'P', 'ꝑ' => 'p', 'Ꝓ' => 'P', 'ꝓ' => 'p', 'Ꝕ' => 'P', 'ꝕ' => 'p', 'Ꝗ' => 'Q', 'ꝗ' => 'q', 'Ꝙ' => 'Q', 'ꝙ' => 'q', 'Ꝟ' => 'V', 'ꝟ' => 'v', 'Ꝡ' => 'VY', 'ꝡ' => 'vy', 'Ꝥ' => 'TH', 'ꝥ' => 'th', 'Ꝧ' => 'TH', 'ꝧ' => 'th', 'ꝱ' => 'd', 'ꝲ' => 'l', 'ꝳ' => 'm', 'ꝴ' => 'n', 'ꝵ' => 'r', 'ꝶ' => 'R', 'ꝷ' => 't', 'Ꝺ' => 'D', 'ꝺ' => 'd', 'Ꝼ' => 'F', 'ꝼ' => 'f', 'Ꞇ' => 'T', 'ꞇ' => 't', 'Ꞑ' => 'N', 'ꞑ' => 'n', 'Ꞓ' => 'C', 'ꞓ' => 'c', 'Ꞡ' => 'G', 'ꞡ' => 'g', 'Ꞣ' => 'K', 'ꞣ' => 'k', 'Ꞥ' => 'N', 'ꞥ' => 'n', 'Ꞧ' => 'R', 'ꞧ' => 'r', 'Ꞩ' => 'S', 'ꞩ' => 's', 'Ɦ' => 'H', '©' => '(C)', '®' => '(R)', '₠' => 'CE', '₢' => 'Cr', '₣' => 'Fr.', '₤' => 'L.', '₧' => 'Pts', '₹' => 'Rs', '₺' => 'TL', '℗' => '(P)', '℘' => 'P', '℞' => 'Rx', '〇' => '0', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', 'ʹ' => '\'', 'ʺ' => '"', 'ʻ' => '\'', 'ʼ' => '\'', 'ʽ' => '\'', 'ˈ' => '\'', 'ˋ' => '`', '‘' => '\'', '’' => '\'', '‚' => ',', '‛' => '\'', '“' => '"', '”' => '"', '„' => ',,', '‟' => '"', '′' => '\'', '〝' => '"', '〞' => '"', '«' => '<<', '»' => '>>', '‹' => '<', '›' => '>', '­' => '-', '‐' => '-', '‑' => '-', '‒' => '-', '–' => '-', '—' => '-', '―' => '-', '︱' => '-', '︲' => '-', '¡' => '!', '¿' => '?', '˂' => '<', '˃' => '>', '˄' => '^', 'ˆ' => '^', 'ː' => ':', '˜' => '~', '‖' => '||', '⁄' => '/', '⁅' => '[', '⁆' => ']', '⁎' => '*', '、' => ',', '。' => '.', '〈' => '<', '〉' => '>', '《' => '<<', '》' => '>>', '〔' => '[', '〕' => ']', '〘' => '[', '〙' => ']', '〚' => '[', '〛' => ']', '︐' => ',', '︑' => ',', '︒' => '.', '︓' => ':', '︔' => ';', '︕' => '!', '︖' => '?', '︙' => '...', '︰' => '..', '︵' => '(', '︶' => ')', '︷' => '{', '︸' => '}', '︹' => '[', '︺' => ']', '︽' => '<<', '︾' => '>>', '︿' => '<', '﹀' => '>', '﹇' => '[', '﹈' => ']', '±' => '+/-', '×' => '*', '÷' => '/', '˖' => '+', '˗' => '-', '−' => '-', '∕' => '/', '∖' => '\\', '∣' => '|', '∥' => '||', '≪' => '<<', '≫' => '>>', '⦅' => '((', '⦆' => '))', ); polyfill-iconv/Resources/charset/from.windows-1253.php000064400000006726150432043200016656 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => '‰', '' => '‹', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '™', '' => '›', '' => ' ', '' => '΅', '' => 'Ά', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '―', '' => '°', '' => '±', '' => '²', '' => '³', '' => '΄', '' => 'µ', '' => '¶', '' => '·', '' => 'Έ', '' => 'Ή', '' => 'Ί', '' => '»', '' => 'Ό', '' => '½', '' => 'Ύ', '' => 'Ώ', '' => 'ΐ', '' => 'Α', '' => 'Β', '' => 'Γ', '' => 'Δ', '' => 'Ε', '' => 'Ζ', '' => 'Η', '' => 'Θ', '' => 'Ι', '' => 'Κ', '' => 'Λ', '' => 'Μ', '' => 'Ν', '' => 'Ξ', '' => 'Ο', '' => 'Π', '' => 'Ρ', '' => 'Σ', '' => 'Τ', '' => 'Υ', '' => 'Φ', '' => 'Χ', '' => 'Ψ', '' => 'Ω', '' => 'Ϊ', '' => 'Ϋ', '' => 'ά', '' => 'έ', '' => 'ή', '' => 'ί', '' => 'ΰ', '' => 'α', '' => 'β', '' => 'γ', '' => 'δ', '' => 'ε', '' => 'ζ', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'ς', '' => 'σ', '' => 'τ', '' => 'υ', '' => 'φ', '' => 'χ', '' => 'ψ', '' => 'ω', '' => 'ϊ', '' => 'ϋ', '' => 'ό', '' => 'ύ', '' => 'ώ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-8.php000064400000006252150432043200016140 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => '¢', '' => '£', '' => '¤', '' => '¥', '' => '¦', '' => '§', '' => '¨', '' => '©', '' => '×', '' => '«', '' => '¬', '' => '­', '' => '®', '' => '¯', '' => '°', '' => '±', '' => '²', '' => '³', '' => '´', '' => 'µ', '' => '¶', '' => '·', '' => '¸', '' => '¹', '' => '÷', '' => '»', '' => '¼', '' => '½', '' => '¾', '' => '‗', '' => 'א', '' => 'ב', '' => 'ג', '' => 'ד', '' => 'ה', '' => 'ו', '' => 'ז', '' => 'ח', '' => 'ט', '' => 'י', '' => 'ך', '' => 'כ', '' => 'ל', '' => 'ם', '' => 'מ', '' => 'ן', '' => 'נ', '' => 'ס', '' => 'ע', '' => 'ף', '' => 'פ', '' => 'ץ', '' => 'צ', '' => 'ק', '' => 'ר', '' => 'ש', '' => 'ת', '' => '‎', '' => '‏', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp737.php000064400000007372150432043200015435 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Α', '' => 'Β', '' => 'Γ', '' => 'Δ', '' => 'Ε', '' => 'Ζ', '' => 'Η', '' => 'Θ', '' => 'Ι', '' => 'Κ', '' => 'Λ', '' => 'Μ', '' => 'Ν', '' => 'Ξ', '' => 'Ο', '' => 'Π', '' => 'Ρ', '' => 'Σ', '' => 'Τ', '' => 'Υ', '' => 'Φ', '' => 'Χ', '' => 'Ψ', '' => 'Ω', '' => 'α', '' => 'β', '' => 'γ', '' => 'δ', '' => 'ε', '' => 'ζ', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'σ', '' => 'ς', '' => 'τ', '' => 'υ', '' => 'φ', '' => 'χ', '' => 'ψ', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => '╡', '' => '╢', '' => '╖', '' => '╕', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => '╜', '' => '╛', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => '╞', '' => '╟', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => '╧', '' => '╨', '' => '╤', '' => '╥', '' => '╙', '' => '╘', '' => '╒', '' => '╓', '' => '╫', '' => '╪', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => '▌', '' => '▐', '' => '▀', '' => 'ω', '' => 'ά', '' => 'έ', '' => 'ή', '' => 'ϊ', '' => 'ί', '' => 'ό', '' => 'ύ', '' => 'ϋ', '' => 'ώ', '' => 'Ά', '' => 'Έ', '' => 'Ή', '' => 'Ί', '' => 'Ό', '' => 'Ύ', '' => 'Ώ', '' => '±', '' => '≥', '' => '≤', '' => 'Ϊ', '' => 'Ϋ', '' => '÷', '' => '≈', '' => '°', '' => '∙', '' => '·', '' => '√', '' => 'ⁿ', '' => '²', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp949.php000064400001071260150432043200015440 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', 'A' => '갂', 'B' => '갃', 'C' => '갅', 'D' => '갆', 'E' => '갋', 'F' => '갌', 'G' => '갍', 'H' => '갎', 'I' => '갏', 'J' => '갘', 'K' => '갞', 'L' => '갟', 'M' => '갡', 'N' => '갢', 'O' => '갣', 'P' => '갥', 'Q' => '갦', 'R' => '갧', 'S' => '갨', 'T' => '갩', 'U' => '갪', 'V' => '갫', 'W' => '갮', 'X' => '갲', 'Y' => '갳', 'Z' => '갴', 'a' => '갵', 'b' => '갶', 'c' => '갷', 'd' => '갺', 'e' => '갻', 'f' => '갽', 'g' => '갾', 'h' => '갿', 'i' => '걁', 'j' => '걂', 'k' => '걃', 'l' => '걄', 'm' => '걅', 'n' => '걆', 'o' => '걇', 'p' => '걈', 'q' => '걉', 'r' => '걊', 's' => '걌', 't' => '걎', 'u' => '걏', 'v' => '걐', 'w' => '걑', 'x' => '걒', 'y' => '걓', 'z' => '걕', '' => '걖', '' => '걗', '' => '걙', '' => '걚', '' => '걛', '' => '걝', '' => '걞', '' => '걟', '' => '걠', '' => '걡', '' => '걢', '' => '걣', '' => '걤', '' => '걥', '' => '걦', '' => '걧', '' => '걨', '' => '걩', '' => '걪', '' => '걫', '' => '걬', '' => '걭', '' => '걮', '' => '걯', '' => '걲', '' => '걳', '' => '걵', '' => '걶', '' => '걹', '' => '걻', '' => '걼', '' => '걽', '' => '걾', '' => '걿', '' => '겂', '' => '겇', '' => '겈', '' => '겍', '' => '겎', '' => '겏', '' => '겑', '' => '겒', '' => '겓', '' => '겕', '' => '겖', '' => '겗', '' => '겘', '' => '겙', '' => '겚', '' => '겛', '' => '겞', '' => '겢', '' => '겣', '' => '겤', '' => '겥', '' => '겦', '' => '겧', '' => '겫', '' => '겭', '' => '겮', '' => '겱', '' => '겲', '' => '겳', '' => '겴', '' => '겵', '' => '겶', '' => '겷', '' => '겺', '' => '겾', '' => '겿', '' => '곀', '' => '곂', '' => '곃', '' => '곅', '' => '곆', '' => '곇', '' => '곉', '' => '곊', '' => '곋', '' => '곍', '' => '곎', '' => '곏', '' => '곐', '' => '곑', '' => '곒', '' => '곓', '' => '곔', '' => '곖', '' => '곘', '' => '곙', '' => '곚', '' => '곛', '' => '곜', '' => '곝', '' => '곞', '' => '곟', '' => '곢', '' => '곣', '' => '곥', '' => '곦', '' => '곩', '' => '곫', '' => '곭', '' => '곮', '' => '곲', '' => '곴', '' => '곷', '' => '곸', '' => '곹', '' => '곺', '' => '곻', '' => '곾', '' => '곿', '' => '괁', '' => '괂', '' => '괃', '' => '괅', '' => '괇', '' => '괈', '' => '괉', '' => '괊', '' => '괋', '' => '괎', '' => '괐', '' => '괒', '' => '괓', 'A' => '괔', 'B' => '괕', 'C' => '괖', 'D' => '괗', 'E' => '괙', 'F' => '괚', 'G' => '괛', 'H' => '괝', 'I' => '괞', 'J' => '괟', 'K' => '괡', 'L' => '괢', 'M' => '괣', 'N' => '괤', 'O' => '괥', 'P' => '괦', 'Q' => '괧', 'R' => '괨', 'S' => '괪', 'T' => '괫', 'U' => '괮', 'V' => '괯', 'W' => '괰', 'X' => '괱', 'Y' => '괲', 'Z' => '괳', 'a' => '괶', 'b' => '괷', 'c' => '괹', 'd' => '괺', 'e' => '괻', 'f' => '괽', 'g' => '괾', 'h' => '괿', 'i' => '굀', 'j' => '굁', 'k' => '굂', 'l' => '굃', 'm' => '굆', 'n' => '굈', 'o' => '굊', 'p' => '굋', 'q' => '굌', 'r' => '굍', 's' => '굎', 't' => '굏', 'u' => '굑', 'v' => '굒', 'w' => '굓', 'x' => '굕', 'y' => '굖', 'z' => '굗', '' => '굙', '' => '굚', '' => '굛', '' => '굜', '' => '굝', '' => '굞', '' => '굟', '' => '굠', '' => '굢', '' => '굤', '' => '굥', '' => '굦', '' => '굧', '' => '굨', '' => '굩', '' => '굪', '' => '굫', '' => '굮', '' => '굯', '' => '굱', '' => '굲', '' => '굷', '' => '굸', '' => '굹', '' => '굺', '' => '굾', '' => '궀', '' => '궃', '' => '궄', '' => '궅', '' => '궆', '' => '궇', '' => '궊', '' => '궋', '' => '궍', '' => '궎', '' => '궏', '' => '궑', '' => '궒', '' => '궓', '' => '궔', '' => '궕', '' => '궖', '' => '궗', '' => '궘', '' => '궙', '' => '궚', '' => '궛', '' => '궞', '' => '궟', '' => '궠', '' => '궡', '' => '궢', '' => '궣', '' => '궥', '' => '궦', '' => '궧', '' => '궨', '' => '궩', '' => '궪', '' => '궫', '' => '궬', '' => '궭', '' => '궮', '' => '궯', '' => '궰', '' => '궱', '' => '궲', '' => '궳', '' => '궴', '' => '궵', '' => '궶', '' => '궸', '' => '궹', '' => '궺', '' => '궻', '' => '궼', '' => '궽', '' => '궾', '' => '궿', '' => '귂', '' => '귃', '' => '귅', '' => '귆', '' => '귇', '' => '귉', '' => '귊', '' => '귋', '' => '귌', '' => '귍', '' => '귎', '' => '귏', '' => '귒', '' => '귔', '' => '귕', '' => '귖', '' => '귗', '' => '귘', '' => '귙', '' => '귚', '' => '귛', '' => '귝', '' => '귞', '' => '귟', '' => '귡', '' => '귢', '' => '귣', '' => '귥', '' => '귦', '' => '귧', '' => '귨', '' => '귩', '' => '귪', '' => '귫', '' => '귬', '' => '귭', '' => '귮', '' => '귯', '' => '귰', '' => '귱', '' => '귲', '' => '귳', '' => '귴', '' => '귵', '' => '귶', '' => '귷', 'A' => '귺', 'B' => '귻', 'C' => '귽', 'D' => '귾', 'E' => '긂', 'F' => '긃', 'G' => '긄', 'H' => '긅', 'I' => '긆', 'J' => '긇', 'K' => '긊', 'L' => '긌', 'M' => '긎', 'N' => '긏', 'O' => '긐', 'P' => '긑', 'Q' => '긒', 'R' => '긓', 'S' => '긕', 'T' => '긖', 'U' => '긗', 'V' => '긘', 'W' => '긙', 'X' => '긚', 'Y' => '긛', 'Z' => '긜', 'a' => '긝', 'b' => '긞', 'c' => '긟', 'd' => '긠', 'e' => '긡', 'f' => '긢', 'g' => '긣', 'h' => '긤', 'i' => '긥', 'j' => '긦', 'k' => '긧', 'l' => '긨', 'm' => '긩', 'n' => '긪', 'o' => '긫', 'p' => '긬', 'q' => '긭', 'r' => '긮', 's' => '긯', 't' => '긲', 'u' => '긳', 'v' => '긵', 'w' => '긶', 'x' => '긹', 'y' => '긻', 'z' => '긼', '' => '긽', '' => '긾', '' => '긿', '' => '깂', '' => '깄', '' => '깇', '' => '깈', '' => '깉', '' => '깋', '' => '깏', '' => '깑', '' => '깒', '' => '깓', '' => '깕', '' => '깗', '' => '깘', '' => '깙', '' => '깚', '' => '깛', '' => '깞', '' => '깢', '' => '깣', '' => '깤', '' => '깦', '' => '깧', '' => '깪', '' => '깫', '' => '깭', '' => '깮', '' => '깯', '' => '깱', '' => '깲', '' => '깳', '' => '깴', '' => '깵', '' => '깶', '' => '깷', '' => '깺', '' => '깾', '' => '깿', '' => '꺀', '' => '꺁', '' => '꺂', '' => '꺃', '' => '꺆', '' => '꺇', '' => '꺈', '' => '꺉', '' => '꺊', '' => '꺋', '' => '꺍', '' => '꺎', '' => '꺏', '' => '꺐', '' => '꺑', '' => '꺒', '' => '꺓', '' => '꺔', '' => '꺕', '' => '꺖', '' => '꺗', '' => '꺘', '' => '꺙', '' => '꺚', '' => '꺛', '' => '꺜', '' => '꺝', '' => '꺞', '' => '꺟', '' => '꺠', '' => '꺡', '' => '꺢', '' => '꺣', '' => '꺤', '' => '꺥', '' => '꺦', '' => '꺧', '' => '꺨', '' => '꺩', '' => '꺪', '' => '꺫', '' => '꺬', '' => '꺭', '' => '꺮', '' => '꺯', '' => '꺰', '' => '꺱', '' => '꺲', '' => '꺳', '' => '꺴', '' => '꺵', '' => '꺶', '' => '꺷', '' => '꺸', '' => '꺹', '' => '꺺', '' => '꺻', '' => '꺿', '' => '껁', '' => '껂', '' => '껃', '' => '껅', '' => '껆', '' => '껇', '' => '껈', '' => '껉', '' => '껊', '' => '껋', '' => '껎', '' => '껒', '' => '껓', '' => '껔', '' => '껕', '' => '껖', '' => '껗', '' => '껚', '' => '껛', '' => '껝', '' => '껞', '' => '껟', '' => '껠', '' => '껡', '' => '껢', '' => '껣', '' => '껤', '' => '껥', 'A' => '껦', 'B' => '껧', 'C' => '껩', 'D' => '껪', 'E' => '껬', 'F' => '껮', 'G' => '껯', 'H' => '껰', 'I' => '껱', 'J' => '껲', 'K' => '껳', 'L' => '껵', 'M' => '껶', 'N' => '껷', 'O' => '껹', 'P' => '껺', 'Q' => '껻', 'R' => '껽', 'S' => '껾', 'T' => '껿', 'U' => '꼀', 'V' => '꼁', 'W' => '꼂', 'X' => '꼃', 'Y' => '꼄', 'Z' => '꼅', 'a' => '꼆', 'b' => '꼉', 'c' => '꼊', 'd' => '꼋', 'e' => '꼌', 'f' => '꼎', 'g' => '꼏', 'h' => '꼑', 'i' => '꼒', 'j' => '꼓', 'k' => '꼔', 'l' => '꼕', 'm' => '꼖', 'n' => '꼗', 'o' => '꼘', 'p' => '꼙', 'q' => '꼚', 'r' => '꼛', 's' => '꼜', 't' => '꼝', 'u' => '꼞', 'v' => '꼟', 'w' => '꼠', 'x' => '꼡', 'y' => '꼢', 'z' => '꼣', '' => '꼤', '' => '꼥', '' => '꼦', '' => '꼧', '' => '꼨', '' => '꼩', '' => '꼪', '' => '꼫', '' => '꼮', '' => '꼯', '' => '꼱', '' => '꼳', '' => '꼵', '' => '꼶', '' => '꼷', '' => '꼸', '' => '꼹', '' => '꼺', '' => '꼻', '' => '꼾', '' => '꽀', '' => '꽄', '' => '꽅', '' => '꽆', '' => '꽇', '' => '꽊', '' => '꽋', '' => '꽌', '' => '꽍', '' => '꽎', '' => '꽏', '' => '꽑', '' => '꽒', '' => '꽓', '' => '꽔', '' => '꽕', '' => '꽖', '' => '꽗', '' => '꽘', '' => '꽙', '' => '꽚', '' => '꽛', '' => '꽞', '' => '꽟', '' => '꽠', '' => '꽡', '' => '꽢', '' => '꽣', '' => '꽦', '' => '꽧', '' => '꽨', '' => '꽩', '' => '꽪', '' => '꽫', '' => '꽬', '' => '꽭', '' => '꽮', '' => '꽯', '' => '꽰', '' => '꽱', '' => '꽲', '' => '꽳', '' => '꽴', '' => '꽵', '' => '꽶', '' => '꽷', '' => '꽸', '' => '꽺', '' => '꽻', '' => '꽼', '' => '꽽', '' => '꽾', '' => '꽿', '' => '꾁', '' => '꾂', '' => '꾃', '' => '꾅', '' => '꾆', '' => '꾇', '' => '꾉', '' => '꾊', '' => '꾋', '' => '꾌', '' => '꾍', '' => '꾎', '' => '꾏', '' => '꾒', '' => '꾓', '' => '꾔', '' => '꾖', '' => '꾗', '' => '꾘', '' => '꾙', '' => '꾚', '' => '꾛', '' => '꾝', '' => '꾞', '' => '꾟', '' => '꾠', '' => '꾡', '' => '꾢', '' => '꾣', '' => '꾤', '' => '꾥', '' => '꾦', '' => '꾧', '' => '꾨', '' => '꾩', '' => '꾪', '' => '꾫', '' => '꾬', '' => '꾭', '' => '꾮', '' => '꾯', '' => '꾰', '' => '꾱', '' => '꾲', '' => '꾳', '' => '꾴', '' => '꾵', '' => '꾶', '' => '꾷', '' => '꾺', '' => '꾻', '' => '꾽', '' => '꾾', 'A' => '꾿', 'B' => '꿁', 'C' => '꿂', 'D' => '꿃', 'E' => '꿄', 'F' => '꿅', 'G' => '꿆', 'H' => '꿊', 'I' => '꿌', 'J' => '꿏', 'K' => '꿐', 'L' => '꿑', 'M' => '꿒', 'N' => '꿓', 'O' => '꿕', 'P' => '꿖', 'Q' => '꿗', 'R' => '꿘', 'S' => '꿙', 'T' => '꿚', 'U' => '꿛', 'V' => '꿝', 'W' => '꿞', 'X' => '꿟', 'Y' => '꿠', 'Z' => '꿡', 'a' => '꿢', 'b' => '꿣', 'c' => '꿤', 'd' => '꿥', 'e' => '꿦', 'f' => '꿧', 'g' => '꿪', 'h' => '꿫', 'i' => '꿬', 'j' => '꿭', 'k' => '꿮', 'l' => '꿯', 'm' => '꿲', 'n' => '꿳', 'o' => '꿵', 'p' => '꿶', 'q' => '꿷', 'r' => '꿹', 's' => '꿺', 't' => '꿻', 'u' => '꿼', 'v' => '꿽', 'w' => '꿾', 'x' => '꿿', 'y' => '뀂', 'z' => '뀃', '' => '뀅', '' => '뀆', '' => '뀇', '' => '뀈', '' => '뀉', '' => '뀊', '' => '뀋', '' => '뀍', '' => '뀎', '' => '뀏', '' => '뀑', '' => '뀒', '' => '뀓', '' => '뀕', '' => '뀖', '' => '뀗', '' => '뀘', '' => '뀙', '' => '뀚', '' => '뀛', '' => '뀞', '' => '뀟', '' => '뀠', '' => '뀡', '' => '뀢', '' => '뀣', '' => '뀤', '' => '뀥', '' => '뀦', '' => '뀧', '' => '뀩', '' => '뀪', '' => '뀫', '' => '뀬', '' => '뀭', '' => '뀮', '' => '뀯', '' => '뀰', '' => '뀱', '' => '뀲', '' => '뀳', '' => '뀴', '' => '뀵', '' => '뀶', '' => '뀷', '' => '뀸', '' => '뀹', '' => '뀺', '' => '뀻', '' => '뀼', '' => '뀽', '' => '뀾', '' => '뀿', '' => '끀', '' => '끁', '' => '끂', '' => '끃', '' => '끆', '' => '끇', '' => '끉', '' => '끋', '' => '끍', '' => '끏', '' => '끐', '' => '끑', '' => '끒', '' => '끖', '' => '끘', '' => '끚', '' => '끛', '' => '끜', '' => '끞', '' => '끟', '' => '끠', '' => '끡', '' => '끢', '' => '끣', '' => '끤', '' => '끥', '' => '끦', '' => '끧', '' => '끨', '' => '끩', '' => '끪', '' => '끫', '' => '끬', '' => '끭', '' => '끮', '' => '끯', '' => '끰', '' => '끱', '' => '끲', '' => '끳', '' => '끴', '' => '끵', '' => '끶', '' => '끷', '' => '끸', '' => '끹', '' => '끺', '' => '끻', '' => '끾', '' => '끿', '' => '낁', '' => '낂', '' => '낃', '' => '낅', '' => '낆', '' => '낇', '' => '낈', '' => '낉', '' => '낊', '' => '낋', '' => '낎', '' => '낐', '' => '낒', '' => '낓', '' => '낔', '' => '낕', '' => '낖', '' => '낗', '' => '낛', '' => '낝', '' => '낞', '' => '낣', '' => '낤', 'A' => '낥', 'B' => '낦', 'C' => '낧', 'D' => '낪', 'E' => '낰', 'F' => '낲', 'G' => '낶', 'H' => '낷', 'I' => '낹', 'J' => '낺', 'K' => '낻', 'L' => '낽', 'M' => '낾', 'N' => '낿', 'O' => '냀', 'P' => '냁', 'Q' => '냂', 'R' => '냃', 'S' => '냆', 'T' => '냊', 'U' => '냋', 'V' => '냌', 'W' => '냍', 'X' => '냎', 'Y' => '냏', 'Z' => '냒', 'a' => '냓', 'b' => '냕', 'c' => '냖', 'd' => '냗', 'e' => '냙', 'f' => '냚', 'g' => '냛', 'h' => '냜', 'i' => '냝', 'j' => '냞', 'k' => '냟', 'l' => '냡', 'm' => '냢', 'n' => '냣', 'o' => '냤', 'p' => '냦', 'q' => '냧', 'r' => '냨', 's' => '냩', 't' => '냪', 'u' => '냫', 'v' => '냬', 'w' => '냭', 'x' => '냮', 'y' => '냯', 'z' => '냰', '' => '냱', '' => '냲', '' => '냳', '' => '냴', '' => '냵', '' => '냶', '' => '냷', '' => '냸', '' => '냹', '' => '냺', '' => '냻', '' => '냼', '' => '냽', '' => '냾', '' => '냿', '' => '넀', '' => '넁', '' => '넂', '' => '넃', '' => '넄', '' => '넅', '' => '넆', '' => '넇', '' => '넊', '' => '넍', '' => '넎', '' => '넏', '' => '넑', '' => '넔', '' => '넕', '' => '넖', '' => '넗', '' => '넚', '' => '넞', '' => '넟', '' => '넠', '' => '넡', '' => '넢', '' => '넦', '' => '넧', '' => '넩', '' => '넪', '' => '넫', '' => '넭', '' => '넮', '' => '넯', '' => '넰', '' => '넱', '' => '넲', '' => '넳', '' => '넶', '' => '넺', '' => '넻', '' => '넼', '' => '넽', '' => '넾', '' => '넿', '' => '녂', '' => '녃', '' => '녅', '' => '녆', '' => '녇', '' => '녉', '' => '녊', '' => '녋', '' => '녌', '' => '녍', '' => '녎', '' => '녏', '' => '녒', '' => '녓', '' => '녖', '' => '녗', '' => '녙', '' => '녚', '' => '녛', '' => '녝', '' => '녞', '' => '녟', '' => '녡', '' => '녢', '' => '녣', '' => '녤', '' => '녥', '' => '녦', '' => '녧', '' => '녨', '' => '녩', '' => '녪', '' => '녫', '' => '녬', '' => '녭', '' => '녮', '' => '녯', '' => '녰', '' => '녱', '' => '녲', '' => '녳', '' => '녴', '' => '녵', '' => '녶', '' => '녷', '' => '녺', '' => '녻', '' => '녽', '' => '녾', '' => '녿', '' => '놁', '' => '놃', '' => '놄', '' => '놅', '' => '놆', '' => '놇', '' => '놊', '' => '놌', '' => '놎', '' => '놏', '' => '놐', '' => '놑', '' => '놕', '' => '놖', '' => '놗', '' => '놙', '' => '놚', '' => '놛', '' => '놝', 'A' => '놞', 'B' => '놟', 'C' => '놠', 'D' => '놡', 'E' => '놢', 'F' => '놣', 'G' => '놤', 'H' => '놥', 'I' => '놦', 'J' => '놧', 'K' => '놩', 'L' => '놪', 'M' => '놫', 'N' => '놬', 'O' => '놭', 'P' => '놮', 'Q' => '놯', 'R' => '놰', 'S' => '놱', 'T' => '놲', 'U' => '놳', 'V' => '놴', 'W' => '놵', 'X' => '놶', 'Y' => '놷', 'Z' => '놸', 'a' => '놹', 'b' => '놺', 'c' => '놻', 'd' => '놼', 'e' => '놽', 'f' => '놾', 'g' => '놿', 'h' => '뇀', 'i' => '뇁', 'j' => '뇂', 'k' => '뇃', 'l' => '뇄', 'm' => '뇅', 'n' => '뇆', 'o' => '뇇', 'p' => '뇈', 'q' => '뇉', 'r' => '뇊', 's' => '뇋', 't' => '뇍', 'u' => '뇎', 'v' => '뇏', 'w' => '뇑', 'x' => '뇒', 'y' => '뇓', 'z' => '뇕', '' => '뇖', '' => '뇗', '' => '뇘', '' => '뇙', '' => '뇚', '' => '뇛', '' => '뇞', '' => '뇠', '' => '뇡', '' => '뇢', '' => '뇣', '' => '뇤', '' => '뇥', '' => '뇦', '' => '뇧', '' => '뇪', '' => '뇫', '' => '뇭', '' => '뇮', '' => '뇯', '' => '뇱', '' => '뇲', '' => '뇳', '' => '뇴', '' => '뇵', '' => '뇶', '' => '뇷', '' => '뇸', '' => '뇺', '' => '뇼', '' => '뇾', '' => '뇿', '' => '눀', '' => '눁', '' => '눂', '' => '눃', '' => '눆', '' => '눇', '' => '눉', '' => '눊', '' => '눍', '' => '눎', '' => '눏', '' => '눐', '' => '눑', '' => '눒', '' => '눓', '' => '눖', '' => '눘', '' => '눚', '' => '눛', '' => '눜', '' => '눝', '' => '눞', '' => '눟', '' => '눡', '' => '눢', '' => '눣', '' => '눤', '' => '눥', '' => '눦', '' => '눧', '' => '눨', '' => '눩', '' => '눪', '' => '눫', '' => '눬', '' => '눭', '' => '눮', '' => '눯', '' => '눰', '' => '눱', '' => '눲', '' => '눳', '' => '눵', '' => '눶', '' => '눷', '' => '눸', '' => '눹', '' => '눺', '' => '눻', '' => '눽', '' => '눾', '' => '눿', '' => '뉀', '' => '뉁', '' => '뉂', '' => '뉃', '' => '뉄', '' => '뉅', '' => '뉆', '' => '뉇', '' => '뉈', '' => '뉉', '' => '뉊', '' => '뉋', '' => '뉌', '' => '뉍', '' => '뉎', '' => '뉏', '' => '뉐', '' => '뉑', '' => '뉒', '' => '뉓', '' => '뉔', '' => '뉕', '' => '뉖', '' => '뉗', '' => '뉙', '' => '뉚', '' => '뉛', '' => '뉝', '' => '뉞', '' => '뉟', '' => '뉡', '' => '뉢', '' => '뉣', '' => '뉤', '' => '뉥', '' => '뉦', '' => '뉧', '' => '뉪', '' => '뉫', '' => '뉬', '' => '뉭', '' => '뉮', 'A' => '뉯', 'B' => '뉰', 'C' => '뉱', 'D' => '뉲', 'E' => '뉳', 'F' => '뉶', 'G' => '뉷', 'H' => '뉸', 'I' => '뉹', 'J' => '뉺', 'K' => '뉻', 'L' => '뉽', 'M' => '뉾', 'N' => '뉿', 'O' => '늀', 'P' => '늁', 'Q' => '늂', 'R' => '늃', 'S' => '늆', 'T' => '늇', 'U' => '늈', 'V' => '늊', 'W' => '늋', 'X' => '늌', 'Y' => '늍', 'Z' => '늎', 'a' => '늏', 'b' => '늒', 'c' => '늓', 'd' => '늕', 'e' => '늖', 'f' => '늗', 'g' => '늛', 'h' => '늜', 'i' => '늝', 'j' => '늞', 'k' => '늟', 'l' => '늢', 'm' => '늤', 'n' => '늧', 'o' => '늨', 'p' => '늩', 'q' => '늫', 'r' => '늭', 's' => '늮', 't' => '늯', 'u' => '늱', 'v' => '늲', 'w' => '늳', 'x' => '늵', 'y' => '늶', 'z' => '늷', '' => '늸', '' => '늹', '' => '늺', '' => '늻', '' => '늼', '' => '늽', '' => '늾', '' => '늿', '' => '닀', '' => '닁', '' => '닂', '' => '닃', '' => '닄', '' => '닅', '' => '닆', '' => '닇', '' => '닊', '' => '닋', '' => '닍', '' => '닎', '' => '닏', '' => '닑', '' => '닓', '' => '닔', '' => '닕', '' => '닖', '' => '닗', '' => '닚', '' => '닜', '' => '닞', '' => '닟', '' => '닠', '' => '닡', '' => '닣', '' => '닧', '' => '닩', '' => '닪', '' => '닰', '' => '닱', '' => '닲', '' => '닶', '' => '닼', '' => '닽', '' => '닾', '' => '댂', '' => '댃', '' => '댅', '' => '댆', '' => '댇', '' => '댉', '' => '댊', '' => '댋', '' => '댌', '' => '댍', '' => '댎', '' => '댏', '' => '댒', '' => '댖', '' => '댗', '' => '댘', '' => '댙', '' => '댚', '' => '댛', '' => '댝', '' => '댞', '' => '댟', '' => '댠', '' => '댡', '' => '댢', '' => '댣', '' => '댤', '' => '댥', '' => '댦', '' => '댧', '' => '댨', '' => '댩', '' => '댪', '' => '댫', '' => '댬', '' => '댭', '' => '댮', '' => '댯', '' => '댰', '' => '댱', '' => '댲', '' => '댳', '' => '댴', '' => '댵', '' => '댶', '' => '댷', '' => '댸', '' => '댹', '' => '댺', '' => '댻', '' => '댼', '' => '댽', '' => '댾', '' => '댿', '' => '덀', '' => '덁', '' => '덂', '' => '덃', '' => '덄', '' => '덅', '' => '덆', '' => '덇', '' => '덈', '' => '덉', '' => '덊', '' => '덋', '' => '덌', '' => '덍', '' => '덎', '' => '덏', '' => '덐', '' => '덑', '' => '덒', '' => '덓', '' => '덗', '' => '덙', '' => '덚', '' => '덝', '' => '덠', '' => '덡', '' => '덢', '' => '덣', 'A' => '덦', 'B' => '덨', 'C' => '덪', 'D' => '덬', 'E' => '덭', 'F' => '덯', 'G' => '덲', 'H' => '덳', 'I' => '덵', 'J' => '덶', 'K' => '덷', 'L' => '덹', 'M' => '덺', 'N' => '덻', 'O' => '덼', 'P' => '덽', 'Q' => '덾', 'R' => '덿', 'S' => '뎂', 'T' => '뎆', 'U' => '뎇', 'V' => '뎈', 'W' => '뎉', 'X' => '뎊', 'Y' => '뎋', 'Z' => '뎍', 'a' => '뎎', 'b' => '뎏', 'c' => '뎑', 'd' => '뎒', 'e' => '뎓', 'f' => '뎕', 'g' => '뎖', 'h' => '뎗', 'i' => '뎘', 'j' => '뎙', 'k' => '뎚', 'l' => '뎛', 'm' => '뎜', 'n' => '뎝', 'o' => '뎞', 'p' => '뎟', 'q' => '뎢', 'r' => '뎣', 's' => '뎤', 't' => '뎥', 'u' => '뎦', 'v' => '뎧', 'w' => '뎩', 'x' => '뎪', 'y' => '뎫', 'z' => '뎭', '' => '뎮', '' => '뎯', '' => '뎰', '' => '뎱', '' => '뎲', '' => '뎳', '' => '뎴', '' => '뎵', '' => '뎶', '' => '뎷', '' => '뎸', '' => '뎹', '' => '뎺', '' => '뎻', '' => '뎼', '' => '뎽', '' => '뎾', '' => '뎿', '' => '돀', '' => '돁', '' => '돂', '' => '돃', '' => '돆', '' => '돇', '' => '돉', '' => '돊', '' => '돍', '' => '돏', '' => '돑', '' => '돒', '' => '돓', '' => '돖', '' => '돘', '' => '돚', '' => '돜', '' => '돞', '' => '돟', '' => '돡', '' => '돢', '' => '돣', '' => '돥', '' => '돦', '' => '돧', '' => '돩', '' => '돪', '' => '돫', '' => '돬', '' => '돭', '' => '돮', '' => '돯', '' => '돰', '' => '돱', '' => '돲', '' => '돳', '' => '돴', '' => '돵', '' => '돶', '' => '돷', '' => '돸', '' => '돹', '' => '돺', '' => '돻', '' => '돽', '' => '돾', '' => '돿', '' => '됀', '' => '됁', '' => '됂', '' => '됃', '' => '됄', '' => '됅', '' => '됆', '' => '됇', '' => '됈', '' => '됉', '' => '됊', '' => '됋', '' => '됌', '' => '됍', '' => '됎', '' => '됏', '' => '됑', '' => '됒', '' => '됓', '' => '됔', '' => '됕', '' => '됖', '' => '됗', '' => '됙', '' => '됚', '' => '됛', '' => '됝', '' => '됞', '' => '됟', '' => '됡', '' => '됢', '' => '됣', '' => '됤', '' => '됥', '' => '됦', '' => '됧', '' => '됪', '' => '됬', '' => '됭', '' => '됮', '' => '됯', '' => '됰', '' => '됱', '' => '됲', '' => '됳', '' => '됵', '' => '됶', '' => '됷', '' => '됸', '' => '됹', '' => '됺', '' => '됻', '' => '됼', '' => '됽', '' => '됾', '' => '됿', '' => '둀', '' => '둁', '' => '둂', '' => '둃', '' => '둄', 'A' => '둅', 'B' => '둆', 'C' => '둇', 'D' => '둈', 'E' => '둉', 'F' => '둊', 'G' => '둋', 'H' => '둌', 'I' => '둍', 'J' => '둎', 'K' => '둏', 'L' => '둒', 'M' => '둓', 'N' => '둕', 'O' => '둖', 'P' => '둗', 'Q' => '둙', 'R' => '둚', 'S' => '둛', 'T' => '둜', 'U' => '둝', 'V' => '둞', 'W' => '둟', 'X' => '둢', 'Y' => '둤', 'Z' => '둦', 'a' => '둧', 'b' => '둨', 'c' => '둩', 'd' => '둪', 'e' => '둫', 'f' => '둭', 'g' => '둮', 'h' => '둯', 'i' => '둰', 'j' => '둱', 'k' => '둲', 'l' => '둳', 'm' => '둴', 'n' => '둵', 'o' => '둶', 'p' => '둷', 'q' => '둸', 'r' => '둹', 's' => '둺', 't' => '둻', 'u' => '둼', 'v' => '둽', 'w' => '둾', 'x' => '둿', 'y' => '뒁', 'z' => '뒂', '' => '뒃', '' => '뒄', '' => '뒅', '' => '뒆', '' => '뒇', '' => '뒉', '' => '뒊', '' => '뒋', '' => '뒌', '' => '뒍', '' => '뒎', '' => '뒏', '' => '뒐', '' => '뒑', '' => '뒒', '' => '뒓', '' => '뒔', '' => '뒕', '' => '뒖', '' => '뒗', '' => '뒘', '' => '뒙', '' => '뒚', '' => '뒛', '' => '뒜', '' => '뒞', '' => '뒟', '' => '뒠', '' => '뒡', '' => '뒢', '' => '뒣', '' => '뒥', '' => '뒦', '' => '뒧', '' => '뒩', '' => '뒪', '' => '뒫', '' => '뒭', '' => '뒮', '' => '뒯', '' => '뒰', '' => '뒱', '' => '뒲', '' => '뒳', '' => '뒴', '' => '뒶', '' => '뒸', '' => '뒺', '' => '뒻', '' => '뒼', '' => '뒽', '' => '뒾', '' => '뒿', '' => '듁', '' => '듂', '' => '듃', '' => '듅', '' => '듆', '' => '듇', '' => '듉', '' => '듊', '' => '듋', '' => '듌', '' => '듍', '' => '듎', '' => '듏', '' => '듑', '' => '듒', '' => '듓', '' => '듔', '' => '듖', '' => '듗', '' => '듘', '' => '듙', '' => '듚', '' => '듛', '' => '듞', '' => '듟', '' => '듡', '' => '듢', '' => '듥', '' => '듧', '' => '듨', '' => '듩', '' => '듪', '' => '듫', '' => '듮', '' => '듰', '' => '듲', '' => '듳', '' => '듴', '' => '듵', '' => '듶', '' => '듷', '' => '듹', '' => '듺', '' => '듻', '' => '듼', '' => '듽', '' => '듾', '' => '듿', '' => '딀', '' => '딁', '' => '딂', '' => '딃', '' => '딄', '' => '딅', '' => '딆', '' => '딇', '' => '딈', '' => '딉', '' => '딊', '' => '딋', '' => '딌', '' => '딍', '' => '딎', '' => '딏', '' => '딐', '' => '딑', '' => '딒', '' => '딓', '' => '딖', '' => '딗', '' => '딙', '' => '딚', '' => '딝', 'A' => '딞', 'B' => '딟', 'C' => '딠', 'D' => '딡', 'E' => '딢', 'F' => '딣', 'G' => '딦', 'H' => '딫', 'I' => '딬', 'J' => '딭', 'K' => '딮', 'L' => '딯', 'M' => '딲', 'N' => '딳', 'O' => '딵', 'P' => '딶', 'Q' => '딷', 'R' => '딹', 'S' => '딺', 'T' => '딻', 'U' => '딼', 'V' => '딽', 'W' => '딾', 'X' => '딿', 'Y' => '땂', 'Z' => '땆', 'a' => '땇', 'b' => '땈', 'c' => '땉', 'd' => '땊', 'e' => '땎', 'f' => '땏', 'g' => '땑', 'h' => '땒', 'i' => '땓', 'j' => '땕', 'k' => '땖', 'l' => '땗', 'm' => '땘', 'n' => '땙', 'o' => '땚', 'p' => '땛', 'q' => '땞', 'r' => '땢', 's' => '땣', 't' => '땤', 'u' => '땥', 'v' => '땦', 'w' => '땧', 'x' => '땨', 'y' => '땩', 'z' => '땪', '' => '땫', '' => '땬', '' => '땭', '' => '땮', '' => '땯', '' => '땰', '' => '땱', '' => '땲', '' => '땳', '' => '땴', '' => '땵', '' => '땶', '' => '땷', '' => '땸', '' => '땹', '' => '땺', '' => '땻', '' => '땼', '' => '땽', '' => '땾', '' => '땿', '' => '떀', '' => '떁', '' => '떂', '' => '떃', '' => '떄', '' => '떅', '' => '떆', '' => '떇', '' => '떈', '' => '떉', '' => '떊', '' => '떋', '' => '떌', '' => '떍', '' => '떎', '' => '떏', '' => '떐', '' => '떑', '' => '떒', '' => '떓', '' => '떔', '' => '떕', '' => '떖', '' => '떗', '' => '떘', '' => '떙', '' => '떚', '' => '떛', '' => '떜', '' => '떝', '' => '떞', '' => '떟', '' => '떢', '' => '떣', '' => '떥', '' => '떦', '' => '떧', '' => '떩', '' => '떬', '' => '떭', '' => '떮', '' => '떯', '' => '떲', '' => '떶', '' => '떷', '' => '떸', '' => '떹', '' => '떺', '' => '떾', '' => '떿', '' => '뗁', '' => '뗂', '' => '뗃', '' => '뗅', '' => '뗆', '' => '뗇', '' => '뗈', '' => '뗉', '' => '뗊', '' => '뗋', '' => '뗎', '' => '뗒', '' => '뗓', '' => '뗔', '' => '뗕', '' => '뗖', '' => '뗗', '' => '뗙', '' => '뗚', '' => '뗛', '' => '뗜', '' => '뗝', '' => '뗞', '' => '뗟', '' => '뗠', '' => '뗡', '' => '뗢', '' => '뗣', '' => '뗤', '' => '뗥', '' => '뗦', '' => '뗧', '' => '뗨', '' => '뗩', '' => '뗪', '' => '뗫', '' => '뗭', '' => '뗮', '' => '뗯', '' => '뗰', '' => '뗱', '' => '뗲', '' => '뗳', '' => '뗴', '' => '뗵', '' => '뗶', '' => '뗷', '' => '뗸', '' => '뗹', '' => '뗺', '' => '뗻', '' => '뗼', '' => '뗽', '' => '뗾', '' => '뗿', 'A' => '똀', 'B' => '똁', 'C' => '똂', 'D' => '똃', 'E' => '똄', 'F' => '똅', 'G' => '똆', 'H' => '똇', 'I' => '똈', 'J' => '똉', 'K' => '똊', 'L' => '똋', 'M' => '똌', 'N' => '똍', 'O' => '똎', 'P' => '똏', 'Q' => '똒', 'R' => '똓', 'S' => '똕', 'T' => '똖', 'U' => '똗', 'V' => '똙', 'W' => '똚', 'X' => '똛', 'Y' => '똜', 'Z' => '똝', 'a' => '똞', 'b' => '똟', 'c' => '똠', 'd' => '똡', 'e' => '똢', 'f' => '똣', 'g' => '똤', 'h' => '똦', 'i' => '똧', 'j' => '똨', 'k' => '똩', 'l' => '똪', 'm' => '똫', 'n' => '똭', 'o' => '똮', 'p' => '똯', 'q' => '똰', 'r' => '똱', 's' => '똲', 't' => '똳', 'u' => '똵', 'v' => '똶', 'w' => '똷', 'x' => '똸', 'y' => '똹', 'z' => '똺', '' => '똻', '' => '똼', '' => '똽', '' => '똾', '' => '똿', '' => '뙀', '' => '뙁', '' => '뙂', '' => '뙃', '' => '뙄', '' => '뙅', '' => '뙆', '' => '뙇', '' => '뙉', '' => '뙊', '' => '뙋', '' => '뙌', '' => '뙍', '' => '뙎', '' => '뙏', '' => '뙐', '' => '뙑', '' => '뙒', '' => '뙓', '' => '뙔', '' => '뙕', '' => '뙖', '' => '뙗', '' => '뙘', '' => '뙙', '' => '뙚', '' => '뙛', '' => '뙜', '' => '뙝', '' => '뙞', '' => '뙟', '' => '뙠', '' => '뙡', '' => '뙢', '' => '뙣', '' => '뙥', '' => '뙦', '' => '뙧', '' => '뙩', '' => '뙪', '' => '뙫', '' => '뙬', '' => '뙭', '' => '뙮', '' => '뙯', '' => '뙰', '' => '뙱', '' => '뙲', '' => '뙳', '' => '뙴', '' => '뙵', '' => '뙶', '' => '뙷', '' => '뙸', '' => '뙹', '' => '뙺', '' => '뙻', '' => '뙼', '' => '뙽', '' => '뙾', '' => '뙿', '' => '뚀', '' => '뚁', '' => '뚂', '' => '뚃', '' => '뚄', '' => '뚅', '' => '뚆', '' => '뚇', '' => '뚈', '' => '뚉', '' => '뚊', '' => '뚋', '' => '뚌', '' => '뚍', '' => '뚎', '' => '뚏', '' => '뚐', '' => '뚑', '' => '뚒', '' => '뚓', '' => '뚔', '' => '뚕', '' => '뚖', '' => '뚗', '' => '뚘', '' => '뚙', '' => '뚚', '' => '뚛', '' => '뚞', '' => '뚟', '' => '뚡', '' => '뚢', '' => '뚣', '' => '뚥', '' => '뚦', '' => '뚧', '' => '뚨', '' => '뚩', '' => '뚪', '' => '뚭', '' => '뚮', '' => '뚯', '' => '뚰', '' => '뚲', '' => '뚳', '' => '뚴', '' => '뚵', '' => '뚶', '' => '뚷', '' => '뚸', '' => '뚹', '' => '뚺', '' => '뚻', '' => '뚼', '' => '뚽', '' => '뚾', '' => '뚿', '' => '뛀', '' => '뛁', '' => '뛂', 'A' => '뛃', 'B' => '뛄', 'C' => '뛅', 'D' => '뛆', 'E' => '뛇', 'F' => '뛈', 'G' => '뛉', 'H' => '뛊', 'I' => '뛋', 'J' => '뛌', 'K' => '뛍', 'L' => '뛎', 'M' => '뛏', 'N' => '뛐', 'O' => '뛑', 'P' => '뛒', 'Q' => '뛓', 'R' => '뛕', 'S' => '뛖', 'T' => '뛗', 'U' => '뛘', 'V' => '뛙', 'W' => '뛚', 'X' => '뛛', 'Y' => '뛜', 'Z' => '뛝', 'a' => '뛞', 'b' => '뛟', 'c' => '뛠', 'd' => '뛡', 'e' => '뛢', 'f' => '뛣', 'g' => '뛤', 'h' => '뛥', 'i' => '뛦', 'j' => '뛧', 'k' => '뛨', 'l' => '뛩', 'm' => '뛪', 'n' => '뛫', 'o' => '뛬', 'p' => '뛭', 'q' => '뛮', 'r' => '뛯', 's' => '뛱', 't' => '뛲', 'u' => '뛳', 'v' => '뛵', 'w' => '뛶', 'x' => '뛷', 'y' => '뛹', 'z' => '뛺', '' => '뛻', '' => '뛼', '' => '뛽', '' => '뛾', '' => '뛿', '' => '뜂', '' => '뜃', '' => '뜄', '' => '뜆', '' => '뜇', '' => '뜈', '' => '뜉', '' => '뜊', '' => '뜋', '' => '뜌', '' => '뜍', '' => '뜎', '' => '뜏', '' => '뜐', '' => '뜑', '' => '뜒', '' => '뜓', '' => '뜔', '' => '뜕', '' => '뜖', '' => '뜗', '' => '뜘', '' => '뜙', '' => '뜚', '' => '뜛', '' => '뜜', '' => '뜝', '' => '뜞', '' => '뜟', '' => '뜠', '' => '뜡', '' => '뜢', '' => '뜣', '' => '뜤', '' => '뜥', '' => '뜦', '' => '뜧', '' => '뜪', '' => '뜫', '' => '뜭', '' => '뜮', '' => '뜱', '' => '뜲', '' => '뜳', '' => '뜴', '' => '뜵', '' => '뜶', '' => '뜷', '' => '뜺', '' => '뜼', '' => '뜽', '' => '뜾', '' => '뜿', '' => '띀', '' => '띁', '' => '띂', '' => '띃', '' => '띅', '' => '띆', '' => '띇', '' => '띉', '' => '띊', '' => '띋', '' => '띍', '' => '띎', '' => '띏', '' => '띐', '' => '띑', '' => '띒', '' => '띓', '' => '띖', '' => '띗', '' => '띘', '' => '띙', '' => '띚', '' => '띛', '' => '띜', '' => '띝', '' => '띞', '' => '띟', '' => '띡', '' => '띢', '' => '띣', '' => '띥', '' => '띦', '' => '띧', '' => '띩', '' => '띪', '' => '띫', '' => '띬', '' => '띭', '' => '띮', '' => '띯', '' => '띲', '' => '띴', '' => '띶', '' => '띷', '' => '띸', '' => '띹', '' => '띺', '' => '띻', '' => '띾', '' => '띿', '' => '랁', '' => '랂', '' => '랃', '' => '랅', '' => '랆', '' => '랇', '' => '랈', '' => '랉', '' => '랊', '' => '랋', '' => '랎', '' => '랓', '' => '랔', '' => '랕', '' => '랚', '' => '랛', '' => '랝', '' => '랞', 'A' => '랟', 'B' => '랡', 'C' => '랢', 'D' => '랣', 'E' => '랤', 'F' => '랥', 'G' => '랦', 'H' => '랧', 'I' => '랪', 'J' => '랮', 'K' => '랯', 'L' => '랰', 'M' => '랱', 'N' => '랲', 'O' => '랳', 'P' => '랶', 'Q' => '랷', 'R' => '랹', 'S' => '랺', 'T' => '랻', 'U' => '랼', 'V' => '랽', 'W' => '랾', 'X' => '랿', 'Y' => '럀', 'Z' => '럁', 'a' => '럂', 'b' => '럃', 'c' => '럄', 'd' => '럅', 'e' => '럆', 'f' => '럈', 'g' => '럊', 'h' => '럋', 'i' => '럌', 'j' => '럍', 'k' => '럎', 'l' => '럏', 'm' => '럐', 'n' => '럑', 'o' => '럒', 'p' => '럓', 'q' => '럔', 'r' => '럕', 's' => '럖', 't' => '럗', 'u' => '럘', 'v' => '럙', 'w' => '럚', 'x' => '럛', 'y' => '럜', 'z' => '럝', '' => '럞', '' => '럟', '' => '럠', '' => '럡', '' => '럢', '' => '럣', '' => '럤', '' => '럥', '' => '럦', '' => '럧', '' => '럨', '' => '럩', '' => '럪', '' => '럫', '' => '럮', '' => '럯', '' => '럱', '' => '럲', '' => '럳', '' => '럵', '' => '럶', '' => '럷', '' => '럸', '' => '럹', '' => '럺', '' => '럻', '' => '럾', '' => '렂', '' => '렃', '' => '렄', '' => '렅', '' => '렆', '' => '렊', '' => '렋', '' => '렍', '' => '렎', '' => '렏', '' => '렑', '' => '렒', '' => '렓', '' => '렔', '' => '렕', '' => '렖', '' => '렗', '' => '렚', '' => '렜', '' => '렞', '' => '렟', '' => '렠', '' => '렡', '' => '렢', '' => '렣', '' => '렦', '' => '렧', '' => '렩', '' => '렪', '' => '렫', '' => '렭', '' => '렮', '' => '렯', '' => '렰', '' => '렱', '' => '렲', '' => '렳', '' => '렶', '' => '렺', '' => '렻', '' => '렼', '' => '렽', '' => '렾', '' => '렿', '' => '롁', '' => '롂', '' => '롃', '' => '롅', '' => '롆', '' => '롇', '' => '롈', '' => '롉', '' => '롊', '' => '롋', '' => '롌', '' => '롍', '' => '롎', '' => '롏', '' => '롐', '' => '롒', '' => '롔', '' => '롕', '' => '롖', '' => '롗', '' => '롘', '' => '롙', '' => '롚', '' => '롛', '' => '롞', '' => '롟', '' => '롡', '' => '롢', '' => '롣', '' => '롥', '' => '롦', '' => '롧', '' => '롨', '' => '롩', '' => '롪', '' => '롫', '' => '롮', '' => '롰', '' => '롲', '' => '롳', '' => '롴', '' => '롵', '' => '롶', '' => '롷', '' => '롹', '' => '롺', '' => '롻', '' => '롽', '' => '롾', '' => '롿', '' => '뢀', '' => '뢁', '' => '뢂', '' => '뢃', '' => '뢄', 'A' => '뢅', 'B' => '뢆', 'C' => '뢇', 'D' => '뢈', 'E' => '뢉', 'F' => '뢊', 'G' => '뢋', 'H' => '뢌', 'I' => '뢎', 'J' => '뢏', 'K' => '뢐', 'L' => '뢑', 'M' => '뢒', 'N' => '뢓', 'O' => '뢔', 'P' => '뢕', 'Q' => '뢖', 'R' => '뢗', 'S' => '뢘', 'T' => '뢙', 'U' => '뢚', 'V' => '뢛', 'W' => '뢜', 'X' => '뢝', 'Y' => '뢞', 'Z' => '뢟', 'a' => '뢠', 'b' => '뢡', 'c' => '뢢', 'd' => '뢣', 'e' => '뢤', 'f' => '뢥', 'g' => '뢦', 'h' => '뢧', 'i' => '뢩', 'j' => '뢪', 'k' => '뢫', 'l' => '뢬', 'm' => '뢭', 'n' => '뢮', 'o' => '뢯', 'p' => '뢱', 'q' => '뢲', 'r' => '뢳', 's' => '뢵', 't' => '뢶', 'u' => '뢷', 'v' => '뢹', 'w' => '뢺', 'x' => '뢻', 'y' => '뢼', 'z' => '뢽', '' => '뢾', '' => '뢿', '' => '룂', '' => '룄', '' => '룆', '' => '룇', '' => '룈', '' => '룉', '' => '룊', '' => '룋', '' => '룍', '' => '룎', '' => '룏', '' => '룑', '' => '룒', '' => '룓', '' => '룕', '' => '룖', '' => '룗', '' => '룘', '' => '룙', '' => '룚', '' => '룛', '' => '룜', '' => '룞', '' => '룠', '' => '룢', '' => '룣', '' => '룤', '' => '룥', '' => '룦', '' => '룧', '' => '룪', '' => '룫', '' => '룭', '' => '룮', '' => '룯', '' => '룱', '' => '룲', '' => '룳', '' => '룴', '' => '룵', '' => '룶', '' => '룷', '' => '룺', '' => '룼', '' => '룾', '' => '룿', '' => '뤀', '' => '뤁', '' => '뤂', '' => '뤃', '' => '뤅', '' => '뤆', '' => '뤇', '' => '뤈', '' => '뤉', '' => '뤊', '' => '뤋', '' => '뤌', '' => '뤍', '' => '뤎', '' => '뤏', '' => '뤐', '' => '뤑', '' => '뤒', '' => '뤓', '' => '뤔', '' => '뤕', '' => '뤖', '' => '뤗', '' => '뤙', '' => '뤚', '' => '뤛', '' => '뤜', '' => '뤝', '' => '뤞', '' => '뤟', '' => '뤡', '' => '뤢', '' => '뤣', '' => '뤤', '' => '뤥', '' => '뤦', '' => '뤧', '' => '뤨', '' => '뤩', '' => '뤪', '' => '뤫', '' => '뤬', '' => '뤭', '' => '뤮', '' => '뤯', '' => '뤰', '' => '뤱', '' => '뤲', '' => '뤳', '' => '뤴', '' => '뤵', '' => '뤶', '' => '뤷', '' => '뤸', '' => '뤹', '' => '뤺', '' => '뤻', '' => '뤾', '' => '뤿', '' => '륁', '' => '륂', '' => '륃', '' => '륅', '' => '륆', '' => '륇', '' => '륈', '' => '륉', '' => '륊', '' => '륋', '' => '륍', '' => '륎', '' => '륐', '' => '륒', '' => '륓', '' => '륔', '' => '륕', '' => '륖', '' => '륗', 'A' => '륚', 'B' => '륛', 'C' => '륝', 'D' => '륞', 'E' => '륟', 'F' => '륡', 'G' => '륢', 'H' => '륣', 'I' => '륤', 'J' => '륥', 'K' => '륦', 'L' => '륧', 'M' => '륪', 'N' => '륬', 'O' => '륮', 'P' => '륯', 'Q' => '륰', 'R' => '륱', 'S' => '륲', 'T' => '륳', 'U' => '륶', 'V' => '륷', 'W' => '륹', 'X' => '륺', 'Y' => '륻', 'Z' => '륽', 'a' => '륾', 'b' => '륿', 'c' => '릀', 'd' => '릁', 'e' => '릂', 'f' => '릃', 'g' => '릆', 'h' => '릈', 'i' => '릋', 'j' => '릌', 'k' => '릏', 'l' => '릐', 'm' => '릑', 'n' => '릒', 'o' => '릓', 'p' => '릔', 'q' => '릕', 'r' => '릖', 's' => '릗', 't' => '릘', 'u' => '릙', 'v' => '릚', 'w' => '릛', 'x' => '릜', 'y' => '릝', 'z' => '릞', '' => '릟', '' => '릠', '' => '릡', '' => '릢', '' => '릣', '' => '릤', '' => '릥', '' => '릦', '' => '릧', '' => '릨', '' => '릩', '' => '릪', '' => '릫', '' => '릮', '' => '릯', '' => '릱', '' => '릲', '' => '릳', '' => '릵', '' => '릶', '' => '릷', '' => '릸', '' => '릹', '' => '릺', '' => '릻', '' => '릾', '' => '맀', '' => '맂', '' => '맃', '' => '맄', '' => '맅', '' => '맆', '' => '맇', '' => '맊', '' => '맋', '' => '맍', '' => '맓', '' => '맔', '' => '맕', '' => '맖', '' => '맗', '' => '맚', '' => '맜', '' => '맟', '' => '맠', '' => '맢', '' => '맦', '' => '맧', '' => '맩', '' => '맪', '' => '맫', '' => '맭', '' => '맮', '' => '맯', '' => '맰', '' => '맱', '' => '맲', '' => '맳', '' => '맶', '' => '맻', '' => '맼', '' => '맽', '' => '맾', '' => '맿', '' => '먂', '' => '먃', '' => '먄', '' => '먅', '' => '먆', '' => '먇', '' => '먉', '' => '먊', '' => '먋', '' => '먌', '' => '먍', '' => '먎', '' => '먏', '' => '먐', '' => '먑', '' => '먒', '' => '먓', '' => '먔', '' => '먖', '' => '먗', '' => '먘', '' => '먙', '' => '먚', '' => '먛', '' => '먜', '' => '먝', '' => '먞', '' => '먟', '' => '먠', '' => '먡', '' => '먢', '' => '먣', '' => '먤', '' => '먥', '' => '먦', '' => '먧', '' => '먨', '' => '먩', '' => '먪', '' => '먫', '' => '먬', '' => '먭', '' => '먮', '' => '먯', '' => '먰', '' => '먱', '' => '먲', '' => '먳', '' => '먴', '' => '먵', '' => '먶', '' => '먷', '' => '먺', '' => '먻', '' => '먽', '' => '먾', '' => '먿', '' => '멁', '' => '멃', '' => '멄', '' => '멅', '' => '멆', 'A' => '멇', 'B' => '멊', 'C' => '멌', 'D' => '멏', 'E' => '멐', 'F' => '멑', 'G' => '멒', 'H' => '멖', 'I' => '멗', 'J' => '멙', 'K' => '멚', 'L' => '멛', 'M' => '멝', 'N' => '멞', 'O' => '멟', 'P' => '멠', 'Q' => '멡', 'R' => '멢', 'S' => '멣', 'T' => '멦', 'U' => '멪', 'V' => '멫', 'W' => '멬', 'X' => '멭', 'Y' => '멮', 'Z' => '멯', 'a' => '멲', 'b' => '멳', 'c' => '멵', 'd' => '멶', 'e' => '멷', 'f' => '멹', 'g' => '멺', 'h' => '멻', 'i' => '멼', 'j' => '멽', 'k' => '멾', 'l' => '멿', 'm' => '몀', 'n' => '몁', 'o' => '몂', 'p' => '몆', 'q' => '몈', 'r' => '몉', 's' => '몊', 't' => '몋', 'u' => '몍', 'v' => '몎', 'w' => '몏', 'x' => '몐', 'y' => '몑', 'z' => '몒', '' => '몓', '' => '몔', '' => '몕', '' => '몖', '' => '몗', '' => '몘', '' => '몙', '' => '몚', '' => '몛', '' => '몜', '' => '몝', '' => '몞', '' => '몟', '' => '몠', '' => '몡', '' => '몢', '' => '몣', '' => '몤', '' => '몥', '' => '몦', '' => '몧', '' => '몪', '' => '몭', '' => '몮', '' => '몯', '' => '몱', '' => '몳', '' => '몴', '' => '몵', '' => '몶', '' => '몷', '' => '몺', '' => '몼', '' => '몾', '' => '몿', '' => '뫀', '' => '뫁', '' => '뫂', '' => '뫃', '' => '뫅', '' => '뫆', '' => '뫇', '' => '뫉', '' => '뫊', '' => '뫋', '' => '뫌', '' => '뫍', '' => '뫎', '' => '뫏', '' => '뫐', '' => '뫑', '' => '뫒', '' => '뫓', '' => '뫔', '' => '뫕', '' => '뫖', '' => '뫗', '' => '뫚', '' => '뫛', '' => '뫜', '' => '뫝', '' => '뫞', '' => '뫟', '' => '뫠', '' => '뫡', '' => '뫢', '' => '뫣', '' => '뫤', '' => '뫥', '' => '뫦', '' => '뫧', '' => '뫨', '' => '뫩', '' => '뫪', '' => '뫫', '' => '뫬', '' => '뫭', '' => '뫮', '' => '뫯', '' => '뫰', '' => '뫱', '' => '뫲', '' => '뫳', '' => '뫴', '' => '뫵', '' => '뫶', '' => '뫷', '' => '뫸', '' => '뫹', '' => '뫺', '' => '뫻', '' => '뫽', '' => '뫾', '' => '뫿', '' => '묁', '' => '묂', '' => '묃', '' => '묅', '' => '묆', '' => '묇', '' => '묈', '' => '묉', '' => '묊', '' => '묋', '' => '묌', '' => '묎', '' => '묐', '' => '묒', '' => '묓', '' => '묔', '' => '묕', '' => '묖', '' => '묗', '' => '묙', '' => '묚', '' => '묛', '' => '묝', '' => '묞', '' => '묟', '' => '묡', '' => '묢', '' => '묣', '' => '묤', '' => '묥', '' => '묦', '' => '묧', 'A' => '묨', 'B' => '묪', 'C' => '묬', 'D' => '묭', 'E' => '묮', 'F' => '묯', 'G' => '묰', 'H' => '묱', 'I' => '묲', 'J' => '묳', 'K' => '묷', 'L' => '묹', 'M' => '묺', 'N' => '묿', 'O' => '뭀', 'P' => '뭁', 'Q' => '뭂', 'R' => '뭃', 'S' => '뭆', 'T' => '뭈', 'U' => '뭊', 'V' => '뭋', 'W' => '뭌', 'X' => '뭎', 'Y' => '뭑', 'Z' => '뭒', 'a' => '뭓', 'b' => '뭕', 'c' => '뭖', 'd' => '뭗', 'e' => '뭙', 'f' => '뭚', 'g' => '뭛', 'h' => '뭜', 'i' => '뭝', 'j' => '뭞', 'k' => '뭟', 'l' => '뭠', 'm' => '뭢', 'n' => '뭤', 'o' => '뭥', 'p' => '뭦', 'q' => '뭧', 'r' => '뭨', 's' => '뭩', 't' => '뭪', 'u' => '뭫', 'v' => '뭭', 'w' => '뭮', 'x' => '뭯', 'y' => '뭰', 'z' => '뭱', '' => '뭲', '' => '뭳', '' => '뭴', '' => '뭵', '' => '뭶', '' => '뭷', '' => '뭸', '' => '뭹', '' => '뭺', '' => '뭻', '' => '뭼', '' => '뭽', '' => '뭾', '' => '뭿', '' => '뮀', '' => '뮁', '' => '뮂', '' => '뮃', '' => '뮄', '' => '뮅', '' => '뮆', '' => '뮇', '' => '뮉', '' => '뮊', '' => '뮋', '' => '뮍', '' => '뮎', '' => '뮏', '' => '뮑', '' => '뮒', '' => '뮓', '' => '뮔', '' => '뮕', '' => '뮖', '' => '뮗', '' => '뮘', '' => '뮙', '' => '뮚', '' => '뮛', '' => '뮜', '' => '뮝', '' => '뮞', '' => '뮟', '' => '뮠', '' => '뮡', '' => '뮢', '' => '뮣', '' => '뮥', '' => '뮦', '' => '뮧', '' => '뮩', '' => '뮪', '' => '뮫', '' => '뮭', '' => '뮮', '' => '뮯', '' => '뮰', '' => '뮱', '' => '뮲', '' => '뮳', '' => '뮵', '' => '뮶', '' => '뮸', '' => '뮹', '' => '뮺', '' => '뮻', '' => '뮼', '' => '뮽', '' => '뮾', '' => '뮿', '' => '믁', '' => '믂', '' => '믃', '' => '믅', '' => '믆', '' => '믇', '' => '믉', '' => '믊', '' => '믋', '' => '믌', '' => '믍', '' => '믎', '' => '믏', '' => '믑', '' => '믒', '' => '믔', '' => '믕', '' => '믖', '' => '믗', '' => '믘', '' => '믙', '' => '믚', '' => '믛', '' => '믜', '' => '믝', '' => '믞', '' => '믟', '' => '믠', '' => '믡', '' => '믢', '' => '믣', '' => '믤', '' => '믥', '' => '믦', '' => '믧', '' => '믨', '' => '믩', '' => '믪', '' => '믫', '' => '믬', '' => '믭', '' => '믮', '' => '믯', '' => '믰', '' => '믱', '' => '믲', '' => '믳', '' => '믴', '' => '믵', '' => '믶', '' => '믷', '' => '믺', '' => '믻', '' => '믽', '' => '믾', '' => '밁', 'A' => '밃', 'B' => '밄', 'C' => '밅', 'D' => '밆', 'E' => '밇', 'F' => '밊', 'G' => '밎', 'H' => '밐', 'I' => '밒', 'J' => '밓', 'K' => '밙', 'L' => '밚', 'M' => '밠', 'N' => '밡', 'O' => '밢', 'P' => '밣', 'Q' => '밦', 'R' => '밨', 'S' => '밪', 'T' => '밫', 'U' => '밬', 'V' => '밮', 'W' => '밯', 'X' => '밲', 'Y' => '밳', 'Z' => '밵', 'a' => '밶', 'b' => '밷', 'c' => '밹', 'd' => '밺', 'e' => '밻', 'f' => '밼', 'g' => '밽', 'h' => '밾', 'i' => '밿', 'j' => '뱂', 'k' => '뱆', 'l' => '뱇', 'm' => '뱈', 'n' => '뱊', 'o' => '뱋', 'p' => '뱎', 'q' => '뱏', 'r' => '뱑', 's' => '뱒', 't' => '뱓', 'u' => '뱔', 'v' => '뱕', 'w' => '뱖', 'x' => '뱗', 'y' => '뱘', 'z' => '뱙', '' => '뱚', '' => '뱛', '' => '뱜', '' => '뱞', '' => '뱟', '' => '뱠', '' => '뱡', '' => '뱢', '' => '뱣', '' => '뱤', '' => '뱥', '' => '뱦', '' => '뱧', '' => '뱨', '' => '뱩', '' => '뱪', '' => '뱫', '' => '뱬', '' => '뱭', '' => '뱮', '' => '뱯', '' => '뱰', '' => '뱱', '' => '뱲', '' => '뱳', '' => '뱴', '' => '뱵', '' => '뱶', '' => '뱷', '' => '뱸', '' => '뱹', '' => '뱺', '' => '뱻', '' => '뱼', '' => '뱽', '' => '뱾', '' => '뱿', '' => '벀', '' => '벁', '' => '벂', '' => '벃', '' => '벆', '' => '벇', '' => '벉', '' => '벊', '' => '벍', '' => '벏', '' => '벐', '' => '벑', '' => '벒', '' => '벓', '' => '벖', '' => '벘', '' => '벛', '' => '벜', '' => '벝', '' => '벞', '' => '벟', '' => '벢', '' => '벣', '' => '벥', '' => '벦', '' => '벩', '' => '벪', '' => '벫', '' => '벬', '' => '벭', '' => '벮', '' => '벯', '' => '벲', '' => '벶', '' => '벷', '' => '벸', '' => '벹', '' => '벺', '' => '벻', '' => '벾', '' => '벿', '' => '볁', '' => '볂', '' => '볃', '' => '볅', '' => '볆', '' => '볇', '' => '볈', '' => '볉', '' => '볊', '' => '볋', '' => '볌', '' => '볎', '' => '볒', '' => '볓', '' => '볔', '' => '볖', '' => '볗', '' => '볙', '' => '볚', '' => '볛', '' => '볝', '' => '볞', '' => '볟', '' => '볠', '' => '볡', '' => '볢', '' => '볣', '' => '볤', '' => '볥', '' => '볦', '' => '볧', '' => '볨', '' => '볩', '' => '볪', '' => '볫', '' => '볬', '' => '볭', '' => '볮', '' => '볯', '' => '볰', '' => '볱', '' => '볲', '' => '볳', '' => '볷', '' => '볹', '' => '볺', '' => '볻', '' => '볽', 'A' => '볾', 'B' => '볿', 'C' => '봀', 'D' => '봁', 'E' => '봂', 'F' => '봃', 'G' => '봆', 'H' => '봈', 'I' => '봊', 'J' => '봋', 'K' => '봌', 'L' => '봍', 'M' => '봎', 'N' => '봏', 'O' => '봑', 'P' => '봒', 'Q' => '봓', 'R' => '봕', 'S' => '봖', 'T' => '봗', 'U' => '봘', 'V' => '봙', 'W' => '봚', 'X' => '봛', 'Y' => '봜', 'Z' => '봝', 'a' => '봞', 'b' => '봟', 'c' => '봠', 'd' => '봡', 'e' => '봢', 'f' => '봣', 'g' => '봥', 'h' => '봦', 'i' => '봧', 'j' => '봨', 'k' => '봩', 'l' => '봪', 'm' => '봫', 'n' => '봭', 'o' => '봮', 'p' => '봯', 'q' => '봰', 'r' => '봱', 's' => '봲', 't' => '봳', 'u' => '봴', 'v' => '봵', 'w' => '봶', 'x' => '봷', 'y' => '봸', 'z' => '봹', '' => '봺', '' => '봻', '' => '봼', '' => '봽', '' => '봾', '' => '봿', '' => '뵁', '' => '뵂', '' => '뵃', '' => '뵄', '' => '뵅', '' => '뵆', '' => '뵇', '' => '뵊', '' => '뵋', '' => '뵍', '' => '뵎', '' => '뵏', '' => '뵑', '' => '뵒', '' => '뵓', '' => '뵔', '' => '뵕', '' => '뵖', '' => '뵗', '' => '뵚', '' => '뵛', '' => '뵜', '' => '뵝', '' => '뵞', '' => '뵟', '' => '뵠', '' => '뵡', '' => '뵢', '' => '뵣', '' => '뵥', '' => '뵦', '' => '뵧', '' => '뵩', '' => '뵪', '' => '뵫', '' => '뵬', '' => '뵭', '' => '뵮', '' => '뵯', '' => '뵰', '' => '뵱', '' => '뵲', '' => '뵳', '' => '뵴', '' => '뵵', '' => '뵶', '' => '뵷', '' => '뵸', '' => '뵹', '' => '뵺', '' => '뵻', '' => '뵼', '' => '뵽', '' => '뵾', '' => '뵿', '' => '붂', '' => '붃', '' => '붅', '' => '붆', '' => '붋', '' => '붌', '' => '붍', '' => '붎', '' => '붏', '' => '붒', '' => '붔', '' => '붖', '' => '붗', '' => '붘', '' => '붛', '' => '붝', '' => '붞', '' => '붟', '' => '붠', '' => '붡', '' => '붢', '' => '붣', '' => '붥', '' => '붦', '' => '붧', '' => '붨', '' => '붩', '' => '붪', '' => '붫', '' => '붬', '' => '붭', '' => '붮', '' => '붯', '' => '붱', '' => '붲', '' => '붳', '' => '붴', '' => '붵', '' => '붶', '' => '붷', '' => '붹', '' => '붺', '' => '붻', '' => '붼', '' => '붽', '' => '붾', '' => '붿', '' => '뷀', '' => '뷁', '' => '뷂', '' => '뷃', '' => '뷄', '' => '뷅', '' => '뷆', '' => '뷇', '' => '뷈', '' => '뷉', '' => '뷊', '' => '뷋', '' => '뷌', '' => '뷍', '' => '뷎', '' => '뷏', '' => '뷐', '' => '뷑', 'A' => '뷒', 'B' => '뷓', 'C' => '뷖', 'D' => '뷗', 'E' => '뷙', 'F' => '뷚', 'G' => '뷛', 'H' => '뷝', 'I' => '뷞', 'J' => '뷟', 'K' => '뷠', 'L' => '뷡', 'M' => '뷢', 'N' => '뷣', 'O' => '뷤', 'P' => '뷥', 'Q' => '뷦', 'R' => '뷧', 'S' => '뷨', 'T' => '뷪', 'U' => '뷫', 'V' => '뷬', 'W' => '뷭', 'X' => '뷮', 'Y' => '뷯', 'Z' => '뷱', 'a' => '뷲', 'b' => '뷳', 'c' => '뷵', 'd' => '뷶', 'e' => '뷷', 'f' => '뷹', 'g' => '뷺', 'h' => '뷻', 'i' => '뷼', 'j' => '뷽', 'k' => '뷾', 'l' => '뷿', 'm' => '븁', 'n' => '븂', 'o' => '븄', 'p' => '븆', 'q' => '븇', 'r' => '븈', 's' => '븉', 't' => '븊', 'u' => '븋', 'v' => '븎', 'w' => '븏', 'x' => '븑', 'y' => '븒', 'z' => '븓', '' => '븕', '' => '븖', '' => '븗', '' => '븘', '' => '븙', '' => '븚', '' => '븛', '' => '븞', '' => '븠', '' => '븡', '' => '븢', '' => '븣', '' => '븤', '' => '븥', '' => '븦', '' => '븧', '' => '븨', '' => '븩', '' => '븪', '' => '븫', '' => '븬', '' => '븭', '' => '븮', '' => '븯', '' => '븰', '' => '븱', '' => '븲', '' => '븳', '' => '븴', '' => '븵', '' => '븶', '' => '븷', '' => '븸', '' => '븹', '' => '븺', '' => '븻', '' => '븼', '' => '븽', '' => '븾', '' => '븿', '' => '빀', '' => '빁', '' => '빂', '' => '빃', '' => '빆', '' => '빇', '' => '빉', '' => '빊', '' => '빋', '' => '빍', '' => '빏', '' => '빐', '' => '빑', '' => '빒', '' => '빓', '' => '빖', '' => '빘', '' => '빜', '' => '빝', '' => '빞', '' => '빟', '' => '빢', '' => '빣', '' => '빥', '' => '빦', '' => '빧', '' => '빩', '' => '빫', '' => '빬', '' => '빭', '' => '빮', '' => '빯', '' => '빲', '' => '빶', '' => '빷', '' => '빸', '' => '빹', '' => '빺', '' => '빾', '' => '빿', '' => '뺁', '' => '뺂', '' => '뺃', '' => '뺅', '' => '뺆', '' => '뺇', '' => '뺈', '' => '뺉', '' => '뺊', '' => '뺋', '' => '뺎', '' => '뺒', '' => '뺓', '' => '뺔', '' => '뺕', '' => '뺖', '' => '뺗', '' => '뺚', '' => '뺛', '' => '뺜', '' => '뺝', '' => '뺞', '' => '뺟', '' => '뺠', '' => '뺡', '' => '뺢', '' => '뺣', '' => '뺤', '' => '뺥', '' => '뺦', '' => '뺧', '' => '뺩', '' => '뺪', '' => '뺫', '' => '뺬', '' => '뺭', '' => '뺮', '' => '뺯', '' => '뺰', '' => '뺱', '' => '뺲', '' => '뺳', '' => '뺴', '' => '뺵', '' => '뺶', '' => '뺷', 'A' => '뺸', 'B' => '뺹', 'C' => '뺺', 'D' => '뺻', 'E' => '뺼', 'F' => '뺽', 'G' => '뺾', 'H' => '뺿', 'I' => '뻀', 'J' => '뻁', 'K' => '뻂', 'L' => '뻃', 'M' => '뻄', 'N' => '뻅', 'O' => '뻆', 'P' => '뻇', 'Q' => '뻈', 'R' => '뻉', 'S' => '뻊', 'T' => '뻋', 'U' => '뻌', 'V' => '뻍', 'W' => '뻎', 'X' => '뻏', 'Y' => '뻒', 'Z' => '뻓', 'a' => '뻕', 'b' => '뻖', 'c' => '뻙', 'd' => '뻚', 'e' => '뻛', 'f' => '뻜', 'g' => '뻝', 'h' => '뻞', 'i' => '뻟', 'j' => '뻡', 'k' => '뻢', 'l' => '뻦', 'm' => '뻧', 'n' => '뻨', 'o' => '뻩', 'p' => '뻪', 'q' => '뻫', 'r' => '뻭', 's' => '뻮', 't' => '뻯', 'u' => '뻰', 'v' => '뻱', 'w' => '뻲', 'x' => '뻳', 'y' => '뻴', 'z' => '뻵', '' => '뻶', '' => '뻷', '' => '뻸', '' => '뻹', '' => '뻺', '' => '뻻', '' => '뻼', '' => '뻽', '' => '뻾', '' => '뻿', '' => '뼀', '' => '뼂', '' => '뼃', '' => '뼄', '' => '뼅', '' => '뼆', '' => '뼇', '' => '뼊', '' => '뼋', '' => '뼌', '' => '뼍', '' => '뼎', '' => '뼏', '' => '뼐', '' => '뼑', '' => '뼒', '' => '뼓', '' => '뼔', '' => '뼕', '' => '뼖', '' => '뼗', '' => '뼚', '' => '뼞', '' => '뼟', '' => '뼠', '' => '뼡', '' => '뼢', '' => '뼣', '' => '뼤', '' => '뼥', '' => '뼦', '' => '뼧', '' => '뼨', '' => '뼩', '' => '뼪', '' => '뼫', '' => '뼬', '' => '뼭', '' => '뼮', '' => '뼯', '' => '뼰', '' => '뼱', '' => '뼲', '' => '뼳', '' => '뼴', '' => '뼵', '' => '뼶', '' => '뼷', '' => '뼸', '' => '뼹', '' => '뼺', '' => '뼻', '' => '뼼', '' => '뼽', '' => '뼾', '' => '뼿', '' => '뽂', '' => '뽃', '' => '뽅', '' => '뽆', '' => '뽇', '' => '뽉', '' => '뽊', '' => '뽋', '' => '뽌', '' => '뽍', '' => '뽎', '' => '뽏', '' => '뽒', '' => '뽓', '' => '뽔', '' => '뽖', '' => '뽗', '' => '뽘', '' => '뽙', '' => '뽚', '' => '뽛', '' => '뽜', '' => '뽝', '' => '뽞', '' => '뽟', '' => '뽠', '' => '뽡', '' => '뽢', '' => '뽣', '' => '뽤', '' => '뽥', '' => '뽦', '' => '뽧', '' => '뽨', '' => '뽩', '' => '뽪', '' => '뽫', '' => '뽬', '' => '뽭', '' => '뽮', '' => '뽯', '' => '뽰', '' => '뽱', '' => '뽲', '' => '뽳', '' => '뽴', '' => '뽵', '' => '뽶', '' => '뽷', '' => '뽸', '' => '뽹', '' => '뽺', '' => '뽻', '' => '뽼', '' => '뽽', '' => '뽾', '' => '뽿', '' => '뾀', '' => '뾁', '' => '뾂', 'A' => '뾃', 'B' => '뾄', 'C' => '뾅', 'D' => '뾆', 'E' => '뾇', 'F' => '뾈', 'G' => '뾉', 'H' => '뾊', 'I' => '뾋', 'J' => '뾌', 'K' => '뾍', 'L' => '뾎', 'M' => '뾏', 'N' => '뾐', 'O' => '뾑', 'P' => '뾒', 'Q' => '뾓', 'R' => '뾕', 'S' => '뾖', 'T' => '뾗', 'U' => '뾘', 'V' => '뾙', 'W' => '뾚', 'X' => '뾛', 'Y' => '뾜', 'Z' => '뾝', 'a' => '뾞', 'b' => '뾟', 'c' => '뾠', 'd' => '뾡', 'e' => '뾢', 'f' => '뾣', 'g' => '뾤', 'h' => '뾥', 'i' => '뾦', 'j' => '뾧', 'k' => '뾨', 'l' => '뾩', 'm' => '뾪', 'n' => '뾫', 'o' => '뾬', 'p' => '뾭', 'q' => '뾮', 'r' => '뾯', 's' => '뾱', 't' => '뾲', 'u' => '뾳', 'v' => '뾴', 'w' => '뾵', 'x' => '뾶', 'y' => '뾷', 'z' => '뾸', '' => '뾹', '' => '뾺', '' => '뾻', '' => '뾼', '' => '뾽', '' => '뾾', '' => '뾿', '' => '뿀', '' => '뿁', '' => '뿂', '' => '뿃', '' => '뿄', '' => '뿆', '' => '뿇', '' => '뿈', '' => '뿉', '' => '뿊', '' => '뿋', '' => '뿎', '' => '뿏', '' => '뿑', '' => '뿒', '' => '뿓', '' => '뿕', '' => '뿖', '' => '뿗', '' => '뿘', '' => '뿙', '' => '뿚', '' => '뿛', '' => '뿝', '' => '뿞', '' => '뿠', '' => '뿢', '' => '뿣', '' => '뿤', '' => '뿥', '' => '뿦', '' => '뿧', '' => '뿨', '' => '뿩', '' => '뿪', '' => '뿫', '' => '뿬', '' => '뿭', '' => '뿮', '' => '뿯', '' => '뿰', '' => '뿱', '' => '뿲', '' => '뿳', '' => '뿴', '' => '뿵', '' => '뿶', '' => '뿷', '' => '뿸', '' => '뿹', '' => '뿺', '' => '뿻', '' => '뿼', '' => '뿽', '' => '뿾', '' => '뿿', '' => '쀀', '' => '쀁', '' => '쀂', '' => '쀃', '' => '쀄', '' => '쀅', '' => '쀆', '' => '쀇', '' => '쀈', '' => '쀉', '' => '쀊', '' => '쀋', '' => '쀌', '' => '쀍', '' => '쀎', '' => '쀏', '' => '쀐', '' => '쀑', '' => '쀒', '' => '쀓', '' => '쀔', '' => '쀕', '' => '쀖', '' => '쀗', '' => '쀘', '' => '쀙', '' => '쀚', '' => '쀛', '' => '쀜', '' => '쀝', '' => '쀞', '' => '쀟', '' => '쀠', '' => '쀡', '' => '쀢', '' => '쀣', '' => '쀤', '' => '쀥', '' => '쀦', '' => '쀧', '' => '쀨', '' => '쀩', '' => '쀪', '' => '쀫', '' => '쀬', '' => '쀭', '' => '쀮', '' => '쀯', '' => '쀰', '' => '쀱', '' => '쀲', '' => '쀳', '' => '쀴', '' => '쀵', '' => '쀶', '' => '쀷', '' => '쀸', '' => '쀹', '' => '쀺', '' => '쀻', '' => '쀽', '' => '쀾', '' => '쀿', 'A' => '쁀', 'B' => '쁁', 'C' => '쁂', 'D' => '쁃', 'E' => '쁄', 'F' => '쁅', 'G' => '쁆', 'H' => '쁇', 'I' => '쁈', 'J' => '쁉', 'K' => '쁊', 'L' => '쁋', 'M' => '쁌', 'N' => '쁍', 'O' => '쁎', 'P' => '쁏', 'Q' => '쁐', 'R' => '쁒', 'S' => '쁓', 'T' => '쁔', 'U' => '쁕', 'V' => '쁖', 'W' => '쁗', 'X' => '쁙', 'Y' => '쁚', 'Z' => '쁛', 'a' => '쁝', 'b' => '쁞', 'c' => '쁟', 'd' => '쁡', 'e' => '쁢', 'f' => '쁣', 'g' => '쁤', 'h' => '쁥', 'i' => '쁦', 'j' => '쁧', 'k' => '쁪', 'l' => '쁫', 'm' => '쁬', 'n' => '쁭', 'o' => '쁮', 'p' => '쁯', 'q' => '쁰', 'r' => '쁱', 's' => '쁲', 't' => '쁳', 'u' => '쁴', 'v' => '쁵', 'w' => '쁶', 'x' => '쁷', 'y' => '쁸', 'z' => '쁹', '' => '쁺', '' => '쁻', '' => '쁼', '' => '쁽', '' => '쁾', '' => '쁿', '' => '삀', '' => '삁', '' => '삂', '' => '삃', '' => '삄', '' => '삅', '' => '삆', '' => '삇', '' => '삈', '' => '삉', '' => '삊', '' => '삋', '' => '삌', '' => '삍', '' => '삎', '' => '삏', '' => '삒', '' => '삓', '' => '삕', '' => '삖', '' => '삗', '' => '삙', '' => '삚', '' => '삛', '' => '삜', '' => '삝', '' => '삞', '' => '삟', '' => '삢', '' => '삤', '' => '삦', '' => '삧', '' => '삨', '' => '삩', '' => '삪', '' => '삫', '' => '삮', '' => '삱', '' => '삲', '' => '삷', '' => '삸', '' => '삹', '' => '삺', '' => '삻', '' => '삾', '' => '샂', '' => '샃', '' => '샄', '' => '샆', '' => '샇', '' => '샊', '' => '샋', '' => '샍', '' => '샎', '' => '샏', '' => '샑', '' => '샒', '' => '샓', '' => '샔', '' => '샕', '' => '샖', '' => '샗', '' => '샚', '' => '샞', '' => '샟', '' => '샠', '' => '샡', '' => '샢', '' => '샣', '' => '샦', '' => '샧', '' => '샩', '' => '샪', '' => '샫', '' => '샭', '' => '샮', '' => '샯', '' => '샰', '' => '샱', '' => '샲', '' => '샳', '' => '샶', '' => '샸', '' => '샺', '' => '샻', '' => '샼', '' => '샽', '' => '샾', '' => '샿', '' => '섁', '' => '섂', '' => '섃', '' => '섅', '' => '섆', '' => '섇', '' => '섉', '' => '섊', '' => '섋', '' => '섌', '' => '섍', '' => '섎', '' => '섏', '' => '섑', '' => '섒', '' => '섓', '' => '섔', '' => '섖', '' => '섗', '' => '섘', '' => '섙', '' => '섚', '' => '섛', '' => '섡', '' => '섢', '' => '섥', '' => '섨', '' => '섩', '' => '섪', '' => '섫', '' => '섮', 'A' => '섲', 'B' => '섳', 'C' => '섴', 'D' => '섵', 'E' => '섷', 'F' => '섺', 'G' => '섻', 'H' => '섽', 'I' => '섾', 'J' => '섿', 'K' => '셁', 'L' => '셂', 'M' => '셃', 'N' => '셄', 'O' => '셅', 'P' => '셆', 'Q' => '셇', 'R' => '셊', 'S' => '셎', 'T' => '셏', 'U' => '셐', 'V' => '셑', 'W' => '셒', 'X' => '셓', 'Y' => '셖', 'Z' => '셗', 'a' => '셙', 'b' => '셚', 'c' => '셛', 'd' => '셝', 'e' => '셞', 'f' => '셟', 'g' => '셠', 'h' => '셡', 'i' => '셢', 'j' => '셣', 'k' => '셦', 'l' => '셪', 'm' => '셫', 'n' => '셬', 'o' => '셭', 'p' => '셮', 'q' => '셯', 'r' => '셱', 's' => '셲', 't' => '셳', 'u' => '셵', 'v' => '셶', 'w' => '셷', 'x' => '셹', 'y' => '셺', 'z' => '셻', '' => '셼', '' => '셽', '' => '셾', '' => '셿', '' => '솀', '' => '솁', '' => '솂', '' => '솃', '' => '솄', '' => '솆', '' => '솇', '' => '솈', '' => '솉', '' => '솊', '' => '솋', '' => '솏', '' => '솑', '' => '솒', '' => '솓', '' => '솕', '' => '솗', '' => '솘', '' => '솙', '' => '솚', '' => '솛', '' => '솞', '' => '솠', '' => '솢', '' => '솣', '' => '솤', '' => '솦', '' => '솧', '' => '솪', '' => '솫', '' => '솭', '' => '솮', '' => '솯', '' => '솱', '' => '솲', '' => '솳', '' => '솴', '' => '솵', '' => '솶', '' => '솷', '' => '솸', '' => '솹', '' => '솺', '' => '솻', '' => '솼', '' => '솾', '' => '솿', '' => '쇀', '' => '쇁', '' => '쇂', '' => '쇃', '' => '쇅', '' => '쇆', '' => '쇇', '' => '쇉', '' => '쇊', '' => '쇋', '' => '쇍', '' => '쇎', '' => '쇏', '' => '쇐', '' => '쇑', '' => '쇒', '' => '쇓', '' => '쇕', '' => '쇖', '' => '쇙', '' => '쇚', '' => '쇛', '' => '쇜', '' => '쇝', '' => '쇞', '' => '쇟', '' => '쇡', '' => '쇢', '' => '쇣', '' => '쇥', '' => '쇦', '' => '쇧', '' => '쇩', '' => '쇪', '' => '쇫', '' => '쇬', '' => '쇭', '' => '쇮', '' => '쇯', '' => '쇲', '' => '쇴', '' => '쇵', '' => '쇶', '' => '쇷', '' => '쇸', '' => '쇹', '' => '쇺', '' => '쇻', '' => '쇾', '' => '쇿', '' => '숁', '' => '숂', '' => '숃', '' => '숅', '' => '숆', '' => '숇', '' => '숈', '' => '숉', '' => '숊', '' => '숋', '' => '숎', '' => '숐', '' => '숒', '' => '숓', '' => '숔', '' => '숕', '' => '숖', '' => '숗', '' => '숚', '' => '숛', '' => '숝', '' => '숞', '' => '숡', '' => '숢', '' => '숣', 'A' => '숤', 'B' => '숥', 'C' => '숦', 'D' => '숧', 'E' => '숪', 'F' => '숬', 'G' => '숮', 'H' => '숰', 'I' => '숳', 'J' => '숵', 'K' => '숶', 'L' => '숷', 'M' => '숸', 'N' => '숹', 'O' => '숺', 'P' => '숻', 'Q' => '숼', 'R' => '숽', 'S' => '숾', 'T' => '숿', 'U' => '쉀', 'V' => '쉁', 'W' => '쉂', 'X' => '쉃', 'Y' => '쉄', 'Z' => '쉅', 'a' => '쉆', 'b' => '쉇', 'c' => '쉉', 'd' => '쉊', 'e' => '쉋', 'f' => '쉌', 'g' => '쉍', 'h' => '쉎', 'i' => '쉏', 'j' => '쉒', 'k' => '쉓', 'l' => '쉕', 'm' => '쉖', 'n' => '쉗', 'o' => '쉙', 'p' => '쉚', 'q' => '쉛', 'r' => '쉜', 's' => '쉝', 't' => '쉞', 'u' => '쉟', 'v' => '쉡', 'w' => '쉢', 'x' => '쉣', 'y' => '쉤', 'z' => '쉦', '' => '쉧', '' => '쉨', '' => '쉩', '' => '쉪', '' => '쉫', '' => '쉮', '' => '쉯', '' => '쉱', '' => '쉲', '' => '쉳', '' => '쉵', '' => '쉶', '' => '쉷', '' => '쉸', '' => '쉹', '' => '쉺', '' => '쉻', '' => '쉾', '' => '슀', '' => '슂', '' => '슃', '' => '슄', '' => '슅', '' => '슆', '' => '슇', '' => '슊', '' => '슋', '' => '슌', '' => '슍', '' => '슎', '' => '슏', '' => '슑', '' => '슒', '' => '슓', '' => '슔', '' => '슕', '' => '슖', '' => '슗', '' => '슙', '' => '슚', '' => '슜', '' => '슞', '' => '슟', '' => '슠', '' => '슡', '' => '슢', '' => '슣', '' => '슦', '' => '슧', '' => '슩', '' => '슪', '' => '슫', '' => '슮', '' => '슯', '' => '슰', '' => '슱', '' => '슲', '' => '슳', '' => '슶', '' => '슸', '' => '슺', '' => '슻', '' => '슼', '' => '슽', '' => '슾', '' => '슿', '' => '싀', '' => '싁', '' => '싂', '' => '싃', '' => '싄', '' => '싅', '' => '싆', '' => '싇', '' => '싈', '' => '싉', '' => '싊', '' => '싋', '' => '싌', '' => '싍', '' => '싎', '' => '싏', '' => '싐', '' => '싑', '' => '싒', '' => '싓', '' => '싔', '' => '싕', '' => '싖', '' => '싗', '' => '싘', '' => '싙', '' => '싚', '' => '싛', '' => '싞', '' => '싟', '' => '싡', '' => '싢', '' => '싥', '' => '싦', '' => '싧', '' => '싨', '' => '싩', '' => '싪', '' => '싮', '' => '싰', '' => '싲', '' => '싳', '' => '싴', '' => '싵', '' => '싷', '' => '싺', '' => '싽', '' => '싾', '' => '싿', '' => '쌁', '' => '쌂', '' => '쌃', '' => '쌄', '' => '쌅', '' => '쌆', '' => '쌇', '' => '쌊', '' => '쌋', '' => '쌎', '' => '쌏', 'A' => '쌐', 'B' => '쌑', 'C' => '쌒', 'D' => '쌖', 'E' => '쌗', 'F' => '쌙', 'G' => '쌚', 'H' => '쌛', 'I' => '쌝', 'J' => '쌞', 'K' => '쌟', 'L' => '쌠', 'M' => '쌡', 'N' => '쌢', 'O' => '쌣', 'P' => '쌦', 'Q' => '쌧', 'R' => '쌪', 'S' => '쌫', 'T' => '쌬', 'U' => '쌭', 'V' => '쌮', 'W' => '쌯', 'X' => '쌰', 'Y' => '쌱', 'Z' => '쌲', 'a' => '쌳', 'b' => '쌴', 'c' => '쌵', 'd' => '쌶', 'e' => '쌷', 'f' => '쌸', 'g' => '쌹', 'h' => '쌺', 'i' => '쌻', 'j' => '쌼', 'k' => '쌽', 'l' => '쌾', 'm' => '쌿', 'n' => '썀', 'o' => '썁', 'p' => '썂', 'q' => '썃', 'r' => '썄', 's' => '썆', 't' => '썇', 'u' => '썈', 'v' => '썉', 'w' => '썊', 'x' => '썋', 'y' => '썌', 'z' => '썍', '' => '썎', '' => '썏', '' => '썐', '' => '썑', '' => '썒', '' => '썓', '' => '썔', '' => '썕', '' => '썖', '' => '썗', '' => '썘', '' => '썙', '' => '썚', '' => '썛', '' => '썜', '' => '썝', '' => '썞', '' => '썟', '' => '썠', '' => '썡', '' => '썢', '' => '썣', '' => '썤', '' => '썥', '' => '썦', '' => '썧', '' => '썪', '' => '썫', '' => '썭', '' => '썮', '' => '썯', '' => '썱', '' => '썳', '' => '썴', '' => '썵', '' => '썶', '' => '썷', '' => '썺', '' => '썻', '' => '썾', '' => '썿', '' => '쎀', '' => '쎁', '' => '쎂', '' => '쎃', '' => '쎅', '' => '쎆', '' => '쎇', '' => '쎉', '' => '쎊', '' => '쎋', '' => '쎍', '' => '쎎', '' => '쎏', '' => '쎐', '' => '쎑', '' => '쎒', '' => '쎓', '' => '쎔', '' => '쎕', '' => '쎖', '' => '쎗', '' => '쎘', '' => '쎙', '' => '쎚', '' => '쎛', '' => '쎜', '' => '쎝', '' => '쎞', '' => '쎟', '' => '쎠', '' => '쎡', '' => '쎢', '' => '쎣', '' => '쎤', '' => '쎥', '' => '쎦', '' => '쎧', '' => '쎨', '' => '쎩', '' => '쎪', '' => '쎫', '' => '쎬', '' => '쎭', '' => '쎮', '' => '쎯', '' => '쎰', '' => '쎱', '' => '쎲', '' => '쎳', '' => '쎴', '' => '쎵', '' => '쎶', '' => '쎷', '' => '쎸', '' => '쎹', '' => '쎺', '' => '쎻', '' => '쎼', '' => '쎽', '' => '쎾', '' => '쎿', '' => '쏁', '' => '쏂', '' => '쏃', '' => '쏄', '' => '쏅', '' => '쏆', '' => '쏇', '' => '쏈', '' => '쏉', '' => '쏊', '' => '쏋', '' => '쏌', '' => '쏍', '' => '쏎', '' => '쏏', '' => '쏐', '' => '쏑', '' => '쏒', '' => '쏓', '' => '쏔', '' => '쏕', '' => '쏖', '' => '쏗', '' => '쏚', 'A' => '쏛', 'B' => '쏝', 'C' => '쏞', 'D' => '쏡', 'E' => '쏣', 'F' => '쏤', 'G' => '쏥', 'H' => '쏦', 'I' => '쏧', 'J' => '쏪', 'K' => '쏫', 'L' => '쏬', 'M' => '쏮', 'N' => '쏯', 'O' => '쏰', 'P' => '쏱', 'Q' => '쏲', 'R' => '쏳', 'S' => '쏶', 'T' => '쏷', 'U' => '쏹', 'V' => '쏺', 'W' => '쏻', 'X' => '쏼', 'Y' => '쏽', 'Z' => '쏾', 'a' => '쏿', 'b' => '쐀', 'c' => '쐁', 'd' => '쐂', 'e' => '쐃', 'f' => '쐄', 'g' => '쐅', 'h' => '쐆', 'i' => '쐇', 'j' => '쐉', 'k' => '쐊', 'l' => '쐋', 'm' => '쐌', 'n' => '쐍', 'o' => '쐎', 'p' => '쐏', 'q' => '쐑', 'r' => '쐒', 's' => '쐓', 't' => '쐔', 'u' => '쐕', 'v' => '쐖', 'w' => '쐗', 'x' => '쐘', 'y' => '쐙', 'z' => '쐚', '' => '쐛', '' => '쐜', '' => '쐝', '' => '쐞', '' => '쐟', '' => '쐠', '' => '쐡', '' => '쐢', '' => '쐣', '' => '쐥', '' => '쐦', '' => '쐧', '' => '쐨', '' => '쐩', '' => '쐪', '' => '쐫', '' => '쐭', '' => '쐮', '' => '쐯', '' => '쐱', '' => '쐲', '' => '쐳', '' => '쐵', '' => '쐶', '' => '쐷', '' => '쐸', '' => '쐹', '' => '쐺', '' => '쐻', '' => '쐾', '' => '쐿', '' => '쑀', '' => '쑁', '' => '쑂', '' => '쑃', '' => '쑄', '' => '쑅', '' => '쑆', '' => '쑇', '' => '쑉', '' => '쑊', '' => '쑋', '' => '쑌', '' => '쑍', '' => '쑎', '' => '쑏', '' => '쑐', '' => '쑑', '' => '쑒', '' => '쑓', '' => '쑔', '' => '쑕', '' => '쑖', '' => '쑗', '' => '쑘', '' => '쑙', '' => '쑚', '' => '쑛', '' => '쑜', '' => '쑝', '' => '쑞', '' => '쑟', '' => '쑠', '' => '쑡', '' => '쑢', '' => '쑣', '' => '쑦', '' => '쑧', '' => '쑩', '' => '쑪', '' => '쑫', '' => '쑭', '' => '쑮', '' => '쑯', '' => '쑰', '' => '쑱', '' => '쑲', '' => '쑳', '' => '쑶', '' => '쑷', '' => '쑸', '' => '쑺', '' => '쑻', '' => '쑼', '' => '쑽', '' => '쑾', '' => '쑿', '' => '쒁', '' => '쒂', '' => '쒃', '' => '쒄', '' => '쒅', '' => '쒆', '' => '쒇', '' => '쒈', '' => '쒉', '' => '쒊', '' => '쒋', '' => '쒌', '' => '쒍', '' => '쒎', '' => '쒏', '' => '쒐', '' => '쒑', '' => '쒒', '' => '쒓', '' => '쒕', '' => '쒖', '' => '쒗', '' => '쒘', '' => '쒙', '' => '쒚', '' => '쒛', '' => '쒝', '' => '쒞', '' => '쒟', '' => '쒠', '' => '쒡', '' => '쒢', '' => '쒣', '' => '쒤', '' => '쒥', '' => '쒦', '' => '쒧', '' => '쒨', '' => '쒩', 'A' => '쒪', 'B' => '쒫', 'C' => '쒬', 'D' => '쒭', 'E' => '쒮', 'F' => '쒯', 'G' => '쒰', 'H' => '쒱', 'I' => '쒲', 'J' => '쒳', 'K' => '쒴', 'L' => '쒵', 'M' => '쒶', 'N' => '쒷', 'O' => '쒹', 'P' => '쒺', 'Q' => '쒻', 'R' => '쒽', 'S' => '쒾', 'T' => '쒿', 'U' => '쓀', 'V' => '쓁', 'W' => '쓂', 'X' => '쓃', 'Y' => '쓄', 'Z' => '쓅', 'a' => '쓆', 'b' => '쓇', 'c' => '쓈', 'd' => '쓉', 'e' => '쓊', 'f' => '쓋', 'g' => '쓌', 'h' => '쓍', 'i' => '쓎', 'j' => '쓏', 'k' => '쓐', 'l' => '쓑', 'm' => '쓒', 'n' => '쓓', 'o' => '쓔', 'p' => '쓕', 'q' => '쓖', 'r' => '쓗', 's' => '쓘', 't' => '쓙', 'u' => '쓚', 'v' => '쓛', 'w' => '쓜', 'x' => '쓝', 'y' => '쓞', 'z' => '쓟', '' => '쓠', '' => '쓡', '' => '쓢', '' => '쓣', '' => '쓤', '' => '쓥', '' => '쓦', '' => '쓧', '' => '쓨', '' => '쓪', '' => '쓫', '' => '쓬', '' => '쓭', '' => '쓮', '' => '쓯', '' => '쓲', '' => '쓳', '' => '쓵', '' => '쓶', '' => '쓷', '' => '쓹', '' => '쓻', '' => '쓼', '' => '쓽', '' => '쓾', '' => '씂', '' => '씃', '' => '씄', '' => '씅', '' => '씆', '' => '씇', '' => '씈', '' => '씉', '' => '씊', '' => '씋', '' => '씍', '' => '씎', '' => '씏', '' => '씑', '' => '씒', '' => '씓', '' => '씕', '' => '씖', '' => '씗', '' => '씘', '' => '씙', '' => '씚', '' => '씛', '' => '씝', '' => '씞', '' => '씟', '' => '씠', '' => '씡', '' => '씢', '' => '씣', '' => '씤', '' => '씥', '' => '씦', '' => '씧', '' => '씪', '' => '씫', '' => '씭', '' => '씮', '' => '씯', '' => '씱', '' => '씲', '' => '씳', '' => '씴', '' => '씵', '' => '씶', '' => '씷', '' => '씺', '' => '씼', '' => '씾', '' => '씿', '' => '앀', '' => '앁', '' => '앂', '' => '앃', '' => '앆', '' => '앇', '' => '앋', '' => '앏', '' => '앐', '' => '앑', '' => '앒', '' => '앖', '' => '앚', '' => '앛', '' => '앜', '' => '앟', '' => '앢', '' => '앣', '' => '앥', '' => '앦', '' => '앧', '' => '앩', '' => '앪', '' => '앫', '' => '앬', '' => '앭', '' => '앮', '' => '앯', '' => '앲', '' => '앶', '' => '앷', '' => '앸', '' => '앹', '' => '앺', '' => '앻', '' => '앾', '' => '앿', '' => '얁', '' => '얂', '' => '얃', '' => '얅', '' => '얆', '' => '얈', '' => '얉', '' => '얊', '' => '얋', '' => '얎', '' => '얐', '' => '얒', '' => '얓', '' => '얔', 'A' => '얖', 'B' => '얙', 'C' => '얚', 'D' => '얛', 'E' => '얝', 'F' => '얞', 'G' => '얟', 'H' => '얡', 'I' => '얢', 'J' => '얣', 'K' => '얤', 'L' => '얥', 'M' => '얦', 'N' => '얧', 'O' => '얨', 'P' => '얪', 'Q' => '얫', 'R' => '얬', 'S' => '얭', 'T' => '얮', 'U' => '얯', 'V' => '얰', 'W' => '얱', 'X' => '얲', 'Y' => '얳', 'Z' => '얶', 'a' => '얷', 'b' => '얺', 'c' => '얿', 'd' => '엀', 'e' => '엁', 'f' => '엂', 'g' => '엃', 'h' => '엋', 'i' => '엍', 'j' => '엏', 'k' => '엒', 'l' => '엓', 'm' => '엕', 'n' => '엖', 'o' => '엗', 'p' => '엙', 'q' => '엚', 'r' => '엛', 's' => '엜', 't' => '엝', 'u' => '엞', 'v' => '엟', 'w' => '엢', 'x' => '엤', 'y' => '엦', 'z' => '엧', '' => '엨', '' => '엩', '' => '엪', '' => '엫', '' => '엯', '' => '엱', '' => '엲', '' => '엳', '' => '엵', '' => '엸', '' => '엹', '' => '엺', '' => '엻', '' => '옂', '' => '옃', '' => '옄', '' => '옉', '' => '옊', '' => '옋', '' => '옍', '' => '옎', '' => '옏', '' => '옑', '' => '옒', '' => '옓', '' => '옔', '' => '옕', '' => '옖', '' => '옗', '' => '옚', '' => '옝', '' => '옞', '' => '옟', '' => '옠', '' => '옡', '' => '옢', '' => '옣', '' => '옦', '' => '옧', '' => '옩', '' => '옪', '' => '옫', '' => '옯', '' => '옱', '' => '옲', '' => '옶', '' => '옸', '' => '옺', '' => '옼', '' => '옽', '' => '옾', '' => '옿', '' => '왂', '' => '왃', '' => '왅', '' => '왆', '' => '왇', '' => '왉', '' => '왊', '' => '왋', '' => '왌', '' => '왍', '' => '왎', '' => '왏', '' => '왒', '' => '왖', '' => '왗', '' => '왘', '' => '왙', '' => '왚', '' => '왛', '' => '왞', '' => '왟', '' => '왡', '' => '왢', '' => '왣', '' => '왤', '' => '왥', '' => '왦', '' => '왧', '' => '왨', '' => '왩', '' => '왪', '' => '왫', '' => '왭', '' => '왮', '' => '왰', '' => '왲', '' => '왳', '' => '왴', '' => '왵', '' => '왶', '' => '왷', '' => '왺', '' => '왻', '' => '왽', '' => '왾', '' => '왿', '' => '욁', '' => '욂', '' => '욃', '' => '욄', '' => '욅', '' => '욆', '' => '욇', '' => '욊', '' => '욌', '' => '욎', '' => '욏', '' => '욐', '' => '욑', '' => '욒', '' => '욓', '' => '욖', '' => '욗', '' => '욙', '' => '욚', '' => '욛', '' => '욝', '' => '욞', '' => '욟', '' => '욠', '' => '욡', '' => '욢', '' => '욣', '' => '욦', 'A' => '욨', 'B' => '욪', 'C' => '욫', 'D' => '욬', 'E' => '욭', 'F' => '욮', 'G' => '욯', 'H' => '욲', 'I' => '욳', 'J' => '욵', 'K' => '욶', 'L' => '욷', 'M' => '욻', 'N' => '욼', 'O' => '욽', 'P' => '욾', 'Q' => '욿', 'R' => '웂', 'S' => '웄', 'T' => '웆', 'U' => '웇', 'V' => '웈', 'W' => '웉', 'X' => '웊', 'Y' => '웋', 'Z' => '웎', 'a' => '웏', 'b' => '웑', 'c' => '웒', 'd' => '웓', 'e' => '웕', 'f' => '웖', 'g' => '웗', 'h' => '웘', 'i' => '웙', 'j' => '웚', 'k' => '웛', 'l' => '웞', 'm' => '웟', 'n' => '웢', 'o' => '웣', 'p' => '웤', 'q' => '웥', 'r' => '웦', 's' => '웧', 't' => '웪', 'u' => '웫', 'v' => '웭', 'w' => '웮', 'x' => '웯', 'y' => '웱', 'z' => '웲', '' => '웳', '' => '웴', '' => '웵', '' => '웶', '' => '웷', '' => '웺', '' => '웻', '' => '웼', '' => '웾', '' => '웿', '' => '윀', '' => '윁', '' => '윂', '' => '윃', '' => '윆', '' => '윇', '' => '윉', '' => '윊', '' => '윋', '' => '윍', '' => '윎', '' => '윏', '' => '윐', '' => '윑', '' => '윒', '' => '윓', '' => '윖', '' => '윘', '' => '윚', '' => '윛', '' => '윜', '' => '윝', '' => '윞', '' => '윟', '' => '윢', '' => '윣', '' => '윥', '' => '윦', '' => '윧', '' => '윩', '' => '윪', '' => '윫', '' => '윬', '' => '윭', '' => '윮', '' => '윯', '' => '윲', '' => '윴', '' => '윶', '' => '윸', '' => '윹', '' => '윺', '' => '윻', '' => '윾', '' => '윿', '' => '읁', '' => '읂', '' => '읃', '' => '읅', '' => '읆', '' => '읇', '' => '읈', '' => '읉', '' => '읋', '' => '읎', '' => '읐', '' => '읙', '' => '읚', '' => '읛', '' => '읝', '' => '읞', '' => '읟', '' => '읡', '' => '읢', '' => '읣', '' => '읤', '' => '읥', '' => '읦', '' => '읧', '' => '읩', '' => '읪', '' => '읬', '' => '읭', '' => '읮', '' => '읯', '' => '읰', '' => '읱', '' => '읲', '' => '읳', '' => '읶', '' => '읷', '' => '읹', '' => '읺', '' => '읻', '' => '읿', '' => '잀', '' => '잁', '' => '잂', '' => '잆', '' => '잋', '' => '잌', '' => '잍', '' => '잏', '' => '잒', '' => '잓', '' => '잕', '' => '잙', '' => '잛', '' => '잜', '' => '잝', '' => '잞', '' => '잟', '' => '잢', '' => '잧', '' => '잨', '' => '잩', '' => '잪', '' => '잫', '' => '잮', '' => '잯', '' => '잱', '' => '잲', '' => '잳', '' => '잵', '' => '잶', '' => '잷', 'A' => '잸', 'B' => '잹', 'C' => '잺', 'D' => '잻', 'E' => '잾', 'F' => '쟂', 'G' => '쟃', 'H' => '쟄', 'I' => '쟅', 'J' => '쟆', 'K' => '쟇', 'L' => '쟊', 'M' => '쟋', 'N' => '쟍', 'O' => '쟏', 'P' => '쟑', 'Q' => '쟒', 'R' => '쟓', 'S' => '쟔', 'T' => '쟕', 'U' => '쟖', 'V' => '쟗', 'W' => '쟙', 'X' => '쟚', 'Y' => '쟛', 'Z' => '쟜', 'a' => '쟞', 'b' => '쟟', 'c' => '쟠', 'd' => '쟡', 'e' => '쟢', 'f' => '쟣', 'g' => '쟥', 'h' => '쟦', 'i' => '쟧', 'j' => '쟩', 'k' => '쟪', 'l' => '쟫', 'm' => '쟭', 'n' => '쟮', 'o' => '쟯', 'p' => '쟰', 'q' => '쟱', 'r' => '쟲', 's' => '쟳', 't' => '쟴', 'u' => '쟵', 'v' => '쟶', 'w' => '쟷', 'x' => '쟸', 'y' => '쟹', 'z' => '쟺', '' => '쟻', '' => '쟼', '' => '쟽', '' => '쟾', '' => '쟿', '' => '젂', '' => '젃', '' => '젅', '' => '젆', '' => '젇', '' => '젉', '' => '젋', '' => '젌', '' => '젍', '' => '젎', '' => '젏', '' => '젒', '' => '젔', '' => '젗', '' => '젘', '' => '젙', '' => '젚', '' => '젛', '' => '젞', '' => '젟', '' => '젡', '' => '젢', '' => '젣', '' => '젥', '' => '젦', '' => '젧', '' => '젨', '' => '젩', '' => '젪', '' => '젫', '' => '젮', '' => '젰', '' => '젲', '' => '젳', '' => '젴', '' => '젵', '' => '젶', '' => '젷', '' => '젹', '' => '젺', '' => '젻', '' => '젽', '' => '젾', '' => '젿', '' => '졁', '' => '졂', '' => '졃', '' => '졄', '' => '졅', '' => '졆', '' => '졇', '' => '졊', '' => '졋', '' => '졎', '' => '졏', '' => '졐', '' => '졑', '' => '졒', '' => '졓', '' => '졕', '' => '졖', '' => '졗', '' => '졘', '' => '졙', '' => '졚', '' => '졛', '' => '졜', '' => '졝', '' => '졞', '' => '졟', '' => '졠', '' => '졡', '' => '졢', '' => '졣', '' => '졤', '' => '졥', '' => '졦', '' => '졧', '' => '졨', '' => '졩', '' => '졪', '' => '졫', '' => '졬', '' => '졭', '' => '졮', '' => '졯', '' => '졲', '' => '졳', '' => '졵', '' => '졶', '' => '졷', '' => '졹', '' => '졻', '' => '졼', '' => '졽', '' => '졾', '' => '졿', '' => '좂', '' => '좄', '' => '좈', '' => '좉', '' => '좊', '' => '좎', '' => '좏', '' => '좐', '' => '좑', '' => '좒', '' => '좓', '' => '좕', '' => '좖', '' => '좗', '' => '좘', '' => '좙', '' => '좚', '' => '좛', '' => '좜', '' => '좞', '' => '좠', '' => '좢', '' => '좣', '' => '좤', 'A' => '좥', 'B' => '좦', 'C' => '좧', 'D' => '좩', 'E' => '좪', 'F' => '좫', 'G' => '좬', 'H' => '좭', 'I' => '좮', 'J' => '좯', 'K' => '좰', 'L' => '좱', 'M' => '좲', 'N' => '좳', 'O' => '좴', 'P' => '좵', 'Q' => '좶', 'R' => '좷', 'S' => '좸', 'T' => '좹', 'U' => '좺', 'V' => '좻', 'W' => '좾', 'X' => '좿', 'Y' => '죀', 'Z' => '죁', 'a' => '죂', 'b' => '죃', 'c' => '죅', 'd' => '죆', 'e' => '죇', 'f' => '죉', 'g' => '죊', 'h' => '죋', 'i' => '죍', 'j' => '죎', 'k' => '죏', 'l' => '죐', 'm' => '죑', 'n' => '죒', 'o' => '죓', 'p' => '죖', 'q' => '죘', 'r' => '죚', 's' => '죛', 't' => '죜', 'u' => '죝', 'v' => '죞', 'w' => '죟', 'x' => '죢', 'y' => '죣', 'z' => '죥', '' => '죦', '' => '죧', '' => '죨', '' => '죩', '' => '죪', '' => '죫', '' => '죬', '' => '죭', '' => '죮', '' => '죯', '' => '죰', '' => '죱', '' => '죲', '' => '죳', '' => '죴', '' => '죶', '' => '죷', '' => '죸', '' => '죹', '' => '죺', '' => '죻', '' => '죾', '' => '죿', '' => '줁', '' => '줂', '' => '줃', '' => '줇', '' => '줈', '' => '줉', '' => '줊', '' => '줋', '' => '줎', '' => ' ', '' => '、', '' => '。', '' => '·', '' => '‥', '' => '…', '' => '¨', '' => '〃', '' => '­', '' => '―', '' => '∥', '' => '\', '' => '∼', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '〔', '' => '〕', '' => '〈', '' => '〉', '' => '《', '' => '》', '' => '「', '' => '」', '' => '『', '' => '』', '' => '【', '' => '】', '' => '±', '' => '×', '' => '÷', '' => '≠', '' => '≤', '' => '≥', '' => '∞', '' => '∴', '' => '°', '' => '′', '' => '″', '' => '℃', '' => 'Å', '' => '¢', '' => '£', '' => '¥', '' => '♂', '' => '♀', '' => '∠', '' => '⊥', '' => '⌒', '' => '∂', '' => '∇', '' => '≡', '' => '≒', '' => '§', '' => '※', '' => '☆', '' => '★', '' => '○', '' => '●', '' => '◎', '' => '◇', '' => '◆', '' => '□', '' => '■', '' => '△', '' => '▲', '' => '▽', '' => '▼', '' => '→', '' => '←', '' => '↑', '' => '↓', '' => '↔', '' => '〓', '' => '≪', '' => '≫', '' => '√', '' => '∽', '' => '∝', '' => '∵', '' => '∫', '' => '∬', '' => '∈', '' => '∋', '' => '⊆', '' => '⊇', '' => '⊂', '' => '⊃', '' => '∪', '' => '∩', '' => '∧', '' => '∨', '' => '¬', 'A' => '줐', 'B' => '줒', 'C' => '줓', 'D' => '줔', 'E' => '줕', 'F' => '줖', 'G' => '줗', 'H' => '줙', 'I' => '줚', 'J' => '줛', 'K' => '줜', 'L' => '줝', 'M' => '줞', 'N' => '줟', 'O' => '줠', 'P' => '줡', 'Q' => '줢', 'R' => '줣', 'S' => '줤', 'T' => '줥', 'U' => '줦', 'V' => '줧', 'W' => '줨', 'X' => '줩', 'Y' => '줪', 'Z' => '줫', 'a' => '줭', 'b' => '줮', 'c' => '줯', 'd' => '줰', 'e' => '줱', 'f' => '줲', 'g' => '줳', 'h' => '줵', 'i' => '줶', 'j' => '줷', 'k' => '줸', 'l' => '줹', 'm' => '줺', 'n' => '줻', 'o' => '줼', 'p' => '줽', 'q' => '줾', 'r' => '줿', 's' => '쥀', 't' => '쥁', 'u' => '쥂', 'v' => '쥃', 'w' => '쥄', 'x' => '쥅', 'y' => '쥆', 'z' => '쥇', '' => '쥈', '' => '쥉', '' => '쥊', '' => '쥋', '' => '쥌', '' => '쥍', '' => '쥎', '' => '쥏', '' => '쥒', '' => '쥓', '' => '쥕', '' => '쥖', '' => '쥗', '' => '쥙', '' => '쥚', '' => '쥛', '' => '쥜', '' => '쥝', '' => '쥞', '' => '쥟', '' => '쥢', '' => '쥤', '' => '쥥', '' => '쥦', '' => '쥧', '' => '쥨', '' => '쥩', '' => '쥪', '' => '쥫', '' => '쥭', '' => '쥮', '' => '쥯', '' => '⇒', '' => '⇔', '' => '∀', '' => '∃', '' => '´', '' => '~', '' => 'ˇ', '' => '˘', '' => '˝', '' => '˚', '' => '˙', '' => '¸', '' => '˛', '' => '¡', '' => '¿', '' => 'ː', '' => '∮', '' => '∑', '' => '∏', '' => '¤', '' => '℉', '' => '‰', '' => '◁', '' => '◀', '' => '▷', '' => '▶', '' => '♤', '' => '♠', '' => '♡', '' => '♥', '' => '♧', '' => '♣', '' => '⊙', '' => '◈', '' => '▣', '' => '◐', '' => '◑', '' => '▒', '' => '▤', '' => '▥', '' => '▨', '' => '▧', '' => '▦', '' => '▩', '' => '♨', '' => '☏', '' => '☎', '' => '☜', '' => '☞', '' => '¶', '' => '†', '' => '‡', '' => '↕', '' => '↗', '' => '↙', '' => '↖', '' => '↘', '' => '♭', '' => '♩', '' => '♪', '' => '♬', '' => '㉿', '' => '㈜', '' => '№', '' => '㏇', '' => '™', '' => '㏂', '' => '㏘', '' => '℡', '' => '€', '' => '®', 'A' => '쥱', 'B' => '쥲', 'C' => '쥳', 'D' => '쥵', 'E' => '쥶', 'F' => '쥷', 'G' => '쥸', 'H' => '쥹', 'I' => '쥺', 'J' => '쥻', 'K' => '쥽', 'L' => '쥾', 'M' => '쥿', 'N' => '즀', 'O' => '즁', 'P' => '즂', 'Q' => '즃', 'R' => '즄', 'S' => '즅', 'T' => '즆', 'U' => '즇', 'V' => '즊', 'W' => '즋', 'X' => '즍', 'Y' => '즎', 'Z' => '즏', 'a' => '즑', 'b' => '즒', 'c' => '즓', 'd' => '즔', 'e' => '즕', 'f' => '즖', 'g' => '즗', 'h' => '즚', 'i' => '즜', 'j' => '즞', 'k' => '즟', 'l' => '즠', 'm' => '즡', 'n' => '즢', 'o' => '즣', 'p' => '즤', 'q' => '즥', 'r' => '즦', 's' => '즧', 't' => '즨', 'u' => '즩', 'v' => '즪', 'w' => '즫', 'x' => '즬', 'y' => '즭', 'z' => '즮', '' => '즯', '' => '즰', '' => '즱', '' => '즲', '' => '즳', '' => '즴', '' => '즵', '' => '즶', '' => '즷', '' => '즸', '' => '즹', '' => '즺', '' => '즻', '' => '즼', '' => '즽', '' => '즾', '' => '즿', '' => '짂', '' => '짃', '' => '짅', '' => '짆', '' => '짉', '' => '짋', '' => '짌', '' => '짍', '' => '짎', '' => '짏', '' => '짒', '' => '짔', '' => '짗', '' => '짘', '' => '짛', '' => '!', '' => '"', '' => '#', '' => '$', '' => '%', '' => '&', '' => ''', '' => '(', '' => ')', '' => '*', '' => '+', '' => ',', '' => '-', '' => '.', '' => '/', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => ':', '' => ';', '' => '<', '' => '=', '' => '>', '' => '?', '' => '@', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => '[', '' => '₩', '' => ']', '' => '^', '' => '_', '' => '`', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => '{', '' => '|', '' => '}', '' => ' ̄', 'A' => '짞', 'B' => '짟', 'C' => '짡', 'D' => '짣', 'E' => '짥', 'F' => '짦', 'G' => '짨', 'H' => '짩', 'I' => '짪', 'J' => '짫', 'K' => '짮', 'L' => '짲', 'M' => '짳', 'N' => '짴', 'O' => '짵', 'P' => '짶', 'Q' => '짷', 'R' => '짺', 'S' => '짻', 'T' => '짽', 'U' => '짾', 'V' => '짿', 'W' => '쨁', 'X' => '쨂', 'Y' => '쨃', 'Z' => '쨄', 'a' => '쨅', 'b' => '쨆', 'c' => '쨇', 'd' => '쨊', 'e' => '쨎', 'f' => '쨏', 'g' => '쨐', 'h' => '쨑', 'i' => '쨒', 'j' => '쨓', 'k' => '쨕', 'l' => '쨖', 'm' => '쨗', 'n' => '쨙', 'o' => '쨚', 'p' => '쨛', 'q' => '쨜', 'r' => '쨝', 's' => '쨞', 't' => '쨟', 'u' => '쨠', 'v' => '쨡', 'w' => '쨢', 'x' => '쨣', 'y' => '쨤', 'z' => '쨥', '' => '쨦', '' => '쨧', '' => '쨨', '' => '쨪', '' => '쨫', '' => '쨬', '' => '쨭', '' => '쨮', '' => '쨯', '' => '쨰', '' => '쨱', '' => '쨲', '' => '쨳', '' => '쨴', '' => '쨵', '' => '쨶', '' => '쨷', '' => '쨸', '' => '쨹', '' => '쨺', '' => '쨻', '' => '쨼', '' => '쨽', '' => '쨾', '' => '쨿', '' => '쩀', '' => '쩁', '' => '쩂', '' => '쩃', '' => '쩄', '' => '쩅', '' => '쩆', '' => 'ㄱ', '' => 'ㄲ', '' => 'ㄳ', '' => 'ㄴ', '' => 'ㄵ', '' => 'ㄶ', '' => 'ㄷ', '' => 'ㄸ', '' => 'ㄹ', '' => 'ㄺ', '' => 'ㄻ', '' => 'ㄼ', '' => 'ㄽ', '' => 'ㄾ', '' => 'ㄿ', '' => 'ㅀ', '' => 'ㅁ', '' => 'ㅂ', '' => 'ㅃ', '' => 'ㅄ', '' => 'ㅅ', '' => 'ㅆ', '' => 'ㅇ', '' => 'ㅈ', '' => 'ㅉ', '' => 'ㅊ', '' => 'ㅋ', '' => 'ㅌ', '' => 'ㅍ', '' => 'ㅎ', '' => 'ㅏ', '' => 'ㅐ', '' => 'ㅑ', '' => 'ㅒ', '' => 'ㅓ', '' => 'ㅔ', '' => 'ㅕ', '' => 'ㅖ', '' => 'ㅗ', '' => 'ㅘ', '' => 'ㅙ', '' => 'ㅚ', '' => 'ㅛ', '' => 'ㅜ', '' => 'ㅝ', '' => 'ㅞ', '' => 'ㅟ', '' => 'ㅠ', '' => 'ㅡ', '' => 'ㅢ', '' => 'ㅣ', '' => 'ㅤ', '' => 'ㅥ', '' => 'ㅦ', '' => 'ㅧ', '' => 'ㅨ', '' => 'ㅩ', '' => 'ㅪ', '' => 'ㅫ', '' => 'ㅬ', '' => 'ㅭ', '' => 'ㅮ', '' => 'ㅯ', '' => 'ㅰ', '' => 'ㅱ', '' => 'ㅲ', '' => 'ㅳ', '' => 'ㅴ', '' => 'ㅵ', '' => 'ㅶ', '' => 'ㅷ', '' => 'ㅸ', '' => 'ㅹ', '' => 'ㅺ', '' => 'ㅻ', '' => 'ㅼ', '' => 'ㅽ', '' => 'ㅾ', '' => 'ㅿ', '' => 'ㆀ', '' => 'ㆁ', '' => 'ㆂ', '' => 'ㆃ', '' => 'ㆄ', '' => 'ㆅ', '' => 'ㆆ', '' => 'ㆇ', '' => 'ㆈ', '' => 'ㆉ', '' => 'ㆊ', '' => 'ㆋ', '' => 'ㆌ', '' => 'ㆍ', '' => 'ㆎ', 'A' => '쩇', 'B' => '쩈', 'C' => '쩉', 'D' => '쩊', 'E' => '쩋', 'F' => '쩎', 'G' => '쩏', 'H' => '쩑', 'I' => '쩒', 'J' => '쩓', 'K' => '쩕', 'L' => '쩖', 'M' => '쩗', 'N' => '쩘', 'O' => '쩙', 'P' => '쩚', 'Q' => '쩛', 'R' => '쩞', 'S' => '쩢', 'T' => '쩣', 'U' => '쩤', 'V' => '쩥', 'W' => '쩦', 'X' => '쩧', 'Y' => '쩩', 'Z' => '쩪', 'a' => '쩫', 'b' => '쩬', 'c' => '쩭', 'd' => '쩮', 'e' => '쩯', 'f' => '쩰', 'g' => '쩱', 'h' => '쩲', 'i' => '쩳', 'j' => '쩴', 'k' => '쩵', 'l' => '쩶', 'm' => '쩷', 'n' => '쩸', 'o' => '쩹', 'p' => '쩺', 'q' => '쩻', 'r' => '쩼', 's' => '쩾', 't' => '쩿', 'u' => '쪀', 'v' => '쪁', 'w' => '쪂', 'x' => '쪃', 'y' => '쪅', 'z' => '쪆', '' => '쪇', '' => '쪈', '' => '쪉', '' => '쪊', '' => '쪋', '' => '쪌', '' => '쪍', '' => '쪎', '' => '쪏', '' => '쪐', '' => '쪑', '' => '쪒', '' => '쪓', '' => '쪔', '' => '쪕', '' => '쪖', '' => '쪗', '' => '쪙', '' => '쪚', '' => '쪛', '' => '쪜', '' => '쪝', '' => '쪞', '' => '쪟', '' => '쪠', '' => '쪡', '' => '쪢', '' => '쪣', '' => '쪤', '' => '쪥', '' => '쪦', '' => '쪧', '' => 'ⅰ', '' => 'ⅱ', '' => 'ⅲ', '' => 'ⅳ', '' => 'ⅴ', '' => 'ⅵ', '' => 'ⅶ', '' => 'ⅷ', '' => 'ⅸ', '' => 'ⅹ', '' => 'Ⅰ', '' => 'Ⅱ', '' => 'Ⅲ', '' => 'Ⅳ', '' => 'Ⅴ', '' => 'Ⅵ', '' => 'Ⅶ', '' => 'Ⅷ', '' => 'Ⅸ', '' => 'Ⅹ', '' => 'Α', '' => 'Β', '' => 'Γ', '' => 'Δ', '' => 'Ε', '' => 'Ζ', '' => 'Η', '' => 'Θ', '' => 'Ι', '' => 'Κ', '' => 'Λ', '' => 'Μ', '' => 'Ν', '' => 'Ξ', '' => 'Ο', '' => 'Π', '' => 'Ρ', '' => 'Σ', '' => 'Τ', '' => 'Υ', '' => 'Φ', '' => 'Χ', '' => 'Ψ', '' => 'Ω', '' => 'α', '' => 'β', '' => 'γ', '' => 'δ', '' => 'ε', '' => 'ζ', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'σ', '' => 'τ', '' => 'υ', '' => 'φ', '' => 'χ', '' => 'ψ', '' => 'ω', 'A' => '쪨', 'B' => '쪩', 'C' => '쪪', 'D' => '쪫', 'E' => '쪬', 'F' => '쪭', 'G' => '쪮', 'H' => '쪯', 'I' => '쪰', 'J' => '쪱', 'K' => '쪲', 'L' => '쪳', 'M' => '쪴', 'N' => '쪵', 'O' => '쪶', 'P' => '쪷', 'Q' => '쪸', 'R' => '쪹', 'S' => '쪺', 'T' => '쪻', 'U' => '쪾', 'V' => '쪿', 'W' => '쫁', 'X' => '쫂', 'Y' => '쫃', 'Z' => '쫅', 'a' => '쫆', 'b' => '쫇', 'c' => '쫈', 'd' => '쫉', 'e' => '쫊', 'f' => '쫋', 'g' => '쫎', 'h' => '쫐', 'i' => '쫒', 'j' => '쫔', 'k' => '쫕', 'l' => '쫖', 'm' => '쫗', 'n' => '쫚', 'o' => '쫛', 'p' => '쫜', 'q' => '쫝', 'r' => '쫞', 's' => '쫟', 't' => '쫡', 'u' => '쫢', 'v' => '쫣', 'w' => '쫤', 'x' => '쫥', 'y' => '쫦', 'z' => '쫧', '' => '쫨', '' => '쫩', '' => '쫪', '' => '쫫', '' => '쫭', '' => '쫮', '' => '쫯', '' => '쫰', '' => '쫱', '' => '쫲', '' => '쫳', '' => '쫵', '' => '쫶', '' => '쫷', '' => '쫸', '' => '쫹', '' => '쫺', '' => '쫻', '' => '쫼', '' => '쫽', '' => '쫾', '' => '쫿', '' => '쬀', '' => '쬁', '' => '쬂', '' => '쬃', '' => '쬄', '' => '쬅', '' => '쬆', '' => '쬇', '' => '쬉', '' => '쬊', '' => '─', '' => '│', '' => '┌', '' => '┐', '' => '┘', '' => '└', '' => '├', '' => '┬', '' => '┤', '' => '┴', '' => '┼', '' => '━', '' => '┃', '' => '┏', '' => '┓', '' => '┛', '' => '┗', '' => '┣', '' => '┳', '' => '┫', '' => '┻', '' => '╋', '' => '┠', '' => '┯', '' => '┨', '' => '┷', '' => '┿', '' => '┝', '' => '┰', '' => '┥', '' => '┸', '' => '╂', '' => '┒', '' => '┑', '' => '┚', '' => '┙', '' => '┖', '' => '┕', '' => '┎', '' => '┍', '' => '┞', '' => '┟', '' => '┡', '' => '┢', '' => '┦', '' => '┧', '' => '┩', '' => '┪', '' => '┭', '' => '┮', '' => '┱', '' => '┲', '' => '┵', '' => '┶', '' => '┹', '' => '┺', '' => '┽', '' => '┾', '' => '╀', '' => '╁', '' => '╃', '' => '╄', '' => '╅', '' => '╆', '' => '╇', '' => '╈', '' => '╉', '' => '╊', 'A' => '쬋', 'B' => '쬌', 'C' => '쬍', 'D' => '쬎', 'E' => '쬏', 'F' => '쬑', 'G' => '쬒', 'H' => '쬓', 'I' => '쬕', 'J' => '쬖', 'K' => '쬗', 'L' => '쬙', 'M' => '쬚', 'N' => '쬛', 'O' => '쬜', 'P' => '쬝', 'Q' => '쬞', 'R' => '쬟', 'S' => '쬢', 'T' => '쬣', 'U' => '쬤', 'V' => '쬥', 'W' => '쬦', 'X' => '쬧', 'Y' => '쬨', 'Z' => '쬩', 'a' => '쬪', 'b' => '쬫', 'c' => '쬬', 'd' => '쬭', 'e' => '쬮', 'f' => '쬯', 'g' => '쬰', 'h' => '쬱', 'i' => '쬲', 'j' => '쬳', 'k' => '쬴', 'l' => '쬵', 'm' => '쬶', 'n' => '쬷', 'o' => '쬸', 'p' => '쬹', 'q' => '쬺', 'r' => '쬻', 's' => '쬼', 't' => '쬽', 'u' => '쬾', 'v' => '쬿', 'w' => '쭀', 'x' => '쭂', 'y' => '쭃', 'z' => '쭄', '' => '쭅', '' => '쭆', '' => '쭇', '' => '쭊', '' => '쭋', '' => '쭍', '' => '쭎', '' => '쭏', '' => '쭑', '' => '쭒', '' => '쭓', '' => '쭔', '' => '쭕', '' => '쭖', '' => '쭗', '' => '쭚', '' => '쭛', '' => '쭜', '' => '쭞', '' => '쭟', '' => '쭠', '' => '쭡', '' => '쭢', '' => '쭣', '' => '쭥', '' => '쭦', '' => '쭧', '' => '쭨', '' => '쭩', '' => '쭪', '' => '쭫', '' => '쭬', '' => '㎕', '' => '㎖', '' => '㎗', '' => 'ℓ', '' => '㎘', '' => '㏄', '' => '㎣', '' => '㎤', '' => '㎥', '' => '㎦', '' => '㎙', '' => '㎚', '' => '㎛', '' => '㎜', '' => '㎝', '' => '㎞', '' => '㎟', '' => '㎠', '' => '㎡', '' => '㎢', '' => '㏊', '' => '㎍', '' => '㎎', '' => '㎏', '' => '㏏', '' => '㎈', '' => '㎉', '' => '㏈', '' => '㎧', '' => '㎨', '' => '㎰', '' => '㎱', '' => '㎲', '' => '㎳', '' => '㎴', '' => '㎵', '' => '㎶', '' => '㎷', '' => '㎸', '' => '㎹', '' => '㎀', '' => '㎁', '' => '㎂', '' => '㎃', '' => '㎄', '' => '㎺', '' => '㎻', '' => '㎼', '' => '㎽', '' => '㎾', '' => '㎿', '' => '㎐', '' => '㎑', '' => '㎒', '' => '㎓', '' => '㎔', '' => 'Ω', '' => '㏀', '' => '㏁', '' => '㎊', '' => '㎋', '' => '㎌', '' => '㏖', '' => '㏅', '' => '㎭', '' => '㎮', '' => '㎯', '' => '㏛', '' => '㎩', '' => '㎪', '' => '㎫', '' => '㎬', '' => '㏝', '' => '㏐', '' => '㏓', '' => '㏃', '' => '㏉', '' => '㏜', '' => '㏆', 'A' => '쭭', 'B' => '쭮', 'C' => '쭯', 'D' => '쭰', 'E' => '쭱', 'F' => '쭲', 'G' => '쭳', 'H' => '쭴', 'I' => '쭵', 'J' => '쭶', 'K' => '쭷', 'L' => '쭺', 'M' => '쭻', 'N' => '쭼', 'O' => '쭽', 'P' => '쭾', 'Q' => '쭿', 'R' => '쮀', 'S' => '쮁', 'T' => '쮂', 'U' => '쮃', 'V' => '쮄', 'W' => '쮅', 'X' => '쮆', 'Y' => '쮇', 'Z' => '쮈', 'a' => '쮉', 'b' => '쮊', 'c' => '쮋', 'd' => '쮌', 'e' => '쮍', 'f' => '쮎', 'g' => '쮏', 'h' => '쮐', 'i' => '쮑', 'j' => '쮒', 'k' => '쮓', 'l' => '쮔', 'm' => '쮕', 'n' => '쮖', 'o' => '쮗', 'p' => '쮘', 'q' => '쮙', 'r' => '쮚', 's' => '쮛', 't' => '쮝', 'u' => '쮞', 'v' => '쮟', 'w' => '쮠', 'x' => '쮡', 'y' => '쮢', 'z' => '쮣', '' => '쮤', '' => '쮥', '' => '쮦', '' => '쮧', '' => '쮨', '' => '쮩', '' => '쮪', '' => '쮫', '' => '쮬', '' => '쮭', '' => '쮮', '' => '쮯', '' => '쮰', '' => '쮱', '' => '쮲', '' => '쮳', '' => '쮴', '' => '쮵', '' => '쮶', '' => '쮷', '' => '쮹', '' => '쮺', '' => '쮻', '' => '쮼', '' => '쮽', '' => '쮾', '' => '쮿', '' => '쯀', '' => '쯁', '' => '쯂', '' => '쯃', '' => '쯄', '' => 'Æ', '' => 'Ð', '' => 'ª', '' => 'Ħ', '' => 'IJ', '' => 'Ŀ', '' => 'Ł', '' => 'Ø', '' => 'Œ', '' => 'º', '' => 'Þ', '' => 'Ŧ', '' => 'Ŋ', '' => '㉠', '' => '㉡', '' => '㉢', '' => '㉣', '' => '㉤', '' => '㉥', '' => '㉦', '' => '㉧', '' => '㉨', '' => '㉩', '' => '㉪', '' => '㉫', '' => '㉬', '' => '㉭', '' => '㉮', '' => '㉯', '' => '㉰', '' => '㉱', '' => '㉲', '' => '㉳', '' => '㉴', '' => '㉵', '' => '㉶', '' => '㉷', '' => '㉸', '' => '㉹', '' => '㉺', '' => '㉻', '' => 'ⓐ', '' => 'ⓑ', '' => 'ⓒ', '' => 'ⓓ', '' => 'ⓔ', '' => 'ⓕ', '' => 'ⓖ', '' => 'ⓗ', '' => 'ⓘ', '' => 'ⓙ', '' => 'ⓚ', '' => 'ⓛ', '' => 'ⓜ', '' => 'ⓝ', '' => 'ⓞ', '' => 'ⓟ', '' => 'ⓠ', '' => 'ⓡ', '' => 'ⓢ', '' => 'ⓣ', '' => 'ⓤ', '' => 'ⓥ', '' => 'ⓦ', '' => 'ⓧ', '' => 'ⓨ', '' => 'ⓩ', '' => '①', '' => '②', '' => '③', '' => '④', '' => '⑤', '' => '⑥', '' => '⑦', '' => '⑧', '' => '⑨', '' => '⑩', '' => '⑪', '' => '⑫', '' => '⑬', '' => '⑭', '' => '⑮', '' => '½', '' => '⅓', '' => '⅔', '' => '¼', '' => '¾', '' => '⅛', '' => '⅜', '' => '⅝', '' => '⅞', 'A' => '쯅', 'B' => '쯆', 'C' => '쯇', 'D' => '쯈', 'E' => '쯉', 'F' => '쯊', 'G' => '쯋', 'H' => '쯌', 'I' => '쯍', 'J' => '쯎', 'K' => '쯏', 'L' => '쯐', 'M' => '쯑', 'N' => '쯒', 'O' => '쯓', 'P' => '쯕', 'Q' => '쯖', 'R' => '쯗', 'S' => '쯘', 'T' => '쯙', 'U' => '쯚', 'V' => '쯛', 'W' => '쯜', 'X' => '쯝', 'Y' => '쯞', 'Z' => '쯟', 'a' => '쯠', 'b' => '쯡', 'c' => '쯢', 'd' => '쯣', 'e' => '쯥', 'f' => '쯦', 'g' => '쯨', 'h' => '쯪', 'i' => '쯫', 'j' => '쯬', 'k' => '쯭', 'l' => '쯮', 'm' => '쯯', 'n' => '쯰', 'o' => '쯱', 'p' => '쯲', 'q' => '쯳', 'r' => '쯴', 's' => '쯵', 't' => '쯶', 'u' => '쯷', 'v' => '쯸', 'w' => '쯹', 'x' => '쯺', 'y' => '쯻', 'z' => '쯼', '' => '쯽', '' => '쯾', '' => '쯿', '' => '찀', '' => '찁', '' => '찂', '' => '찃', '' => '찄', '' => '찅', '' => '찆', '' => '찇', '' => '찈', '' => '찉', '' => '찊', '' => '찋', '' => '찎', '' => '찏', '' => '찑', '' => '찒', '' => '찓', '' => '찕', '' => '찖', '' => '찗', '' => '찘', '' => '찙', '' => '찚', '' => '찛', '' => '찞', '' => '찟', '' => '찠', '' => '찣', '' => '찤', '' => 'æ', '' => 'đ', '' => 'ð', '' => 'ħ', '' => 'ı', '' => 'ij', '' => 'ĸ', '' => 'ŀ', '' => 'ł', '' => 'ø', '' => 'œ', '' => 'ß', '' => 'þ', '' => 'ŧ', '' => 'ŋ', '' => 'ʼn', '' => '㈀', '' => '㈁', '' => '㈂', '' => '㈃', '' => '㈄', '' => '㈅', '' => '㈆', '' => '㈇', '' => '㈈', '' => '㈉', '' => '㈊', '' => '㈋', '' => '㈌', '' => '㈍', '' => '㈎', '' => '㈏', '' => '㈐', '' => '㈑', '' => '㈒', '' => '㈓', '' => '㈔', '' => '㈕', '' => '㈖', '' => '㈗', '' => '㈘', '' => '㈙', '' => '㈚', '' => '㈛', '' => '⒜', '' => '⒝', '' => '⒞', '' => '⒟', '' => '⒠', '' => '⒡', '' => '⒢', '' => '⒣', '' => '⒤', '' => '⒥', '' => '⒦', '' => '⒧', '' => '⒨', '' => '⒩', '' => '⒪', '' => '⒫', '' => '⒬', '' => '⒭', '' => '⒮', '' => '⒯', '' => '⒰', '' => '⒱', '' => '⒲', '' => '⒳', '' => '⒴', '' => '⒵', '' => '⑴', '' => '⑵', '' => '⑶', '' => '⑷', '' => '⑸', '' => '⑹', '' => '⑺', '' => '⑻', '' => '⑼', '' => '⑽', '' => '⑾', '' => '⑿', '' => '⒀', '' => '⒁', '' => '⒂', '' => '¹', '' => '²', '' => '³', '' => '⁴', '' => 'ⁿ', '' => '₁', '' => '₂', '' => '₃', '' => '₄', 'A' => '찥', 'B' => '찦', 'C' => '찪', 'D' => '찫', 'E' => '찭', 'F' => '찯', 'G' => '찱', 'H' => '찲', 'I' => '찳', 'J' => '찴', 'K' => '찵', 'L' => '찶', 'M' => '찷', 'N' => '찺', 'O' => '찿', 'P' => '챀', 'Q' => '챁', 'R' => '챂', 'S' => '챃', 'T' => '챆', 'U' => '챇', 'V' => '챉', 'W' => '챊', 'X' => '챋', 'Y' => '챍', 'Z' => '챎', 'a' => '챏', 'b' => '챐', 'c' => '챑', 'd' => '챒', 'e' => '챓', 'f' => '챖', 'g' => '챚', 'h' => '챛', 'i' => '챜', 'j' => '챝', 'k' => '챞', 'l' => '챟', 'm' => '챡', 'n' => '챢', 'o' => '챣', 'p' => '챥', 'q' => '챧', 'r' => '챩', 's' => '챪', 't' => '챫', 'u' => '챬', 'v' => '챭', 'w' => '챮', 'x' => '챯', 'y' => '챱', 'z' => '챲', '' => '챳', '' => '챴', '' => '챶', '' => '챷', '' => '챸', '' => '챹', '' => '챺', '' => '챻', '' => '챼', '' => '챽', '' => '챾', '' => '챿', '' => '첀', '' => '첁', '' => '첂', '' => '첃', '' => '첄', '' => '첅', '' => '첆', '' => '첇', '' => '첈', '' => '첉', '' => '첊', '' => '첋', '' => '첌', '' => '첍', '' => '첎', '' => '첏', '' => '첐', '' => '첑', '' => '첒', '' => '첓', '' => 'ぁ', '' => 'あ', '' => 'ぃ', '' => 'い', '' => 'ぅ', '' => 'う', '' => 'ぇ', '' => 'え', '' => 'ぉ', '' => 'お', '' => 'か', '' => 'が', '' => 'き', '' => 'ぎ', '' => 'く', '' => 'ぐ', '' => 'け', '' => 'げ', '' => 'こ', '' => 'ご', '' => 'さ', '' => 'ざ', '' => 'し', '' => 'じ', '' => 'す', '' => 'ず', '' => 'せ', '' => 'ぜ', '' => 'そ', '' => 'ぞ', '' => 'た', '' => 'だ', '' => 'ち', '' => 'ぢ', '' => 'っ', '' => 'つ', '' => 'づ', '' => 'て', '' => 'で', '' => 'と', '' => 'ど', '' => 'な', '' => 'に', '' => 'ぬ', '' => 'ね', '' => 'の', '' => 'は', '' => 'ば', '' => 'ぱ', '' => 'ひ', '' => 'び', '' => 'ぴ', '' => 'ふ', '' => 'ぶ', '' => 'ぷ', '' => 'へ', '' => 'べ', '' => 'ぺ', '' => 'ほ', '' => 'ぼ', '' => 'ぽ', '' => 'ま', '' => 'み', '' => 'む', '' => 'め', '' => 'も', '' => 'ゃ', '' => 'や', '' => 'ゅ', '' => 'ゆ', '' => 'ょ', '' => 'よ', '' => 'ら', '' => 'り', '' => 'る', '' => 'れ', '' => 'ろ', '' => 'ゎ', '' => 'わ', '' => 'ゐ', '' => 'ゑ', '' => 'を', '' => 'ん', 'A' => '첔', 'B' => '첕', 'C' => '첖', 'D' => '첗', 'E' => '첚', 'F' => '첛', 'G' => '첝', 'H' => '첞', 'I' => '첟', 'J' => '첡', 'K' => '첢', 'L' => '첣', 'M' => '첤', 'N' => '첥', 'O' => '첦', 'P' => '첧', 'Q' => '첪', 'R' => '첮', 'S' => '첯', 'T' => '첰', 'U' => '첱', 'V' => '첲', 'W' => '첳', 'X' => '첶', 'Y' => '첷', 'Z' => '첹', 'a' => '첺', 'b' => '첻', 'c' => '첽', 'd' => '첾', 'e' => '첿', 'f' => '쳀', 'g' => '쳁', 'h' => '쳂', 'i' => '쳃', 'j' => '쳆', 'k' => '쳈', 'l' => '쳊', 'm' => '쳋', 'n' => '쳌', 'o' => '쳍', 'p' => '쳎', 'q' => '쳏', 'r' => '쳑', 's' => '쳒', 't' => '쳓', 'u' => '쳕', 'v' => '쳖', 'w' => '쳗', 'x' => '쳘', 'y' => '쳙', 'z' => '쳚', '' => '쳛', '' => '쳜', '' => '쳝', '' => '쳞', '' => '쳟', '' => '쳠', '' => '쳡', '' => '쳢', '' => '쳣', '' => '쳥', '' => '쳦', '' => '쳧', '' => '쳨', '' => '쳩', '' => '쳪', '' => '쳫', '' => '쳭', '' => '쳮', '' => '쳯', '' => '쳱', '' => '쳲', '' => '쳳', '' => '쳴', '' => '쳵', '' => '쳶', '' => '쳷', '' => '쳸', '' => '쳹', '' => '쳺', '' => '쳻', '' => '쳼', '' => '쳽', '' => 'ァ', '' => 'ア', '' => 'ィ', '' => 'イ', '' => 'ゥ', '' => 'ウ', '' => 'ェ', '' => 'エ', '' => 'ォ', '' => 'オ', '' => 'カ', '' => 'ガ', '' => 'キ', '' => 'ギ', '' => 'ク', '' => 'グ', '' => 'ケ', '' => 'ゲ', '' => 'コ', '' => 'ゴ', '' => 'サ', '' => 'ザ', '' => 'シ', '' => 'ジ', '' => 'ス', '' => 'ズ', '' => 'セ', '' => 'ゼ', '' => 'ソ', '' => 'ゾ', '' => 'タ', '' => 'ダ', '' => 'チ', '' => 'ヂ', '' => 'ッ', '' => 'ツ', '' => 'ヅ', '' => 'テ', '' => 'デ', '' => 'ト', '' => 'ド', '' => 'ナ', '' => 'ニ', '' => 'ヌ', '' => 'ネ', '' => 'ノ', '' => 'ハ', '' => 'バ', '' => 'パ', '' => 'ヒ', '' => 'ビ', '' => 'ピ', '' => 'フ', '' => 'ブ', '' => 'プ', '' => 'ヘ', '' => 'ベ', '' => 'ペ', '' => 'ホ', '' => 'ボ', '' => 'ポ', '' => 'マ', '' => 'ミ', '' => 'ム', '' => 'メ', '' => 'モ', '' => 'ャ', '' => 'ヤ', '' => 'ュ', '' => 'ユ', '' => 'ョ', '' => 'ヨ', '' => 'ラ', '' => 'リ', '' => 'ル', '' => 'レ', '' => 'ロ', '' => 'ヮ', '' => 'ワ', '' => 'ヰ', '' => 'ヱ', '' => 'ヲ', '' => 'ン', '' => 'ヴ', '' => 'ヵ', '' => 'ヶ', 'A' => '쳾', 'B' => '쳿', 'C' => '촀', 'D' => '촂', 'E' => '촃', 'F' => '촄', 'G' => '촅', 'H' => '촆', 'I' => '촇', 'J' => '촊', 'K' => '촋', 'L' => '촍', 'M' => '촎', 'N' => '촏', 'O' => '촑', 'P' => '촒', 'Q' => '촓', 'R' => '촔', 'S' => '촕', 'T' => '촖', 'U' => '촗', 'V' => '촚', 'W' => '촜', 'X' => '촞', 'Y' => '촟', 'Z' => '촠', 'a' => '촡', 'b' => '촢', 'c' => '촣', 'd' => '촥', 'e' => '촦', 'f' => '촧', 'g' => '촩', 'h' => '촪', 'i' => '촫', 'j' => '촭', 'k' => '촮', 'l' => '촯', 'm' => '촰', 'n' => '촱', 'o' => '촲', 'p' => '촳', 'q' => '촴', 'r' => '촵', 's' => '촶', 't' => '촷', 'u' => '촸', 'v' => '촺', 'w' => '촻', 'x' => '촼', 'y' => '촽', 'z' => '촾', '' => '촿', '' => '쵀', '' => '쵁', '' => '쵂', '' => '쵃', '' => '쵄', '' => '쵅', '' => '쵆', '' => '쵇', '' => '쵈', '' => '쵉', '' => '쵊', '' => '쵋', '' => '쵌', '' => '쵍', '' => '쵎', '' => '쵏', '' => '쵐', '' => '쵑', '' => '쵒', '' => '쵓', '' => '쵔', '' => '쵕', '' => '쵖', '' => '쵗', '' => '쵘', '' => '쵙', '' => '쵚', '' => '쵛', '' => '쵝', '' => '쵞', '' => '쵟', '' => 'А', '' => 'Б', '' => 'В', '' => 'Г', '' => 'Д', '' => 'Е', '' => 'Ё', '' => 'Ж', '' => 'З', '' => 'И', '' => 'Й', '' => 'К', '' => 'Л', '' => 'М', '' => 'Н', '' => 'О', '' => 'П', '' => 'Р', '' => 'С', '' => 'Т', '' => 'У', '' => 'Ф', '' => 'Х', '' => 'Ц', '' => 'Ч', '' => 'Ш', '' => 'Щ', '' => 'Ъ', '' => 'Ы', '' => 'Ь', '' => 'Э', '' => 'Ю', '' => 'Я', '' => 'а', '' => 'б', '' => 'в', '' => 'г', '' => 'д', '' => 'е', '' => 'ё', '' => 'ж', '' => 'з', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ф', '' => 'х', '' => 'ц', '' => 'ч', '' => 'ш', '' => 'щ', '' => 'ъ', '' => 'ы', '' => 'ь', '' => 'э', '' => 'ю', '' => 'я', 'A' => '쵡', 'B' => '쵢', 'C' => '쵣', 'D' => '쵥', 'E' => '쵦', 'F' => '쵧', 'G' => '쵨', 'H' => '쵩', 'I' => '쵪', 'J' => '쵫', 'K' => '쵮', 'L' => '쵰', 'M' => '쵲', 'N' => '쵳', 'O' => '쵴', 'P' => '쵵', 'Q' => '쵶', 'R' => '쵷', 'S' => '쵹', 'T' => '쵺', 'U' => '쵻', 'V' => '쵼', 'W' => '쵽', 'X' => '쵾', 'Y' => '쵿', 'Z' => '춀', 'a' => '춁', 'b' => '춂', 'c' => '춃', 'd' => '춄', 'e' => '춅', 'f' => '춆', 'g' => '춇', 'h' => '춉', 'i' => '춊', 'j' => '춋', 'k' => '춌', 'l' => '춍', 'm' => '춎', 'n' => '춏', 'o' => '춐', 'p' => '춑', 'q' => '춒', 'r' => '춓', 's' => '춖', 't' => '춗', 'u' => '춙', 'v' => '춚', 'w' => '춛', 'x' => '춝', 'y' => '춞', 'z' => '춟', '' => '춠', '' => '춡', '' => '춢', '' => '춣', '' => '춦', '' => '춨', '' => '춪', '' => '춫', '' => '춬', '' => '춭', '' => '춮', '' => '춯', '' => '춱', '' => '춲', '' => '춳', '' => '춴', '' => '춵', '' => '춶', '' => '춷', '' => '춸', '' => '춹', '' => '춺', '' => '춻', '' => '춼', '' => '춽', '' => '춾', '' => '춿', '' => '췀', '' => '췁', '' => '췂', '' => '췃', '' => '췅', 'A' => '췆', 'B' => '췇', 'C' => '췈', 'D' => '췉', 'E' => '췊', 'F' => '췋', 'G' => '췍', 'H' => '췎', 'I' => '췏', 'J' => '췑', 'K' => '췒', 'L' => '췓', 'M' => '췔', 'N' => '췕', 'O' => '췖', 'P' => '췗', 'Q' => '췘', 'R' => '췙', 'S' => '췚', 'T' => '췛', 'U' => '췜', 'V' => '췝', 'W' => '췞', 'X' => '췟', 'Y' => '췠', 'Z' => '췡', 'a' => '췢', 'b' => '췣', 'c' => '췤', 'd' => '췥', 'e' => '췦', 'f' => '췧', 'g' => '췩', 'h' => '췪', 'i' => '췫', 'j' => '췭', 'k' => '췮', 'l' => '췯', 'm' => '췱', 'n' => '췲', 'o' => '췳', 'p' => '췴', 'q' => '췵', 'r' => '췶', 's' => '췷', 't' => '췺', 'u' => '췼', 'v' => '췾', 'w' => '췿', 'x' => '츀', 'y' => '츁', 'z' => '츂', '' => '츃', '' => '츅', '' => '츆', '' => '츇', '' => '츉', '' => '츊', '' => '츋', '' => '츍', '' => '츎', '' => '츏', '' => '츐', '' => '츑', '' => '츒', '' => '츓', '' => '츕', '' => '츖', '' => '츗', '' => '츘', '' => '츚', '' => '츛', '' => '츜', '' => '츝', '' => '츞', '' => '츟', '' => '츢', '' => '츣', '' => '츥', '' => '츦', '' => '츧', '' => '츩', '' => '츪', '' => '츫', 'A' => '츬', 'B' => '츭', 'C' => '츮', 'D' => '츯', 'E' => '츲', 'F' => '츴', 'G' => '츶', 'H' => '츷', 'I' => '츸', 'J' => '츹', 'K' => '츺', 'L' => '츻', 'M' => '츼', 'N' => '츽', 'O' => '츾', 'P' => '츿', 'Q' => '칀', 'R' => '칁', 'S' => '칂', 'T' => '칃', 'U' => '칄', 'V' => '칅', 'W' => '칆', 'X' => '칇', 'Y' => '칈', 'Z' => '칉', 'a' => '칊', 'b' => '칋', 'c' => '칌', 'd' => '칍', 'e' => '칎', 'f' => '칏', 'g' => '칐', 'h' => '칑', 'i' => '칒', 'j' => '칓', 'k' => '칔', 'l' => '칕', 'm' => '칖', 'n' => '칗', 'o' => '칚', 'p' => '칛', 'q' => '칝', 'r' => '칞', 's' => '칢', 't' => '칣', 'u' => '칤', 'v' => '칥', 'w' => '칦', 'x' => '칧', 'y' => '칪', 'z' => '칬', '' => '칮', '' => '칯', '' => '칰', '' => '칱', '' => '칲', '' => '칳', '' => '칶', '' => '칷', '' => '칹', '' => '칺', '' => '칻', '' => '칽', '' => '칾', '' => '칿', '' => '캀', '' => '캁', '' => '캂', '' => '캃', '' => '캆', '' => '캈', '' => '캊', '' => '캋', '' => '캌', '' => '캍', '' => '캎', '' => '캏', '' => '캒', '' => '캓', '' => '캕', '' => '캖', '' => '캗', '' => '캙', 'A' => '캚', 'B' => '캛', 'C' => '캜', 'D' => '캝', 'E' => '캞', 'F' => '캟', 'G' => '캢', 'H' => '캦', 'I' => '캧', 'J' => '캨', 'K' => '캩', 'L' => '캪', 'M' => '캫', 'N' => '캮', 'O' => '캯', 'P' => '캰', 'Q' => '캱', 'R' => '캲', 'S' => '캳', 'T' => '캴', 'U' => '캵', 'V' => '캶', 'W' => '캷', 'X' => '캸', 'Y' => '캹', 'Z' => '캺', 'a' => '캻', 'b' => '캼', 'c' => '캽', 'd' => '캾', 'e' => '캿', 'f' => '컀', 'g' => '컂', 'h' => '컃', 'i' => '컄', 'j' => '컅', 'k' => '컆', 'l' => '컇', 'm' => '컈', 'n' => '컉', 'o' => '컊', 'p' => '컋', 'q' => '컌', 'r' => '컍', 's' => '컎', 't' => '컏', 'u' => '컐', 'v' => '컑', 'w' => '컒', 'x' => '컓', 'y' => '컔', 'z' => '컕', '' => '컖', '' => '컗', '' => '컘', '' => '컙', '' => '컚', '' => '컛', '' => '컜', '' => '컝', '' => '컞', '' => '컟', '' => '컠', '' => '컡', '' => '컢', '' => '컣', '' => '컦', '' => '컧', '' => '컩', '' => '컪', '' => '컭', '' => '컮', '' => '컯', '' => '컰', '' => '컱', '' => '컲', '' => '컳', '' => '컶', '' => '컺', '' => '컻', '' => '컼', '' => '컽', '' => '컾', '' => '컿', '' => '가', '' => '각', '' => '간', '' => '갇', '' => '갈', '' => '갉', '' => '갊', '' => '감', '' => '갑', '' => '값', '' => '갓', '' => '갔', '' => '강', '' => '갖', '' => '갗', '' => '같', '' => '갚', '' => '갛', '' => '개', '' => '객', '' => '갠', '' => '갤', '' => '갬', '' => '갭', '' => '갯', '' => '갰', '' => '갱', '' => '갸', '' => '갹', '' => '갼', '' => '걀', '' => '걋', '' => '걍', '' => '걔', '' => '걘', '' => '걜', '' => '거', '' => '걱', '' => '건', '' => '걷', '' => '걸', '' => '걺', '' => '검', '' => '겁', '' => '것', '' => '겄', '' => '겅', '' => '겆', '' => '겉', '' => '겊', '' => '겋', '' => '게', '' => '겐', '' => '겔', '' => '겜', '' => '겝', '' => '겟', '' => '겠', '' => '겡', '' => '겨', '' => '격', '' => '겪', '' => '견', '' => '겯', '' => '결', '' => '겸', '' => '겹', '' => '겻', '' => '겼', '' => '경', '' => '곁', '' => '계', '' => '곈', '' => '곌', '' => '곕', '' => '곗', '' => '고', '' => '곡', '' => '곤', '' => '곧', '' => '골', '' => '곪', '' => '곬', '' => '곯', '' => '곰', '' => '곱', '' => '곳', '' => '공', '' => '곶', '' => '과', '' => '곽', '' => '관', '' => '괄', '' => '괆', 'A' => '켂', 'B' => '켃', 'C' => '켅', 'D' => '켆', 'E' => '켇', 'F' => '켉', 'G' => '켊', 'H' => '켋', 'I' => '켌', 'J' => '켍', 'K' => '켎', 'L' => '켏', 'M' => '켒', 'N' => '켔', 'O' => '켖', 'P' => '켗', 'Q' => '켘', 'R' => '켙', 'S' => '켚', 'T' => '켛', 'U' => '켝', 'V' => '켞', 'W' => '켟', 'X' => '켡', 'Y' => '켢', 'Z' => '켣', 'a' => '켥', 'b' => '켦', 'c' => '켧', 'd' => '켨', 'e' => '켩', 'f' => '켪', 'g' => '켫', 'h' => '켮', 'i' => '켲', 'j' => '켳', 'k' => '켴', 'l' => '켵', 'm' => '켶', 'n' => '켷', 'o' => '켹', 'p' => '켺', 'q' => '켻', 'r' => '켼', 's' => '켽', 't' => '켾', 'u' => '켿', 'v' => '콀', 'w' => '콁', 'x' => '콂', 'y' => '콃', 'z' => '콄', '' => '콅', '' => '콆', '' => '콇', '' => '콈', '' => '콉', '' => '콊', '' => '콋', '' => '콌', '' => '콍', '' => '콎', '' => '콏', '' => '콐', '' => '콑', '' => '콒', '' => '콓', '' => '콖', '' => '콗', '' => '콙', '' => '콚', '' => '콛', '' => '콝', '' => '콞', '' => '콟', '' => '콠', '' => '콡', '' => '콢', '' => '콣', '' => '콦', '' => '콨', '' => '콪', '' => '콫', '' => '콬', '' => '괌', '' => '괍', '' => '괏', '' => '광', '' => '괘', '' => '괜', '' => '괠', '' => '괩', '' => '괬', '' => '괭', '' => '괴', '' => '괵', '' => '괸', '' => '괼', '' => '굄', '' => '굅', '' => '굇', '' => '굉', '' => '교', '' => '굔', '' => '굘', '' => '굡', '' => '굣', '' => '구', '' => '국', '' => '군', '' => '굳', '' => '굴', '' => '굵', '' => '굶', '' => '굻', '' => '굼', '' => '굽', '' => '굿', '' => '궁', '' => '궂', '' => '궈', '' => '궉', '' => '권', '' => '궐', '' => '궜', '' => '궝', '' => '궤', '' => '궷', '' => '귀', '' => '귁', '' => '귄', '' => '귈', '' => '귐', '' => '귑', '' => '귓', '' => '규', '' => '균', '' => '귤', '' => '그', '' => '극', '' => '근', '' => '귿', '' => '글', '' => '긁', '' => '금', '' => '급', '' => '긋', '' => '긍', '' => '긔', '' => '기', '' => '긱', '' => '긴', '' => '긷', '' => '길', '' => '긺', '' => '김', '' => '깁', '' => '깃', '' => '깅', '' => '깆', '' => '깊', '' => '까', '' => '깍', '' => '깎', '' => '깐', '' => '깔', '' => '깖', '' => '깜', '' => '깝', '' => '깟', '' => '깠', '' => '깡', '' => '깥', '' => '깨', '' => '깩', '' => '깬', '' => '깰', '' => '깸', 'A' => '콭', 'B' => '콮', 'C' => '콯', 'D' => '콲', 'E' => '콳', 'F' => '콵', 'G' => '콶', 'H' => '콷', 'I' => '콹', 'J' => '콺', 'K' => '콻', 'L' => '콼', 'M' => '콽', 'N' => '콾', 'O' => '콿', 'P' => '쾁', 'Q' => '쾂', 'R' => '쾃', 'S' => '쾄', 'T' => '쾆', 'U' => '쾇', 'V' => '쾈', 'W' => '쾉', 'X' => '쾊', 'Y' => '쾋', 'Z' => '쾍', 'a' => '쾎', 'b' => '쾏', 'c' => '쾐', 'd' => '쾑', 'e' => '쾒', 'f' => '쾓', 'g' => '쾔', 'h' => '쾕', 'i' => '쾖', 'j' => '쾗', 'k' => '쾘', 'l' => '쾙', 'm' => '쾚', 'n' => '쾛', 'o' => '쾜', 'p' => '쾝', 'q' => '쾞', 'r' => '쾟', 's' => '쾠', 't' => '쾢', 'u' => '쾣', 'v' => '쾤', 'w' => '쾥', 'x' => '쾦', 'y' => '쾧', 'z' => '쾩', '' => '쾪', '' => '쾫', '' => '쾬', '' => '쾭', '' => '쾮', '' => '쾯', '' => '쾱', '' => '쾲', '' => '쾳', '' => '쾴', '' => '쾵', '' => '쾶', '' => '쾷', '' => '쾸', '' => '쾹', '' => '쾺', '' => '쾻', '' => '쾼', '' => '쾽', '' => '쾾', '' => '쾿', '' => '쿀', '' => '쿁', '' => '쿂', '' => '쿃', '' => '쿅', '' => '쿆', '' => '쿇', '' => '쿈', '' => '쿉', '' => '쿊', '' => '쿋', '' => '깹', '' => '깻', '' => '깼', '' => '깽', '' => '꺄', '' => '꺅', '' => '꺌', '' => '꺼', '' => '꺽', '' => '꺾', '' => '껀', '' => '껄', '' => '껌', '' => '껍', '' => '껏', '' => '껐', '' => '껑', '' => '께', '' => '껙', '' => '껜', '' => '껨', '' => '껫', '' => '껭', '' => '껴', '' => '껸', '' => '껼', '' => '꼇', '' => '꼈', '' => '꼍', '' => '꼐', '' => '꼬', '' => '꼭', '' => '꼰', '' => '꼲', '' => '꼴', '' => '꼼', '' => '꼽', '' => '꼿', '' => '꽁', '' => '꽂', '' => '꽃', '' => '꽈', '' => '꽉', '' => '꽐', '' => '꽜', '' => '꽝', '' => '꽤', '' => '꽥', '' => '꽹', '' => '꾀', '' => '꾄', '' => '꾈', '' => '꾐', '' => '꾑', '' => '꾕', '' => '꾜', '' => '꾸', '' => '꾹', '' => '꾼', '' => '꿀', '' => '꿇', '' => '꿈', '' => '꿉', '' => '꿋', '' => '꿍', '' => '꿎', '' => '꿔', '' => '꿜', '' => '꿨', '' => '꿩', '' => '꿰', '' => '꿱', '' => '꿴', '' => '꿸', '' => '뀀', '' => '뀁', '' => '뀄', '' => '뀌', '' => '뀐', '' => '뀔', '' => '뀜', '' => '뀝', '' => '뀨', '' => '끄', '' => '끅', '' => '끈', '' => '끊', '' => '끌', '' => '끎', '' => '끓', '' => '끔', '' => '끕', '' => '끗', '' => '끙', 'A' => '쿌', 'B' => '쿍', 'C' => '쿎', 'D' => '쿏', 'E' => '쿐', 'F' => '쿑', 'G' => '쿒', 'H' => '쿓', 'I' => '쿔', 'J' => '쿕', 'K' => '쿖', 'L' => '쿗', 'M' => '쿘', 'N' => '쿙', 'O' => '쿚', 'P' => '쿛', 'Q' => '쿜', 'R' => '쿝', 'S' => '쿞', 'T' => '쿟', 'U' => '쿢', 'V' => '쿣', 'W' => '쿥', 'X' => '쿦', 'Y' => '쿧', 'Z' => '쿩', 'a' => '쿪', 'b' => '쿫', 'c' => '쿬', 'd' => '쿭', 'e' => '쿮', 'f' => '쿯', 'g' => '쿲', 'h' => '쿴', 'i' => '쿶', 'j' => '쿷', 'k' => '쿸', 'l' => '쿹', 'm' => '쿺', 'n' => '쿻', 'o' => '쿽', 'p' => '쿾', 'q' => '쿿', 'r' => '퀁', 's' => '퀂', 't' => '퀃', 'u' => '퀅', 'v' => '퀆', 'w' => '퀇', 'x' => '퀈', 'y' => '퀉', 'z' => '퀊', '' => '퀋', '' => '퀌', '' => '퀍', '' => '퀎', '' => '퀏', '' => '퀐', '' => '퀒', '' => '퀓', '' => '퀔', '' => '퀕', '' => '퀖', '' => '퀗', '' => '퀙', '' => '퀚', '' => '퀛', '' => '퀜', '' => '퀝', '' => '퀞', '' => '퀟', '' => '퀠', '' => '퀡', '' => '퀢', '' => '퀣', '' => '퀤', '' => '퀥', '' => '퀦', '' => '퀧', '' => '퀨', '' => '퀩', '' => '퀪', '' => '퀫', '' => '퀬', '' => '끝', '' => '끼', '' => '끽', '' => '낀', '' => '낄', '' => '낌', '' => '낍', '' => '낏', '' => '낑', '' => '나', '' => '낙', '' => '낚', '' => '난', '' => '낟', '' => '날', '' => '낡', '' => '낢', '' => '남', '' => '납', '' => '낫', '' => '났', '' => '낭', '' => '낮', '' => '낯', '' => '낱', '' => '낳', '' => '내', '' => '낵', '' => '낸', '' => '낼', '' => '냄', '' => '냅', '' => '냇', '' => '냈', '' => '냉', '' => '냐', '' => '냑', '' => '냔', '' => '냘', '' => '냠', '' => '냥', '' => '너', '' => '넉', '' => '넋', '' => '넌', '' => '널', '' => '넒', '' => '넓', '' => '넘', '' => '넙', '' => '넛', '' => '넜', '' => '넝', '' => '넣', '' => '네', '' => '넥', '' => '넨', '' => '넬', '' => '넴', '' => '넵', '' => '넷', '' => '넸', '' => '넹', '' => '녀', '' => '녁', '' => '년', '' => '녈', '' => '념', '' => '녑', '' => '녔', '' => '녕', '' => '녘', '' => '녜', '' => '녠', '' => '노', '' => '녹', '' => '논', '' => '놀', '' => '놂', '' => '놈', '' => '놉', '' => '놋', '' => '농', '' => '높', '' => '놓', '' => '놔', '' => '놘', '' => '놜', '' => '놨', '' => '뇌', '' => '뇐', '' => '뇔', '' => '뇜', '' => '뇝', 'A' => '퀮', 'B' => '퀯', 'C' => '퀰', 'D' => '퀱', 'E' => '퀲', 'F' => '퀳', 'G' => '퀶', 'H' => '퀷', 'I' => '퀹', 'J' => '퀺', 'K' => '퀻', 'L' => '퀽', 'M' => '퀾', 'N' => '퀿', 'O' => '큀', 'P' => '큁', 'Q' => '큂', 'R' => '큃', 'S' => '큆', 'T' => '큈', 'U' => '큊', 'V' => '큋', 'W' => '큌', 'X' => '큍', 'Y' => '큎', 'Z' => '큏', 'a' => '큑', 'b' => '큒', 'c' => '큓', 'd' => '큕', 'e' => '큖', 'f' => '큗', 'g' => '큙', 'h' => '큚', 'i' => '큛', 'j' => '큜', 'k' => '큝', 'l' => '큞', 'm' => '큟', 'n' => '큡', 'o' => '큢', 'p' => '큣', 'q' => '큤', 'r' => '큥', 's' => '큦', 't' => '큧', 'u' => '큨', 'v' => '큩', 'w' => '큪', 'x' => '큫', 'y' => '큮', 'z' => '큯', '' => '큱', '' => '큲', '' => '큳', '' => '큵', '' => '큶', '' => '큷', '' => '큸', '' => '큹', '' => '큺', '' => '큻', '' => '큾', '' => '큿', '' => '킀', '' => '킂', '' => '킃', '' => '킄', '' => '킅', '' => '킆', '' => '킇', '' => '킈', '' => '킉', '' => '킊', '' => '킋', '' => '킌', '' => '킍', '' => '킎', '' => '킏', '' => '킐', '' => '킑', '' => '킒', '' => '킓', '' => '킔', '' => '뇟', '' => '뇨', '' => '뇩', '' => '뇬', '' => '뇰', '' => '뇹', '' => '뇻', '' => '뇽', '' => '누', '' => '눅', '' => '눈', '' => '눋', '' => '눌', '' => '눔', '' => '눕', '' => '눗', '' => '눙', '' => '눠', '' => '눴', '' => '눼', '' => '뉘', '' => '뉜', '' => '뉠', '' => '뉨', '' => '뉩', '' => '뉴', '' => '뉵', '' => '뉼', '' => '늄', '' => '늅', '' => '늉', '' => '느', '' => '늑', '' => '는', '' => '늘', '' => '늙', '' => '늚', '' => '늠', '' => '늡', '' => '늣', '' => '능', '' => '늦', '' => '늪', '' => '늬', '' => '늰', '' => '늴', '' => '니', '' => '닉', '' => '닌', '' => '닐', '' => '닒', '' => '님', '' => '닙', '' => '닛', '' => '닝', '' => '닢', '' => '다', '' => '닥', '' => '닦', '' => '단', '' => '닫', '' => '달', '' => '닭', '' => '닮', '' => '닯', '' => '닳', '' => '담', '' => '답', '' => '닷', '' => '닸', '' => '당', '' => '닺', '' => '닻', '' => '닿', '' => '대', '' => '댁', '' => '댄', '' => '댈', '' => '댐', '' => '댑', '' => '댓', '' => '댔', '' => '댕', '' => '댜', '' => '더', '' => '덕', '' => '덖', '' => '던', '' => '덛', '' => '덜', '' => '덞', '' => '덟', '' => '덤', '' => '덥', 'A' => '킕', 'B' => '킖', 'C' => '킗', 'D' => '킘', 'E' => '킙', 'F' => '킚', 'G' => '킛', 'H' => '킜', 'I' => '킝', 'J' => '킞', 'K' => '킟', 'L' => '킠', 'M' => '킡', 'N' => '킢', 'O' => '킣', 'P' => '킦', 'Q' => '킧', 'R' => '킩', 'S' => '킪', 'T' => '킫', 'U' => '킭', 'V' => '킮', 'W' => '킯', 'X' => '킰', 'Y' => '킱', 'Z' => '킲', 'a' => '킳', 'b' => '킶', 'c' => '킸', 'd' => '킺', 'e' => '킻', 'f' => '킼', 'g' => '킽', 'h' => '킾', 'i' => '킿', 'j' => '탂', 'k' => '탃', 'l' => '탅', 'm' => '탆', 'n' => '탇', 'o' => '탊', 'p' => '탋', 'q' => '탌', 'r' => '탍', 's' => '탎', 't' => '탏', 'u' => '탒', 'v' => '탖', 'w' => '탗', 'x' => '탘', 'y' => '탙', 'z' => '탚', '' => '탛', '' => '탞', '' => '탟', '' => '탡', '' => '탢', '' => '탣', '' => '탥', '' => '탦', '' => '탧', '' => '탨', '' => '탩', '' => '탪', '' => '탫', '' => '탮', '' => '탲', '' => '탳', '' => '탴', '' => '탵', '' => '탶', '' => '탷', '' => '탹', '' => '탺', '' => '탻', '' => '탼', '' => '탽', '' => '탾', '' => '탿', '' => '턀', '' => '턁', '' => '턂', '' => '턃', '' => '턄', '' => '덧', '' => '덩', '' => '덫', '' => '덮', '' => '데', '' => '덱', '' => '덴', '' => '델', '' => '뎀', '' => '뎁', '' => '뎃', '' => '뎄', '' => '뎅', '' => '뎌', '' => '뎐', '' => '뎔', '' => '뎠', '' => '뎡', '' => '뎨', '' => '뎬', '' => '도', '' => '독', '' => '돈', '' => '돋', '' => '돌', '' => '돎', '' => '돐', '' => '돔', '' => '돕', '' => '돗', '' => '동', '' => '돛', '' => '돝', '' => '돠', '' => '돤', '' => '돨', '' => '돼', '' => '됐', '' => '되', '' => '된', '' => '될', '' => '됨', '' => '됩', '' => '됫', '' => '됴', '' => '두', '' => '둑', '' => '둔', '' => '둘', '' => '둠', '' => '둡', '' => '둣', '' => '둥', '' => '둬', '' => '뒀', '' => '뒈', '' => '뒝', '' => '뒤', '' => '뒨', '' => '뒬', '' => '뒵', '' => '뒷', '' => '뒹', '' => '듀', '' => '듄', '' => '듈', '' => '듐', '' => '듕', '' => '드', '' => '득', '' => '든', '' => '듣', '' => '들', '' => '듦', '' => '듬', '' => '듭', '' => '듯', '' => '등', '' => '듸', '' => '디', '' => '딕', '' => '딘', '' => '딛', '' => '딜', '' => '딤', '' => '딥', '' => '딧', '' => '딨', '' => '딩', '' => '딪', '' => '따', '' => '딱', '' => '딴', '' => '딸', 'A' => '턅', 'B' => '턆', 'C' => '턇', 'D' => '턈', 'E' => '턉', 'F' => '턊', 'G' => '턋', 'H' => '턌', 'I' => '턎', 'J' => '턏', 'K' => '턐', 'L' => '턑', 'M' => '턒', 'N' => '턓', 'O' => '턔', 'P' => '턕', 'Q' => '턖', 'R' => '턗', 'S' => '턘', 'T' => '턙', 'U' => '턚', 'V' => '턛', 'W' => '턜', 'X' => '턝', 'Y' => '턞', 'Z' => '턟', 'a' => '턠', 'b' => '턡', 'c' => '턢', 'd' => '턣', 'e' => '턤', 'f' => '턥', 'g' => '턦', 'h' => '턧', 'i' => '턨', 'j' => '턩', 'k' => '턪', 'l' => '턫', 'm' => '턬', 'n' => '턭', 'o' => '턮', 'p' => '턯', 'q' => '턲', 'r' => '턳', 's' => '턵', 't' => '턶', 'u' => '턷', 'v' => '턹', 'w' => '턻', 'x' => '턼', 'y' => '턽', 'z' => '턾', '' => '턿', '' => '텂', '' => '텆', '' => '텇', '' => '텈', '' => '텉', '' => '텊', '' => '텋', '' => '텎', '' => '텏', '' => '텑', '' => '텒', '' => '텓', '' => '텕', '' => '텖', '' => '텗', '' => '텘', '' => '텙', '' => '텚', '' => '텛', '' => '텞', '' => '텠', '' => '텢', '' => '텣', '' => '텤', '' => '텥', '' => '텦', '' => '텧', '' => '텩', '' => '텪', '' => '텫', '' => '텭', '' => '땀', '' => '땁', '' => '땃', '' => '땄', '' => '땅', '' => '땋', '' => '때', '' => '땍', '' => '땐', '' => '땔', '' => '땜', '' => '땝', '' => '땟', '' => '땠', '' => '땡', '' => '떠', '' => '떡', '' => '떤', '' => '떨', '' => '떪', '' => '떫', '' => '떰', '' => '떱', '' => '떳', '' => '떴', '' => '떵', '' => '떻', '' => '떼', '' => '떽', '' => '뗀', '' => '뗄', '' => '뗌', '' => '뗍', '' => '뗏', '' => '뗐', '' => '뗑', '' => '뗘', '' => '뗬', '' => '또', '' => '똑', '' => '똔', '' => '똘', '' => '똥', '' => '똬', '' => '똴', '' => '뙈', '' => '뙤', '' => '뙨', '' => '뚜', '' => '뚝', '' => '뚠', '' => '뚤', '' => '뚫', '' => '뚬', '' => '뚱', '' => '뛔', '' => '뛰', '' => '뛴', '' => '뛸', '' => '뜀', '' => '뜁', '' => '뜅', '' => '뜨', '' => '뜩', '' => '뜬', '' => '뜯', '' => '뜰', '' => '뜸', '' => '뜹', '' => '뜻', '' => '띄', '' => '띈', '' => '띌', '' => '띔', '' => '띕', '' => '띠', '' => '띤', '' => '띨', '' => '띰', '' => '띱', '' => '띳', '' => '띵', '' => '라', '' => '락', '' => '란', '' => '랄', '' => '람', '' => '랍', '' => '랏', '' => '랐', '' => '랑', '' => '랒', '' => '랖', '' => '랗', 'A' => '텮', 'B' => '텯', 'C' => '텰', 'D' => '텱', 'E' => '텲', 'F' => '텳', 'G' => '텴', 'H' => '텵', 'I' => '텶', 'J' => '텷', 'K' => '텸', 'L' => '텹', 'M' => '텺', 'N' => '텻', 'O' => '텽', 'P' => '텾', 'Q' => '텿', 'R' => '톀', 'S' => '톁', 'T' => '톂', 'U' => '톃', 'V' => '톅', 'W' => '톆', 'X' => '톇', 'Y' => '톉', 'Z' => '톊', 'a' => '톋', 'b' => '톌', 'c' => '톍', 'd' => '톎', 'e' => '톏', 'f' => '톐', 'g' => '톑', 'h' => '톒', 'i' => '톓', 'j' => '톔', 'k' => '톕', 'l' => '톖', 'm' => '톗', 'n' => '톘', 'o' => '톙', 'p' => '톚', 'q' => '톛', 'r' => '톜', 's' => '톝', 't' => '톞', 'u' => '톟', 'v' => '톢', 'w' => '톣', 'x' => '톥', 'y' => '톦', 'z' => '톧', '' => '톩', '' => '톪', '' => '톫', '' => '톬', '' => '톭', '' => '톮', '' => '톯', '' => '톲', '' => '톴', '' => '톶', '' => '톷', '' => '톸', '' => '톹', '' => '톻', '' => '톽', '' => '톾', '' => '톿', '' => '퇁', '' => '퇂', '' => '퇃', '' => '퇄', '' => '퇅', '' => '퇆', '' => '퇇', '' => '퇈', '' => '퇉', '' => '퇊', '' => '퇋', '' => '퇌', '' => '퇍', '' => '퇎', '' => '퇏', '' => '래', '' => '랙', '' => '랜', '' => '랠', '' => '램', '' => '랩', '' => '랫', '' => '랬', '' => '랭', '' => '랴', '' => '략', '' => '랸', '' => '럇', '' => '량', '' => '러', '' => '럭', '' => '런', '' => '럴', '' => '럼', '' => '럽', '' => '럿', '' => '렀', '' => '렁', '' => '렇', '' => '레', '' => '렉', '' => '렌', '' => '렐', '' => '렘', '' => '렙', '' => '렛', '' => '렝', '' => '려', '' => '력', '' => '련', '' => '렬', '' => '렴', '' => '렵', '' => '렷', '' => '렸', '' => '령', '' => '례', '' => '롄', '' => '롑', '' => '롓', '' => '로', '' => '록', '' => '론', '' => '롤', '' => '롬', '' => '롭', '' => '롯', '' => '롱', '' => '롸', '' => '롼', '' => '뢍', '' => '뢨', '' => '뢰', '' => '뢴', '' => '뢸', '' => '룀', '' => '룁', '' => '룃', '' => '룅', '' => '료', '' => '룐', '' => '룔', '' => '룝', '' => '룟', '' => '룡', '' => '루', '' => '룩', '' => '룬', '' => '룰', '' => '룸', '' => '룹', '' => '룻', '' => '룽', '' => '뤄', '' => '뤘', '' => '뤠', '' => '뤼', '' => '뤽', '' => '륀', '' => '륄', '' => '륌', '' => '륏', '' => '륑', '' => '류', '' => '륙', '' => '륜', '' => '률', '' => '륨', '' => '륩', 'A' => '퇐', 'B' => '퇑', 'C' => '퇒', 'D' => '퇓', 'E' => '퇔', 'F' => '퇕', 'G' => '퇖', 'H' => '퇗', 'I' => '퇙', 'J' => '퇚', 'K' => '퇛', 'L' => '퇜', 'M' => '퇝', 'N' => '퇞', 'O' => '퇟', 'P' => '퇠', 'Q' => '퇡', 'R' => '퇢', 'S' => '퇣', 'T' => '퇤', 'U' => '퇥', 'V' => '퇦', 'W' => '퇧', 'X' => '퇨', 'Y' => '퇩', 'Z' => '퇪', 'a' => '퇫', 'b' => '퇬', 'c' => '퇭', 'd' => '퇮', 'e' => '퇯', 'f' => '퇰', 'g' => '퇱', 'h' => '퇲', 'i' => '퇳', 'j' => '퇵', 'k' => '퇶', 'l' => '퇷', 'm' => '퇹', 'n' => '퇺', 'o' => '퇻', 'p' => '퇼', 'q' => '퇽', 'r' => '퇾', 's' => '퇿', 't' => '툀', 'u' => '툁', 'v' => '툂', 'w' => '툃', 'x' => '툄', 'y' => '툅', 'z' => '툆', '' => '툈', '' => '툊', '' => '툋', '' => '툌', '' => '툍', '' => '툎', '' => '툏', '' => '툑', '' => '툒', '' => '툓', '' => '툔', '' => '툕', '' => '툖', '' => '툗', '' => '툘', '' => '툙', '' => '툚', '' => '툛', '' => '툜', '' => '툝', '' => '툞', '' => '툟', '' => '툠', '' => '툡', '' => '툢', '' => '툣', '' => '툤', '' => '툥', '' => '툦', '' => '툧', '' => '툨', '' => '툩', '' => '륫', '' => '륭', '' => '르', '' => '륵', '' => '른', '' => '를', '' => '름', '' => '릅', '' => '릇', '' => '릉', '' => '릊', '' => '릍', '' => '릎', '' => '리', '' => '릭', '' => '린', '' => '릴', '' => '림', '' => '립', '' => '릿', '' => '링', '' => '마', '' => '막', '' => '만', '' => '많', '' => '맏', '' => '말', '' => '맑', '' => '맒', '' => '맘', '' => '맙', '' => '맛', '' => '망', '' => '맞', '' => '맡', '' => '맣', '' => '매', '' => '맥', '' => '맨', '' => '맬', '' => '맴', '' => '맵', '' => '맷', '' => '맸', '' => '맹', '' => '맺', '' => '먀', '' => '먁', '' => '먈', '' => '먕', '' => '머', '' => '먹', '' => '먼', '' => '멀', '' => '멂', '' => '멈', '' => '멉', '' => '멋', '' => '멍', '' => '멎', '' => '멓', '' => '메', '' => '멕', '' => '멘', '' => '멜', '' => '멤', '' => '멥', '' => '멧', '' => '멨', '' => '멩', '' => '며', '' => '멱', '' => '면', '' => '멸', '' => '몃', '' => '몄', '' => '명', '' => '몇', '' => '몌', '' => '모', '' => '목', '' => '몫', '' => '몬', '' => '몰', '' => '몲', '' => '몸', '' => '몹', '' => '못', '' => '몽', '' => '뫄', '' => '뫈', '' => '뫘', '' => '뫙', '' => '뫼', 'A' => '툪', 'B' => '툫', 'C' => '툮', 'D' => '툯', 'E' => '툱', 'F' => '툲', 'G' => '툳', 'H' => '툵', 'I' => '툶', 'J' => '툷', 'K' => '툸', 'L' => '툹', 'M' => '툺', 'N' => '툻', 'O' => '툾', 'P' => '퉀', 'Q' => '퉂', 'R' => '퉃', 'S' => '퉄', 'T' => '퉅', 'U' => '퉆', 'V' => '퉇', 'W' => '퉉', 'X' => '퉊', 'Y' => '퉋', 'Z' => '퉌', 'a' => '퉍', 'b' => '퉎', 'c' => '퉏', 'd' => '퉐', 'e' => '퉑', 'f' => '퉒', 'g' => '퉓', 'h' => '퉔', 'i' => '퉕', 'j' => '퉖', 'k' => '퉗', 'l' => '퉘', 'm' => '퉙', 'n' => '퉚', 'o' => '퉛', 'p' => '퉝', 'q' => '퉞', 'r' => '퉟', 's' => '퉠', 't' => '퉡', 'u' => '퉢', 'v' => '퉣', 'w' => '퉥', 'x' => '퉦', 'y' => '퉧', 'z' => '퉨', '' => '퉩', '' => '퉪', '' => '퉫', '' => '퉬', '' => '퉭', '' => '퉮', '' => '퉯', '' => '퉰', '' => '퉱', '' => '퉲', '' => '퉳', '' => '퉴', '' => '퉵', '' => '퉶', '' => '퉷', '' => '퉸', '' => '퉹', '' => '퉺', '' => '퉻', '' => '퉼', '' => '퉽', '' => '퉾', '' => '퉿', '' => '튂', '' => '튃', '' => '튅', '' => '튆', '' => '튇', '' => '튉', '' => '튊', '' => '튋', '' => '튌', '' => '묀', '' => '묄', '' => '묍', '' => '묏', '' => '묑', '' => '묘', '' => '묜', '' => '묠', '' => '묩', '' => '묫', '' => '무', '' => '묵', '' => '묶', '' => '문', '' => '묻', '' => '물', '' => '묽', '' => '묾', '' => '뭄', '' => '뭅', '' => '뭇', '' => '뭉', '' => '뭍', '' => '뭏', '' => '뭐', '' => '뭔', '' => '뭘', '' => '뭡', '' => '뭣', '' => '뭬', '' => '뮈', '' => '뮌', '' => '뮐', '' => '뮤', '' => '뮨', '' => '뮬', '' => '뮴', '' => '뮷', '' => '므', '' => '믄', '' => '믈', '' => '믐', '' => '믓', '' => '미', '' => '믹', '' => '민', '' => '믿', '' => '밀', '' => '밂', '' => '밈', '' => '밉', '' => '밋', '' => '밌', '' => '밍', '' => '및', '' => '밑', '' => '바', '' => '박', '' => '밖', '' => '밗', '' => '반', '' => '받', '' => '발', '' => '밝', '' => '밞', '' => '밟', '' => '밤', '' => '밥', '' => '밧', '' => '방', '' => '밭', '' => '배', '' => '백', '' => '밴', '' => '밸', '' => '뱀', '' => '뱁', '' => '뱃', '' => '뱄', '' => '뱅', '' => '뱉', '' => '뱌', '' => '뱍', '' => '뱐', '' => '뱝', '' => '버', '' => '벅', '' => '번', '' => '벋', '' => '벌', '' => '벎', '' => '범', '' => '법', '' => '벗', 'A' => '튍', 'B' => '튎', 'C' => '튏', 'D' => '튒', 'E' => '튓', 'F' => '튔', 'G' => '튖', 'H' => '튗', 'I' => '튘', 'J' => '튙', 'K' => '튚', 'L' => '튛', 'M' => '튝', 'N' => '튞', 'O' => '튟', 'P' => '튡', 'Q' => '튢', 'R' => '튣', 'S' => '튥', 'T' => '튦', 'U' => '튧', 'V' => '튨', 'W' => '튩', 'X' => '튪', 'Y' => '튫', 'Z' => '튭', 'a' => '튮', 'b' => '튯', 'c' => '튰', 'd' => '튲', 'e' => '튳', 'f' => '튴', 'g' => '튵', 'h' => '튶', 'i' => '튷', 'j' => '튺', 'k' => '튻', 'l' => '튽', 'm' => '튾', 'n' => '틁', 'o' => '틃', 'p' => '틄', 'q' => '틅', 'r' => '틆', 's' => '틇', 't' => '틊', 'u' => '틌', 'v' => '틍', 'w' => '틎', 'x' => '틏', 'y' => '틐', 'z' => '틑', '' => '틒', '' => '틓', '' => '틕', '' => '틖', '' => '틗', '' => '틙', '' => '틚', '' => '틛', '' => '틝', '' => '틞', '' => '틟', '' => '틠', '' => '틡', '' => '틢', '' => '틣', '' => '틦', '' => '틧', '' => '틨', '' => '틩', '' => '틪', '' => '틫', '' => '틬', '' => '틭', '' => '틮', '' => '틯', '' => '틲', '' => '틳', '' => '틵', '' => '틶', '' => '틷', '' => '틹', '' => '틺', '' => '벙', '' => '벚', '' => '베', '' => '벡', '' => '벤', '' => '벧', '' => '벨', '' => '벰', '' => '벱', '' => '벳', '' => '벴', '' => '벵', '' => '벼', '' => '벽', '' => '변', '' => '별', '' => '볍', '' => '볏', '' => '볐', '' => '병', '' => '볕', '' => '볘', '' => '볜', '' => '보', '' => '복', '' => '볶', '' => '본', '' => '볼', '' => '봄', '' => '봅', '' => '봇', '' => '봉', '' => '봐', '' => '봔', '' => '봤', '' => '봬', '' => '뵀', '' => '뵈', '' => '뵉', '' => '뵌', '' => '뵐', '' => '뵘', '' => '뵙', '' => '뵤', '' => '뵨', '' => '부', '' => '북', '' => '분', '' => '붇', '' => '불', '' => '붉', '' => '붊', '' => '붐', '' => '붑', '' => '붓', '' => '붕', '' => '붙', '' => '붚', '' => '붜', '' => '붤', '' => '붰', '' => '붸', '' => '뷔', '' => '뷕', '' => '뷘', '' => '뷜', '' => '뷩', '' => '뷰', '' => '뷴', '' => '뷸', '' => '븀', '' => '븃', '' => '븅', '' => '브', '' => '븍', '' => '븐', '' => '블', '' => '븜', '' => '븝', '' => '븟', '' => '비', '' => '빅', '' => '빈', '' => '빌', '' => '빎', '' => '빔', '' => '빕', '' => '빗', '' => '빙', '' => '빚', '' => '빛', '' => '빠', '' => '빡', '' => '빤', 'A' => '틻', 'B' => '틼', 'C' => '틽', 'D' => '틾', 'E' => '틿', 'F' => '팂', 'G' => '팄', 'H' => '팆', 'I' => '팇', 'J' => '팈', 'K' => '팉', 'L' => '팊', 'M' => '팋', 'N' => '팏', 'O' => '팑', 'P' => '팒', 'Q' => '팓', 'R' => '팕', 'S' => '팗', 'T' => '팘', 'U' => '팙', 'V' => '팚', 'W' => '팛', 'X' => '팞', 'Y' => '팢', 'Z' => '팣', 'a' => '팤', 'b' => '팦', 'c' => '팧', 'd' => '팪', 'e' => '팫', 'f' => '팭', 'g' => '팮', 'h' => '팯', 'i' => '팱', 'j' => '팲', 'k' => '팳', 'l' => '팴', 'm' => '팵', 'n' => '팶', 'o' => '팷', 'p' => '팺', 'q' => '팾', 'r' => '팿', 's' => '퍀', 't' => '퍁', 'u' => '퍂', 'v' => '퍃', 'w' => '퍆', 'x' => '퍇', 'y' => '퍈', 'z' => '퍉', '' => '퍊', '' => '퍋', '' => '퍌', '' => '퍍', '' => '퍎', '' => '퍏', '' => '퍐', '' => '퍑', '' => '퍒', '' => '퍓', '' => '퍔', '' => '퍕', '' => '퍖', '' => '퍗', '' => '퍘', '' => '퍙', '' => '퍚', '' => '퍛', '' => '퍜', '' => '퍝', '' => '퍞', '' => '퍟', '' => '퍠', '' => '퍡', '' => '퍢', '' => '퍣', '' => '퍤', '' => '퍥', '' => '퍦', '' => '퍧', '' => '퍨', '' => '퍩', '' => '빨', '' => '빪', '' => '빰', '' => '빱', '' => '빳', '' => '빴', '' => '빵', '' => '빻', '' => '빼', '' => '빽', '' => '뺀', '' => '뺄', '' => '뺌', '' => '뺍', '' => '뺏', '' => '뺐', '' => '뺑', '' => '뺘', '' => '뺙', '' => '뺨', '' => '뻐', '' => '뻑', '' => '뻔', '' => '뻗', '' => '뻘', '' => '뻠', '' => '뻣', '' => '뻤', '' => '뻥', '' => '뻬', '' => '뼁', '' => '뼈', '' => '뼉', '' => '뼘', '' => '뼙', '' => '뼛', '' => '뼜', '' => '뼝', '' => '뽀', '' => '뽁', '' => '뽄', '' => '뽈', '' => '뽐', '' => '뽑', '' => '뽕', '' => '뾔', '' => '뾰', '' => '뿅', '' => '뿌', '' => '뿍', '' => '뿐', '' => '뿔', '' => '뿜', '' => '뿟', '' => '뿡', '' => '쀼', '' => '쁑', '' => '쁘', '' => '쁜', '' => '쁠', '' => '쁨', '' => '쁩', '' => '삐', '' => '삑', '' => '삔', '' => '삘', '' => '삠', '' => '삡', '' => '삣', '' => '삥', '' => '사', '' => '삭', '' => '삯', '' => '산', '' => '삳', '' => '살', '' => '삵', '' => '삶', '' => '삼', '' => '삽', '' => '삿', '' => '샀', '' => '상', '' => '샅', '' => '새', '' => '색', '' => '샌', '' => '샐', '' => '샘', '' => '샙', '' => '샛', '' => '샜', '' => '생', '' => '샤', 'A' => '퍪', 'B' => '퍫', 'C' => '퍬', 'D' => '퍭', 'E' => '퍮', 'F' => '퍯', 'G' => '퍰', 'H' => '퍱', 'I' => '퍲', 'J' => '퍳', 'K' => '퍴', 'L' => '퍵', 'M' => '퍶', 'N' => '퍷', 'O' => '퍸', 'P' => '퍹', 'Q' => '퍺', 'R' => '퍻', 'S' => '퍾', 'T' => '퍿', 'U' => '펁', 'V' => '펂', 'W' => '펃', 'X' => '펅', 'Y' => '펆', 'Z' => '펇', 'a' => '펈', 'b' => '펉', 'c' => '펊', 'd' => '펋', 'e' => '펎', 'f' => '펒', 'g' => '펓', 'h' => '펔', 'i' => '펕', 'j' => '펖', 'k' => '펗', 'l' => '펚', 'm' => '펛', 'n' => '펝', 'o' => '펞', 'p' => '펟', 'q' => '펡', 'r' => '펢', 's' => '펣', 't' => '펤', 'u' => '펥', 'v' => '펦', 'w' => '펧', 'x' => '펪', 'y' => '펬', 'z' => '펮', '' => '펯', '' => '펰', '' => '펱', '' => '펲', '' => '펳', '' => '펵', '' => '펶', '' => '펷', '' => '펹', '' => '펺', '' => '펻', '' => '펽', '' => '펾', '' => '펿', '' => '폀', '' => '폁', '' => '폂', '' => '폃', '' => '폆', '' => '폇', '' => '폊', '' => '폋', '' => '폌', '' => '폍', '' => '폎', '' => '폏', '' => '폑', '' => '폒', '' => '폓', '' => '폔', '' => '폕', '' => '폖', '' => '샥', '' => '샨', '' => '샬', '' => '샴', '' => '샵', '' => '샷', '' => '샹', '' => '섀', '' => '섄', '' => '섈', '' => '섐', '' => '섕', '' => '서', '' => '석', '' => '섞', '' => '섟', '' => '선', '' => '섣', '' => '설', '' => '섦', '' => '섧', '' => '섬', '' => '섭', '' => '섯', '' => '섰', '' => '성', '' => '섶', '' => '세', '' => '섹', '' => '센', '' => '셀', '' => '셈', '' => '셉', '' => '셋', '' => '셌', '' => '셍', '' => '셔', '' => '셕', '' => '션', '' => '셜', '' => '셤', '' => '셥', '' => '셧', '' => '셨', '' => '셩', '' => '셰', '' => '셴', '' => '셸', '' => '솅', '' => '소', '' => '속', '' => '솎', '' => '손', '' => '솔', '' => '솖', '' => '솜', '' => '솝', '' => '솟', '' => '송', '' => '솥', '' => '솨', '' => '솩', '' => '솬', '' => '솰', '' => '솽', '' => '쇄', '' => '쇈', '' => '쇌', '' => '쇔', '' => '쇗', '' => '쇘', '' => '쇠', '' => '쇤', '' => '쇨', '' => '쇰', '' => '쇱', '' => '쇳', '' => '쇼', '' => '쇽', '' => '숀', '' => '숄', '' => '숌', '' => '숍', '' => '숏', '' => '숑', '' => '수', '' => '숙', '' => '순', '' => '숟', '' => '술', '' => '숨', '' => '숩', '' => '숫', '' => '숭', 'A' => '폗', 'B' => '폙', 'C' => '폚', 'D' => '폛', 'E' => '폜', 'F' => '폝', 'G' => '폞', 'H' => '폟', 'I' => '폠', 'J' => '폢', 'K' => '폤', 'L' => '폥', 'M' => '폦', 'N' => '폧', 'O' => '폨', 'P' => '폩', 'Q' => '폪', 'R' => '폫', 'S' => '폮', 'T' => '폯', 'U' => '폱', 'V' => '폲', 'W' => '폳', 'X' => '폵', 'Y' => '폶', 'Z' => '폷', 'a' => '폸', 'b' => '폹', 'c' => '폺', 'd' => '폻', 'e' => '폾', 'f' => '퐀', 'g' => '퐂', 'h' => '퐃', 'i' => '퐄', 'j' => '퐅', 'k' => '퐆', 'l' => '퐇', 'm' => '퐉', 'n' => '퐊', 'o' => '퐋', 'p' => '퐌', 'q' => '퐍', 'r' => '퐎', 's' => '퐏', 't' => '퐐', 'u' => '퐑', 'v' => '퐒', 'w' => '퐓', 'x' => '퐔', 'y' => '퐕', 'z' => '퐖', '' => '퐗', '' => '퐘', '' => '퐙', '' => '퐚', '' => '퐛', '' => '퐜', '' => '퐞', '' => '퐟', '' => '퐠', '' => '퐡', '' => '퐢', '' => '퐣', '' => '퐤', '' => '퐥', '' => '퐦', '' => '퐧', '' => '퐨', '' => '퐩', '' => '퐪', '' => '퐫', '' => '퐬', '' => '퐭', '' => '퐮', '' => '퐯', '' => '퐰', '' => '퐱', '' => '퐲', '' => '퐳', '' => '퐴', '' => '퐵', '' => '퐶', '' => '퐷', '' => '숯', '' => '숱', '' => '숲', '' => '숴', '' => '쉈', '' => '쉐', '' => '쉑', '' => '쉔', '' => '쉘', '' => '쉠', '' => '쉥', '' => '쉬', '' => '쉭', '' => '쉰', '' => '쉴', '' => '쉼', '' => '쉽', '' => '쉿', '' => '슁', '' => '슈', '' => '슉', '' => '슐', '' => '슘', '' => '슛', '' => '슝', '' => '스', '' => '슥', '' => '슨', '' => '슬', '' => '슭', '' => '슴', '' => '습', '' => '슷', '' => '승', '' => '시', '' => '식', '' => '신', '' => '싣', '' => '실', '' => '싫', '' => '심', '' => '십', '' => '싯', '' => '싱', '' => '싶', '' => '싸', '' => '싹', '' => '싻', '' => '싼', '' => '쌀', '' => '쌈', '' => '쌉', '' => '쌌', '' => '쌍', '' => '쌓', '' => '쌔', '' => '쌕', '' => '쌘', '' => '쌜', '' => '쌤', '' => '쌥', '' => '쌨', '' => '쌩', '' => '썅', '' => '써', '' => '썩', '' => '썬', '' => '썰', '' => '썲', '' => '썸', '' => '썹', '' => '썼', '' => '썽', '' => '쎄', '' => '쎈', '' => '쎌', '' => '쏀', '' => '쏘', '' => '쏙', '' => '쏜', '' => '쏟', '' => '쏠', '' => '쏢', '' => '쏨', '' => '쏩', '' => '쏭', '' => '쏴', '' => '쏵', '' => '쏸', '' => '쐈', '' => '쐐', '' => '쐤', '' => '쐬', '' => '쐰', 'A' => '퐸', 'B' => '퐹', 'C' => '퐺', 'D' => '퐻', 'E' => '퐼', 'F' => '퐽', 'G' => '퐾', 'H' => '퐿', 'I' => '푁', 'J' => '푂', 'K' => '푃', 'L' => '푅', 'M' => '푆', 'N' => '푇', 'O' => '푈', 'P' => '푉', 'Q' => '푊', 'R' => '푋', 'S' => '푌', 'T' => '푍', 'U' => '푎', 'V' => '푏', 'W' => '푐', 'X' => '푑', 'Y' => '푒', 'Z' => '푓', 'a' => '푔', 'b' => '푕', 'c' => '푖', 'd' => '푗', 'e' => '푘', 'f' => '푙', 'g' => '푚', 'h' => '푛', 'i' => '푝', 'j' => '푞', 'k' => '푟', 'l' => '푡', 'm' => '푢', 'n' => '푣', 'o' => '푥', 'p' => '푦', 'q' => '푧', 'r' => '푨', 's' => '푩', 't' => '푪', 'u' => '푫', 'v' => '푬', 'w' => '푮', 'x' => '푰', 'y' => '푱', 'z' => '푲', '' => '푳', '' => '푴', '' => '푵', '' => '푶', '' => '푷', '' => '푺', '' => '푻', '' => '푽', '' => '푾', '' => '풁', '' => '풃', '' => '풄', '' => '풅', '' => '풆', '' => '풇', '' => '풊', '' => '풌', '' => '풎', '' => '풏', '' => '풐', '' => '풑', '' => '풒', '' => '풓', '' => '풕', '' => '풖', '' => '풗', '' => '풘', '' => '풙', '' => '풚', '' => '풛', '' => '풜', '' => '풝', '' => '쐴', '' => '쐼', '' => '쐽', '' => '쑈', '' => '쑤', '' => '쑥', '' => '쑨', '' => '쑬', '' => '쑴', '' => '쑵', '' => '쑹', '' => '쒀', '' => '쒔', '' => '쒜', '' => '쒸', '' => '쒼', '' => '쓩', '' => '쓰', '' => '쓱', '' => '쓴', '' => '쓸', '' => '쓺', '' => '쓿', '' => '씀', '' => '씁', '' => '씌', '' => '씐', '' => '씔', '' => '씜', '' => '씨', '' => '씩', '' => '씬', '' => '씰', '' => '씸', '' => '씹', '' => '씻', '' => '씽', '' => '아', '' => '악', '' => '안', '' => '앉', '' => '않', '' => '알', '' => '앍', '' => '앎', '' => '앓', '' => '암', '' => '압', '' => '앗', '' => '았', '' => '앙', '' => '앝', '' => '앞', '' => '애', '' => '액', '' => '앤', '' => '앨', '' => '앰', '' => '앱', '' => '앳', '' => '앴', '' => '앵', '' => '야', '' => '약', '' => '얀', '' => '얄', '' => '얇', '' => '얌', '' => '얍', '' => '얏', '' => '양', '' => '얕', '' => '얗', '' => '얘', '' => '얜', '' => '얠', '' => '얩', '' => '어', '' => '억', '' => '언', '' => '얹', '' => '얻', '' => '얼', '' => '얽', '' => '얾', '' => '엄', '' => '업', '' => '없', '' => '엇', '' => '었', '' => '엉', '' => '엊', '' => '엌', '' => '엎', 'A' => '풞', 'B' => '풟', 'C' => '풠', 'D' => '풡', 'E' => '풢', 'F' => '풣', 'G' => '풤', 'H' => '풥', 'I' => '풦', 'J' => '풧', 'K' => '풨', 'L' => '풪', 'M' => '풫', 'N' => '풬', 'O' => '풭', 'P' => '풮', 'Q' => '풯', 'R' => '풰', 'S' => '풱', 'T' => '풲', 'U' => '풳', 'V' => '풴', 'W' => '풵', 'X' => '풶', 'Y' => '풷', 'Z' => '풸', 'a' => '풹', 'b' => '풺', 'c' => '풻', 'd' => '풼', 'e' => '풽', 'f' => '풾', 'g' => '풿', 'h' => '퓀', 'i' => '퓁', 'j' => '퓂', 'k' => '퓃', 'l' => '퓄', 'm' => '퓅', 'n' => '퓆', 'o' => '퓇', 'p' => '퓈', 'q' => '퓉', 'r' => '퓊', 's' => '퓋', 't' => '퓍', 'u' => '퓎', 'v' => '퓏', 'w' => '퓑', 'x' => '퓒', 'y' => '퓓', 'z' => '퓕', '' => '퓖', '' => '퓗', '' => '퓘', '' => '퓙', '' => '퓚', '' => '퓛', '' => '퓝', '' => '퓞', '' => '퓠', '' => '퓡', '' => '퓢', '' => '퓣', '' => '퓤', '' => '퓥', '' => '퓦', '' => '퓧', '' => '퓩', '' => '퓪', '' => '퓫', '' => '퓭', '' => '퓮', '' => '퓯', '' => '퓱', '' => '퓲', '' => '퓳', '' => '퓴', '' => '퓵', '' => '퓶', '' => '퓷', '' => '퓹', '' => '퓺', '' => '퓼', '' => '에', '' => '엑', '' => '엔', '' => '엘', '' => '엠', '' => '엡', '' => '엣', '' => '엥', '' => '여', '' => '역', '' => '엮', '' => '연', '' => '열', '' => '엶', '' => '엷', '' => '염', '' => '엽', '' => '엾', '' => '엿', '' => '였', '' => '영', '' => '옅', '' => '옆', '' => '옇', '' => '예', '' => '옌', '' => '옐', '' => '옘', '' => '옙', '' => '옛', '' => '옜', '' => '오', '' => '옥', '' => '온', '' => '올', '' => '옭', '' => '옮', '' => '옰', '' => '옳', '' => '옴', '' => '옵', '' => '옷', '' => '옹', '' => '옻', '' => '와', '' => '왁', '' => '완', '' => '왈', '' => '왐', '' => '왑', '' => '왓', '' => '왔', '' => '왕', '' => '왜', '' => '왝', '' => '왠', '' => '왬', '' => '왯', '' => '왱', '' => '외', '' => '왹', '' => '왼', '' => '욀', '' => '욈', '' => '욉', '' => '욋', '' => '욍', '' => '요', '' => '욕', '' => '욘', '' => '욜', '' => '욤', '' => '욥', '' => '욧', '' => '용', '' => '우', '' => '욱', '' => '운', '' => '울', '' => '욹', '' => '욺', '' => '움', '' => '웁', '' => '웃', '' => '웅', '' => '워', '' => '웍', '' => '원', '' => '월', '' => '웜', '' => '웝', '' => '웠', '' => '웡', '' => '웨', 'A' => '퓾', 'B' => '퓿', 'C' => '픀', 'D' => '픁', 'E' => '픂', 'F' => '픃', 'G' => '픅', 'H' => '픆', 'I' => '픇', 'J' => '픉', 'K' => '픊', 'L' => '픋', 'M' => '픍', 'N' => '픎', 'O' => '픏', 'P' => '픐', 'Q' => '픑', 'R' => '픒', 'S' => '픓', 'T' => '픖', 'U' => '픘', 'V' => '픙', 'W' => '픚', 'X' => '픛', 'Y' => '픜', 'Z' => '픝', 'a' => '픞', 'b' => '픟', 'c' => '픠', 'd' => '픡', 'e' => '픢', 'f' => '픣', 'g' => '픤', 'h' => '픥', 'i' => '픦', 'j' => '픧', 'k' => '픨', 'l' => '픩', 'm' => '픪', 'n' => '픫', 'o' => '픬', 'p' => '픭', 'q' => '픮', 'r' => '픯', 's' => '픰', 't' => '픱', 'u' => '픲', 'v' => '픳', 'w' => '픴', 'x' => '픵', 'y' => '픶', 'z' => '픷', '' => '픸', '' => '픹', '' => '픺', '' => '픻', '' => '픾', '' => '픿', '' => '핁', '' => '핂', '' => '핃', '' => '핅', '' => '핆', '' => '핇', '' => '핈', '' => '핉', '' => '핊', '' => '핋', '' => '핎', '' => '핐', '' => '핒', '' => '핓', '' => '핔', '' => '핕', '' => '핖', '' => '핗', '' => '핚', '' => '핛', '' => '핝', '' => '핞', '' => '핟', '' => '핡', '' => '핢', '' => '핣', '' => '웩', '' => '웬', '' => '웰', '' => '웸', '' => '웹', '' => '웽', '' => '위', '' => '윅', '' => '윈', '' => '윌', '' => '윔', '' => '윕', '' => '윗', '' => '윙', '' => '유', '' => '육', '' => '윤', '' => '율', '' => '윰', '' => '윱', '' => '윳', '' => '융', '' => '윷', '' => '으', '' => '윽', '' => '은', '' => '을', '' => '읊', '' => '음', '' => '읍', '' => '읏', '' => '응', '' => '읒', '' => '읓', '' => '읔', '' => '읕', '' => '읖', '' => '읗', '' => '의', '' => '읜', '' => '읠', '' => '읨', '' => '읫', '' => '이', '' => '익', '' => '인', '' => '일', '' => '읽', '' => '읾', '' => '잃', '' => '임', '' => '입', '' => '잇', '' => '있', '' => '잉', '' => '잊', '' => '잎', '' => '자', '' => '작', '' => '잔', '' => '잖', '' => '잗', '' => '잘', '' => '잚', '' => '잠', '' => '잡', '' => '잣', '' => '잤', '' => '장', '' => '잦', '' => '재', '' => '잭', '' => '잰', '' => '잴', '' => '잼', '' => '잽', '' => '잿', '' => '쟀', '' => '쟁', '' => '쟈', '' => '쟉', '' => '쟌', '' => '쟎', '' => '쟐', '' => '쟘', '' => '쟝', '' => '쟤', '' => '쟨', '' => '쟬', '' => '저', '' => '적', '' => '전', '' => '절', '' => '젊', 'A' => '핤', 'B' => '핦', 'C' => '핧', 'D' => '핪', 'E' => '핬', 'F' => '핮', 'G' => '핯', 'H' => '핰', 'I' => '핱', 'J' => '핲', 'K' => '핳', 'L' => '핶', 'M' => '핷', 'N' => '핹', 'O' => '핺', 'P' => '핻', 'Q' => '핽', 'R' => '핾', 'S' => '핿', 'T' => '햀', 'U' => '햁', 'V' => '햂', 'W' => '햃', 'X' => '햆', 'Y' => '햊', 'Z' => '햋', 'a' => '햌', 'b' => '햍', 'c' => '햎', 'd' => '햏', 'e' => '햑', 'f' => '햒', 'g' => '햓', 'h' => '햔', 'i' => '햕', 'j' => '햖', 'k' => '햗', 'l' => '햘', 'm' => '햙', 'n' => '햚', 'o' => '햛', 'p' => '햜', 'q' => '햝', 'r' => '햞', 's' => '햟', 't' => '햠', 'u' => '햡', 'v' => '햢', 'w' => '햣', 'x' => '햤', 'y' => '햦', 'z' => '햧', '' => '햨', '' => '햩', '' => '햪', '' => '햫', '' => '햬', '' => '햭', '' => '햮', '' => '햯', '' => '햰', '' => '햱', '' => '햲', '' => '햳', '' => '햴', '' => '햵', '' => '햶', '' => '햷', '' => '햸', '' => '햹', '' => '햺', '' => '햻', '' => '햼', '' => '햽', '' => '햾', '' => '햿', '' => '헀', '' => '헁', '' => '헂', '' => '헃', '' => '헄', '' => '헅', '' => '헆', '' => '헇', '' => '점', '' => '접', '' => '젓', '' => '정', '' => '젖', '' => '제', '' => '젝', '' => '젠', '' => '젤', '' => '젬', '' => '젭', '' => '젯', '' => '젱', '' => '져', '' => '젼', '' => '졀', '' => '졈', '' => '졉', '' => '졌', '' => '졍', '' => '졔', '' => '조', '' => '족', '' => '존', '' => '졸', '' => '졺', '' => '좀', '' => '좁', '' => '좃', '' => '종', '' => '좆', '' => '좇', '' => '좋', '' => '좌', '' => '좍', '' => '좔', '' => '좝', '' => '좟', '' => '좡', '' => '좨', '' => '좼', '' => '좽', '' => '죄', '' => '죈', '' => '죌', '' => '죔', '' => '죕', '' => '죗', '' => '죙', '' => '죠', '' => '죡', '' => '죤', '' => '죵', '' => '주', '' => '죽', '' => '준', '' => '줄', '' => '줅', '' => '줆', '' => '줌', '' => '줍', '' => '줏', '' => '중', '' => '줘', '' => '줬', '' => '줴', '' => '쥐', '' => '쥑', '' => '쥔', '' => '쥘', '' => '쥠', '' => '쥡', '' => '쥣', '' => '쥬', '' => '쥰', '' => '쥴', '' => '쥼', '' => '즈', '' => '즉', '' => '즌', '' => '즐', '' => '즘', '' => '즙', '' => '즛', '' => '증', '' => '지', '' => '직', '' => '진', '' => '짇', '' => '질', '' => '짊', '' => '짐', '' => '집', '' => '짓', 'A' => '헊', 'B' => '헋', 'C' => '헍', 'D' => '헎', 'E' => '헏', 'F' => '헑', 'G' => '헓', 'H' => '헔', 'I' => '헕', 'J' => '헖', 'K' => '헗', 'L' => '헚', 'M' => '헜', 'N' => '헞', 'O' => '헟', 'P' => '헠', 'Q' => '헡', 'R' => '헢', 'S' => '헣', 'T' => '헦', 'U' => '헧', 'V' => '헩', 'W' => '헪', 'X' => '헫', 'Y' => '헭', 'Z' => '헮', 'a' => '헯', 'b' => '헰', 'c' => '헱', 'd' => '헲', 'e' => '헳', 'f' => '헶', 'g' => '헸', 'h' => '헺', 'i' => '헻', 'j' => '헼', 'k' => '헽', 'l' => '헾', 'm' => '헿', 'n' => '혂', 'o' => '혃', 'p' => '혅', 'q' => '혆', 'r' => '혇', 's' => '혉', 't' => '혊', 'u' => '혋', 'v' => '혌', 'w' => '혍', 'x' => '혎', 'y' => '혏', 'z' => '혒', '' => '혖', '‚' => '혗', 'ƒ' => '혘', '„' => '혙', '…' => '혚', '†' => '혛', '‡' => '혝', 'ˆ' => '혞', '‰' => '혟', 'Š' => '혡', '‹' => '혢', 'Œ' => '혣', '' => '혥', 'Ž' => '혦', '' => '혧', '' => '혨', '‘' => '혩', '’' => '혪', '“' => '혫', '”' => '혬', '•' => '혮', '–' => '혯', '—' => '혰', '˜' => '혱', '™' => '혲', 'š' => '혳', '›' => '혴', 'œ' => '혵', '' => '혶', 'ž' => '혷', 'Ÿ' => '혺', ' ' => '혻', '¡' => '징', '¢' => '짖', '£' => '짙', '¤' => '짚', '¥' => '짜', '¦' => '짝', '§' => '짠', '¨' => '짢', '©' => '짤', 'ª' => '짧', '«' => '짬', '¬' => '짭', '­' => '짯', '®' => '짰', '¯' => '짱', '°' => '째', '±' => '짹', '²' => '짼', '³' => '쨀', '´' => '쨈', 'µ' => '쨉', '¶' => '쨋', '·' => '쨌', '¸' => '쨍', '¹' => '쨔', 'º' => '쨘', '»' => '쨩', '¼' => '쩌', '½' => '쩍', '¾' => '쩐', '¿' => '쩔', '' => '쩜', '' => '쩝', '' => '쩟', '' => '쩠', '' => '쩡', '' => '쩨', '' => '쩽', '' => '쪄', '' => '쪘', '' => '쪼', '' => '쪽', '' => '쫀', '' => '쫄', '' => '쫌', '' => '쫍', '' => '쫏', '' => '쫑', '' => '쫓', '' => '쫘', '' => '쫙', '' => '쫠', '' => '쫬', '' => '쫴', '' => '쬈', '' => '쬐', '' => '쬔', '' => '쬘', '' => '쬠', '' => '쬡', '' => '쭁', '' => '쭈', '' => '쭉', '' => '쭌', '' => '쭐', '' => '쭘', '' => '쭙', '' => '쭝', '' => '쭤', '' => '쭸', '' => '쭹', '' => '쮜', '' => '쮸', '' => '쯔', '' => '쯤', '' => '쯧', '' => '쯩', '' => '찌', '' => '찍', '' => '찐', '' => '찔', '' => '찜', '' => '찝', '' => '찡', '' => '찢', '' => '찧', '' => '차', '' => '착', '' => '찬', '' => '찮', '' => '찰', '' => '참', '' => '찹', '' => '찻', 'A' => '혽', 'B' => '혾', 'C' => '혿', 'D' => '홁', 'E' => '홂', 'F' => '홃', 'G' => '홄', 'H' => '홆', 'I' => '홇', 'J' => '홊', 'K' => '홌', 'L' => '홎', 'M' => '홏', 'N' => '홐', 'O' => '홒', 'P' => '홓', 'Q' => '홖', 'R' => '홗', 'S' => '홙', 'T' => '홚', 'U' => '홛', 'V' => '홝', 'W' => '홞', 'X' => '홟', 'Y' => '홠', 'Z' => '홡', 'a' => '홢', 'b' => '홣', 'c' => '홤', 'd' => '홥', 'e' => '홦', 'f' => '홨', 'g' => '홪', 'h' => '홫', 'i' => '홬', 'j' => '홭', 'k' => '홮', 'l' => '홯', 'm' => '홲', 'n' => '홳', 'o' => '홵', 'p' => '홶', 'q' => '홷', 'r' => '홸', 's' => '홹', 't' => '홺', 'u' => '홻', 'v' => '홼', 'w' => '홽', 'x' => '홾', 'y' => '홿', 'z' => '횀', 'Á' => '횁', 'Â' => '횂', 'Ã' => '횄', 'Ä' => '횆', 'Å' => '횇', 'Æ' => '횈', 'Ç' => '횉', 'È' => '횊', 'É' => '횋', 'Ê' => '횎', 'Ë' => '횏', 'Ì' => '횑', 'Í' => '횒', 'Î' => '횓', 'Ï' => '횕', 'Ð' => '횖', 'Ñ' => '횗', 'Ò' => '횘', 'Ó' => '횙', 'Ô' => '횚', 'Õ' => '횛', 'Ö' => '횜', '×' => '횞', 'Ø' => '횠', 'Ù' => '횢', 'Ú' => '횣', 'Û' => '횤', 'Ü' => '횥', 'Ý' => '횦', 'Þ' => '횧', 'ß' => '횩', 'à' => '횪', 'á' => '찼', 'â' => '창', 'ã' => '찾', 'ä' => '채', 'å' => '책', 'æ' => '챈', 'ç' => '챌', 'è' => '챔', 'é' => '챕', 'ê' => '챗', 'ë' => '챘', 'ì' => '챙', 'í' => '챠', 'î' => '챤', 'ï' => '챦', 'ð' => '챨', 'ñ' => '챰', 'ò' => '챵', 'ó' => '처', 'ô' => '척', 'õ' => '천', 'ö' => '철', '÷' => '첨', 'ø' => '첩', 'ù' => '첫', 'ú' => '첬', 'û' => '청', 'ü' => '체', 'ý' => '첵', 'þ' => '첸', 'ÿ' => '첼', '' => '쳄', '' => '쳅', '' => '쳇', '' => '쳉', '' => '쳐', '' => '쳔', '' => '쳤', '' => '쳬', '' => '쳰', '' => '촁', '' => '초', '' => '촉', '' => '촌', '' => '촐', '' => '촘', '' => '촙', '' => '촛', '' => '총', '' => '촤', '' => '촨', '' => '촬', '' => '촹', '' => '최', '' => '쵠', '' => '쵤', '' => '쵬', '' => '쵭', '' => '쵯', '' => '쵱', '' => '쵸', '' => '춈', '' => '추', '' => '축', '' => '춘', '' => '출', '' => '춤', '' => '춥', '' => '춧', '' => '충', '' => '춰', '' => '췄', '' => '췌', '' => '췐', '' => '취', '' => '췬', '' => '췰', '' => '췸', '' => '췹', '' => '췻', '' => '췽', '' => '츄', '' => '츈', '' => '츌', '' => '츔', '' => '츙', '' => '츠', '' => '측', '' => '츤', '' => '츨', '' => '츰', '' => '츱', '' => '츳', '' => '층', 'A' => '횫', 'B' => '횭', 'C' => '횮', 'D' => '횯', 'E' => '횱', 'F' => '횲', 'G' => '횳', 'H' => '횴', 'I' => '횵', 'J' => '횶', 'K' => '횷', 'L' => '횸', 'M' => '횺', 'N' => '횼', 'O' => '횽', 'P' => '횾', 'Q' => '횿', 'R' => '훀', 'S' => '훁', 'T' => '훂', 'U' => '훃', 'V' => '훆', 'W' => '훇', 'X' => '훉', 'Y' => '훊', 'Z' => '훋', 'a' => '훍', 'b' => '훎', 'c' => '훏', 'd' => '훐', 'e' => '훒', 'f' => '훓', 'g' => '훕', 'h' => '훖', 'i' => '훘', 'j' => '훚', 'k' => '훛', 'l' => '훜', 'm' => '훝', 'n' => '훞', 'o' => '훟', 'p' => '훡', 'q' => '훢', 'r' => '훣', 's' => '훥', 't' => '훦', 'u' => '훧', 'v' => '훩', 'w' => '훪', 'x' => '훫', 'y' => '훬', 'z' => '훭', 'ā' => '훮', 'Ă' => '훯', 'ă' => '훱', 'Ą' => '훲', 'ą' => '훳', 'Ć' => '훴', 'ć' => '훶', 'Ĉ' => '훷', 'ĉ' => '훸', 'Ċ' => '훹', 'ċ' => '훺', 'Č' => '훻', 'č' => '훾', 'Ď' => '훿', 'ď' => '휁', 'Đ' => '휂', 'đ' => '휃', 'Ē' => '휅', 'ē' => '휆', 'Ĕ' => '휇', 'ĕ' => '휈', 'Ė' => '휉', 'ė' => '휊', 'Ę' => '휋', 'ę' => '휌', 'Ě' => '휍', 'ě' => '휎', 'Ĝ' => '휏', 'ĝ' => '휐', 'Ğ' => '휒', 'ğ' => '휓', 'Ġ' => '휔', 'ġ' => '치', 'Ģ' => '칙', 'ģ' => '친', 'Ĥ' => '칟', 'ĥ' => '칠', 'Ħ' => '칡', 'ħ' => '침', 'Ĩ' => '칩', 'ĩ' => '칫', 'Ī' => '칭', 'ī' => '카', 'Ĭ' => '칵', 'ĭ' => '칸', 'Į' => '칼', 'į' => '캄', 'İ' => '캅', 'ı' => '캇', 'IJ' => '캉', 'ij' => '캐', 'Ĵ' => '캑', 'ĵ' => '캔', 'Ķ' => '캘', 'ķ' => '캠', 'ĸ' => '캡', 'Ĺ' => '캣', 'ĺ' => '캤', 'Ļ' => '캥', 'ļ' => '캬', 'Ľ' => '캭', 'ľ' => '컁', 'Ŀ' => '커', '' => '컥', '' => '컨', '' => '컫', '' => '컬', '' => '컴', '' => '컵', '' => '컷', '' => '컸', '' => '컹', '' => '케', '' => '켁', '' => '켄', '' => '켈', '' => '켐', '' => '켑', '' => '켓', '' => '켕', '' => '켜', '' => '켠', '' => '켤', '' => '켬', '' => '켭', '' => '켯', '' => '켰', '' => '켱', '' => '켸', '' => '코', '' => '콕', '' => '콘', '' => '콜', '' => '콤', '' => '콥', '' => '콧', '' => '콩', '' => '콰', '' => '콱', '' => '콴', '' => '콸', '' => '쾀', '' => '쾅', '' => '쾌', '' => '쾡', '' => '쾨', '' => '쾰', '' => '쿄', '' => '쿠', '' => '쿡', '' => '쿤', '' => '쿨', '' => '쿰', '' => '쿱', '' => '쿳', '' => '쿵', '' => '쿼', '' => '퀀', '' => '퀄', '' => '퀑', '' => '퀘', '' => '퀭', '' => '퀴', '' => '퀵', '' => '퀸', '' => '퀼', 'A' => '휕', 'B' => '휖', 'C' => '휗', 'D' => '휚', 'E' => '휛', 'F' => '휝', 'G' => '휞', 'H' => '휟', 'I' => '휡', 'J' => '휢', 'K' => '휣', 'L' => '휤', 'M' => '휥', 'N' => '휦', 'O' => '휧', 'P' => '휪', 'Q' => '휬', 'R' => '휮', 'S' => '휯', 'T' => '휰', 'U' => '휱', 'V' => '휲', 'W' => '휳', 'X' => '휶', 'Y' => '휷', 'Z' => '휹', 'a' => '휺', 'b' => '휻', 'c' => '휽', 'd' => '휾', 'e' => '휿', 'f' => '흀', 'g' => '흁', 'h' => '흂', 'i' => '흃', 'j' => '흅', 'k' => '흆', 'l' => '흈', 'm' => '흊', 'n' => '흋', 'o' => '흌', 'p' => '흍', 'q' => '흎', 'r' => '흏', 's' => '흒', 't' => '흓', 'u' => '흕', 'v' => '흚', 'w' => '흛', 'x' => '흜', 'y' => '흝', 'z' => '흞', 'Ł' => '흟', 'ł' => '흢', 'Ń' => '흤', 'ń' => '흦', 'Ņ' => '흧', 'ņ' => '흨', 'Ň' => '흪', 'ň' => '흫', 'ʼn' => '흭', 'Ŋ' => '흮', 'ŋ' => '흯', 'Ō' => '흱', 'ō' => '흲', 'Ŏ' => '흳', 'ŏ' => '흵', 'Ő' => '흶', 'ő' => '흷', 'Œ' => '흸', 'œ' => '흹', 'Ŕ' => '흺', 'ŕ' => '흻', 'Ŗ' => '흾', 'ŗ' => '흿', 'Ř' => '힀', 'ř' => '힂', 'Ś' => '힃', 'ś' => '힄', 'Ŝ' => '힅', 'ŝ' => '힆', 'Ş' => '힇', 'ş' => '힊', 'Š' => '힋', 'š' => '큄', 'Ţ' => '큅', 'ţ' => '큇', 'Ť' => '큉', 'ť' => '큐', 'Ŧ' => '큔', 'ŧ' => '큘', 'Ũ' => '큠', 'ũ' => '크', 'Ū' => '큭', 'ū' => '큰', 'Ŭ' => '클', 'ŭ' => '큼', 'Ů' => '큽', 'ů' => '킁', 'Ű' => '키', 'ű' => '킥', 'Ų' => '킨', 'ų' => '킬', 'Ŵ' => '킴', 'ŵ' => '킵', 'Ŷ' => '킷', 'ŷ' => '킹', 'Ÿ' => '타', 'Ź' => '탁', 'ź' => '탄', 'Ż' => '탈', 'ż' => '탉', 'Ž' => '탐', 'ž' => '탑', 'ſ' => '탓', '' => '탔', '' => '탕', '' => '태', '' => '택', '' => '탠', '' => '탤', '' => '탬', '' => '탭', '' => '탯', '' => '탰', '' => '탱', '' => '탸', '' => '턍', '' => '터', '' => '턱', '' => '턴', '' => '털', '' => '턺', '' => '텀', '' => '텁', '' => '텃', '' => '텄', '' => '텅', '' => '테', '' => '텍', '' => '텐', '' => '텔', '' => '템', '' => '텝', '' => '텟', '' => '텡', '' => '텨', '' => '텬', '' => '텼', '' => '톄', '' => '톈', '' => '토', '' => '톡', '' => '톤', '' => '톨', '' => '톰', '' => '톱', '' => '톳', '' => '통', '' => '톺', '' => '톼', '' => '퇀', '' => '퇘', '' => '퇴', '' => '퇸', '' => '툇', '' => '툉', '' => '툐', '' => '투', '' => '툭', '' => '툰', '' => '툴', '' => '툼', '' => '툽', '' => '툿', '' => '퉁', '' => '퉈', '' => '퉜', 'A' => '힍', 'B' => '힎', 'C' => '힏', 'D' => '힑', 'E' => '힒', 'F' => '힓', 'G' => '힔', 'H' => '힕', 'I' => '힖', 'J' => '힗', 'K' => '힚', 'L' => '힜', 'M' => '힞', 'N' => '힟', 'O' => '힠', 'P' => '힡', 'Q' => '힢', 'R' => '힣', 'ơ' => '퉤', 'Ƣ' => '튀', 'ƣ' => '튁', 'Ƥ' => '튄', 'ƥ' => '튈', 'Ʀ' => '튐', 'Ƨ' => '튑', 'ƨ' => '튕', 'Ʃ' => '튜', 'ƪ' => '튠', 'ƫ' => '튤', 'Ƭ' => '튬', 'ƭ' => '튱', 'Ʈ' => '트', 'Ư' => '특', 'ư' => '튼', 'Ʊ' => '튿', 'Ʋ' => '틀', 'Ƴ' => '틂', 'ƴ' => '틈', 'Ƶ' => '틉', 'ƶ' => '틋', 'Ʒ' => '틔', 'Ƹ' => '틘', 'ƹ' => '틜', 'ƺ' => '틤', 'ƻ' => '틥', 'Ƽ' => '티', 'ƽ' => '틱', 'ƾ' => '틴', 'ƿ' => '틸', '' => '팀', '' => '팁', '' => '팃', '' => '팅', '' => '파', '' => '팍', '' => '팎', '' => '판', '' => '팔', '' => '팖', '' => '팜', '' => '팝', '' => '팟', '' => '팠', '' => '팡', '' => '팥', '' => '패', '' => '팩', '' => '팬', '' => '팰', '' => '팸', '' => '팹', '' => '팻', '' => '팼', '' => '팽', '' => '퍄', '' => '퍅', '' => '퍼', '' => '퍽', '' => '펀', '' => '펄', '' => '펌', '' => '펍', '' => '펏', '' => '펐', '' => '펑', '' => '페', '' => '펙', '' => '펜', '' => '펠', '' => '펨', '' => '펩', '' => '펫', '' => '펭', '' => '펴', '' => '편', '' => '펼', '' => '폄', '' => '폅', '' => '폈', '' => '평', '' => '폐', '' => '폘', '' => '폡', '' => '폣', '' => '포', '' => '폭', '' => '폰', '' => '폴', '' => '폼', '' => '폽', '' => '폿', '' => '퐁', 'ǡ' => '퐈', 'Ǣ' => '퐝', 'ǣ' => '푀', 'Ǥ' => '푄', 'ǥ' => '표', 'Ǧ' => '푠', 'ǧ' => '푤', 'Ǩ' => '푭', 'ǩ' => '푯', 'Ǫ' => '푸', 'ǫ' => '푹', 'Ǭ' => '푼', 'ǭ' => '푿', 'Ǯ' => '풀', 'ǯ' => '풂', 'ǰ' => '품', 'DZ' => '풉', 'Dz' => '풋', 'dz' => '풍', 'Ǵ' => '풔', 'ǵ' => '풩', 'Ƕ' => '퓌', 'Ƿ' => '퓐', 'Ǹ' => '퓔', 'ǹ' => '퓜', 'Ǻ' => '퓟', 'ǻ' => '퓨', 'Ǽ' => '퓬', 'ǽ' => '퓰', 'Ǿ' => '퓸', 'ǿ' => '퓻', '' => '퓽', '' => '프', '' => '픈', '' => '플', '' => '픔', '' => '픕', '' => '픗', '' => '피', '' => '픽', '' => '핀', '' => '필', '' => '핌', '' => '핍', '' => '핏', '' => '핑', '' => '하', '' => '학', '' => '한', '' => '할', '' => '핥', '' => '함', '' => '합', '' => '핫', '' => '항', '' => '해', '' => '핵', '' => '핸', '' => '핼', '' => '햄', '' => '햅', '' => '햇', '' => '했', '' => '행', '' => '햐', '' => '향', '' => '허', '' => '헉', '' => '헌', '' => '헐', '' => '헒', '' => '험', '' => '헙', '' => '헛', '' => '헝', '' => '헤', '' => '헥', '' => '헨', '' => '헬', '' => '헴', '' => '헵', '' => '헷', '' => '헹', '' => '혀', '' => '혁', '' => '현', '' => '혈', '' => '혐', '' => '협', '' => '혓', '' => '혔', '' => '형', '' => '혜', '' => '혠', 'ȡ' => '혤', 'Ȣ' => '혭', 'ȣ' => '호', 'Ȥ' => '혹', 'ȥ' => '혼', 'Ȧ' => '홀', 'ȧ' => '홅', 'Ȩ' => '홈', 'ȩ' => '홉', 'Ȫ' => '홋', 'ȫ' => '홍', 'Ȭ' => '홑', 'ȭ' => '화', 'Ȯ' => '확', 'ȯ' => '환', 'Ȱ' => '활', 'ȱ' => '홧', 'Ȳ' => '황', 'ȳ' => '홰', 'ȴ' => '홱', 'ȵ' => '홴', 'ȶ' => '횃', 'ȷ' => '횅', 'ȸ' => '회', 'ȹ' => '획', 'Ⱥ' => '횐', 'Ȼ' => '횔', 'ȼ' => '횝', 'Ƚ' => '횟', 'Ⱦ' => '횡', 'ȿ' => '효', '' => '횬', '' => '횰', '' => '횹', '' => '횻', '' => '후', '' => '훅', '' => '훈', '' => '훌', '' => '훑', '' => '훔', '' => '훗', '' => '훙', '' => '훠', '' => '훤', '' => '훨', '' => '훰', '' => '훵', '' => '훼', '' => '훽', '' => '휀', '' => '휄', '' => '휑', '' => '휘', '' => '휙', '' => '휜', '' => '휠', '' => '휨', '' => '휩', '' => '휫', '' => '휭', '' => '휴', '' => '휵', '' => '휸', '' => '휼', '' => '흄', '' => '흇', '' => '흉', '' => '흐', '' => '흑', '' => '흔', '' => '흖', '' => '흗', '' => '흘', '' => '흙', '' => '흠', '' => '흡', '' => '흣', '' => '흥', '' => '흩', '' => '희', '' => '흰', '' => '흴', '' => '흼', '' => '흽', '' => '힁', '' => '히', '' => '힉', '' => '힌', '' => '힐', '' => '힘', '' => '힙', '' => '힛', '' => '힝', 'ʡ' => '伽', 'ʢ' => '佳', 'ʣ' => '假', 'ʤ' => '價', 'ʥ' => '加', 'ʦ' => '可', 'ʧ' => '呵', 'ʨ' => '哥', 'ʩ' => '嘉', 'ʪ' => '嫁', 'ʫ' => '家', 'ʬ' => '暇', 'ʭ' => '架', 'ʮ' => '枷', 'ʯ' => '柯', 'ʰ' => '歌', 'ʱ' => '珂', 'ʲ' => '痂', 'ʳ' => '稼', 'ʴ' => '苛', 'ʵ' => '茄', 'ʶ' => '街', 'ʷ' => '袈', 'ʸ' => '訶', 'ʹ' => '賈', 'ʺ' => '跏', 'ʻ' => '軻', 'ʼ' => '迦', 'ʽ' => '駕', 'ʾ' => '刻', 'ʿ' => '却', '' => '各', '' => '恪', '' => '慤', '' => '殼', '' => '珏', '' => '脚', '' => '覺', '' => '角', '' => '閣', '' => '侃', '' => '刊', '' => '墾', '' => '奸', '' => '姦', '' => '干', '' => '幹', '' => '懇', '' => '揀', '' => '杆', '' => '柬', '' => '桿', '' => '澗', '' => '癎', '' => '看', '' => '磵', '' => '稈', '' => '竿', '' => '簡', '' => '肝', '' => '艮', '' => '艱', '' => '諫', '' => '間', '' => '乫', '' => '喝', '' => '曷', '' => '渴', '' => '碣', '' => '竭', '' => '葛', '' => '褐', '' => '蝎', '' => '鞨', '' => '勘', '' => '坎', '' => '堪', '' => '嵌', '' => '感', '' => '憾', '' => '戡', '' => '敢', '' => '柑', '' => '橄', '' => '減', '' => '甘', '' => '疳', '' => '監', '' => '瞰', '' => '紺', '' => '邯', '' => '鑑', '' => '鑒', '' => '龕', 'ˡ' => '匣', 'ˢ' => '岬', 'ˣ' => '甲', 'ˤ' => '胛', '˥' => '鉀', '˦' => '閘', '˧' => '剛', '˨' => '堈', '˩' => '姜', '˪' => '岡', '˫' => '崗', 'ˬ' => '康', '˭' => '强', 'ˮ' => '彊', '˯' => '慷', '˰' => '江', '˱' => '畺', '˲' => '疆', '˳' => '糠', '˴' => '絳', '˵' => '綱', '˶' => '羌', '˷' => '腔', '˸' => '舡', '˹' => '薑', '˺' => '襁', '˻' => '講', '˼' => '鋼', '˽' => '降', '˾' => '鱇', '˿' => '介', '' => '价', '' => '個', '' => '凱', '' => '塏', '' => '愷', '' => '愾', '' => '慨', '' => '改', '' => '槪', '' => '漑', '' => '疥', '' => '皆', '' => '盖', '' => '箇', '' => '芥', '' => '蓋', '' => '豈', '' => '鎧', '' => '開', '' => '喀', '' => '客', '' => '坑', '' => '更', '' => '粳', '' => '羹', '' => '醵', '' => '倨', '' => '去', '' => '居', '' => '巨', '' => '拒', '' => '据', '' => '據', '' => '擧', '' => '渠', '' => '炬', '' => '祛', '' => '距', '' => '踞', '' => '車', '' => '遽', '' => '鉅', '' => '鋸', '' => '乾', '' => '件', '' => '健', '' => '巾', '' => '建', '' => '愆', '' => '楗', '' => '腱', '' => '虔', '' => '蹇', '' => '鍵', '' => '騫', '' => '乞', '' => '傑', '' => '杰', '' => '桀', '' => '儉', '' => '劍', '' => '劒', '' => '檢', '̡' => '瞼', '̢' => '鈐', '̣' => '黔', '̤' => '劫', '̥' => '怯', '̦' => '迲', '̧' => '偈', '̨' => '憩', '̩' => '揭', '̪' => '擊', '̫' => '格', '̬' => '檄', '̭' => '激', '̮' => '膈', '̯' => '覡', '̰' => '隔', '̱' => '堅', '̲' => '牽', '̳' => '犬', '̴' => '甄', '̵' => '絹', '̶' => '繭', '̷' => '肩', '̸' => '見', '̹' => '譴', '̺' => '遣', '̻' => '鵑', '̼' => '抉', '̽' => '決', '̾' => '潔', '̿' => '結', '' => '缺', '' => '訣', '' => '兼', '' => '慊', '' => '箝', '' => '謙', '' => '鉗', '' => '鎌', '' => '京', '' => '俓', '' => '倞', '' => '傾', '' => '儆', '' => '勁', '' => '勍', '' => '卿', '' => '坰', '' => '境', '' => '庚', '' => '徑', '' => '慶', '' => '憬', '' => '擎', '' => '敬', '' => '景', '' => '暻', '' => '更', '' => '梗', '' => '涇', '' => '炅', '' => '烱', '' => '璟', '' => '璥', '' => '瓊', '' => '痙', '' => '硬', '' => '磬', '' => '竟', '' => '競', '' => '絅', '' => '經', '' => '耕', '' => '耿', '' => '脛', '' => '莖', '' => '警', '' => '輕', '' => '逕', '' => '鏡', '' => '頃', '' => '頸', '' => '驚', '' => '鯨', '' => '係', '' => '啓', '' => '堺', '' => '契', '' => '季', '' => '屆', '' => '悸', '' => '戒', '' => '桂', '' => '械', '͡' => '棨', '͢' => '溪', 'ͣ' => '界', 'ͤ' => '癸', 'ͥ' => '磎', 'ͦ' => '稽', 'ͧ' => '系', 'ͨ' => '繫', 'ͩ' => '繼', 'ͪ' => '計', 'ͫ' => '誡', 'ͬ' => '谿', 'ͭ' => '階', 'ͮ' => '鷄', 'ͯ' => '古', 'Ͱ' => '叩', 'ͱ' => '告', 'Ͳ' => '呱', 'ͳ' => '固', 'ʹ' => '姑', '͵' => '孤', 'Ͷ' => '尻', 'ͷ' => '庫', '͸' => '拷', '͹' => '攷', 'ͺ' => '故', 'ͻ' => '敲', 'ͼ' => '暠', 'ͽ' => '枯', ';' => '槁', 'Ϳ' => '沽', '' => '痼', '' => '皐', '' => '睾', '' => '稿', '' => '羔', '' => '考', '' => '股', '' => '膏', '' => '苦', '' => '苽', '' => '菰', '' => '藁', '' => '蠱', '' => '袴', '' => '誥', '' => '賈', '' => '辜', '' => '錮', '' => '雇', '' => '顧', '' => '高', '' => '鼓', '' => '哭', '' => '斛', '' => '曲', '' => '梏', '' => '穀', '' => '谷', '' => '鵠', '' => '困', '' => '坤', '' => '崑', '' => '昆', '' => '梱', '' => '棍', '' => '滾', '' => '琨', '' => '袞', '' => '鯤', '' => '汨', '' => '滑', '' => '骨', '' => '供', '' => '公', '' => '共', '' => '功', '' => '孔', '' => '工', '' => '恐', '' => '恭', '' => '拱', '' => '控', '' => '攻', '' => '珙', '' => '空', '' => '蚣', '' => '貢', '' => '鞏', '' => '串', '' => '寡', '' => '戈', '' => '果', '' => '瓜', 'Ρ' => '科', '΢' => '菓', 'Σ' => '誇', 'Τ' => '課', 'Υ' => '跨', 'Φ' => '過', 'Χ' => '鍋', 'Ψ' => '顆', 'Ω' => '廓', 'Ϊ' => '槨', 'Ϋ' => '藿', 'ά' => '郭', 'έ' => '串', 'ή' => '冠', 'ί' => '官', 'ΰ' => '寬', 'α' => '慣', 'β' => '棺', 'γ' => '款', 'δ' => '灌', 'ε' => '琯', 'ζ' => '瓘', 'η' => '管', 'θ' => '罐', 'ι' => '菅', 'κ' => '觀', 'λ' => '貫', 'μ' => '關', 'ν' => '館', 'ξ' => '刮', 'ο' => '恝', '' => '括', '' => '适', '' => '侊', '' => '光', '' => '匡', '' => '壙', '' => '廣', '' => '曠', '' => '洸', '' => '炚', '' => '狂', '' => '珖', '' => '筐', '' => '胱', '' => '鑛', '' => '卦', '' => '掛', '' => '罫', '' => '乖', '' => '傀', '' => '塊', '' => '壞', '' => '怪', '' => '愧', '' => '拐', '' => '槐', '' => '魁', '' => '宏', '' => '紘', '' => '肱', '' => '轟', '' => '交', '' => '僑', '' => '咬', '' => '喬', '' => '嬌', '' => '嶠', '' => '巧', '' => '攪', '' => '敎', '' => '校', '' => '橋', '' => '狡', '' => '皎', '' => '矯', '' => '絞', '' => '翹', '' => '膠', '' => '蕎', '' => '蛟', '' => '較', '' => '轎', '' => '郊', '' => '餃', '' => '驕', '' => '鮫', '' => '丘', '' => '久', '' => '九', '' => '仇', '' => '俱', '' => '具', '' => '勾', 'ϡ' => '區', 'Ϣ' => '口', 'ϣ' => '句', 'Ϥ' => '咎', 'ϥ' => '嘔', 'Ϧ' => '坵', 'ϧ' => '垢', 'Ϩ' => '寇', 'ϩ' => '嶇', 'Ϫ' => '廐', 'ϫ' => '懼', 'Ϭ' => '拘', 'ϭ' => '救', 'Ϯ' => '枸', 'ϯ' => '柩', 'ϰ' => '構', 'ϱ' => '歐', 'ϲ' => '毆', 'ϳ' => '毬', 'ϴ' => '求', 'ϵ' => '溝', '϶' => '灸', 'Ϸ' => '狗', 'ϸ' => '玖', 'Ϲ' => '球', 'Ϻ' => '瞿', 'ϻ' => '矩', 'ϼ' => '究', 'Ͻ' => '絿', 'Ͼ' => '耉', 'Ͽ' => '臼', '' => '舅', '' => '舊', '' => '苟', '' => '衢', '' => '謳', '' => '購', '' => '軀', '' => '逑', '' => '邱', '' => '鉤', '' => '銶', '' => '駒', '' => '驅', '' => '鳩', '' => '鷗', '' => '龜', '' => '國', '' => '局', '' => '菊', '' => '鞠', '' => '鞫', '' => '麴', '' => '君', '' => '窘', '' => '群', '' => '裙', '' => '軍', '' => '郡', '' => '堀', '' => '屈', '' => '掘', '' => '窟', '' => '宮', '' => '弓', '' => '穹', '' => '窮', '' => '芎', '' => '躬', '' => '倦', '' => '券', '' => '勸', '' => '卷', '' => '圈', '' => '拳', '' => '捲', '' => '權', '' => '淃', '' => '眷', '' => '厥', '' => '獗', '' => '蕨', '' => '蹶', '' => '闕', '' => '机', '' => '櫃', '' => '潰', '' => '詭', '' => '軌', '' => '饋', '' => '句', '' => '晷', '' => '歸', '' => '貴', 'С' => '鬼', 'Т' => '龜', 'У' => '叫', 'Ф' => '圭', 'Х' => '奎', 'Ц' => '揆', 'Ч' => '槻', 'Ш' => '珪', 'Щ' => '硅', 'Ъ' => '窺', 'Ы' => '竅', 'Ь' => '糾', 'Э' => '葵', 'Ю' => '規', 'Я' => '赳', 'а' => '逵', 'б' => '閨', 'в' => '勻', 'г' => '均', 'д' => '畇', 'е' => '筠', 'ж' => '菌', 'з' => '鈞', 'и' => '龜', 'й' => '橘', 'к' => '克', 'л' => '剋', 'м' => '劇', 'н' => '戟', 'о' => '棘', 'п' => '極', '' => '隙', '' => '僅', '' => '劤', '' => '勤', '' => '懃', '' => '斤', '' => '根', '' => '槿', '' => '瑾', '' => '筋', '' => '芹', '' => '菫', '' => '覲', '' => '謹', '' => '近', '' => '饉', '' => '契', '' => '今', '' => '妗', '' => '擒', '' => '昑', '' => '檎', '' => '琴', '' => '禁', '' => '禽', '' => '芩', '' => '衾', '' => '衿', '' => '襟', '' => '金', '' => '錦', '' => '伋', '' => '及', '' => '急', '' => '扱', '' => '汲', '' => '級', '' => '給', '' => '亘', '' => '兢', '' => '矜', '' => '肯', '' => '企', '' => '伎', '' => '其', '' => '冀', '' => '嗜', '' => '器', '' => '圻', '' => '基', '' => '埼', '' => '夔', '' => '奇', '' => '妓', '' => '寄', '' => '岐', '' => '崎', '' => '己', '' => '幾', '' => '忌', '' => '技', '' => '旗', '' => '旣', 'ѡ' => '朞', 'Ѣ' => '期', 'ѣ' => '杞', 'Ѥ' => '棋', 'ѥ' => '棄', 'Ѧ' => '機', 'ѧ' => '欺', 'Ѩ' => '氣', 'ѩ' => '汽', 'Ѫ' => '沂', 'ѫ' => '淇', 'Ѭ' => '玘', 'ѭ' => '琦', 'Ѯ' => '琪', 'ѯ' => '璂', 'Ѱ' => '璣', 'ѱ' => '畸', 'Ѳ' => '畿', 'ѳ' => '碁', 'Ѵ' => '磯', 'ѵ' => '祁', 'Ѷ' => '祇', 'ѷ' => '祈', 'Ѹ' => '祺', 'ѹ' => '箕', 'Ѻ' => '紀', 'ѻ' => '綺', 'Ѽ' => '羈', 'ѽ' => '耆', 'Ѿ' => '耭', 'ѿ' => '肌', '' => '記', '' => '譏', '' => '豈', '' => '起', '' => '錡', '' => '錤', '' => '飢', '' => '饑', '' => '騎', '' => '騏', '' => '驥', '' => '麒', '' => '緊', '' => '佶', '' => '吉', '' => '拮', '' => '桔', '' => '金', '' => '喫', '' => '儺', '' => '喇', '' => '奈', '' => '娜', '' => '懦', '' => '懶', '' => '拏', '' => '拿', '' => '癩', '' => '羅', '' => '蘿', '' => '螺', '' => '裸', '' => '邏', '' => '那', '' => '樂', '' => '洛', '' => '烙', '' => '珞', '' => '落', '' => '諾', '' => '酪', '' => '駱', '' => '亂', '' => '卵', '' => '暖', '' => '欄', '' => '煖', '' => '爛', '' => '蘭', '' => '難', '' => '鸞', '' => '捏', '' => '捺', '' => '南', '' => '嵐', '' => '枏', '' => '楠', '' => '湳', '' => '濫', '' => '男', '' => '藍', '' => '襤', '' => '拉', 'ҡ' => '納', 'Ң' => '臘', 'ң' => '蠟', 'Ҥ' => '衲', 'ҥ' => '囊', 'Ҧ' => '娘', 'ҧ' => '廊', 'Ҩ' => '朗', 'ҩ' => '浪', 'Ҫ' => '狼', 'ҫ' => '郎', 'Ҭ' => '乃', 'ҭ' => '來', 'Ү' => '內', 'ү' => '奈', 'Ұ' => '柰', 'ұ' => '耐', 'Ҳ' => '冷', 'ҳ' => '女', 'Ҵ' => '年', 'ҵ' => '撚', 'Ҷ' => '秊', 'ҷ' => '念', 'Ҹ' => '恬', 'ҹ' => '拈', 'Һ' => '捻', 'һ' => '寧', 'Ҽ' => '寗', 'ҽ' => '努', 'Ҿ' => '勞', 'ҿ' => '奴', '' => '弩', '' => '怒', '' => '擄', '' => '櫓', '' => '爐', '' => '瑙', '' => '盧', '' => '老', '' => '蘆', '' => '虜', '' => '路', '' => '露', '' => '駑', '' => '魯', '' => '鷺', '' => '碌', '' => '祿', '' => '綠', '' => '菉', '' => '錄', '' => '鹿', '' => '論', '' => '壟', '' => '弄', '' => '濃', '' => '籠', '' => '聾', '' => '膿', '' => '農', '' => '惱', '' => '牢', '' => '磊', '' => '腦', '' => '賂', '' => '雷', '' => '尿', '' => '壘', '' => '屢', '' => '樓', '' => '淚', '' => '漏', '' => '累', '' => '縷', '' => '陋', '' => '嫩', '' => '訥', '' => '杻', '' => '紐', '' => '勒', '' => '肋', '' => '凜', '' => '凌', '' => '稜', '' => '綾', '' => '能', '' => '菱', '' => '陵', '' => '尼', '' => '泥', '' => '匿', '' => '溺', '' => '多', '' => '茶', 'ӡ' => '丹', 'Ӣ' => '亶', 'ӣ' => '但', 'Ӥ' => '單', 'ӥ' => '團', 'Ӧ' => '壇', 'ӧ' => '彖', 'Ө' => '斷', 'ө' => '旦', 'Ӫ' => '檀', 'ӫ' => '段', 'Ӭ' => '湍', 'ӭ' => '短', 'Ӯ' => '端', 'ӯ' => '簞', 'Ӱ' => '緞', 'ӱ' => '蛋', 'Ӳ' => '袒', 'ӳ' => '鄲', 'Ӵ' => '鍛', 'ӵ' => '撻', 'Ӷ' => '澾', 'ӷ' => '獺', 'Ӹ' => '疸', 'ӹ' => '達', 'Ӻ' => '啖', 'ӻ' => '坍', 'Ӽ' => '憺', 'ӽ' => '擔', 'Ӿ' => '曇', 'ӿ' => '淡', '' => '湛', '' => '潭', '' => '澹', '' => '痰', '' => '聃', '' => '膽', '' => '蕁', '' => '覃', '' => '談', '' => '譚', '' => '錟', '' => '沓', '' => '畓', '' => '答', '' => '踏', '' => '遝', '' => '唐', '' => '堂', '' => '塘', '' => '幢', '' => '戇', '' => '撞', '' => '棠', '' => '當', '' => '糖', '' => '螳', '' => '黨', '' => '代', '' => '垈', '' => '坮', '' => '大', '' => '對', '' => '岱', '' => '帶', '' => '待', '' => '戴', '' => '擡', '' => '玳', '' => '臺', '' => '袋', '' => '貸', '' => '隊', '' => '黛', '' => '宅', '' => '德', '' => '悳', '' => '倒', '' => '刀', '' => '到', '' => '圖', '' => '堵', '' => '塗', '' => '導', '' => '屠', '' => '島', '' => '嶋', '' => '度', '' => '徒', '' => '悼', '' => '挑', '' => '掉', '' => '搗', '' => '桃', 'ԡ' => '棹', 'Ԣ' => '櫂', 'ԣ' => '淘', 'Ԥ' => '渡', 'ԥ' => '滔', 'Ԧ' => '濤', 'ԧ' => '燾', 'Ԩ' => '盜', 'ԩ' => '睹', 'Ԫ' => '禱', 'ԫ' => '稻', 'Ԭ' => '萄', 'ԭ' => '覩', 'Ԯ' => '賭', 'ԯ' => '跳', '԰' => '蹈', 'Ա' => '逃', 'Բ' => '途', 'Գ' => '道', 'Դ' => '都', 'Ե' => '鍍', 'Զ' => '陶', 'Է' => '韜', 'Ը' => '毒', 'Թ' => '瀆', 'Ժ' => '牘', 'Ի' => '犢', 'Լ' => '獨', 'Խ' => '督', 'Ծ' => '禿', 'Կ' => '篤', '' => '纛', '' => '讀', '' => '墩', '' => '惇', '' => '敦', '' => '旽', '' => '暾', '' => '沌', '' => '焞', '' => '燉', '' => '豚', '' => '頓', '' => '乭', '' => '突', '' => '仝', '' => '冬', '' => '凍', '' => '動', '' => '同', '' => '憧', '' => '東', '' => '桐', '' => '棟', '' => '洞', '' => '潼', '' => '疼', '' => '瞳', '' => '童', '' => '胴', '' => '董', '' => '銅', '' => '兜', '' => '斗', '' => '杜', '' => '枓', '' => '痘', '' => '竇', '' => '荳', '' => '讀', '' => '豆', '' => '逗', '' => '頭', '' => '屯', '' => '臀', '' => '芚', '' => '遁', '' => '遯', '' => '鈍', '' => '得', '' => '嶝', '' => '橙', '' => '燈', '' => '登', '' => '等', '' => '藤', '' => '謄', '' => '鄧', '' => '騰', '' => '喇', '' => '懶', '' => '拏', '' => '癩', '' => '羅', 'ա' => '蘿', 'բ' => '螺', 'գ' => '裸', 'դ' => '邏', 'ե' => '樂', 'զ' => '洛', 'է' => '烙', 'ը' => '珞', 'թ' => '絡', 'ժ' => '落', 'ի' => '諾', 'լ' => '酪', 'խ' => '駱', 'ծ' => '丹', 'կ' => '亂', 'հ' => '卵', 'ձ' => '欄', 'ղ' => '欒', 'ճ' => '瀾', 'մ' => '爛', 'յ' => '蘭', 'ն' => '鸞', 'շ' => '剌', 'ո' => '辣', 'չ' => '嵐', 'պ' => '擥', 'ջ' => '攬', 'ռ' => '欖', 'ս' => '濫', 'վ' => '籃', 'տ' => '纜', '' => '藍', '' => '襤', '' => '覽', '' => '拉', '' => '臘', '' => '蠟', '' => '廊', '' => '朗', '' => '浪', '' => '狼', '' => '琅', '' => '瑯', '' => '螂', '' => '郞', '' => '來', '' => '崍', '' => '徠', '' => '萊', '' => '冷', '' => '掠', '' => '略', '' => '亮', '' => '倆', '' => '兩', '' => '凉', '' => '梁', '' => '樑', '' => '粮', '' => '粱', '' => '糧', '' => '良', '' => '諒', '' => '輛', '' => '量', '' => '侶', '' => '儷', '' => '勵', '' => '呂', '' => '廬', '' => '慮', '' => '戾', '' => '旅', '' => '櫚', '' => '濾', '' => '礪', '' => '藜', '' => '蠣', '' => '閭', '' => '驢', '' => '驪', '' => '麗', '' => '黎', '' => '力', '' => '曆', '' => '歷', '' => '瀝', '' => '礫', '' => '轢', '' => '靂', '' => '憐', '' => '戀', '' => '攣', '' => '漣', '֡' => '煉', '֢' => '璉', '֣' => '練', '֤' => '聯', '֥' => '蓮', '֦' => '輦', '֧' => '連', '֨' => '鍊', '֩' => '冽', '֪' => '列', '֫' => '劣', '֬' => '洌', '֭' => '烈', '֮' => '裂', '֯' => '廉', 'ְ' => '斂', 'ֱ' => '殮', 'ֲ' => '濂', 'ֳ' => '簾', 'ִ' => '獵', 'ֵ' => '令', 'ֶ' => '伶', 'ַ' => '囹', 'ָ' => '寧', 'ֹ' => '岺', 'ֺ' => '嶺', 'ֻ' => '怜', 'ּ' => '玲', 'ֽ' => '笭', '־' => '羚', 'ֿ' => '翎', '' => '聆', '' => '逞', '' => '鈴', '' => '零', '' => '靈', '' => '領', '' => '齡', '' => '例', '' => '澧', '' => '禮', '' => '醴', '' => '隷', '' => '勞', '' => '怒', '' => '撈', '' => '擄', '' => '櫓', '' => '潞', '' => '瀘', '' => '爐', '' => '盧', '' => '老', '' => '蘆', '' => '虜', '' => '路', '' => '輅', '' => '露', '' => '魯', '' => '鷺', '' => '鹵', '' => '碌', '' => '祿', '' => '綠', '' => '菉', '' => '錄', '' => '鹿', '' => '麓', '' => '論', '' => '壟', '' => '弄', '' => '朧', '' => '瀧', '' => '瓏', '' => '籠', '' => '聾', '' => '儡', '' => '瀨', '' => '牢', '' => '磊', '' => '賂', '' => '賚', '' => '賴', '' => '雷', '' => '了', '' => '僚', '' => '寮', '' => '廖', '' => '料', '' => '燎', '' => '療', '' => '瞭', '' => '聊', '' => '蓼', 'ס' => '遼', 'ע' => '鬧', 'ף' => '龍', 'פ' => '壘', 'ץ' => '婁', 'צ' => '屢', 'ק' => '樓', 'ר' => '淚', 'ש' => '漏', 'ת' => '瘻', '׫' => '累', '׬' => '縷', '׭' => '蔞', '׮' => '褸', 'ׯ' => '鏤', 'װ' => '陋', 'ױ' => '劉', 'ײ' => '旒', '׳' => '柳', '״' => '榴', '׵' => '流', '׶' => '溜', '׷' => '瀏', '׸' => '琉', '׹' => '瑠', '׺' => '留', '׻' => '瘤', '׼' => '硫', '׽' => '謬', '׾' => '類', '׿' => '六', '' => '戮', '' => '陸', '' => '侖', '' => '倫', '' => '崙', '' => '淪', '' => '綸', '' => '輪', '' => '律', '' => '慄', '' => '栗', '' => '率', '' => '隆', '' => '勒', '' => '肋', '' => '凜', '' => '凌', '' => '楞', '' => '稜', '' => '綾', '' => '菱', '' => '陵', '' => '俚', '' => '利', '' => '厘', '' => '吏', '' => '唎', '' => '履', '' => '悧', '' => '李', '' => '梨', '' => '浬', '' => '犁', '' => '狸', '' => '理', '' => '璃', '' => '異', '' => '痢', '' => '籬', '' => '罹', '' => '羸', '' => '莉', '' => '裏', '' => '裡', '' => '里', '' => '釐', '' => '離', '' => '鯉', '' => '吝', '' => '潾', '' => '燐', '' => '璘', '' => '藺', '' => '躪', '' => '隣', '' => '鱗', '' => '麟', '' => '林', '' => '淋', '' => '琳', '' => '臨', '' => '霖', '' => '砬', 'ء' => '立', 'آ' => '笠', 'أ' => '粒', 'ؤ' => '摩', 'إ' => '瑪', 'ئ' => '痲', 'ا' => '碼', 'ب' => '磨', 'ة' => '馬', 'ت' => '魔', 'ث' => '麻', 'ج' => '寞', 'ح' => '幕', 'خ' => '漠', 'د' => '膜', 'ذ' => '莫', 'ر' => '邈', 'ز' => '万', 'س' => '卍', 'ش' => '娩', 'ص' => '巒', 'ض' => '彎', 'ط' => '慢', 'ظ' => '挽', 'ع' => '晩', 'غ' => '曼', 'ػ' => '滿', 'ؼ' => '漫', 'ؽ' => '灣', 'ؾ' => '瞞', 'ؿ' => '萬', '' => '蔓', '' => '蠻', '' => '輓', '' => '饅', '' => '鰻', '' => '唜', '' => '抹', '' => '末', '' => '沫', '' => '茉', '' => '襪', '' => '靺', '' => '亡', '' => '妄', '' => '忘', '' => '忙', '' => '望', '' => '網', '' => '罔', '' => '芒', '' => '茫', '' => '莽', '' => '輞', '' => '邙', '' => '埋', '' => '妹', '' => '媒', '' => '寐', '' => '昧', '' => '枚', '' => '梅', '' => '每', '' => '煤', '' => '罵', '' => '買', '' => '賣', '' => '邁', '' => '魅', '' => '脈', '' => '貊', '' => '陌', '' => '驀', '' => '麥', '' => '孟', '' => '氓', '' => '猛', '' => '盲', '' => '盟', '' => '萌', '' => '冪', '' => '覓', '' => '免', '' => '冕', '' => '勉', '' => '棉', '' => '沔', '' => '眄', '' => '眠', '' => '綿', '' => '緬', '' => '面', '' => '麵', '' => '滅', '١' => '蔑', '٢' => '冥', '٣' => '名', '٤' => '命', '٥' => '明', '٦' => '暝', '٧' => '椧', '٨' => '溟', '٩' => '皿', '٪' => '瞑', '٫' => '茗', '٬' => '蓂', '٭' => '螟', 'ٮ' => '酩', 'ٯ' => '銘', 'ٰ' => '鳴', 'ٱ' => '袂', 'ٲ' => '侮', 'ٳ' => '冒', 'ٴ' => '募', 'ٵ' => '姆', 'ٶ' => '帽', 'ٷ' => '慕', 'ٸ' => '摸', 'ٹ' => '摹', 'ٺ' => '暮', 'ٻ' => '某', 'ټ' => '模', 'ٽ' => '母', 'پ' => '毛', 'ٿ' => '牟', '' => '牡', '' => '瑁', '' => '眸', '' => '矛', '' => '耗', '' => '芼', '' => '茅', '' => '謀', '' => '謨', '' => '貌', '' => '木', '' => '沐', '' => '牧', '' => '目', '' => '睦', '' => '穆', '' => '鶩', '' => '歿', '' => '沒', '' => '夢', '' => '朦', '' => '蒙', '' => '卯', '' => '墓', '' => '妙', '' => '廟', '' => '描', '' => '昴', '' => '杳', '' => '渺', '' => '猫', '' => '竗', '' => '苗', '' => '錨', '' => '務', '' => '巫', '' => '憮', '' => '懋', '' => '戊', '' => '拇', '' => '撫', '' => '无', '' => '楙', '' => '武', '' => '毋', '' => '無', '' => '珷', '' => '畝', '' => '繆', '' => '舞', '' => '茂', '' => '蕪', '' => '誣', '' => '貿', '' => '霧', '' => '鵡', '' => '墨', '' => '默', '' => '們', '' => '刎', '' => '吻', '' => '問', '' => '文', 'ڡ' => '汶', 'ڢ' => '紊', 'ڣ' => '紋', 'ڤ' => '聞', 'ڥ' => '蚊', 'ڦ' => '門', 'ڧ' => '雯', 'ڨ' => '勿', 'ک' => '沕', 'ڪ' => '物', 'ګ' => '味', 'ڬ' => '媚', 'ڭ' => '尾', 'ڮ' => '嵋', 'گ' => '彌', 'ڰ' => '微', 'ڱ' => '未', 'ڲ' => '梶', 'ڳ' => '楣', 'ڴ' => '渼', 'ڵ' => '湄', 'ڶ' => '眉', 'ڷ' => '米', 'ڸ' => '美', 'ڹ' => '薇', 'ں' => '謎', 'ڻ' => '迷', 'ڼ' => '靡', 'ڽ' => '黴', 'ھ' => '岷', 'ڿ' => '悶', '' => '愍', '' => '憫', '' => '敏', '' => '旻', '' => '旼', '' => '民', '' => '泯', '' => '玟', '' => '珉', '' => '緡', '' => '閔', '' => '密', '' => '蜜', '' => '謐', '' => '剝', '' => '博', '' => '拍', '' => '搏', '' => '撲', '' => '朴', '' => '樸', '' => '泊', '' => '珀', '' => '璞', '' => '箔', '' => '粕', '' => '縛', '' => '膊', '' => '舶', '' => '薄', '' => '迫', '' => '雹', '' => '駁', '' => '伴', '' => '半', '' => '反', '' => '叛', '' => '拌', '' => '搬', '' => '攀', '' => '斑', '' => '槃', '' => '泮', '' => '潘', '' => '班', '' => '畔', '' => '瘢', '' => '盤', '' => '盼', '' => '磐', '' => '磻', '' => '礬', '' => '絆', '' => '般', '' => '蟠', '' => '返', '' => '頒', '' => '飯', '' => '勃', '' => '拔', '' => '撥', '' => '渤', '' => '潑', 'ۡ' => '發', 'ۢ' => '跋', 'ۣ' => '醱', 'ۤ' => '鉢', 'ۥ' => '髮', 'ۦ' => '魃', 'ۧ' => '倣', 'ۨ' => '傍', '۩' => '坊', '۪' => '妨', '۫' => '尨', '۬' => '幇', 'ۭ' => '彷', 'ۮ' => '房', 'ۯ' => '放', '۰' => '方', '۱' => '旁', '۲' => '昉', '۳' => '枋', '۴' => '榜', '۵' => '滂', '۶' => '磅', '۷' => '紡', '۸' => '肪', '۹' => '膀', 'ۺ' => '舫', 'ۻ' => '芳', 'ۼ' => '蒡', '۽' => '蚌', '۾' => '訪', 'ۿ' => '謗', '' => '邦', '' => '防', '' => '龐', '' => '倍', '' => '俳', '' => '北', '' => '培', '' => '徘', '' => '拜', '' => '排', '' => '杯', '' => '湃', '' => '焙', '' => '盃', '' => '背', '' => '胚', '' => '裴', '' => '裵', '' => '褙', '' => '賠', '' => '輩', '' => '配', '' => '陪', '' => '伯', '' => '佰', '' => '帛', '' => '柏', '' => '栢', '' => '白', '' => '百', '' => '魄', '' => '幡', '' => '樊', '' => '煩', '' => '燔', '' => '番', '' => '磻', '' => '繁', '' => '蕃', '' => '藩', '' => '飜', '' => '伐', '' => '筏', '' => '罰', '' => '閥', '' => '凡', '' => '帆', '' => '梵', '' => '氾', '' => '汎', '' => '泛', '' => '犯', '' => '範', '' => '范', '' => '法', '' => '琺', '' => '僻', '' => '劈', '' => '壁', '' => '擘', '' => '檗', '' => '璧', '' => '癖', 'ܡ' => '碧', 'ܢ' => '蘗', 'ܣ' => '闢', 'ܤ' => '霹', 'ܥ' => '便', 'ܦ' => '卞', 'ܧ' => '弁', 'ܨ' => '變', 'ܩ' => '辨', 'ܪ' => '辯', 'ܫ' => '邊', 'ܬ' => '別', 'ܭ' => '瞥', 'ܮ' => '鱉', 'ܯ' => '鼈', 'ܰ' => '丙', 'ܱ' => '倂', 'ܲ' => '兵', 'ܳ' => '屛', 'ܴ' => '幷', 'ܵ' => '昞', 'ܶ' => '昺', 'ܷ' => '柄', 'ܸ' => '棅', 'ܹ' => '炳', 'ܺ' => '甁', 'ܻ' => '病', 'ܼ' => '秉', 'ܽ' => '竝', 'ܾ' => '輧', 'ܿ' => '餠', '' => '騈', '' => '保', '' => '堡', '' => '報', '' => '寶', '' => '普', '' => '步', '' => '洑', '' => '湺', '' => '潽', '' => '珤', '' => '甫', '' => '菩', '' => '補', '' => '褓', '' => '譜', '' => '輔', '' => '伏', '' => '僕', '' => '匐', '' => '卜', '' => '宓', '' => '復', '' => '服', '' => '福', '' => '腹', '' => '茯', '' => '蔔', '' => '複', '' => '覆', '' => '輹', '' => '輻', '' => '馥', '' => '鰒', '' => '本', '' => '乶', '' => '俸', '' => '奉', '' => '封', '' => '峯', '' => '峰', '' => '捧', '' => '棒', '' => '烽', '' => '熢', '' => '琫', '' => '縫', '' => '蓬', '' => '蜂', '' => '逢', '' => '鋒', '' => '鳳', '' => '不', '' => '付', '' => '俯', '' => '傅', '' => '剖', '' => '副', '' => '否', '' => '咐', '' => '埠', '' => '夫', '' => '婦', 'ݡ' => '孚', 'ݢ' => '孵', 'ݣ' => '富', 'ݤ' => '府', 'ݥ' => '復', 'ݦ' => '扶', 'ݧ' => '敷', 'ݨ' => '斧', 'ݩ' => '浮', 'ݪ' => '溥', 'ݫ' => '父', 'ݬ' => '符', 'ݭ' => '簿', 'ݮ' => '缶', 'ݯ' => '腐', 'ݰ' => '腑', 'ݱ' => '膚', 'ݲ' => '艀', 'ݳ' => '芙', 'ݴ' => '莩', 'ݵ' => '訃', 'ݶ' => '負', 'ݷ' => '賦', 'ݸ' => '賻', 'ݹ' => '赴', 'ݺ' => '趺', 'ݻ' => '部', 'ݼ' => '釜', 'ݽ' => '阜', 'ݾ' => '附', 'ݿ' => '駙', '' => '鳧', '' => '北', '' => '分', '' => '吩', '' => '噴', '' => '墳', '' => '奔', '' => '奮', '' => '忿', '' => '憤', '' => '扮', '' => '昐', '' => '汾', '' => '焚', '' => '盆', '' => '粉', '' => '糞', '' => '紛', '' => '芬', '' => '賁', '' => '雰', '' => '不', '' => '佛', '' => '弗', '' => '彿', '' => '拂', '' => '崩', '' => '朋', '' => '棚', '' => '硼', '' => '繃', '' => '鵬', '' => '丕', '' => '備', '' => '匕', '' => '匪', '' => '卑', '' => '妃', '' => '婢', '' => '庇', '' => '悲', '' => '憊', '' => '扉', '' => '批', '' => '斐', '' => '枇', '' => '榧', '' => '比', '' => '毖', '' => '毗', '' => '毘', '' => '沸', '' => '泌', '' => '琵', '' => '痺', '' => '砒', '' => '碑', '' => '秕', '' => '秘', '' => '粃', '' => '緋', '' => '翡', '' => '肥', 'ޡ' => '脾', 'ޢ' => '臂', 'ޣ' => '菲', 'ޤ' => '蜚', 'ޥ' => '裨', 'ަ' => '誹', 'ާ' => '譬', 'ި' => '費', 'ީ' => '鄙', 'ު' => '非', 'ޫ' => '飛', 'ެ' => '鼻', 'ޭ' => '嚬', 'ޮ' => '嬪', 'ޯ' => '彬', 'ް' => '斌', 'ޱ' => '檳', '޲' => '殯', '޳' => '浜', '޴' => '濱', '޵' => '瀕', '޶' => '牝', '޷' => '玭', '޸' => '貧', '޹' => '賓', '޺' => '頻', '޻' => '憑', '޼' => '氷', '޽' => '聘', '޾' => '騁', '޿' => '乍', '' => '事', '' => '些', '' => '仕', '' => '伺', '' => '似', '' => '使', '' => '俟', '' => '僿', '' => '史', '' => '司', '' => '唆', '' => '嗣', '' => '四', '' => '士', '' => '奢', '' => '娑', '' => '寫', '' => '寺', '' => '射', '' => '巳', '' => '師', '' => '徙', '' => '思', '' => '捨', '' => '斜', '' => '斯', '' => '柶', '' => '査', '' => '梭', '' => '死', '' => '沙', '' => '泗', '' => '渣', '' => '瀉', '' => '獅', '' => '砂', '' => '社', '' => '祀', '' => '祠', '' => '私', '' => '篩', '' => '紗', '' => '絲', '' => '肆', '' => '舍', '' => '莎', '' => '蓑', '' => '蛇', '' => '裟', '' => '詐', '' => '詞', '' => '謝', '' => '賜', '' => '赦', '' => '辭', '' => '邪', '' => '飼', '' => '駟', '' => '麝', '' => '削', '' => '數', '' => '朔', '' => '索', 'ߡ' => '傘', 'ߢ' => '刪', 'ߣ' => '山', 'ߤ' => '散', 'ߥ' => '汕', 'ߦ' => '珊', 'ߧ' => '産', 'ߨ' => '疝', 'ߩ' => '算', 'ߪ' => '蒜', '߫' => '酸', '߬' => '霰', '߭' => '乷', '߮' => '撒', '߯' => '殺', '߰' => '煞', '߱' => '薩', '߲' => '三', '߳' => '參', 'ߴ' => '杉', 'ߵ' => '森', '߶' => '渗', '߷' => '芟', '߸' => '蔘', '߹' => '衫', 'ߺ' => '揷', '߻' => '澁', '߼' => '鈒', '߽' => '颯', '߾' => '上', '߿' => '傷', '' => '像', '' => '償', '' => '商', '' => '喪', '' => '嘗', '' => '孀', '' => '尙', '' => '峠', '' => '常', '' => '床', '' => '庠', '' => '廂', '' => '想', '' => '桑', '' => '橡', '' => '湘', '' => '爽', '' => '牀', '' => '狀', '' => '相', '' => '祥', '' => '箱', '' => '翔', '' => '裳', '' => '觴', '' => '詳', '' => '象', '' => '賞', '' => '霜', '' => '塞', '' => '璽', '' => '賽', '' => '嗇', '' => '塞', '' => '穡', '' => '索', '' => '色', '' => '牲', '' => '生', '' => '甥', '' => '省', '' => '笙', '' => '墅', '' => '壻', '' => '嶼', '' => '序', '' => '庶', '' => '徐', '' => '恕', '' => '抒', '' => '捿', '' => '敍', '' => '暑', '' => '曙', '' => '書', '' => '栖', '' => '棲', '' => '犀', '' => '瑞', '' => '筮', '' => '絮', '' => '緖', '' => '署', '' => '胥', '' => '舒', '' => '薯', '' => '西', '' => '誓', '' => '逝', '' => '鋤', '' => '黍', '' => '鼠', '' => '夕', '' => '奭', '' => '席', '' => '惜', '' => '昔', '' => '晳', '' => '析', '' => '汐', '' => '淅', '' => '潟', '' => '石', '' => '碩', '' => '蓆', '' => '釋', '' => '錫', '' => '仙', '' => '僊', '' => '先', '' => '善', '' => '嬋', '' => '宣', '' => '扇', '' => '敾', '' => '旋', '' => '渲', '' => '煽', '' => '琁', '' => '瑄', '' => '璇', '' => '璿', '' => '癬', '' => '禪', '' => '線', '' => '繕', '' => '羨', '' => '腺', '' => '膳', '' => '船', '' => '蘚', '' => '蟬', '' => '詵', '' => '跣', '' => '選', '' => '銑', '' => '鐥', '' => '饍', '' => '鮮', '' => '卨', '' => '屑', '' => '楔', '' => '泄', '' => '洩', '' => '渫', '' => '舌', '' => '薛', '' => '褻', '' => '設', '' => '說', '' => '雪', '' => '齧', '' => '剡', '' => '暹', '' => '殲', '' => '纖', '' => '蟾', '' => '贍', '' => '閃', '' => '陝', '' => '攝', '' => '涉', '' => '燮', '' => '葉', '' => '城', '' => '姓', '' => '宬', '' => '性', '' => '惺', '' => '成', '' => '星', '' => '晟', '' => '猩', '' => '珹', '' => '盛', '' => '省', '' => '筬', '' => '聖', '' => '聲', '' => '腥', '' => '誠', '' => '醒', '' => '世', '' => '勢', '' => '歲', '' => '洗', '' => '稅', '' => '笹', '' => '細', '' => '說', '' => '貰', '' => '召', '' => '嘯', '' => '塑', '' => '宵', '' => '小', '' => '少', '' => '巢', '' => '所', '' => '掃', '' => '搔', '' => '昭', '' => '梳', '' => '沼', '' => '消', '' => '溯', '' => '瀟', '' => '炤', '' => '燒', '' => '甦', '' => '疏', '' => '疎', '' => '瘙', '' => '笑', '' => '篠', '' => '簫', '' => '素', '' => '紹', '' => '蔬', '' => '蕭', '' => '蘇', '' => '訴', '' => '逍', '' => '遡', '' => '邵', '' => '銷', '' => '韶', '' => '騷', '' => '俗', '' => '屬', '' => '束', '' => '涑', '' => '粟', '' => '續', '' => '謖', '' => '贖', '' => '速', '' => '孫', '' => '巽', '' => '損', '' => '蓀', '' => '遜', '' => '飡', '' => '率', '' => '宋', '' => '悚', '' => '松', '' => '淞', '' => '訟', '' => '誦', '' => '送', '' => '頌', '' => '刷', '' => '殺', '' => '灑', '' => '碎', '' => '鎖', '' => '衰', '' => '釗', '' => '修', '' => '受', '' => '嗽', '' => '囚', '' => '垂', '' => '壽', '' => '嫂', '' => '守', '' => '岫', '' => '峀', '' => '帥', '' => '愁', '' => '戍', '' => '手', '' => '授', '' => '搜', '' => '收', '' => '數', '' => '樹', '' => '殊', '' => '水', '' => '洙', '' => '漱', '' => '燧', '' => '狩', '' => '獸', '' => '琇', '' => '璲', '' => '瘦', '' => '睡', '' => '秀', '' => '穗', '' => '竪', '' => '粹', '' => '綏', '' => '綬', '' => '繡', '' => '羞', '' => '脩', '' => '茱', '' => '蒐', '' => '蓚', '' => '藪', '' => '袖', '' => '誰', '' => '讐', '' => '輸', '' => '遂', '' => '邃', '' => '酬', '' => '銖', '' => '銹', '' => '隋', '' => '隧', '' => '隨', '' => '雖', '' => '需', '' => '須', '' => '首', '' => '髓', '' => '鬚', '' => '叔', '' => '塾', '' => '夙', '' => '孰', '' => '宿', '' => '淑', '' => '潚', '' => '熟', '' => '琡', '' => '璹', '' => '肅', '' => '菽', '' => '巡', '' => '徇', '' => '循', '' => '恂', '' => '旬', '' => '栒', '' => '楯', '' => '橓', '' => '殉', '' => '洵', '' => '淳', '' => '珣', '' => '盾', '' => '瞬', '' => '筍', '' => '純', '' => '脣', '' => '舜', '' => '荀', '' => '蓴', '' => '蕣', '' => '詢', '' => '諄', '' => '醇', '' => '錞', '' => '順', '' => '馴', '' => '戌', '' => '術', '' => '述', '' => '鉥', '' => '崇', '' => '崧', '' => '嵩', '' => '瑟', '' => '膝', '' => '蝨', '' => '濕', '' => '拾', '' => '習', '' => '褶', '' => '襲', '' => '丞', '' => '乘', '' => '僧', '' => '勝', '' => '升', '' => '承', '' => '昇', '' => '繩', '' => '蠅', '' => '陞', '' => '侍', '' => '匙', '' => '嘶', '' => '始', '' => '媤', '' => '尸', '' => '屎', '' => '屍', '' => '市', '' => '弑', '' => '恃', '' => '施', '' => '是', '' => '時', '' => '枾', '' => '柴', '' => '猜', '' => '矢', '' => '示', '' => '翅', '' => '蒔', '' => '蓍', '' => '視', '' => '試', '' => '詩', '' => '諡', '' => '豕', '' => '豺', '' => '埴', '' => '寔', '' => '式', '' => '息', '' => '拭', '' => '植', '' => '殖', '' => '湜', '' => '熄', '' => '篒', '' => '蝕', '' => '識', '' => '軾', '' => '食', '' => '飾', '' => '伸', '' => '侁', '' => '信', '' => '呻', '' => '娠', '' => '宸', '' => '愼', '' => '新', '' => '晨', '' => '燼', '' => '申', '' => '神', '' => '紳', '' => '腎', '' => '臣', '' => '莘', '' => '薪', '' => '藎', '' => '蜃', '' => '訊', '' => '身', '' => '辛', '' => '辰', '' => '迅', '' => '失', '' => '室', '' => '實', '' => '悉', '' => '審', '' => '尋', '' => '心', '' => '沁', '' => '沈', '' => '深', '' => '瀋', '' => '甚', '' => '芯', '' => '諶', '' => '什', '' => '十', '' => '拾', '' => '雙', '' => '氏', '' => '亞', '' => '俄', '' => '兒', '' => '啞', '' => '娥', '' => '峨', '' => '我', '' => '牙', '' => '芽', '' => '莪', '' => '蛾', '' => '衙', '' => '訝', '' => '阿', '' => '雅', '' => '餓', '' => '鴉', '' => '鵝', '' => '堊', '' => '岳', '' => '嶽', '' => '幄', '' => '惡', '' => '愕', '' => '握', '' => '樂', '' => '渥', '' => '鄂', '' => '鍔', '' => '顎', '' => '鰐', '' => '齷', '' => '安', '' => '岸', '' => '按', '' => '晏', '' => '案', '' => '眼', '' => '雁', '' => '鞍', '' => '顔', '' => '鮟', '' => '斡', '' => '謁', '' => '軋', '' => '閼', '' => '唵', '' => '岩', '' => '巖', '' => '庵', '' => '暗', '' => '癌', '' => '菴', '' => '闇', '' => '壓', '' => '押', '' => '狎', '' => '鴨', '' => '仰', '' => '央', '' => '怏', '' => '昻', '' => '殃', '' => '秧', '' => '鴦', '' => '厓', '' => '哀', '' => '埃', '' => '崖', '' => '愛', '' => '曖', '' => '涯', '' => '碍', '' => '艾', '' => '隘', '' => '靄', '' => '厄', '' => '扼', '' => '掖', '' => '液', '' => '縊', '' => '腋', '' => '額', '' => '櫻', '' => '罌', '' => '鶯', '' => '鸚', '' => '也', '' => '倻', '' => '冶', '' => '夜', '' => '惹', '' => '揶', '' => '椰', '' => '爺', '' => '耶', '' => '若', '' => '野', '' => '弱', '' => '掠', '' => '略', '' => '約', '' => '若', '' => '葯', '' => '蒻', '' => '藥', '' => '躍', '' => '亮', '' => '佯', '' => '兩', '' => '凉', '' => '壤', '' => '孃', '' => '恙', '' => '揚', '' => '攘', '' => '敭', '' => '暘', '' => '梁', '' => '楊', '' => '樣', '' => '洋', '' => '瀁', '' => '煬', '' => '痒', '' => '瘍', '' => '禳', '' => '穰', '' => '糧', '' => '羊', '' => '良', '' => '襄', '' => '諒', '' => '讓', '' => '釀', '' => '陽', '' => '量', '' => '養', '' => '圄', '' => '御', '' => '於', '' => '漁', '' => '瘀', '' => '禦', '' => '語', '' => '馭', '' => '魚', '' => '齬', '' => '億', '' => '憶', '' => '抑', '' => '檍', '' => '臆', '' => '偃', '' => '堰', '' => '彦', '' => '焉', '' => '言', '' => '諺', '' => '孼', '' => '蘖', '' => '俺', '' => '儼', '' => '嚴', '' => '奄', '' => '掩', '' => '淹', '' => '嶪', '' => '業', '' => '円', '' => '予', '' => '余', '' => '勵', '' => '呂', '' => '女', '' => '如', '' => '廬', '' => '旅', '' => '歟', '' => '汝', '' => '濾', '' => '璵', '' => '礖', '' => '礪', '' => '與', '' => '艅', '' => '茹', '' => '輿', '' => '轝', '' => '閭', '' => '餘', '' => '驪', '' => '麗', '' => '黎', '' => '亦', '' => '力', '' => '域', '' => '役', '' => '易', '' => '曆', '' => '歷', '' => '疫', '' => '繹', '' => '譯', '' => '轢', '' => '逆', '' => '驛', '' => '嚥', '' => '堧', '' => '姸', '' => '娟', '' => '宴', '' => '年', '' => '延', '' => '憐', '' => '戀', '' => '捐', '' => '挻', '' => '撚', '' => '椽', '' => '沇', '' => '沿', '' => '涎', '' => '涓', '' => '淵', '' => '演', '' => '漣', '' => '烟', '' => '然', '' => '煙', '' => '煉', '' => '燃', '' => '燕', '' => '璉', '' => '硏', '' => '硯', '' => '秊', '' => '筵', '' => '緣', '' => '練', '' => '縯', '' => '聯', '' => '衍', '' => '軟', '' => '輦', '' => '蓮', '' => '連', '' => '鉛', '' => '鍊', '' => '鳶', '' => '列', '' => '劣', '' => '咽', '' => '悅', '' => '涅', '' => '烈', '' => '熱', '' => '裂', '' => '說', '' => '閱', '' => '厭', '' => '廉', '' => '念', '' => '捻', '' => '染', '' => '殮', '' => '炎', '' => '焰', '' => '琰', '' => '艶', '' => '苒', '' => '簾', '' => '閻', '' => '髥', '' => '鹽', '' => '曄', '' => '獵', '' => '燁', '' => '葉', '' => '令', '' => '囹', '' => '塋', '' => '寧', '' => '嶺', '' => '嶸', '' => '影', '' => '怜', '' => '映', '' => '暎', '' => '楹', '' => '榮', '' => '永', '' => '泳', '' => '渶', '' => '潁', '' => '濚', '' => '瀛', '' => '瀯', '' => '煐', '' => '營', '' => '獰', '' => '玲', '' => '瑛', '' => '瑩', '' => '瓔', '' => '盈', '' => '穎', '' => '纓', '' => '羚', '' => '聆', '' => '英', '' => '詠', '' => '迎', '' => '鈴', '' => '鍈', '' => '零', '' => '霙', '' => '靈', '' => '領', '' => '乂', '' => '倪', '' => '例', '' => '刈', '' => '叡', '' => '曳', '' => '汭', '' => '濊', '' => '猊', '' => '睿', '' => '穢', '' => '芮', '' => '藝', '' => '蘂', '' => '禮', '' => '裔', '' => '詣', '' => '譽', '' => '豫', '' => '醴', '' => '銳', '' => '隸', '' => '霓', '' => '預', '' => '五', '' => '伍', '' => '俉', '' => '傲', '' => '午', '' => '吾', '' => '吳', '' => '嗚', '' => '塢', '' => '墺', '' => '奧', '' => '娛', '' => '寤', '' => '悟', '' => '惡', '' => '懊', '' => '敖', '' => '旿', '' => '晤', '' => '梧', '' => '汚', '' => '澳', '' => '烏', '' => '熬', '' => '獒', '' => '筽', '' => '蜈', '' => '誤', '' => '鰲', '' => '鼇', '' => '屋', '' => '沃', '' => '獄', '' => '玉', '' => '鈺', '' => '溫', '' => '瑥', '' => '瘟', '' => '穩', '' => '縕', '' => '蘊', '' => '兀', '' => '壅', '' => '擁', '' => '瓮', '' => '甕', '' => '癰', '' => '翁', '' => '邕', '' => '雍', '' => '饔', '' => '渦', '' => '瓦', '' => '窩', '' => '窪', '' => '臥', '' => '蛙', '' => '蝸', '' => '訛', '' => '婉', '' => '完', '' => '宛', '' => '梡', '' => '椀', '' => '浣', '' => '玩', '' => '琓', '' => '琬', '' => '碗', '' => '緩', '' => '翫', '' => '脘', '' => '腕', '' => '莞', '' => '豌', '' => '阮', '' => '頑', '' => '曰', '' => '往', '' => '旺', '' => '枉', '' => '汪', '' => '王', '' => '倭', '' => '娃', '' => '歪', '' => '矮', '' => '外', '' => '嵬', '' => '巍', '' => '猥', '' => '畏', '' => '了', '' => '僚', '' => '僥', '' => '凹', '' => '堯', '' => '夭', '' => '妖', '' => '姚', '' => '寥', '' => '寮', '' => '尿', '' => '嶢', '' => '拗', '' => '搖', '' => '撓', '' => '擾', '' => '料', '' => '曜', '' => '樂', '' => '橈', '' => '燎', '' => '燿', '' => '瑤', '' => '療', '' => '窈', '' => '窯', '' => '繇', '' => '繞', '' => '耀', '' => '腰', '' => '蓼', '' => '蟯', '' => '要', '' => '謠', '' => '遙', '' => '遼', '' => '邀', '' => '饒', '' => '慾', '' => '欲', '' => '浴', '' => '縟', '' => '褥', '' => '辱', '' => '俑', '' => '傭', '' => '冗', '' => '勇', '' => '埇', '' => '墉', '' => '容', '' => '庸', '' => '慂', '' => '榕', '' => '涌', '' => '湧', '' => '溶', '' => '熔', '' => '瑢', '' => '用', '' => '甬', '' => '聳', '' => '茸', '' => '蓉', '' => '踊', '' => '鎔', '' => '鏞', '' => '龍', '' => '于', '' => '佑', '' => '偶', '' => '優', '' => '又', '' => '友', '' => '右', '' => '宇', '' => '寓', '' => '尤', '' => '愚', '' => '憂', '' => '旴', '' => '牛', '' => '玗', '' => '瑀', '' => '盂', '' => '祐', '' => '禑', '' => '禹', '' => '紆', '' => '羽', '' => '芋', '' => '藕', '' => '虞', '' => '迂', '' => '遇', '' => '郵', '' => '釪', '' => '隅', '' => '雨', '' => '雩', '' => '勖', '' => '彧', '' => '旭', '' => '昱', '' => '栯', '' => '煜', '' => '稶', '' => '郁', '' => '頊', '' => '云', '' => '暈', '' => '橒', '' => '殞', '' => '澐', '' => '熉', '' => '耘', '' => '芸', '' => '蕓', '' => '運', '' => '隕', '' => '雲', '' => '韻', '' => '蔚', '' => '鬱', '' => '亐', '' => '熊', '' => '雄', '' => '元', '' => '原', '' => '員', '' => '圓', '' => '園', '' => '垣', '' => '媛', '' => '嫄', '' => '寃', '' => '怨', '' => '愿', '' => '援', '' => '沅', '' => '洹', '' => '湲', '' => '源', '' => '爰', '' => '猿', '' => '瑗', '' => '苑', '' => '袁', '' => '轅', '' => '遠', '' => '阮', '' => '院', '' => '願', '' => '鴛', '' => '月', '' => '越', '' => '鉞', '' => '位', '' => '偉', '' => '僞', '' => '危', '' => '圍', '' => '委', '' => '威', '' => '尉', '' => '慰', '' => '暐', '' => '渭', '' => '爲', '' => '瑋', '' => '緯', '' => '胃', '' => '萎', '' => '葦', '' => '蔿', '' => '蝟', '' => '衛', '' => '褘', '' => '謂', '' => '違', '' => '韋', '' => '魏', '' => '乳', '' => '侑', '' => '儒', '' => '兪', '' => '劉', '' => '唯', '' => '喩', '' => '孺', '' => '宥', '' => '幼', '' => '幽', '' => '庾', '' => '悠', '' => '惟', '' => '愈', '' => '愉', '' => '揄', '' => '攸', '' => '有', '' => '杻', '' => '柔', '' => '柚', '' => '柳', '' => '楡', '' => '楢', '' => '油', '' => '洧', '' => '流', '' => '游', '' => '溜', '' => '濡', '' => '猶', '' => '猷', '' => '琉', '' => '瑜', '' => '由', '' => '留', '' => '癒', '' => '硫', '' => '紐', '' => '維', '' => '臾', '' => '萸', '' => '裕', '' => '誘', '' => '諛', '' => '諭', '' => '踰', '' => '蹂', '' => '遊', '' => '逾', '' => '遺', '' => '酉', '' => '釉', '' => '鍮', '' => '類', '' => '六', '' => '堉', '' => '戮', '' => '毓', '' => '肉', '' => '育', '' => '陸', '' => '倫', '' => '允', '' => '奫', '' => '尹', '' => '崙', '' => '淪', '' => '潤', '' => '玧', '' => '胤', '' => '贇', '' => '輪', '' => '鈗', '' => '閏', '' => '律', '' => '慄', '' => '栗', '' => '率', '' => '聿', '' => '戎', '' => '瀜', '' => '絨', '' => '融', '' => '隆', '' => '垠', '' => '恩', '' => '慇', '' => '殷', '' => '誾', '' => '銀', '' => '隱', '' => '乙', '' => '吟', '' => '淫', '' => '蔭', '' => '陰', '' => '音', '' => '飮', '' => '揖', '' => '泣', '' => '邑', '' => '凝', '' => '應', '' => '膺', '' => '鷹', '' => '依', '' => '倚', '' => '儀', '' => '宜', '' => '意', '' => '懿', '' => '擬', '' => '椅', '' => '毅', '' => '疑', '' => '矣', '' => '義', '' => '艤', '' => '薏', '' => '蟻', '' => '衣', '' => '誼', '' => '議', '' => '醫', '' => '二', '' => '以', '' => '伊', '' => '利', '' => '吏', '' => '夷', '' => '姨', '' => '履', '' => '已', '' => '弛', '' => '彛', '' => '怡', '' => '易', '' => '李', '' => '梨', '' => '泥', '' => '爾', '' => '珥', '' => '理', '' => '異', '' => '痍', '' => '痢', '' => '移', '' => '罹', '' => '而', '' => '耳', '' => '肄', '' => '苡', '' => '荑', '' => '裏', '' => '裡', '' => '貽', '' => '貳', '' => '邇', '' => '里', '' => '離', '' => '飴', '' => '餌', '' => '匿', '' => '溺', '' => '瀷', '' => '益', '' => '翊', '' => '翌', '' => '翼', '' => '謚', '' => '人', '' => '仁', '' => '刃', '' => '印', '' => '吝', '' => '咽', '' => '因', '' => '姻', '' => '寅', '' => '引', '' => '忍', '' => '湮', '' => '燐', '' => '璘', '' => '絪', '' => '茵', '' => '藺', '' => '蚓', '' => '認', '' => '隣', '' => '靭', '' => '靷', '' => '鱗', '' => '麟', '' => '一', '' => '佚', '' => '佾', '' => '壹', '' => '日', '' => '溢', '' => '逸', '' => '鎰', '' => '馹', '' => '任', '' => '壬', '' => '妊', '' => '姙', '' => '恁', '' => '林', '' => '淋', '' => '稔', '' => '臨', '' => '荏', '' => '賃', '' => '入', '' => '卄', '' => '立', '' => '笠', '' => '粒', '' => '仍', '' => '剩', '' => '孕', '' => '芿', '' => '仔', '' => '刺', '' => '咨', '' => '姉', '' => '姿', '' => '子', '' => '字', '' => '孜', '' => '恣', '' => '慈', '' => '滋', '' => '炙', '' => '煮', '' => '玆', '' => '瓷', '' => '疵', '' => '磁', '' => '紫', '' => '者', '' => '自', '' => '茨', '' => '蔗', '' => '藉', '' => '諮', '' => '資', '' => '雌', '' => '作', '' => '勺', '' => '嚼', '' => '斫', '' => '昨', '' => '灼', '' => '炸', '' => '爵', '' => '綽', '' => '芍', '' => '酌', '' => '雀', '' => '鵲', '' => '孱', '' => '棧', '' => '殘', '' => '潺', '' => '盞', '' => '岑', '' => '暫', '' => '潛', '' => '箴', '' => '簪', '' => '蠶', '' => '雜', '' => '丈', '' => '仗', '' => '匠', '' => '場', '' => '墻', '' => '壯', '' => '奬', '' => '將', '' => '帳', '' => '庄', '' => '張', '' => '掌', '' => '暲', '' => '杖', '' => '樟', '' => '檣', '' => '欌', '' => '漿', '' => '牆', '' => '狀', '' => '獐', '' => '璋', '' => '章', '' => '粧', '' => '腸', '' => '臟', '' => '臧', '' => '莊', '' => '葬', '' => '蔣', '' => '薔', '' => '藏', '' => '裝', '' => '贓', '' => '醬', '' => '長', '' => '障', '' => '再', '' => '哉', '' => '在', '' => '宰', '' => '才', '' => '材', '' => '栽', '' => '梓', '' => '渽', '' => '滓', '' => '災', '' => '縡', '' => '裁', '' => '財', '' => '載', '' => '齋', '' => '齎', '' => '爭', '' => '箏', '' => '諍', '' => '錚', '' => '佇', '' => '低', '' => '儲', '' => '咀', '' => '姐', '' => '底', '' => '抵', '' => '杵', '' => '楮', '' => '樗', '' => '沮', '' => '渚', '' => '狙', '' => '猪', '' => '疽', '' => '箸', '' => '紵', '' => '苧', '' => '菹', '' => '著', '' => '藷', '' => '詛', '' => '貯', '' => '躇', '' => '這', '' => '邸', '' => '雎', '' => '齟', '' => '勣', '' => '吊', '' => '嫡', '' => '寂', '' => '摘', '' => '敵', '' => '滴', '' => '狄', '' => '炙', '' => '的', '' => '積', '' => '笛', '' => '籍', '' => '績', '' => '翟', '' => '荻', '' => '謫', '' => '賊', '' => '赤', '' => '跡', '' => '蹟', '' => '迪', '' => '迹', '' => '適', '' => '鏑', '' => '佃', '' => '佺', '' => '傳', '' => '全', '' => '典', '' => '前', '' => '剪', '' => '塡', '' => '塼', '' => '奠', '' => '專', '' => '展', '' => '廛', '' => '悛', '' => '戰', '' => '栓', '' => '殿', '' => '氈', '' => '澱', '' => '煎', '' => '琠', '' => '田', '' => '甸', '' => '畑', '' => '癲', '' => '筌', '' => '箋', '' => '箭', '' => '篆', '' => '纏', '' => '詮', '' => '輾', '' => '轉', '' => '鈿', '' => '銓', '' => '錢', '' => '鐫', '' => '電', '' => '顚', '' => '顫', '' => '餞', '' => '切', '' => '截', '' => '折', '' => '浙', '' => '癤', '' => '竊', '' => '節', '' => '絶', '' => '占', '' => '岾', '' => '店', '' => '漸', '' => '点', '' => '粘', '' => '霑', '' => '鮎', '' => '點', '' => '接', '' => '摺', '' => '蝶', '' => '丁', '' => '井', '' => '亭', '' => '停', '' => '偵', '' => '呈', '' => '姃', '' => '定', '' => '幀', '' => '庭', '' => '廷', '' => '征', '' => '情', '' => '挺', '' => '政', '' => '整', '' => '旌', '' => '晶', '' => '晸', '' => '柾', '' => '楨', '' => '檉', '' => '正', '' => '汀', '' => '淀', '' => '淨', '' => '渟', '' => '湞', '' => '瀞', '' => '炡', '' => '玎', '' => '珽', '' => '町', '' => '睛', '' => '碇', '' => '禎', '' => '程', '' => '穽', '' => '精', '' => '綎', '' => '艇', '' => '訂', '' => '諪', '' => '貞', '' => '鄭', '' => '酊', '' => '釘', '' => '鉦', '' => '鋌', '' => '錠', '' => '霆', '' => '靖', '' => '靜', '' => '頂', '' => '鼎', '' => '制', '' => '劑', '' => '啼', '' => '堤', '' => '帝', '' => '弟', '' => '悌', '' => '提', '' => '梯', '' => '濟', '' => '祭', '' => '第', '' => '臍', '' => '薺', '' => '製', '' => '諸', '' => '蹄', '' => '醍', '' => '除', '' => '際', '' => '霽', '' => '題', '' => '齊', '' => '俎', '' => '兆', '' => '凋', '' => '助', '' => '嘲', '' => '弔', '' => '彫', '' => '措', '' => '操', '' => '早', '' => '晁', '' => '曺', '' => '曹', '' => '朝', '' => '條', '' => '棗', '' => '槽', '' => '漕', '' => '潮', '' => '照', '' => '燥', '' => '爪', '' => '璪', '' => '眺', '' => '祖', '' => '祚', '' => '租', '' => '稠', '' => '窕', '' => '粗', '' => '糟', '' => '組', '' => '繰', '' => '肇', '' => '藻', '' => '蚤', '' => '詔', '' => '調', '' => '趙', '' => '躁', '' => '造', '' => '遭', '' => '釣', '' => '阻', '' => '雕', '' => '鳥', '' => '族', '' => '簇', '' => '足', '' => '鏃', '' => '存', '' => '尊', '' => '卒', '' => '拙', '' => '猝', '' => '倧', '' => '宗', '' => '從', '' => '悰', '' => '慫', '' => '棕', '' => '淙', '' => '琮', '' => '種', '' => '終', '' => '綜', '' => '縱', '' => '腫', '' => '踪', '' => '踵', '' => '鍾', '' => '鐘', '' => '佐', '' => '坐', '' => '左', '' => '座', '' => '挫', '' => '罪', '' => '主', '' => '住', '' => '侏', '' => '做', '' => '姝', '' => '胄', '' => '呪', '' => '周', '' => '嗾', '' => '奏', '' => '宙', '' => '州', '' => '廚', '' => '晝', '' => '朱', '' => '柱', '' => '株', '' => '注', '' => '洲', '' => '湊', '' => '澍', '' => '炷', '' => '珠', '' => '疇', '' => '籌', '' => '紂', '' => '紬', '' => '綢', '' => '舟', '' => '蛛', '' => '註', '' => '誅', '' => '走', '' => '躊', '' => '輳', '' => '週', '' => '酎', '' => '酒', '' => '鑄', '' => '駐', '' => '竹', '' => '粥', '' => '俊', '' => '儁', '' => '准', '' => '埈', '' => '寯', '' => '峻', '' => '晙', '' => '樽', '' => '浚', '' => '準', '' => '濬', '' => '焌', '' => '畯', '' => '竣', '' => '蠢', '' => '逡', '' => '遵', '' => '雋', '' => '駿', '' => '茁', '' => '中', '' => '仲', '' => '衆', '' => '重', '' => '卽', '' => '櫛', '' => '楫', '' => '汁', '' => '葺', '' => '增', '' => '憎', '' => '曾', '' => '拯', '' => '烝', '' => '甑', '' => '症', '' => '繒', '' => '蒸', '' => '證', '' => '贈', '' => '之', '' => '只', '' => '咫', '' => '地', '' => '址', '' => '志', '' => '持', '' => '指', '' => '摯', '' => '支', '' => '旨', '' => '智', '' => '枝', '' => '枳', '' => '止', '' => '池', '' => '沚', '' => '漬', '' => '知', '' => '砥', '' => '祉', '' => '祗', '' => '紙', '' => '肢', '' => '脂', '' => '至', '' => '芝', '' => '芷', '' => '蜘', '' => '誌', '' => '識', '' => '贄', '' => '趾', '' => '遲', '' => '直', '' => '稙', '' => '稷', '' => '織', '' => '職', '' => '唇', '' => '嗔', '' => '塵', '' => '振', '' => '搢', '' => '晉', '' => '晋', '' => '桭', '' => '榛', '' => '殄', '' => '津', '' => '溱', '' => '珍', '' => '瑨', '' => '璡', '' => '畛', '' => '疹', '' => '盡', '' => '眞', '' => '瞋', '' => '秦', '' => '縉', '' => '縝', '' => '臻', '' => '蔯', '' => '袗', '' => '診', '' => '賑', '' => '軫', '' => '辰', '' => '進', '' => '鎭', '' => '陣', '' => '陳', '' => '震', '' => '侄', '' => '叱', '' => '姪', '' => '嫉', '' => '帙', '' => '桎', '' => '瓆', '' => '疾', '' => '秩', '' => '窒', '' => '膣', '' => '蛭', '' => '質', '' => '跌', '' => '迭', '' => '斟', '' => '朕', '' => '什', '' => '執', '' => '潗', '' => '緝', '' => '輯', '' => '鏶', '' => '集', '' => '徵', '' => '懲', '' => '澄', '' => '且', '' => '侘', '' => '借', '' => '叉', '' => '嗟', '' => '嵯', '' => '差', '' => '次', '' => '此', '' => '磋', '' => '箚', '' => '茶', '' => '蹉', '' => '車', '' => '遮', '' => '捉', '' => '搾', '' => '着', '' => '窄', '' => '錯', '' => '鑿', '' => '齪', '' => '撰', '' => '澯', '' => '燦', '' => '璨', '' => '瓚', '' => '竄', '' => '簒', '' => '纂', '' => '粲', '' => '纘', '' => '讚', '' => '贊', '' => '鑽', '' => '餐', '' => '饌', '' => '刹', '' => '察', '' => '擦', '' => '札', '' => '紮', '' => '僭', '' => '參', '' => '塹', '' => '慘', '' => '慙', '' => '懺', '' => '斬', '' => '站', '' => '讒', '' => '讖', '' => '倉', '' => '倡', '' => '創', '' => '唱', '' => '娼', '' => '廠', '' => '彰', '' => '愴', '' => '敞', '' => '昌', '' => '昶', '' => '暢', '' => '槍', '' => '滄', '' => '漲', '' => '猖', '' => '瘡', '' => '窓', '' => '脹', '' => '艙', '' => '菖', '' => '蒼', '' => '債', '' => '埰', '' => '寀', '' => '寨', '' => '彩', '' => '採', '' => '砦', '' => '綵', '' => '菜', '' => '蔡', '' => '采', '' => '釵', '' => '冊', '' => '柵', '' => '策', '' => '責', '' => '凄', '' => '妻', '' => '悽', '' => '處', '' => '倜', '' => '刺', '' => '剔', '' => '尺', '' => '慽', '' => '戚', '' => '拓', '' => '擲', '' => '斥', '' => '滌', '' => '瘠', '' => '脊', '' => '蹠', '' => '陟', '' => '隻', '' => '仟', '' => '千', '' => '喘', '' => '天', '' => '川', '' => '擅', '' => '泉', '' => '淺', '' => '玔', '' => '穿', '' => '舛', '' => '薦', '' => '賤', '' => '踐', '' => '遷', '' => '釧', '' => '闡', '' => '阡', '' => '韆', '' => '凸', '' => '哲', '' => '喆', '' => '徹', '' => '撤', '' => '澈', '' => '綴', '' => '輟', '' => '轍', '' => '鐵', '' => '僉', '' => '尖', '' => '沾', '' => '添', '' => '甛', '' => '瞻', '' => '簽', '' => '籤', '' => '詹', '' => '諂', '' => '堞', '' => '妾', '' => '帖', '' => '捷', '' => '牒', '' => '疊', '' => '睫', '' => '諜', '' => '貼', '' => '輒', '' => '廳', '' => '晴', '' => '淸', '' => '聽', '' => '菁', '' => '請', '' => '靑', '' => '鯖', '' => '切', '' => '剃', '' => '替', '' => '涕', '' => '滯', '' => '締', '' => '諦', '' => '逮', '' => '遞', '' => '體', '' => '初', '' => '剿', '' => '哨', '' => '憔', '' => '抄', '' => '招', '' => '梢', '' => '椒', '' => '楚', '' => '樵', '' => '炒', '' => '焦', '' => '硝', '' => '礁', '' => '礎', '' => '秒', '' => '稍', '' => '肖', '' => '艸', '' => '苕', '' => '草', '' => '蕉', '' => '貂', '' => '超', '' => '酢', '' => '醋', '' => '醮', '' => '促', '' => '囑', '' => '燭', '' => '矗', '' => '蜀', '' => '觸', '' => '寸', '' => '忖', '' => '村', '' => '邨', '' => '叢', '' => '塚', '' => '寵', '' => '悤', '' => '憁', '' => '摠', '' => '總', '' => '聰', '' => '蔥', '' => '銃', '' => '撮', '' => '催', '' => '崔', '' => '最', '' => '墜', '' => '抽', '' => '推', '' => '椎', '' => '楸', '' => '樞', '' => '湫', '' => '皺', '' => '秋', '' => '芻', '' => '萩', '' => '諏', '' => '趨', '' => '追', '' => '鄒', '' => '酋', '' => '醜', '' => '錐', '' => '錘', '' => '鎚', '' => '雛', '' => '騶', '' => '鰍', '' => '丑', '' => '畜', '' => '祝', '' => '竺', '' => '筑', '' => '築', '' => '縮', '' => '蓄', '' => '蹙', '' => '蹴', '' => '軸', '' => '逐', '' => '春', '' => '椿', '' => '瑃', '' => '出', '' => '朮', '' => '黜', '' => '充', '' => '忠', '' => '沖', '' => '蟲', '' => '衝', '' => '衷', '' => '悴', '' => '膵', '' => '萃', '' => '贅', '' => '取', '' => '吹', '' => '嘴', '' => '娶', '' => '就', '' => '炊', '' => '翠', '' => '聚', '' => '脆', '' => '臭', '' => '趣', '' => '醉', '' => '驟', '' => '鷲', '' => '側', '' => '仄', '' => '厠', '' => '惻', '' => '測', '' => '層', '' => '侈', '' => '値', '' => '嗤', '' => '峙', '' => '幟', '' => '恥', '' => '梔', '' => '治', '' => '淄', '' => '熾', '' => '痔', '' => '痴', '' => '癡', '' => '稚', '' => '穉', '' => '緇', '' => '緻', '' => '置', '' => '致', '' => '蚩', '' => '輜', '' => '雉', '' => '馳', '' => '齒', '' => '則', '' => '勅', '' => '飭', '' => '親', '' => '七', '' => '柒', '' => '漆', '' => '侵', '' => '寢', '' => '枕', '' => '沈', '' => '浸', '' => '琛', '' => '砧', '' => '針', '' => '鍼', '' => '蟄', '' => '秤', '' => '稱', '' => '快', '' => '他', '' => '咤', '' => '唾', '' => '墮', '' => '妥', '' => '惰', '' => '打', '' => '拖', '' => '朶', '' => '楕', '' => '舵', '' => '陀', '' => '馱', '' => '駝', '' => '倬', '' => '卓', '' => '啄', '' => '坼', '' => '度', '' => '托', '' => '拓', '' => '擢', '' => '晫', '' => '柝', '' => '濁', '' => '濯', '' => '琢', '' => '琸', '' => '託', '' => '鐸', '' => '呑', '' => '嘆', '' => '坦', '' => '彈', '' => '憚', '' => '歎', '' => '灘', '' => '炭', '' => '綻', '' => '誕', '' => '奪', '' => '脫', '' => '探', '' => '眈', '' => '耽', '' => '貪', '' => '塔', '' => '搭', '' => '榻', '' => '宕', '' => '帑', '' => '湯', '' => '糖', '' => '蕩', '' => '兌', '' => '台', '' => '太', '' => '怠', '' => '態', '' => '殆', '' => '汰', '' => '泰', '' => '笞', '' => '胎', '' => '苔', '' => '跆', '' => '邰', '' => '颱', '' => '宅', '' => '擇', '' => '澤', '' => '撑', '' => '攄', '' => '兎', '' => '吐', '' => '土', '' => '討', '' => '慟', '' => '桶', '' => '洞', '' => '痛', '' => '筒', '' => '統', '' => '通', '' => '堆', '' => '槌', '' => '腿', '' => '褪', '' => '退', '' => '頹', '' => '偸', '' => '套', '' => '妬', '' => '投', '' => '透', '' => '鬪', '' => '慝', '' => '特', '' => '闖', '' => '坡', '' => '婆', '' => '巴', '' => '把', '' => '播', '' => '擺', '' => '杷', '' => '波', '' => '派', '' => '爬', '' => '琶', '' => '破', '' => '罷', '' => '芭', '' => '跛', '' => '頗', '' => '判', '' => '坂', '' => '板', '' => '版', '' => '瓣', '' => '販', '' => '辦', '' => '鈑', '' => '阪', '' => '八', '' => '叭', '' => '捌', '' => '佩', '' => '唄', '' => '悖', '' => '敗', '' => '沛', '' => '浿', '' => '牌', '' => '狽', '' => '稗', '' => '覇', '' => '貝', '' => '彭', '' => '澎', '' => '烹', '' => '膨', '' => '愎', '' => '便', '' => '偏', '' => '扁', '' => '片', '' => '篇', '' => '編', '' => '翩', '' => '遍', '' => '鞭', '' => '騙', '' => '貶', '' => '坪', '' => '平', '' => '枰', '' => '萍', '' => '評', '' => '吠', '' => '嬖', '' => '幣', '' => '廢', '' => '弊', '' => '斃', '' => '肺', '' => '蔽', '' => '閉', '' => '陛', '' => '佈', '' => '包', '' => '匍', '' => '匏', '' => '咆', '' => '哺', '' => '圃', '' => '布', '' => '怖', '' => '抛', '' => '抱', '' => '捕', '' => '暴', '' => '泡', '' => '浦', '' => '疱', '' => '砲', '' => '胞', '' => '脯', '' => '苞', '' => '葡', '' => '蒲', '' => '袍', '' => '褒', '' => '逋', '' => '鋪', '' => '飽', '' => '鮑', '' => '幅', '' => '暴', '' => '曝', '' => '瀑', '' => '爆', '' => '輻', '' => '俵', '' => '剽', '' => '彪', '' => '慓', '' => '杓', '' => '標', '' => '漂', '' => '瓢', '' => '票', '' => '表', '' => '豹', '' => '飇', '' => '飄', '' => '驃', '' => '品', '' => '稟', '' => '楓', '' => '諷', '' => '豊', '' => '風', '' => '馮', '' => '彼', '' => '披', '' => '疲', '' => '皮', '' => '被', '' => '避', '' => '陂', '' => '匹', '' => '弼', '' => '必', '' => '泌', '' => '珌', '' => '畢', '' => '疋', '' => '筆', '' => '苾', '' => '馝', '' => '乏', '' => '逼', '' => '下', '' => '何', '' => '厦', '' => '夏', '' => '廈', '' => '昰', '' => '河', '' => '瑕', '' => '荷', '' => '蝦', '' => '賀', '' => '遐', '' => '霞', '' => '鰕', '' => '壑', '' => '學', '' => '虐', '' => '謔', '' => '鶴', '' => '寒', '' => '恨', '' => '悍', '' => '旱', '' => '汗', '' => '漢', '' => '澣', '' => '瀚', '' => '罕', '' => '翰', '' => '閑', '' => '閒', '' => '限', '' => '韓', '' => '割', '' => '轄', '' => '函', '' => '含', '' => '咸', '' => '啣', '' => '喊', '' => '檻', '' => '涵', '' => '緘', '' => '艦', '' => '銜', '' => '陷', '' => '鹹', '' => '合', '' => '哈', '' => '盒', '' => '蛤', '' => '閤', '' => '闔', '' => '陜', '' => '亢', '' => '伉', '' => '姮', '' => '嫦', '' => '巷', '' => '恒', '' => '抗', '' => '杭', '' => '桁', '' => '沆', '' => '港', '' => '缸', '' => '肛', '' => '航', '' => '行', '' => '降', '' => '項', '' => '亥', '' => '偕', '' => '咳', '' => '垓', '' => '奚', '' => '孩', '' => '害', '' => '懈', '' => '楷', '' => '海', '' => '瀣', '' => '蟹', '' => '解', '' => '該', '' => '諧', '' => '邂', '' => '駭', '' => '骸', '' => '劾', '' => '核', '' => '倖', '' => '幸', '' => '杏', '' => '荇', '' => '行', '' => '享', '' => '向', '' => '嚮', '' => '珦', '' => '鄕', '' => '響', '' => '餉', '' => '饗', '' => '香', '' => '噓', '' => '墟', '' => '虛', '' => '許', '' => '憲', '' => '櫶', '' => '獻', '' => '軒', '' => '歇', '' => '險', '' => '驗', '' => '奕', '' => '爀', '' => '赫', '' => '革', '' => '俔', '' => '峴', '' => '弦', '' => '懸', '' => '晛', '' => '泫', '' => '炫', '' => '玄', '' => '玹', '' => '現', '' => '眩', '' => '睍', '' => '絃', '' => '絢', '' => '縣', '' => '舷', '' => '衒', '' => '見', '' => '賢', '' => '鉉', '' => '顯', '' => '孑', '' => '穴', '' => '血', '' => '頁', '' => '嫌', '' => '俠', '' => '協', '' => '夾', '' => '峽', '' => '挾', '' => '浹', '' => '狹', '' => '脅', '' => '脇', '' => '莢', '' => '鋏', '' => '頰', '' => '亨', '' => '兄', '' => '刑', '' => '型', '' => '形', '' => '泂', '' => '滎', '' => '瀅', '' => '灐', '' => '炯', '' => '熒', '' => '珩', '' => '瑩', '' => '荊', '' => '螢', '' => '衡', '' => '逈', '' => '邢', '' => '鎣', '' => '馨', '' => '兮', '' => '彗', '' => '惠', '' => '慧', '' => '暳', '' => '蕙', '' => '蹊', '' => '醯', '' => '鞋', '' => '乎', '' => '互', '' => '呼', '' => '壕', '' => '壺', '' => '好', '' => '岵', '' => '弧', '' => '戶', '' => '扈', '' => '昊', '' => '晧', '' => '毫', '' => '浩', '' => '淏', '' => '湖', '' => '滸', '' => '澔', '' => '濠', '' => '濩', '' => '灝', '' => '狐', '' => '琥', '' => '瑚', '' => '瓠', '' => '皓', '' => '祜', '' => '糊', '' => '縞', '' => '胡', '' => '芦', '' => '葫', '' => '蒿', '' => '虎', '' => '號', '' => '蝴', '' => '護', '' => '豪', '' => '鎬', '' => '頀', '' => '顥', '' => '惑', '' => '或', '' => '酷', '' => '婚', '' => '昏', '' => '混', '' => '渾', '' => '琿', '' => '魂', '' => '忽', '' => '惚', '' => '笏', '' => '哄', '' => '弘', '' => '汞', '' => '泓', '' => '洪', '' => '烘', '' => '紅', '' => '虹', '' => '訌', '' => '鴻', '' => '化', '' => '和', '' => '嬅', '' => '樺', '' => '火', '' => '畵', '' => '禍', '' => '禾', '' => '花', '' => '華', '' => '話', '' => '譁', '' => '貨', '' => '靴', '' => '廓', '' => '擴', '' => '攫', '' => '確', '' => '碻', '' => '穫', '' => '丸', '' => '喚', '' => '奐', '' => '宦', '' => '幻', '' => '患', '' => '換', '' => '歡', '' => '晥', '' => '桓', '' => '渙', '' => '煥', '' => '環', '' => '紈', '' => '還', '' => '驩', '' => '鰥', '' => '活', '' => '滑', '' => '猾', '' => '豁', '' => '闊', '' => '凰', '' => '幌', '' => '徨', '' => '恍', '' => '惶', '' => '愰', '' => '慌', '' => '晃', '' => '晄', '' => '榥', '' => '況', '' => '湟', '' => '滉', '' => '潢', '' => '煌', '' => '璜', '' => '皇', '' => '篁', '' => '簧', '' => '荒', '' => '蝗', '' => '遑', '' => '隍', '' => '黃', '' => '匯', '' => '回', '' => '廻', '' => '徊', '' => '恢', '' => '悔', '' => '懷', '' => '晦', '' => '會', '' => '檜', '' => '淮', '' => '澮', '' => '灰', '' => '獪', '' => '繪', '' => '膾', '' => '茴', '' => '蛔', '' => '誨', '' => '賄', '' => '劃', '' => '獲', '' => '宖', '' => '橫', '' => '鐄', '' => '哮', '' => '嚆', '' => '孝', '' => '效', '' => '斅', '' => '曉', '' => '梟', '' => '涍', '' => '淆', '' => '爻', '' => '肴', '' => '酵', '' => '驍', '' => '侯', '' => '候', '' => '厚', '' => '后', '' => '吼', '' => '喉', '' => '嗅', '' => '帿', '' => '後', '' => '朽', '' => '煦', '' => '珝', '' => '逅', '' => '勛', '' => '勳', '' => '塤', '' => '壎', '' => '焄', '' => '熏', '' => '燻', '' => '薰', '' => '訓', '' => '暈', '' => '薨', '' => '喧', '' => '暄', '' => '煊', '' => '萱', '' => '卉', '' => '喙', '' => '毁', '' => '彙', '' => '徽', '' => '揮', '' => '暉', '' => '煇', '' => '諱', '' => '輝', '' => '麾', '' => '休', '' => '携', '' => '烋', '' => '畦', '' => '虧', '' => '恤', '' => '譎', '' => '鷸', '' => '兇', '' => '凶', '' => '匈', '' => '洶', '' => '胸', '' => '黑', '' => '昕', '' => '欣', '' => '炘', '' => '痕', '' => '吃', '' => '屹', '' => '紇', '' => '訖', '' => '欠', '' => '欽', '' => '歆', '' => '吸', '' => '恰', '' => '洽', '' => '翕', '' => '興', '' => '僖', '' => '凞', '' => '喜', '' => '噫', '' => '囍', '' => '姬', '' => '嬉', '' => '希', '' => '憙', '' => '憘', '' => '戱', '' => '晞', '' => '曦', '' => '熙', '' => '熹', '' => '熺', '' => '犧', '' => '禧', '' => '稀', '' => '羲', '' => '詰', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp869.php000064400000007134150432043200015437 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => 'Ά', '' => '·', '' => '¬', '' => '¦', '' => '‘', '' => '’', '' => 'Έ', '' => '―', '' => 'Ή', '' => 'Ί', '' => 'Ϊ', '' => 'Ό', '' => 'Ύ', '' => 'Ϋ', '' => '©', '' => 'Ώ', '' => '²', '' => '³', '' => 'ά', '' => '£', '' => 'έ', '' => 'ή', '' => 'ί', '' => 'ϊ', '' => 'ΐ', '' => 'ό', '' => 'ύ', '' => 'Α', '' => 'Β', '' => 'Γ', '' => 'Δ', '' => 'Ε', '' => 'Ζ', '' => 'Η', '' => '½', '' => 'Θ', '' => 'Ι', '' => '«', '' => '»', '' => '░', '' => '▒', '' => '▓', '' => '│', '' => '┤', '' => 'Κ', '' => 'Λ', '' => 'Μ', '' => 'Ν', '' => '╣', '' => '║', '' => '╗', '' => '╝', '' => 'Ξ', '' => 'Ο', '' => '┐', '' => '└', '' => '┴', '' => '┬', '' => '├', '' => '─', '' => '┼', '' => 'Π', '' => 'Ρ', '' => '╚', '' => '╔', '' => '╩', '' => '╦', '' => '╠', '' => '═', '' => '╬', '' => 'Σ', '' => 'Τ', '' => 'Υ', '' => 'Φ', '' => 'Χ', '' => 'Ψ', '' => 'Ω', '' => 'α', '' => 'β', '' => 'γ', '' => '┘', '' => '┌', '' => '█', '' => '▄', '' => 'δ', '' => 'ε', '' => '▀', '' => 'ζ', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'σ', '' => 'ς', '' => 'τ', '' => '΄', '' => '­', '' => '±', '' => 'υ', '' => 'φ', '' => 'χ', '' => '§', '' => 'ψ', '' => '΅', '' => '°', '' => '¨', '' => 'ω', '' => 'ϋ', '' => 'ΰ', '' => 'ώ', '' => '■', '' => ' ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.koi8-r.php000064400000007373150432043200015704 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '─', '' => '│', '' => '┌', '' => '┐', '' => '└', '' => '┘', '' => '├', '' => '┤', '' => '┬', '' => '┴', '' => '┼', '' => '▀', '' => '▄', '' => '█', '' => '▌', '' => '▐', '' => '░', '' => '▒', '' => '▓', '' => '⌠', '' => '■', '' => '∙', '' => '√', '' => '≈', '' => '≤', '' => '≥', '' => ' ', '' => '⌡', '' => '°', '' => '²', '' => '·', '' => '÷', '' => '═', '' => '║', '' => '╒', '' => 'ё', '' => '╓', '' => '╔', '' => '╕', '' => '╖', '' => '╗', '' => '╘', '' => '╙', '' => '╚', '' => '╛', '' => '╜', '' => '╝', '' => '╞', '' => '╟', '' => '╠', '' => '╡', '' => 'Ё', '' => '╢', '' => '╣', '' => '╤', '' => '╥', '' => '╦', '' => '╧', '' => '╨', '' => '╩', '' => '╪', '' => '╫', '' => '╬', '' => '©', '' => 'ю', '' => 'а', '' => 'б', '' => 'ц', '' => 'д', '' => 'е', '' => 'ф', '' => 'г', '' => 'х', '' => 'и', '' => 'й', '' => 'к', '' => 'л', '' => 'м', '' => 'н', '' => 'о', '' => 'п', '' => 'я', '' => 'р', '' => 'с', '' => 'т', '' => 'у', '' => 'ж', '' => 'в', '' => 'ь', '' => 'ы', '' => 'з', '' => 'ш', '' => 'э', '' => 'щ', '' => 'ч', '' => 'ъ', '' => 'Ю', '' => 'А', '' => 'Б', '' => 'Ц', '' => 'Д', '' => 'Е', '' => 'Ф', '' => 'Г', '' => 'Х', '' => 'И', '' => 'Й', '' => 'К', '' => 'Л', '' => 'М', '' => 'Н', '' => 'О', '' => 'П', '' => 'Я', '' => 'Р', '' => 'С', '' => 'Т', '' => 'У', '' => 'Ж', '' => 'В', '' => 'Ь', '' => 'Ы', '' => 'З', '' => 'Ш', '' => 'Э', '' => 'Щ', '' => 'Ч', '' => 'Ъ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.cp875.php000064400000007300150432043200015427 0ustar00 '', '' => '', '' => '', '' => '', '' => 'œ', '' => ' ', '' => '†', '' => '', '' => '—', ' ' => '', ' ' => 'Ž', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '…', '' => '', '' => '‡', '' => '', '' => '', '' => '’', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => '€', '!' => '', '"' => '‚', '#' => 'ƒ', '$' => '„', '%' => ' ', '&' => '', '\'' => '', '(' => 'ˆ', ')' => '‰', '*' => 'Š', '+' => '‹', ',' => 'Œ', '-' => '', '.' => '', '/' => '', 0 => '', 1 => '‘', 2 => '', 3 => '“', 4 => '”', 5 => '•', 6 => '–', 7 => '', 8 => '˜', 9 => '™', ':' => 'š', ';' => '›', '<' => '', '=' => '', '>' => 'ž', '?' => '', '@' => ' ', 'A' => 'Α', 'B' => 'Β', 'C' => 'Γ', 'D' => 'Δ', 'E' => 'Ε', 'F' => 'Ζ', 'G' => 'Η', 'H' => 'Θ', 'I' => 'Ι', 'J' => '[', 'K' => '.', 'L' => '<', 'M' => '(', 'N' => '+', 'O' => '!', 'P' => '&', 'Q' => 'Κ', 'R' => 'Λ', 'S' => 'Μ', 'T' => 'Ν', 'U' => 'Ξ', 'V' => 'Ο', 'W' => 'Π', 'X' => 'Ρ', 'Y' => 'Σ', 'Z' => ']', '[' => '$', '\\' => '*', ']' => ')', '^' => ';', '_' => '^', '`' => '-', 'a' => '/', 'b' => 'Τ', 'c' => 'Υ', 'd' => 'Φ', 'e' => 'Χ', 'f' => 'Ψ', 'g' => 'Ω', 'h' => 'Ϊ', 'i' => 'Ϋ', 'j' => '|', 'k' => ',', 'l' => '%', 'm' => '_', 'n' => '>', 'o' => '?', 'p' => '¨', 'q' => 'Ά', 'r' => 'Έ', 's' => 'Ή', 't' => ' ', 'u' => 'Ί', 'v' => 'Ό', 'w' => 'Ύ', 'x' => 'Ώ', 'y' => '`', 'z' => ':', '{' => '#', '|' => '@', '}' => '\'', '~' => '=', '' => '"', '' => '΅', '' => 'a', '' => 'b', '' => 'c', '' => 'd', '' => 'e', '' => 'f', '' => 'g', '' => 'h', '' => 'i', '' => 'α', '' => 'β', '' => 'γ', '' => 'δ', '' => 'ε', '' => 'ζ', '' => '°', '' => 'j', '' => 'k', '' => 'l', '' => 'm', '' => 'n', '' => 'o', '' => 'p', '' => 'q', '' => 'r', '' => 'η', '' => 'θ', '' => 'ι', '' => 'κ', '' => 'λ', '' => 'μ', '' => '´', '' => '~', '' => 's', '' => 't', '' => 'u', '' => 'v', '' => 'w', '' => 'x', '' => 'y', '' => 'z', '' => 'ν', '' => 'ξ', '' => 'ο', '' => 'π', '' => 'ρ', '' => 'σ', '' => '£', '' => 'ά', '' => 'έ', '' => 'ή', '' => 'ϊ', '' => 'ί', '' => 'ό', '' => 'ύ', '' => 'ϋ', '' => 'ώ', '' => 'ς', '' => 'τ', '' => 'υ', '' => 'φ', '' => 'χ', '' => 'ψ', '' => '{', '' => 'A', '' => 'B', '' => 'C', '' => 'D', '' => 'E', '' => 'F', '' => 'G', '' => 'H', '' => 'I', '' => '­', '' => 'ω', '' => 'ΐ', '' => 'ΰ', '' => '‘', '' => '―', '' => '}', '' => 'J', '' => 'K', '' => 'L', '' => 'M', '' => 'N', '' => 'O', '' => 'P', '' => 'Q', '' => 'R', '' => '±', '' => '½', '' => '', '' => '·', '' => '’', '' => '¦', '' => '\\', '' => '', '' => 'S', '' => 'T', '' => 'U', '' => 'V', '' => 'W', '' => 'X', '' => 'Y', '' => 'Z', '' => '²', '' => '§', '' => '', '' => '', '' => '«', '' => '¬', '' => '0', '' => '1', '' => '2', '' => '3', '' => '4', '' => '5', '' => '6', '' => '7', '' => '8', '' => '9', '' => '³', '' => '©', '' => '', '' => '', '' => '»', '' => 'Ÿ', ); $result =& $data; unset($data); return $result; polyfill-iconv/Resources/charset/from.iso-8859-2.php000064400000007303150432043200016130 0ustar00 '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', '' => '', ' ' => ' ', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', '\'' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', 0 => '0', 1 => '1', 2 => '2', 3 => '3', 4 => '4', 5 => '5', 6 => '6', 7 => '7', 8 => '8', 9 => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '' => '', '' => '€', '' => '', '' => '‚', '' => 'ƒ', '' => '„', '' => '…', '' => '†', '' => '‡', '' => 'ˆ', '' => '‰', '' => 'Š', '' => '‹', '' => 'Œ', '' => '', '' => 'Ž', '' => '', '' => '', '' => '‘', '' => '’', '' => '“', '' => '”', '' => '•', '' => '–', '' => '—', '' => '˜', '' => '™', '' => 'š', '' => '›', '' => 'œ', '' => '', '' => 'ž', '' => 'Ÿ', '' => ' ', '' => 'Ą', '' => '˘', '' => 'Ł', '' => '¤', '' => 'Ľ', '' => 'Ś', '' => '§', '' => '¨', '' => 'Š', '' => 'Ş', '' => 'Ť', '' => 'Ź', '' => '­', '' => 'Ž', '' => 'Ż', '' => '°', '' => 'ą', '' => '˛', '' => 'ł', '' => '´', '' => 'ľ', '' => 'ś', '' => 'ˇ', '' => '¸', '' => 'š', '' => 'ş', '' => 'ť', '' => 'ź', '' => '˝', '' => 'ž', '' => 'ż', '' => 'Ŕ', '' => 'Á', '' => 'Â', '' => 'Ă', '' => 'Ä', '' => 'Ĺ', '' => 'Ć', '' => 'Ç', '' => 'Č', '' => 'É', '' => 'Ę', '' => 'Ë', '' => 'Ě', '' => 'Í', '' => 'Î', '' => 'Ď', '' => 'Đ', '' => 'Ń', '' => 'Ň', '' => 'Ó', '' => 'Ô', '' => 'Ő', '' => 'Ö', '' => '×', '' => 'Ř', '' => 'Ů', '' => 'Ú', '' => 'Ű', '' => 'Ü', '' => 'Ý', '' => 'Ţ', '' => 'ß', '' => 'ŕ', '' => 'á', '' => 'â', '' => 'ă', '' => 'ä', '' => 'ĺ', '' => 'ć', '' => 'ç', '' => 'č', '' => 'é', '' => 'ę', '' => 'ë', '' => 'ě', '' => 'í', '' => 'î', '' => 'ď', '' => 'đ', '' => 'ń', '' => 'ň', '' => 'ó', '' => 'ô', '' => 'ő', '' => 'ö', '' => '÷', '' => 'ř', '' => 'ů', '' => 'ú', '' => 'ű', '' => 'ü', '' => 'ý', '' => 'ţ', '' => '˙', ); $result =& $data; unset($data); return $result; polyfill-iconv/README.md000064400000000650150432043200010763 0ustar00Symfony Polyfill / Iconv ======================== This component provides a native PHP implementation of the [php.net/iconv](https://php.net/iconv) functions (short of [`ob_iconv_handler`](https://php.net/ob-iconv-handler)). More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= This library is released under the [MIT license](LICENSE). polyfill-iconv/bootstrap80.php000064400000011010150432043200012372 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Iconv as p; if (!defined('ICONV_IMPL')) { define('ICONV_IMPL', 'Symfony'); } if (!defined('ICONV_VERSION')) { define('ICONV_VERSION', '1.0'); } if (!defined('ICONV_MIME_DECODE_STRICT')) { define('ICONV_MIME_DECODE_STRICT', 1); } if (!defined('ICONV_MIME_DECODE_CONTINUE_ON_ERROR')) { define('ICONV_MIME_DECODE_CONTINUE_ON_ERROR', 2); } if (!function_exists('iconv')) { function iconv(?string $from_encoding, ?string $to_encoding, ?string $string): string|false { return p\Iconv::iconv((string) $from_encoding, (string) $to_encoding, (string) $string); } } if (!function_exists('iconv_get_encoding')) { function iconv_get_encoding(?string $type = 'all'): array|string|false { return p\Iconv::iconv_get_encoding((string) $type); } } if (!function_exists('iconv_set_encoding')) { function iconv_set_encoding(?string $type, ?string $encoding): bool { return p\Iconv::iconv_set_encoding((string) $type, (string) $encoding); } } if (!function_exists('iconv_mime_encode')) { function iconv_mime_encode(?string $field_name, ?string $field_value, ?array $options = []): string|false { return p\Iconv::iconv_mime_encode((string) $field_name, (string) $field_value, (array) $options); } } if (!function_exists('iconv_mime_decode_headers')) { function iconv_mime_decode_headers(?string $headers, ?int $mode = 0, ?string $encoding = null): array|false { return p\Iconv::iconv_mime_decode_headers((string) $headers, (int) $mode, $encoding); } } if (extension_loaded('mbstring')) { if (!function_exists('iconv_strlen')) { function iconv_strlen(?string $string, ?string $encoding = null): int|false { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_strlen((string) $string, $encoding); } } if (!function_exists('iconv_strpos')) { function iconv_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } } if (!function_exists('iconv_strrpos')) { function iconv_strrpos(?string $haystack, ?string $needle, ?string $encoding = null): int|false { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_strrpos((string) $haystack, (string) $needle, 0, $encoding); } } if (!function_exists('iconv_substr')) { function iconv_substr(?string $string, ?int $offset, ?int $length = null, ?string $encoding = null): string|false { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_substr((string) $string, (int) $offset, $length, $encoding); } } if (!function_exists('iconv_mime_decode')) { function iconv_mime_decode($string, $mode = 0, $encoding = null) { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_decode_mimeheader($string, $mode, $encoding); } } } else { if (!function_exists('iconv_strlen')) { if (extension_loaded('xml')) { function iconv_strlen(?string $string, ?string $encoding = null): int|false { return p\Iconv::strlen1((string) $string, $encoding); } } else { function iconv_strlen(?string $string, ?string $encoding = null): int|false { return p\Iconv::strlen2((string) $string, $encoding); } } } if (!function_exists('iconv_strpos')) { function iconv_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Iconv::iconv_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } } if (!function_exists('iconv_strrpos')) { function iconv_strrpos(?string $haystack, ?string $needle, ?string $encoding = null): int|false { return p\Iconv::iconv_strrpos((string) $haystack, (string) $needle, $encoding); } } if (!function_exists('iconv_substr')) { function iconv_substr(?string $string, ?int $offset, ?int $length = null, ?string $encoding = null): string|false { return p\Iconv::iconv_substr((string) $string, (string) $offset, $length, $encoding); } } if (!function_exists('iconv_mime_decode')) { function iconv_mime_decode(?string $string, ?int $mode = 0, ?string $encoding = null): string|false { return p\Iconv::iconv_mime_decode((string) $string, (int) $mode, $encoding); } } } polyfill-iconv/bootstrap.php000064400000007637150432043200012246 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Iconv as p; if (extension_loaded('iconv')) { return; } if (\PHP_VERSION_ID >= 80000) { return require __DIR__.'/bootstrap80.php'; } if (!defined('ICONV_IMPL')) { define('ICONV_IMPL', 'Symfony'); } if (!defined('ICONV_VERSION')) { define('ICONV_VERSION', '1.0'); } if (!defined('ICONV_MIME_DECODE_STRICT')) { define('ICONV_MIME_DECODE_STRICT', 1); } if (!defined('ICONV_MIME_DECODE_CONTINUE_ON_ERROR')) { define('ICONV_MIME_DECODE_CONTINUE_ON_ERROR', 2); } if (!function_exists('iconv')) { function iconv($from_encoding, $to_encoding, $string) { return p\Iconv::iconv($from_encoding, $to_encoding, $string); } } if (!function_exists('iconv_get_encoding')) { function iconv_get_encoding($type = 'all') { return p\Iconv::iconv_get_encoding($type); } } if (!function_exists('iconv_set_encoding')) { function iconv_set_encoding($type, $encoding) { return p\Iconv::iconv_set_encoding($type, $encoding); } } if (!function_exists('iconv_mime_encode')) { function iconv_mime_encode($field_name, $field_value, $options = []) { return p\Iconv::iconv_mime_encode($field_name, $field_value, $options); } } if (!function_exists('iconv_mime_decode_headers')) { function iconv_mime_decode_headers($headers, $mode = 0, $encoding = null) { return p\Iconv::iconv_mime_decode_headers($headers, $mode, $encoding); } } if (extension_loaded('mbstring')) { if (!function_exists('iconv_strlen')) { function iconv_strlen($string, $encoding = null) { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_strlen($string, $encoding); } } if (!function_exists('iconv_strpos')) { function iconv_strpos($haystack, $needle, $offset = 0, $encoding = null) { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_strpos($haystack, $needle, $offset, $encoding); } } if (!function_exists('iconv_strrpos')) { function iconv_strrpos($haystack, $needle, $encoding = null) { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_strrpos($haystack, $needle, 0, $encoding); } } if (!function_exists('iconv_substr')) { function iconv_substr($string, $offset, $length = 2147483647, $encoding = null) { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_substr($string, $offset, $length, $encoding); } } if (!function_exists('iconv_mime_decode')) { function iconv_mime_decode($string, $mode = 0, $encoding = null) { null === $encoding && $encoding = p\Iconv::$internalEncoding; return mb_decode_mimeheader($string, $mode, $encoding); } } } else { if (!function_exists('iconv_strlen')) { if (extension_loaded('xml')) { function iconv_strlen($string, $encoding = null) { return p\Iconv::strlen1($string, $encoding); } } else { function iconv_strlen($string, $encoding = null) { return p\Iconv::strlen2($string, $encoding); } } } if (!function_exists('iconv_strpos')) { function iconv_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Iconv::iconv_strpos($haystack, $needle, $offset, $encoding); } } if (!function_exists('iconv_strrpos')) { function iconv_strrpos($haystack, $needle, $encoding = null) { return p\Iconv::iconv_strrpos($haystack, $needle, $encoding); } } if (!function_exists('iconv_substr')) { function iconv_substr($string, $offset, $length = 2147483647, $encoding = null) { return p\Iconv::iconv_substr($string, $offset, $length, $encoding); } } if (!function_exists('iconv_mime_decode')) { function iconv_mime_decode($string, $mode = 0, $encoding = null) { return p\Iconv::iconv_mime_decode($string, $mode, $encoding); } } } polyfill-iconv/composer.json000064400000001735150432043200012233 0ustar00{ "name": "symfony/polyfill-iconv", "type": "library", "description": "Symfony polyfill for the Iconv extension", "keywords": ["polyfill", "shim", "compatibility", "portable", "iconv"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Iconv\\": "" }, "files": [ "bootstrap.php" ] }, "suggest": { "ext-iconv": "For best performance" }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-iconv/LICENSE000064400000002051150432043200010506 0ustar00Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. polyfill-iconv/Iconv.php000064400000054141150432043200011277 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Iconv; /** * iconv implementation in pure PHP, UTF-8 centric. * * Implemented: * - iconv - Convert string to requested character encoding * - iconv_mime_decode - Decodes a MIME header field * - iconv_mime_decode_headers - Decodes multiple MIME header fields at once * - iconv_get_encoding - Retrieve internal configuration variables of iconv extension * - iconv_set_encoding - Set current setting for character encoding conversion * - iconv_mime_encode - Composes a MIME header field * - iconv_strlen - Returns the character count of string * - iconv_strpos - Finds position of first occurrence of a needle within a haystack * - iconv_strrpos - Finds the last occurrence of a needle within a haystack * - iconv_substr - Cut out part of a string * * Charsets available for conversion are defined by files * in the charset/ directory and by Iconv::$alias below. * You're welcome to send back any addition you make. * * @author Nicolas Grekas * * @internal */ final class Iconv { public const ERROR_ILLEGAL_CHARACTER = 'iconv(): Detected an illegal character in input string'; public const ERROR_WRONG_CHARSET = 'iconv(): Wrong charset, conversion from `%s\' to `%s\' is not allowed'; public static $inputEncoding = 'utf-8'; public static $outputEncoding = 'utf-8'; public static $internalEncoding = 'utf-8'; private static $alias = [ 'utf8' => 'utf-8', 'ascii' => 'us-ascii', 'tis-620' => 'iso-8859-11', 'cp1250' => 'windows-1250', 'cp1251' => 'windows-1251', 'cp1252' => 'windows-1252', 'cp1253' => 'windows-1253', 'cp1254' => 'windows-1254', 'cp1255' => 'windows-1255', 'cp1256' => 'windows-1256', 'cp1257' => 'windows-1257', 'cp1258' => 'windows-1258', 'shift-jis' => 'cp932', 'shift_jis' => 'cp932', 'latin1' => 'iso-8859-1', 'latin2' => 'iso-8859-2', 'latin3' => 'iso-8859-3', 'latin4' => 'iso-8859-4', 'latin5' => 'iso-8859-9', 'latin6' => 'iso-8859-10', 'latin7' => 'iso-8859-13', 'latin8' => 'iso-8859-14', 'latin9' => 'iso-8859-15', 'latin10' => 'iso-8859-16', 'iso8859-1' => 'iso-8859-1', 'iso8859-2' => 'iso-8859-2', 'iso8859-3' => 'iso-8859-3', 'iso8859-4' => 'iso-8859-4', 'iso8859-5' => 'iso-8859-5', 'iso8859-6' => 'iso-8859-6', 'iso8859-7' => 'iso-8859-7', 'iso8859-8' => 'iso-8859-8', 'iso8859-9' => 'iso-8859-9', 'iso8859-10' => 'iso-8859-10', 'iso8859-11' => 'iso-8859-11', 'iso8859-12' => 'iso-8859-12', 'iso8859-13' => 'iso-8859-13', 'iso8859-14' => 'iso-8859-14', 'iso8859-15' => 'iso-8859-15', 'iso8859-16' => 'iso-8859-16', 'iso_8859-1' => 'iso-8859-1', 'iso_8859-2' => 'iso-8859-2', 'iso_8859-3' => 'iso-8859-3', 'iso_8859-4' => 'iso-8859-4', 'iso_8859-5' => 'iso-8859-5', 'iso_8859-6' => 'iso-8859-6', 'iso_8859-7' => 'iso-8859-7', 'iso_8859-8' => 'iso-8859-8', 'iso_8859-9' => 'iso-8859-9', 'iso_8859-10' => 'iso-8859-10', 'iso_8859-11' => 'iso-8859-11', 'iso_8859-12' => 'iso-8859-12', 'iso_8859-13' => 'iso-8859-13', 'iso_8859-14' => 'iso-8859-14', 'iso_8859-15' => 'iso-8859-15', 'iso_8859-16' => 'iso-8859-16', 'iso88591' => 'iso-8859-1', 'iso88592' => 'iso-8859-2', 'iso88593' => 'iso-8859-3', 'iso88594' => 'iso-8859-4', 'iso88595' => 'iso-8859-5', 'iso88596' => 'iso-8859-6', 'iso88597' => 'iso-8859-7', 'iso88598' => 'iso-8859-8', 'iso88599' => 'iso-8859-9', 'iso885910' => 'iso-8859-10', 'iso885911' => 'iso-8859-11', 'iso885912' => 'iso-8859-12', 'iso885913' => 'iso-8859-13', 'iso885914' => 'iso-8859-14', 'iso885915' => 'iso-8859-15', 'iso885916' => 'iso-8859-16', ]; private static $translitMap = []; private static $convertMap = []; private static $errorHandler; private static $lastError; private static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; private static $isValidUtf8; public static function iconv($inCharset, $outCharset, $str) { $str = (string) $str; if ('' === $str) { return ''; } // Prepare for //IGNORE and //TRANSLIT $translit = $ignore = ''; $outCharset = strtolower($outCharset); $inCharset = strtolower($inCharset); if ('' === $outCharset) { $outCharset = 'iso-8859-1'; } if ('' === $inCharset) { $inCharset = 'iso-8859-1'; } do { $loop = false; if ('//translit' === substr($outCharset, -10)) { $loop = $translit = true; $outCharset = substr($outCharset, 0, -10); } if ('//ignore' === substr($outCharset, -8)) { $loop = $ignore = true; $outCharset = substr($outCharset, 0, -8); } } while ($loop); do { $loop = false; if ('//translit' === substr($inCharset, -10)) { $loop = true; $inCharset = substr($inCharset, 0, -10); } if ('//ignore' === substr($inCharset, -8)) { $loop = true; $inCharset = substr($inCharset, 0, -8); } } while ($loop); if (isset(self::$alias[$inCharset])) { $inCharset = self::$alias[$inCharset]; } if (isset(self::$alias[$outCharset])) { $outCharset = self::$alias[$outCharset]; } // Load charset maps if (('utf-8' !== $inCharset && !self::loadMap('from.', $inCharset, $inMap)) || ('utf-8' !== $outCharset && !self::loadMap('to.', $outCharset, $outMap))) { trigger_error(sprintf(self::ERROR_WRONG_CHARSET, $inCharset, $outCharset)); return false; } if ('utf-8' !== $inCharset) { // Convert input to UTF-8 $result = ''; if (self::mapToUtf8($result, $inMap, $str, $ignore)) { $str = $result; } else { $str = false; } self::$isValidUtf8 = true; } else { self::$isValidUtf8 = preg_match('//u', $str); if (!self::$isValidUtf8 && !$ignore) { trigger_error(self::ERROR_ILLEGAL_CHARACTER); return false; } if ('utf-8' === $outCharset) { // UTF-8 validation $str = self::utf8ToUtf8($str, $ignore); } } if ('utf-8' !== $outCharset && false !== $str) { // Convert output to UTF-8 $result = ''; if (self::mapFromUtf8($result, $outMap, $str, $ignore, $translit)) { return $result; } return false; } return $str; } public static function iconv_mime_decode_headers($str, $mode = 0, $charset = null) { if (null === $charset) { $charset = self::$internalEncoding; } if (false !== strpos($str, "\r")) { $str = strtr(str_replace("\r\n", "\n", $str), "\r", "\n"); } $str = explode("\n\n", $str, 2); $headers = []; $str = preg_split('/\n(?![ \t])/', $str[0]); foreach ($str as $str) { $str = self::iconv_mime_decode($str, $mode, $charset); if (false === $str) { return false; } $str = explode(':', $str, 2); if (2 === \count($str)) { if (isset($headers[$str[0]])) { if (!\is_array($headers[$str[0]])) { $headers[$str[0]] = [$headers[$str[0]]]; } $headers[$str[0]][] = ltrim($str[1]); } else { $headers[$str[0]] = ltrim($str[1]); } } } return $headers; } public static function iconv_mime_decode($str, $mode = 0, $charset = null) { if (null === $charset) { $charset = self::$internalEncoding; } if (\ICONV_MIME_DECODE_CONTINUE_ON_ERROR & $mode) { $charset .= '//IGNORE'; } if (false !== strpos($str, "\r")) { $str = strtr(str_replace("\r\n", "\n", $str), "\r", "\n"); } $str = preg_split('/\n(?![ \t])/', rtrim($str), 2); $str = preg_replace('/[ \t]*\n[ \t]+/', ' ', rtrim($str[0])); $str = preg_split('/=\?([^?]+)\?([bqBQ])\?(.*?)\?=/', $str, -1, \PREG_SPLIT_DELIM_CAPTURE); $result = self::iconv('utf-8', $charset, $str[0]); if (false === $result) { return false; } $i = 1; $len = \count($str); while ($i < $len) { $c = strtolower($str[$i]); if ((\ICONV_MIME_DECODE_CONTINUE_ON_ERROR & $mode) && 'utf-8' !== $c && !isset(self::$alias[$c]) && !self::loadMap('from.', $c, $d)) { $d = false; } elseif ('B' === strtoupper($str[$i + 1])) { $d = base64_decode($str[$i + 2]); } else { $d = rawurldecode(strtr(str_replace('%', '%25', $str[$i + 2]), '=_', '% ')); } if (false !== $d) { if ('' !== $d) { if ('' === $d = self::iconv($c, $charset, $d)) { $str[$i + 3] = substr($str[$i + 3], 1); } else { $result .= $d; } } $d = self::iconv('utf-8', $charset, $str[$i + 3]); if ('' !== trim($d)) { $result .= $d; } } elseif (\ICONV_MIME_DECODE_CONTINUE_ON_ERROR & $mode) { $result .= "=?{$str[$i]}?{$str[$i + 1]}?{$str[$i + 2]}?={$str[$i + 3]}"; } else { $result = false; break; } $i += 4; } return $result; } public static function iconv_get_encoding($type = 'all') { switch ($type) { case 'input_encoding': return self::$inputEncoding; case 'output_encoding': return self::$outputEncoding; case 'internal_encoding': return self::$internalEncoding; } return [ 'input_encoding' => self::$inputEncoding, 'output_encoding' => self::$outputEncoding, 'internal_encoding' => self::$internalEncoding, ]; } public static function iconv_set_encoding($type, $charset) { switch ($type) { case 'input_encoding': self::$inputEncoding = $charset; break; case 'output_encoding': self::$outputEncoding = $charset; break; case 'internal_encoding': self::$internalEncoding = $charset; break; default: return false; } return true; } public static function iconv_mime_encode($fieldName, $fieldValue, $pref = null) { if (!\is_array($pref)) { $pref = []; } $pref += [ 'scheme' => 'B', 'input-charset' => self::$internalEncoding, 'output-charset' => self::$internalEncoding, 'line-length' => 76, 'line-break-chars' => "\r\n", ]; if (preg_match('/[\x80-\xFF]/', $fieldName)) { $fieldName = ''; } $scheme = strtoupper(substr($pref['scheme'], 0, 1)); $in = strtolower($pref['input-charset']); $out = strtolower($pref['output-charset']); if ('utf-8' !== $in && false === $fieldValue = self::iconv($in, 'utf-8', $fieldValue)) { return false; } preg_match_all('/./us', $fieldValue, $chars); $chars = $chars[0] ?? []; $lineBreak = (int) $pref['line-length']; $lineStart = "=?{$pref['output-charset']}?{$scheme}?"; $lineLength = \strlen($fieldName) + 2 + \strlen($lineStart) + 2; $lineOffset = \strlen($lineStart) + 3; $lineData = ''; $fieldValue = []; $Q = 'Q' === $scheme; foreach ($chars as $c) { if ('utf-8' !== $out && false === $c = self::iconv('utf-8', $out, $c)) { return false; } $o = $Q ? $c = preg_replace_callback( '/[=_\?\x00-\x1F\x80-\xFF]/', [__CLASS__, 'qpByteCallback'], $c ) : base64_encode($lineData.$c); if (isset($o[$lineBreak - $lineLength])) { if (!$Q) { $lineData = base64_encode($lineData); } $fieldValue[] = $lineStart.$lineData.'?='; $lineLength = $lineOffset; $lineData = ''; } $lineData .= $c; $Q && $lineLength += \strlen($c); } if ('' !== $lineData) { if (!$Q) { $lineData = base64_encode($lineData); } $fieldValue[] = $lineStart.$lineData.'?='; } return $fieldName.': '.implode($pref['line-break-chars'].' ', $fieldValue); } public static function iconv_strlen($s, $encoding = null) { static $hasXml = null; if (null === $hasXml) { $hasXml = \extension_loaded('xml'); } if ($hasXml) { return self::strlen1($s, $encoding); } return self::strlen2($s, $encoding); } public static function strlen1($s, $encoding = null) { if (null === $encoding) { $encoding = self::$internalEncoding; } if (0 !== stripos($encoding, 'utf-8') && false === $s = self::iconv($encoding, 'utf-8', $s)) { return false; } return \strlen(utf8_decode($s)); } public static function strlen2($s, $encoding = null) { if (null === $encoding) { $encoding = self::$internalEncoding; } if (0 !== stripos($encoding, 'utf-8') && false === $s = self::iconv($encoding, 'utf-8', $s)) { return false; } $ulenMask = self::$ulenMask; $i = 0; $j = 0; $len = \strlen($s); while ($i < $len) { $u = $s[$i] & "\xF0"; $i += $ulenMask[$u] ?? 1; ++$j; } return $j; } public static function iconv_strpos($haystack, $needle, $offset = 0, $encoding = null) { if (null === $encoding) { $encoding = self::$internalEncoding; } if (0 !== stripos($encoding, 'utf-8')) { if (false === $haystack = self::iconv($encoding, 'utf-8', $haystack)) { return false; } if (false === $needle = self::iconv($encoding, 'utf-8', $needle)) { return false; } } if ($offset = (int) $offset) { $haystack = self::iconv_substr($haystack, $offset, 2147483647, 'utf-8'); } $pos = strpos($haystack, $needle); return false === $pos ? false : ($offset + ($pos ? self::iconv_strlen(substr($haystack, 0, $pos), 'utf-8') : 0)); } public static function iconv_strrpos($haystack, $needle, $encoding = null) { if (null === $encoding) { $encoding = self::$internalEncoding; } if (0 !== stripos($encoding, 'utf-8')) { if (false === $haystack = self::iconv($encoding, 'utf-8', $haystack)) { return false; } if (false === $needle = self::iconv($encoding, 'utf-8', $needle)) { return false; } } $pos = isset($needle[0]) ? strrpos($haystack, $needle) : false; return false === $pos ? false : self::iconv_strlen($pos ? substr($haystack, 0, $pos) : $haystack, 'utf-8'); } public static function iconv_substr($s, $start, $length = 2147483647, $encoding = null) { if (null === $encoding) { $encoding = self::$internalEncoding; } if (0 !== stripos($encoding, 'utf-8')) { $encoding = null; } elseif (false === $s = self::iconv($encoding, 'utf-8', $s)) { return false; } $s = (string) $s; $slen = self::iconv_strlen($s, 'utf-8'); $start = (int) $start; if (0 > $start) { $start += $slen; } if (0 > $start) { if (\PHP_VERSION_ID < 80000) { return false; } $start = 0; } if ($start >= $slen) { return \PHP_VERSION_ID >= 80000 ? '' : false; } $rx = $slen - $start; if (0 > $length) { $length += $rx; } if (0 === $length) { return ''; } if (0 > $length) { return \PHP_VERSION_ID >= 80000 ? '' : false; } if ($length > $rx) { $length = $rx; } $rx = '/^'.($start ? self::pregOffset($start) : '').'('.self::pregOffset($length).')/u'; $s = preg_match($rx, $s, $s) ? $s[1] : ''; if (null === $encoding) { return $s; } return self::iconv('utf-8', $encoding, $s); } private static function loadMap($type, $charset, &$map) { if (!isset(self::$convertMap[$type.$charset])) { if (false === $map = self::getData($type.$charset)) { if ('to.' === $type && self::loadMap('from.', $charset, $map)) { $map = array_flip($map); } else { return false; } } self::$convertMap[$type.$charset] = $map; } else { $map = self::$convertMap[$type.$charset]; } return true; } private static function utf8ToUtf8($str, $ignore) { $ulenMask = self::$ulenMask; $valid = self::$isValidUtf8; $u = $str; $i = $j = 0; $len = \strlen($str); while ($i < $len) { if ($str[$i] < "\x80") { $u[$j++] = $str[$i++]; } else { $ulen = $str[$i] & "\xF0"; $ulen = $ulenMask[$ulen] ?? 1; $uchr = substr($str, $i, $ulen); if (1 === $ulen || !($valid || preg_match('/^.$/us', $uchr))) { if ($ignore) { ++$i; continue; } trigger_error(self::ERROR_ILLEGAL_CHARACTER); return false; } $i += $ulen; $u[$j++] = $uchr[0]; isset($uchr[1]) && 0 !== ($u[$j++] = $uchr[1]) && isset($uchr[2]) && 0 !== ($u[$j++] = $uchr[2]) && isset($uchr[3]) && 0 !== ($u[$j++] = $uchr[3]); } } return substr($u, 0, $j); } private static function mapToUtf8(&$result, array $map, $str, $ignore) { $len = \strlen($str); for ($i = 0; $i < $len; ++$i) { if (isset($str[$i + 1], $map[$str[$i].$str[$i + 1]])) { $result .= $map[$str[$i].$str[++$i]]; } elseif (isset($map[$str[$i]])) { $result .= $map[$str[$i]]; } elseif (!$ignore) { trigger_error(self::ERROR_ILLEGAL_CHARACTER); return false; } } return true; } private static function mapFromUtf8(&$result, array $map, $str, $ignore, $translit) { $ulenMask = self::$ulenMask; $valid = self::$isValidUtf8; if ($translit && !self::$translitMap) { self::$translitMap = self::getData('translit'); } $i = 0; $len = \strlen($str); while ($i < $len) { if ($str[$i] < "\x80") { $uchr = $str[$i++]; } else { $ulen = $str[$i] & "\xF0"; $ulen = $ulenMask[$ulen] ?? 1; $uchr = substr($str, $i, $ulen); if ($ignore && (1 === $ulen || !($valid || preg_match('/^.$/us', $uchr)))) { ++$i; continue; } $i += $ulen; } if (isset($map[$uchr])) { $result .= $map[$uchr]; } elseif ($translit) { if (isset(self::$translitMap[$uchr])) { $uchr = self::$translitMap[$uchr]; } elseif ($uchr >= "\xC3\x80") { $uchr = \Normalizer::normalize($uchr, \Normalizer::NFD); if ($uchr[0] < "\x80") { $uchr = $uchr[0]; } elseif ($ignore) { continue; } else { return false; } } elseif ($ignore) { continue; } else { return false; } $str = $uchr.substr($str, $i); $len = \strlen($str); $i = 0; } elseif (!$ignore) { return false; } } return true; } private static function qpByteCallback(array $m) { return '='.strtoupper(dechex(\ord($m[0]))); } private static function pregOffset($offset) { $rx = []; $offset = (int) $offset; while ($offset > 65535) { $rx[] = '.{65535}'; $offset -= 65535; } return implode('', $rx).'.{'.$offset.'}'; } private static function getData($file) { if (file_exists($file = __DIR__.'/Resources/charset/'.$file.'.php')) { return require $file; } return false; } } polyfill-ctype/README.md000064400000000540150432043200010767 0ustar00Symfony Polyfill / Ctype ======================== This component provides `ctype_*` functions to users who run php versions without the ctype extension. More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= This library is released under the [MIT license](LICENSE). polyfill-ctype/bootstrap80.php000064400000003162150432043200012411 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Ctype as p; if (!function_exists('ctype_alnum')) { function ctype_alnum(mixed $text): bool { return p\Ctype::ctype_alnum($text); } } if (!function_exists('ctype_alpha')) { function ctype_alpha(mixed $text): bool { return p\Ctype::ctype_alpha($text); } } if (!function_exists('ctype_cntrl')) { function ctype_cntrl(mixed $text): bool { return p\Ctype::ctype_cntrl($text); } } if (!function_exists('ctype_digit')) { function ctype_digit(mixed $text): bool { return p\Ctype::ctype_digit($text); } } if (!function_exists('ctype_graph')) { function ctype_graph(mixed $text): bool { return p\Ctype::ctype_graph($text); } } if (!function_exists('ctype_lower')) { function ctype_lower(mixed $text): bool { return p\Ctype::ctype_lower($text); } } if (!function_exists('ctype_print')) { function ctype_print(mixed $text): bool { return p\Ctype::ctype_print($text); } } if (!function_exists('ctype_punct')) { function ctype_punct(mixed $text): bool { return p\Ctype::ctype_punct($text); } } if (!function_exists('ctype_space')) { function ctype_space(mixed $text): bool { return p\Ctype::ctype_space($text); } } if (!function_exists('ctype_upper')) { function ctype_upper(mixed $text): bool { return p\Ctype::ctype_upper($text); } } if (!function_exists('ctype_xdigit')) { function ctype_xdigit(mixed $text): bool { return p\Ctype::ctype_xdigit($text); } } polyfill-ctype/bootstrap.php000064400000003100150432043200012231 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Ctype as p; if (\PHP_VERSION_ID >= 80000) { return require __DIR__.'/bootstrap80.php'; } if (!function_exists('ctype_alnum')) { function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } } if (!function_exists('ctype_alpha')) { function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } } if (!function_exists('ctype_cntrl')) { function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } } if (!function_exists('ctype_digit')) { function ctype_digit($text) { return p\Ctype::ctype_digit($text); } } if (!function_exists('ctype_graph')) { function ctype_graph($text) { return p\Ctype::ctype_graph($text); } } if (!function_exists('ctype_lower')) { function ctype_lower($text) { return p\Ctype::ctype_lower($text); } } if (!function_exists('ctype_print')) { function ctype_print($text) { return p\Ctype::ctype_print($text); } } if (!function_exists('ctype_punct')) { function ctype_punct($text) { return p\Ctype::ctype_punct($text); } } if (!function_exists('ctype_space')) { function ctype_space($text) { return p\Ctype::ctype_space($text); } } if (!function_exists('ctype_upper')) { function ctype_upper($text) { return p\Ctype::ctype_upper($text); } } if (!function_exists('ctype_xdigit')) { function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } } polyfill-ctype/composer.json000064400000001730150432043200012234 0ustar00{ "name": "symfony/polyfill-ctype", "type": "library", "description": "Symfony polyfill for ctype functions", "keywords": ["polyfill", "compatibility", "portable", "ctype"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Gert de Pagter", "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, "files": [ "bootstrap.php" ] }, "suggest": { "ext-ctype": "For best performance" }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-ctype/LICENSE000064400000002051150432043200010514 0ustar00Copyright (c) 2018-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. polyfill-ctype/Ctype.php000064400000014175150432043200011316 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Ctype; /** * Ctype implementation through regex. * * @internal * * @author Gert de Pagter */ final class Ctype { /** * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. * * @see https://php.net/ctype-alnum * * @param string|int $text * * @return bool */ public static function ctype_alnum($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); } /** * Returns TRUE if every character in text is a letter, FALSE otherwise. * * @see https://php.net/ctype-alpha * * @param string|int $text * * @return bool */ public static function ctype_alpha($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); } /** * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. * * @see https://php.net/ctype-cntrl * * @param string|int $text * * @return bool */ public static function ctype_cntrl($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); } /** * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. * * @see https://php.net/ctype-digit * * @param string|int $text * * @return bool */ public static function ctype_digit($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); } /** * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. * * @see https://php.net/ctype-graph * * @param string|int $text * * @return bool */ public static function ctype_graph($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); } /** * Returns TRUE if every character in text is a lowercase letter. * * @see https://php.net/ctype-lower * * @param string|int $text * * @return bool */ public static function ctype_lower($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); } /** * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. * * @see https://php.net/ctype-print * * @param string|int $text * * @return bool */ public static function ctype_print($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); } /** * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. * * @see https://php.net/ctype-punct * * @param string|int $text * * @return bool */ public static function ctype_punct($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); } /** * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. * * @see https://php.net/ctype-space * * @param string|int $text * * @return bool */ public static function ctype_space($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); } /** * Returns TRUE if every character in text is an uppercase letter. * * @see https://php.net/ctype-upper * * @param string|int $text * * @return bool */ public static function ctype_upper($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); } /** * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. * * @see https://php.net/ctype-xdigit * * @param string|int $text * * @return bool */ public static function ctype_xdigit($text) { $text = self::convert_int_to_char_for_ctype($text); return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); } /** * Converts integers to their char versions according to normal ctype behaviour, if needed. * * If an integer between -128 and 255 inclusive is provided, * it is interpreted as the ASCII value of a single character * (negative values have 256 added in order to allow characters in the Extended ASCII range). * Any other integer is interpreted as a string containing the decimal digits of the integer. * * @param string|int $int * * @return mixed */ private static function convert_int_to_char_for_ctype($int) { if (!\is_int($int)) { return $int; } if ($int < -128 || $int > 255) { return (string) $int; } if ($int < 0) { $int += 256; } return \chr($int); } } polyfill-mbstring/Resources/unidata/lowerCase.php000064400000057733150432043200016265 0ustar00 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', 'À' => 'à', 'Á' => 'á', 'Â' => 'â', 'Ã' => 'ã', 'Ä' => 'ä', 'Å' => 'å', 'Æ' => 'æ', 'Ç' => 'ç', 'È' => 'è', 'É' => 'é', 'Ê' => 'ê', 'Ë' => 'ë', 'Ì' => 'ì', 'Í' => 'í', 'Î' => 'î', 'Ï' => 'ï', 'Ð' => 'ð', 'Ñ' => 'ñ', 'Ò' => 'ò', 'Ó' => 'ó', 'Ô' => 'ô', 'Õ' => 'õ', 'Ö' => 'ö', 'Ø' => 'ø', 'Ù' => 'ù', 'Ú' => 'ú', 'Û' => 'û', 'Ü' => 'ü', 'Ý' => 'ý', 'Þ' => 'þ', 'Ā' => 'ā', 'Ă' => 'ă', 'Ą' => 'ą', 'Ć' => 'ć', 'Ĉ' => 'ĉ', 'Ċ' => 'ċ', 'Č' => 'č', 'Ď' => 'ď', 'Đ' => 'đ', 'Ē' => 'ē', 'Ĕ' => 'ĕ', 'Ė' => 'ė', 'Ę' => 'ę', 'Ě' => 'ě', 'Ĝ' => 'ĝ', 'Ğ' => 'ğ', 'Ġ' => 'ġ', 'Ģ' => 'ģ', 'Ĥ' => 'ĥ', 'Ħ' => 'ħ', 'Ĩ' => 'ĩ', 'Ī' => 'ī', 'Ĭ' => 'ĭ', 'Į' => 'į', 'İ' => 'i̇', 'IJ' => 'ij', 'Ĵ' => 'ĵ', 'Ķ' => 'ķ', 'Ĺ' => 'ĺ', 'Ļ' => 'ļ', 'Ľ' => 'ľ', 'Ŀ' => 'ŀ', 'Ł' => 'ł', 'Ń' => 'ń', 'Ņ' => 'ņ', 'Ň' => 'ň', 'Ŋ' => 'ŋ', 'Ō' => 'ō', 'Ŏ' => 'ŏ', 'Ő' => 'ő', 'Œ' => 'œ', 'Ŕ' => 'ŕ', 'Ŗ' => 'ŗ', 'Ř' => 'ř', 'Ś' => 'ś', 'Ŝ' => 'ŝ', 'Ş' => 'ş', 'Š' => 'š', 'Ţ' => 'ţ', 'Ť' => 'ť', 'Ŧ' => 'ŧ', 'Ũ' => 'ũ', 'Ū' => 'ū', 'Ŭ' => 'ŭ', 'Ů' => 'ů', 'Ű' => 'ű', 'Ų' => 'ų', 'Ŵ' => 'ŵ', 'Ŷ' => 'ŷ', 'Ÿ' => 'ÿ', 'Ź' => 'ź', 'Ż' => 'ż', 'Ž' => 'ž', 'Ɓ' => 'ɓ', 'Ƃ' => 'ƃ', 'Ƅ' => 'ƅ', 'Ɔ' => 'ɔ', 'Ƈ' => 'ƈ', 'Ɖ' => 'ɖ', 'Ɗ' => 'ɗ', 'Ƌ' => 'ƌ', 'Ǝ' => 'ǝ', 'Ə' => 'ə', 'Ɛ' => 'ɛ', 'Ƒ' => 'ƒ', 'Ɠ' => 'ɠ', 'Ɣ' => 'ɣ', 'Ɩ' => 'ɩ', 'Ɨ' => 'ɨ', 'Ƙ' => 'ƙ', 'Ɯ' => 'ɯ', 'Ɲ' => 'ɲ', 'Ɵ' => 'ɵ', 'Ơ' => 'ơ', 'Ƣ' => 'ƣ', 'Ƥ' => 'ƥ', 'Ʀ' => 'ʀ', 'Ƨ' => 'ƨ', 'Ʃ' => 'ʃ', 'Ƭ' => 'ƭ', 'Ʈ' => 'ʈ', 'Ư' => 'ư', 'Ʊ' => 'ʊ', 'Ʋ' => 'ʋ', 'Ƴ' => 'ƴ', 'Ƶ' => 'ƶ', 'Ʒ' => 'ʒ', 'Ƹ' => 'ƹ', 'Ƽ' => 'ƽ', 'DŽ' => 'dž', 'Dž' => 'dž', 'LJ' => 'lj', 'Lj' => 'lj', 'NJ' => 'nj', 'Nj' => 'nj', 'Ǎ' => 'ǎ', 'Ǐ' => 'ǐ', 'Ǒ' => 'ǒ', 'Ǔ' => 'ǔ', 'Ǖ' => 'ǖ', 'Ǘ' => 'ǘ', 'Ǚ' => 'ǚ', 'Ǜ' => 'ǜ', 'Ǟ' => 'ǟ', 'Ǡ' => 'ǡ', 'Ǣ' => 'ǣ', 'Ǥ' => 'ǥ', 'Ǧ' => 'ǧ', 'Ǩ' => 'ǩ', 'Ǫ' => 'ǫ', 'Ǭ' => 'ǭ', 'Ǯ' => 'ǯ', 'DZ' => 'dz', 'Dz' => 'dz', 'Ǵ' => 'ǵ', 'Ƕ' => 'ƕ', 'Ƿ' => 'ƿ', 'Ǹ' => 'ǹ', 'Ǻ' => 'ǻ', 'Ǽ' => 'ǽ', 'Ǿ' => 'ǿ', 'Ȁ' => 'ȁ', 'Ȃ' => 'ȃ', 'Ȅ' => 'ȅ', 'Ȇ' => 'ȇ', 'Ȉ' => 'ȉ', 'Ȋ' => 'ȋ', 'Ȍ' => 'ȍ', 'Ȏ' => 'ȏ', 'Ȑ' => 'ȑ', 'Ȓ' => 'ȓ', 'Ȕ' => 'ȕ', 'Ȗ' => 'ȗ', 'Ș' => 'ș', 'Ț' => 'ț', 'Ȝ' => 'ȝ', 'Ȟ' => 'ȟ', 'Ƞ' => 'ƞ', 'Ȣ' => 'ȣ', 'Ȥ' => 'ȥ', 'Ȧ' => 'ȧ', 'Ȩ' => 'ȩ', 'Ȫ' => 'ȫ', 'Ȭ' => 'ȭ', 'Ȯ' => 'ȯ', 'Ȱ' => 'ȱ', 'Ȳ' => 'ȳ', 'Ⱥ' => 'ⱥ', 'Ȼ' => 'ȼ', 'Ƚ' => 'ƚ', 'Ⱦ' => 'ⱦ', 'Ɂ' => 'ɂ', 'Ƀ' => 'ƀ', 'Ʉ' => 'ʉ', 'Ʌ' => 'ʌ', 'Ɇ' => 'ɇ', 'Ɉ' => 'ɉ', 'Ɋ' => 'ɋ', 'Ɍ' => 'ɍ', 'Ɏ' => 'ɏ', 'Ͱ' => 'ͱ', 'Ͳ' => 'ͳ', 'Ͷ' => 'ͷ', 'Ϳ' => 'ϳ', 'Ά' => 'ά', 'Έ' => 'έ', 'Ή' => 'ή', 'Ί' => 'ί', 'Ό' => 'ό', 'Ύ' => 'ύ', 'Ώ' => 'ώ', 'Α' => 'α', 'Β' => 'β', 'Γ' => 'γ', 'Δ' => 'δ', 'Ε' => 'ε', 'Ζ' => 'ζ', 'Η' => 'η', 'Θ' => 'θ', 'Ι' => 'ι', 'Κ' => 'κ', 'Λ' => 'λ', 'Μ' => 'μ', 'Ν' => 'ν', 'Ξ' => 'ξ', 'Ο' => 'ο', 'Π' => 'π', 'Ρ' => 'ρ', 'Σ' => 'σ', 'Τ' => 'τ', 'Υ' => 'υ', 'Φ' => 'φ', 'Χ' => 'χ', 'Ψ' => 'ψ', 'Ω' => 'ω', 'Ϊ' => 'ϊ', 'Ϋ' => 'ϋ', 'Ϗ' => 'ϗ', 'Ϙ' => 'ϙ', 'Ϛ' => 'ϛ', 'Ϝ' => 'ϝ', 'Ϟ' => 'ϟ', 'Ϡ' => 'ϡ', 'Ϣ' => 'ϣ', 'Ϥ' => 'ϥ', 'Ϧ' => 'ϧ', 'Ϩ' => 'ϩ', 'Ϫ' => 'ϫ', 'Ϭ' => 'ϭ', 'Ϯ' => 'ϯ', 'ϴ' => 'θ', 'Ϸ' => 'ϸ', 'Ϲ' => 'ϲ', 'Ϻ' => 'ϻ', 'Ͻ' => 'ͻ', 'Ͼ' => 'ͼ', 'Ͽ' => 'ͽ', 'Ѐ' => 'ѐ', 'Ё' => 'ё', 'Ђ' => 'ђ', 'Ѓ' => 'ѓ', 'Є' => 'є', 'Ѕ' => 'ѕ', 'І' => 'і', 'Ї' => 'ї', 'Ј' => 'ј', 'Љ' => 'љ', 'Њ' => 'њ', 'Ћ' => 'ћ', 'Ќ' => 'ќ', 'Ѝ' => 'ѝ', 'Ў' => 'ў', 'Џ' => 'џ', 'А' => 'а', 'Б' => 'б', 'В' => 'в', 'Г' => 'г', 'Д' => 'д', 'Е' => 'е', 'Ж' => 'ж', 'З' => 'з', 'И' => 'и', 'Й' => 'й', 'К' => 'к', 'Л' => 'л', 'М' => 'м', 'Н' => 'н', 'О' => 'о', 'П' => 'п', 'Р' => 'р', 'С' => 'с', 'Т' => 'т', 'У' => 'у', 'Ф' => 'ф', 'Х' => 'х', 'Ц' => 'ц', 'Ч' => 'ч', 'Ш' => 'ш', 'Щ' => 'щ', 'Ъ' => 'ъ', 'Ы' => 'ы', 'Ь' => 'ь', 'Э' => 'э', 'Ю' => 'ю', 'Я' => 'я', 'Ѡ' => 'ѡ', 'Ѣ' => 'ѣ', 'Ѥ' => 'ѥ', 'Ѧ' => 'ѧ', 'Ѩ' => 'ѩ', 'Ѫ' => 'ѫ', 'Ѭ' => 'ѭ', 'Ѯ' => 'ѯ', 'Ѱ' => 'ѱ', 'Ѳ' => 'ѳ', 'Ѵ' => 'ѵ', 'Ѷ' => 'ѷ', 'Ѹ' => 'ѹ', 'Ѻ' => 'ѻ', 'Ѽ' => 'ѽ', 'Ѿ' => 'ѿ', 'Ҁ' => 'ҁ', 'Ҋ' => 'ҋ', 'Ҍ' => 'ҍ', 'Ҏ' => 'ҏ', 'Ґ' => 'ґ', 'Ғ' => 'ғ', 'Ҕ' => 'ҕ', 'Җ' => 'җ', 'Ҙ' => 'ҙ', 'Қ' => 'қ', 'Ҝ' => 'ҝ', 'Ҟ' => 'ҟ', 'Ҡ' => 'ҡ', 'Ң' => 'ң', 'Ҥ' => 'ҥ', 'Ҧ' => 'ҧ', 'Ҩ' => 'ҩ', 'Ҫ' => 'ҫ', 'Ҭ' => 'ҭ', 'Ү' => 'ү', 'Ұ' => 'ұ', 'Ҳ' => 'ҳ', 'Ҵ' => 'ҵ', 'Ҷ' => 'ҷ', 'Ҹ' => 'ҹ', 'Һ' => 'һ', 'Ҽ' => 'ҽ', 'Ҿ' => 'ҿ', 'Ӏ' => 'ӏ', 'Ӂ' => 'ӂ', 'Ӄ' => 'ӄ', 'Ӆ' => 'ӆ', 'Ӈ' => 'ӈ', 'Ӊ' => 'ӊ', 'Ӌ' => 'ӌ', 'Ӎ' => 'ӎ', 'Ӑ' => 'ӑ', 'Ӓ' => 'ӓ', 'Ӕ' => 'ӕ', 'Ӗ' => 'ӗ', 'Ә' => 'ә', 'Ӛ' => 'ӛ', 'Ӝ' => 'ӝ', 'Ӟ' => 'ӟ', 'Ӡ' => 'ӡ', 'Ӣ' => 'ӣ', 'Ӥ' => 'ӥ', 'Ӧ' => 'ӧ', 'Ө' => 'ө', 'Ӫ' => 'ӫ', 'Ӭ' => 'ӭ', 'Ӯ' => 'ӯ', 'Ӱ' => 'ӱ', 'Ӳ' => 'ӳ', 'Ӵ' => 'ӵ', 'Ӷ' => 'ӷ', 'Ӹ' => 'ӹ', 'Ӻ' => 'ӻ', 'Ӽ' => 'ӽ', 'Ӿ' => 'ӿ', 'Ԁ' => 'ԁ', 'Ԃ' => 'ԃ', 'Ԅ' => 'ԅ', 'Ԇ' => 'ԇ', 'Ԉ' => 'ԉ', 'Ԋ' => 'ԋ', 'Ԍ' => 'ԍ', 'Ԏ' => 'ԏ', 'Ԑ' => 'ԑ', 'Ԓ' => 'ԓ', 'Ԕ' => 'ԕ', 'Ԗ' => 'ԗ', 'Ԙ' => 'ԙ', 'Ԛ' => 'ԛ', 'Ԝ' => 'ԝ', 'Ԟ' => 'ԟ', 'Ԡ' => 'ԡ', 'Ԣ' => 'ԣ', 'Ԥ' => 'ԥ', 'Ԧ' => 'ԧ', 'Ԩ' => 'ԩ', 'Ԫ' => 'ԫ', 'Ԭ' => 'ԭ', 'Ԯ' => 'ԯ', 'Ա' => 'ա', 'Բ' => 'բ', 'Գ' => 'գ', 'Դ' => 'դ', 'Ե' => 'ե', 'Զ' => 'զ', 'Է' => 'է', 'Ը' => 'ը', 'Թ' => 'թ', 'Ժ' => 'ժ', 'Ի' => 'ի', 'Լ' => 'լ', 'Խ' => 'խ', 'Ծ' => 'ծ', 'Կ' => 'կ', 'Հ' => 'հ', 'Ձ' => 'ձ', 'Ղ' => 'ղ', 'Ճ' => 'ճ', 'Մ' => 'մ', 'Յ' => 'յ', 'Ն' => 'ն', 'Շ' => 'շ', 'Ո' => 'ո', 'Չ' => 'չ', 'Պ' => 'պ', 'Ջ' => 'ջ', 'Ռ' => 'ռ', 'Ս' => 'ս', 'Վ' => 'վ', 'Տ' => 'տ', 'Ր' => 'ր', 'Ց' => 'ց', 'Ւ' => 'ւ', 'Փ' => 'փ', 'Ք' => 'ք', 'Օ' => 'օ', 'Ֆ' => 'ֆ', 'Ⴀ' => 'ⴀ', 'Ⴁ' => 'ⴁ', 'Ⴂ' => 'ⴂ', 'Ⴃ' => 'ⴃ', 'Ⴄ' => 'ⴄ', 'Ⴅ' => 'ⴅ', 'Ⴆ' => 'ⴆ', 'Ⴇ' => 'ⴇ', 'Ⴈ' => 'ⴈ', 'Ⴉ' => 'ⴉ', 'Ⴊ' => 'ⴊ', 'Ⴋ' => 'ⴋ', 'Ⴌ' => 'ⴌ', 'Ⴍ' => 'ⴍ', 'Ⴎ' => 'ⴎ', 'Ⴏ' => 'ⴏ', 'Ⴐ' => 'ⴐ', 'Ⴑ' => 'ⴑ', 'Ⴒ' => 'ⴒ', 'Ⴓ' => 'ⴓ', 'Ⴔ' => 'ⴔ', 'Ⴕ' => 'ⴕ', 'Ⴖ' => 'ⴖ', 'Ⴗ' => 'ⴗ', 'Ⴘ' => 'ⴘ', 'Ⴙ' => 'ⴙ', 'Ⴚ' => 'ⴚ', 'Ⴛ' => 'ⴛ', 'Ⴜ' => 'ⴜ', 'Ⴝ' => 'ⴝ', 'Ⴞ' => 'ⴞ', 'Ⴟ' => 'ⴟ', 'Ⴠ' => 'ⴠ', 'Ⴡ' => 'ⴡ', 'Ⴢ' => 'ⴢ', 'Ⴣ' => 'ⴣ', 'Ⴤ' => 'ⴤ', 'Ⴥ' => 'ⴥ', 'Ⴧ' => 'ⴧ', 'Ⴭ' => 'ⴭ', 'Ꭰ' => 'ꭰ', 'Ꭱ' => 'ꭱ', 'Ꭲ' => 'ꭲ', 'Ꭳ' => 'ꭳ', 'Ꭴ' => 'ꭴ', 'Ꭵ' => 'ꭵ', 'Ꭶ' => 'ꭶ', 'Ꭷ' => 'ꭷ', 'Ꭸ' => 'ꭸ', 'Ꭹ' => 'ꭹ', 'Ꭺ' => 'ꭺ', 'Ꭻ' => 'ꭻ', 'Ꭼ' => 'ꭼ', 'Ꭽ' => 'ꭽ', 'Ꭾ' => 'ꭾ', 'Ꭿ' => 'ꭿ', 'Ꮀ' => 'ꮀ', 'Ꮁ' => 'ꮁ', 'Ꮂ' => 'ꮂ', 'Ꮃ' => 'ꮃ', 'Ꮄ' => 'ꮄ', 'Ꮅ' => 'ꮅ', 'Ꮆ' => 'ꮆ', 'Ꮇ' => 'ꮇ', 'Ꮈ' => 'ꮈ', 'Ꮉ' => 'ꮉ', 'Ꮊ' => 'ꮊ', 'Ꮋ' => 'ꮋ', 'Ꮌ' => 'ꮌ', 'Ꮍ' => 'ꮍ', 'Ꮎ' => 'ꮎ', 'Ꮏ' => 'ꮏ', 'Ꮐ' => 'ꮐ', 'Ꮑ' => 'ꮑ', 'Ꮒ' => 'ꮒ', 'Ꮓ' => 'ꮓ', 'Ꮔ' => 'ꮔ', 'Ꮕ' => 'ꮕ', 'Ꮖ' => 'ꮖ', 'Ꮗ' => 'ꮗ', 'Ꮘ' => 'ꮘ', 'Ꮙ' => 'ꮙ', 'Ꮚ' => 'ꮚ', 'Ꮛ' => 'ꮛ', 'Ꮜ' => 'ꮜ', 'Ꮝ' => 'ꮝ', 'Ꮞ' => 'ꮞ', 'Ꮟ' => 'ꮟ', 'Ꮠ' => 'ꮠ', 'Ꮡ' => 'ꮡ', 'Ꮢ' => 'ꮢ', 'Ꮣ' => 'ꮣ', 'Ꮤ' => 'ꮤ', 'Ꮥ' => 'ꮥ', 'Ꮦ' => 'ꮦ', 'Ꮧ' => 'ꮧ', 'Ꮨ' => 'ꮨ', 'Ꮩ' => 'ꮩ', 'Ꮪ' => 'ꮪ', 'Ꮫ' => 'ꮫ', 'Ꮬ' => 'ꮬ', 'Ꮭ' => 'ꮭ', 'Ꮮ' => 'ꮮ', 'Ꮯ' => 'ꮯ', 'Ꮰ' => 'ꮰ', 'Ꮱ' => 'ꮱ', 'Ꮲ' => 'ꮲ', 'Ꮳ' => 'ꮳ', 'Ꮴ' => 'ꮴ', 'Ꮵ' => 'ꮵ', 'Ꮶ' => 'ꮶ', 'Ꮷ' => 'ꮷ', 'Ꮸ' => 'ꮸ', 'Ꮹ' => 'ꮹ', 'Ꮺ' => 'ꮺ', 'Ꮻ' => 'ꮻ', 'Ꮼ' => 'ꮼ', 'Ꮽ' => 'ꮽ', 'Ꮾ' => 'ꮾ', 'Ꮿ' => 'ꮿ', 'Ᏸ' => 'ᏸ', 'Ᏹ' => 'ᏹ', 'Ᏺ' => 'ᏺ', 'Ᏻ' => 'ᏻ', 'Ᏼ' => 'ᏼ', 'Ᏽ' => 'ᏽ', 'Ა' => 'ა', 'Ბ' => 'ბ', 'Გ' => 'გ', 'Დ' => 'დ', 'Ე' => 'ე', 'Ვ' => 'ვ', 'Ზ' => 'ზ', 'Თ' => 'თ', 'Ი' => 'ი', 'Კ' => 'კ', 'Ლ' => 'ლ', 'Მ' => 'მ', 'Ნ' => 'ნ', 'Ო' => 'ო', 'Პ' => 'პ', 'Ჟ' => 'ჟ', 'Რ' => 'რ', 'Ს' => 'ს', 'Ტ' => 'ტ', 'Უ' => 'უ', 'Ფ' => 'ფ', 'Ქ' => 'ქ', 'Ღ' => 'ღ', 'Ყ' => 'ყ', 'Შ' => 'შ', 'Ჩ' => 'ჩ', 'Ც' => 'ც', 'Ძ' => 'ძ', 'Წ' => 'წ', 'Ჭ' => 'ჭ', 'Ხ' => 'ხ', 'Ჯ' => 'ჯ', 'Ჰ' => 'ჰ', 'Ჱ' => 'ჱ', 'Ჲ' => 'ჲ', 'Ჳ' => 'ჳ', 'Ჴ' => 'ჴ', 'Ჵ' => 'ჵ', 'Ჶ' => 'ჶ', 'Ჷ' => 'ჷ', 'Ჸ' => 'ჸ', 'Ჹ' => 'ჹ', 'Ჺ' => 'ჺ', 'Ჽ' => 'ჽ', 'Ჾ' => 'ჾ', 'Ჿ' => 'ჿ', 'Ḁ' => 'ḁ', 'Ḃ' => 'ḃ', 'Ḅ' => 'ḅ', 'Ḇ' => 'ḇ', 'Ḉ' => 'ḉ', 'Ḋ' => 'ḋ', 'Ḍ' => 'ḍ', 'Ḏ' => 'ḏ', 'Ḑ' => 'ḑ', 'Ḓ' => 'ḓ', 'Ḕ' => 'ḕ', 'Ḗ' => 'ḗ', 'Ḙ' => 'ḙ', 'Ḛ' => 'ḛ', 'Ḝ' => 'ḝ', 'Ḟ' => 'ḟ', 'Ḡ' => 'ḡ', 'Ḣ' => 'ḣ', 'Ḥ' => 'ḥ', 'Ḧ' => 'ḧ', 'Ḩ' => 'ḩ', 'Ḫ' => 'ḫ', 'Ḭ' => 'ḭ', 'Ḯ' => 'ḯ', 'Ḱ' => 'ḱ', 'Ḳ' => 'ḳ', 'Ḵ' => 'ḵ', 'Ḷ' => 'ḷ', 'Ḹ' => 'ḹ', 'Ḻ' => 'ḻ', 'Ḽ' => 'ḽ', 'Ḿ' => 'ḿ', 'Ṁ' => 'ṁ', 'Ṃ' => 'ṃ', 'Ṅ' => 'ṅ', 'Ṇ' => 'ṇ', 'Ṉ' => 'ṉ', 'Ṋ' => 'ṋ', 'Ṍ' => 'ṍ', 'Ṏ' => 'ṏ', 'Ṑ' => 'ṑ', 'Ṓ' => 'ṓ', 'Ṕ' => 'ṕ', 'Ṗ' => 'ṗ', 'Ṙ' => 'ṙ', 'Ṛ' => 'ṛ', 'Ṝ' => 'ṝ', 'Ṟ' => 'ṟ', 'Ṡ' => 'ṡ', 'Ṣ' => 'ṣ', 'Ṥ' => 'ṥ', 'Ṧ' => 'ṧ', 'Ṩ' => 'ṩ', 'Ṫ' => 'ṫ', 'Ṭ' => 'ṭ', 'Ṯ' => 'ṯ', 'Ṱ' => 'ṱ', 'Ṳ' => 'ṳ', 'Ṵ' => 'ṵ', 'Ṷ' => 'ṷ', 'Ṹ' => 'ṹ', 'Ṻ' => 'ṻ', 'Ṽ' => 'ṽ', 'Ṿ' => 'ṿ', 'Ẁ' => 'ẁ', 'Ẃ' => 'ẃ', 'Ẅ' => 'ẅ', 'Ẇ' => 'ẇ', 'Ẉ' => 'ẉ', 'Ẋ' => 'ẋ', 'Ẍ' => 'ẍ', 'Ẏ' => 'ẏ', 'Ẑ' => 'ẑ', 'Ẓ' => 'ẓ', 'Ẕ' => 'ẕ', 'ẞ' => 'ß', 'Ạ' => 'ạ', 'Ả' => 'ả', 'Ấ' => 'ấ', 'Ầ' => 'ầ', 'Ẩ' => 'ẩ', 'Ẫ' => 'ẫ', 'Ậ' => 'ậ', 'Ắ' => 'ắ', 'Ằ' => 'ằ', 'Ẳ' => 'ẳ', 'Ẵ' => 'ẵ', 'Ặ' => 'ặ', 'Ẹ' => 'ẹ', 'Ẻ' => 'ẻ', 'Ẽ' => 'ẽ', 'Ế' => 'ế', 'Ề' => 'ề', 'Ể' => 'ể', 'Ễ' => 'ễ', 'Ệ' => 'ệ', 'Ỉ' => 'ỉ', 'Ị' => 'ị', 'Ọ' => 'ọ', 'Ỏ' => 'ỏ', 'Ố' => 'ố', 'Ồ' => 'ồ', 'Ổ' => 'ổ', 'Ỗ' => 'ỗ', 'Ộ' => 'ộ', 'Ớ' => 'ớ', 'Ờ' => 'ờ', 'Ở' => 'ở', 'Ỡ' => 'ỡ', 'Ợ' => 'ợ', 'Ụ' => 'ụ', 'Ủ' => 'ủ', 'Ứ' => 'ứ', 'Ừ' => 'ừ', 'Ử' => 'ử', 'Ữ' => 'ữ', 'Ự' => 'ự', 'Ỳ' => 'ỳ', 'Ỵ' => 'ỵ', 'Ỷ' => 'ỷ', 'Ỹ' => 'ỹ', 'Ỻ' => 'ỻ', 'Ỽ' => 'ỽ', 'Ỿ' => 'ỿ', 'Ἀ' => 'ἀ', 'Ἁ' => 'ἁ', 'Ἂ' => 'ἂ', 'Ἃ' => 'ἃ', 'Ἄ' => 'ἄ', 'Ἅ' => 'ἅ', 'Ἆ' => 'ἆ', 'Ἇ' => 'ἇ', 'Ἐ' => 'ἐ', 'Ἑ' => 'ἑ', 'Ἒ' => 'ἒ', 'Ἓ' => 'ἓ', 'Ἔ' => 'ἔ', 'Ἕ' => 'ἕ', 'Ἠ' => 'ἠ', 'Ἡ' => 'ἡ', 'Ἢ' => 'ἢ', 'Ἣ' => 'ἣ', 'Ἤ' => 'ἤ', 'Ἥ' => 'ἥ', 'Ἦ' => 'ἦ', 'Ἧ' => 'ἧ', 'Ἰ' => 'ἰ', 'Ἱ' => 'ἱ', 'Ἲ' => 'ἲ', 'Ἳ' => 'ἳ', 'Ἴ' => 'ἴ', 'Ἵ' => 'ἵ', 'Ἶ' => 'ἶ', 'Ἷ' => 'ἷ', 'Ὀ' => 'ὀ', 'Ὁ' => 'ὁ', 'Ὂ' => 'ὂ', 'Ὃ' => 'ὃ', 'Ὄ' => 'ὄ', 'Ὅ' => 'ὅ', 'Ὑ' => 'ὑ', 'Ὓ' => 'ὓ', 'Ὕ' => 'ὕ', 'Ὗ' => 'ὗ', 'Ὠ' => 'ὠ', 'Ὡ' => 'ὡ', 'Ὢ' => 'ὢ', 'Ὣ' => 'ὣ', 'Ὤ' => 'ὤ', 'Ὥ' => 'ὥ', 'Ὦ' => 'ὦ', 'Ὧ' => 'ὧ', 'ᾈ' => 'ᾀ', 'ᾉ' => 'ᾁ', 'ᾊ' => 'ᾂ', 'ᾋ' => 'ᾃ', 'ᾌ' => 'ᾄ', 'ᾍ' => 'ᾅ', 'ᾎ' => 'ᾆ', 'ᾏ' => 'ᾇ', 'ᾘ' => 'ᾐ', 'ᾙ' => 'ᾑ', 'ᾚ' => 'ᾒ', 'ᾛ' => 'ᾓ', 'ᾜ' => 'ᾔ', 'ᾝ' => 'ᾕ', 'ᾞ' => 'ᾖ', 'ᾟ' => 'ᾗ', 'ᾨ' => 'ᾠ', 'ᾩ' => 'ᾡ', 'ᾪ' => 'ᾢ', 'ᾫ' => 'ᾣ', 'ᾬ' => 'ᾤ', 'ᾭ' => 'ᾥ', 'ᾮ' => 'ᾦ', 'ᾯ' => 'ᾧ', 'Ᾰ' => 'ᾰ', 'Ᾱ' => 'ᾱ', 'Ὰ' => 'ὰ', 'Ά' => 'ά', 'ᾼ' => 'ᾳ', 'Ὲ' => 'ὲ', 'Έ' => 'έ', 'Ὴ' => 'ὴ', 'Ή' => 'ή', 'ῌ' => 'ῃ', 'Ῐ' => 'ῐ', 'Ῑ' => 'ῑ', 'Ὶ' => 'ὶ', 'Ί' => 'ί', 'Ῠ' => 'ῠ', 'Ῡ' => 'ῡ', 'Ὺ' => 'ὺ', 'Ύ' => 'ύ', 'Ῥ' => 'ῥ', 'Ὸ' => 'ὸ', 'Ό' => 'ό', 'Ὼ' => 'ὼ', 'Ώ' => 'ώ', 'ῼ' => 'ῳ', 'Ω' => 'ω', 'K' => 'k', 'Å' => 'å', 'Ⅎ' => 'ⅎ', 'Ⅰ' => 'ⅰ', 'Ⅱ' => 'ⅱ', 'Ⅲ' => 'ⅲ', 'Ⅳ' => 'ⅳ', 'Ⅴ' => 'ⅴ', 'Ⅵ' => 'ⅵ', 'Ⅶ' => 'ⅶ', 'Ⅷ' => 'ⅷ', 'Ⅸ' => 'ⅸ', 'Ⅹ' => 'ⅹ', 'Ⅺ' => 'ⅺ', 'Ⅻ' => 'ⅻ', 'Ⅼ' => 'ⅼ', 'Ⅽ' => 'ⅽ', 'Ⅾ' => 'ⅾ', 'Ⅿ' => 'ⅿ', 'Ↄ' => 'ↄ', 'Ⓐ' => 'ⓐ', 'Ⓑ' => 'ⓑ', 'Ⓒ' => 'ⓒ', 'Ⓓ' => 'ⓓ', 'Ⓔ' => 'ⓔ', 'Ⓕ' => 'ⓕ', 'Ⓖ' => 'ⓖ', 'Ⓗ' => 'ⓗ', 'Ⓘ' => 'ⓘ', 'Ⓙ' => 'ⓙ', 'Ⓚ' => 'ⓚ', 'Ⓛ' => 'ⓛ', 'Ⓜ' => 'ⓜ', 'Ⓝ' => 'ⓝ', 'Ⓞ' => 'ⓞ', 'Ⓟ' => 'ⓟ', 'Ⓠ' => 'ⓠ', 'Ⓡ' => 'ⓡ', 'Ⓢ' => 'ⓢ', 'Ⓣ' => 'ⓣ', 'Ⓤ' => 'ⓤ', 'Ⓥ' => 'ⓥ', 'Ⓦ' => 'ⓦ', 'Ⓧ' => 'ⓧ', 'Ⓨ' => 'ⓨ', 'Ⓩ' => 'ⓩ', 'Ⰰ' => 'ⰰ', 'Ⰱ' => 'ⰱ', 'Ⰲ' => 'ⰲ', 'Ⰳ' => 'ⰳ', 'Ⰴ' => 'ⰴ', 'Ⰵ' => 'ⰵ', 'Ⰶ' => 'ⰶ', 'Ⰷ' => 'ⰷ', 'Ⰸ' => 'ⰸ', 'Ⰹ' => 'ⰹ', 'Ⰺ' => 'ⰺ', 'Ⰻ' => 'ⰻ', 'Ⰼ' => 'ⰼ', 'Ⰽ' => 'ⰽ', 'Ⰾ' => 'ⰾ', 'Ⰿ' => 'ⰿ', 'Ⱀ' => 'ⱀ', 'Ⱁ' => 'ⱁ', 'Ⱂ' => 'ⱂ', 'Ⱃ' => 'ⱃ', 'Ⱄ' => 'ⱄ', 'Ⱅ' => 'ⱅ', 'Ⱆ' => 'ⱆ', 'Ⱇ' => 'ⱇ', 'Ⱈ' => 'ⱈ', 'Ⱉ' => 'ⱉ', 'Ⱊ' => 'ⱊ', 'Ⱋ' => 'ⱋ', 'Ⱌ' => 'ⱌ', 'Ⱍ' => 'ⱍ', 'Ⱎ' => 'ⱎ', 'Ⱏ' => 'ⱏ', 'Ⱐ' => 'ⱐ', 'Ⱑ' => 'ⱑ', 'Ⱒ' => 'ⱒ', 'Ⱓ' => 'ⱓ', 'Ⱔ' => 'ⱔ', 'Ⱕ' => 'ⱕ', 'Ⱖ' => 'ⱖ', 'Ⱗ' => 'ⱗ', 'Ⱘ' => 'ⱘ', 'Ⱙ' => 'ⱙ', 'Ⱚ' => 'ⱚ', 'Ⱛ' => 'ⱛ', 'Ⱜ' => 'ⱜ', 'Ⱝ' => 'ⱝ', 'Ⱞ' => 'ⱞ', 'Ⱡ' => 'ⱡ', 'Ɫ' => 'ɫ', 'Ᵽ' => 'ᵽ', 'Ɽ' => 'ɽ', 'Ⱨ' => 'ⱨ', 'Ⱪ' => 'ⱪ', 'Ⱬ' => 'ⱬ', 'Ɑ' => 'ɑ', 'Ɱ' => 'ɱ', 'Ɐ' => 'ɐ', 'Ɒ' => 'ɒ', 'Ⱳ' => 'ⱳ', 'Ⱶ' => 'ⱶ', 'Ȿ' => 'ȿ', 'Ɀ' => 'ɀ', 'Ⲁ' => 'ⲁ', 'Ⲃ' => 'ⲃ', 'Ⲅ' => 'ⲅ', 'Ⲇ' => 'ⲇ', 'Ⲉ' => 'ⲉ', 'Ⲋ' => 'ⲋ', 'Ⲍ' => 'ⲍ', 'Ⲏ' => 'ⲏ', 'Ⲑ' => 'ⲑ', 'Ⲓ' => 'ⲓ', 'Ⲕ' => 'ⲕ', 'Ⲗ' => 'ⲗ', 'Ⲙ' => 'ⲙ', 'Ⲛ' => 'ⲛ', 'Ⲝ' => 'ⲝ', 'Ⲟ' => 'ⲟ', 'Ⲡ' => 'ⲡ', 'Ⲣ' => 'ⲣ', 'Ⲥ' => 'ⲥ', 'Ⲧ' => 'ⲧ', 'Ⲩ' => 'ⲩ', 'Ⲫ' => 'ⲫ', 'Ⲭ' => 'ⲭ', 'Ⲯ' => 'ⲯ', 'Ⲱ' => 'ⲱ', 'Ⲳ' => 'ⲳ', 'Ⲵ' => 'ⲵ', 'Ⲷ' => 'ⲷ', 'Ⲹ' => 'ⲹ', 'Ⲻ' => 'ⲻ', 'Ⲽ' => 'ⲽ', 'Ⲿ' => 'ⲿ', 'Ⳁ' => 'ⳁ', 'Ⳃ' => 'ⳃ', 'Ⳅ' => 'ⳅ', 'Ⳇ' => 'ⳇ', 'Ⳉ' => 'ⳉ', 'Ⳋ' => 'ⳋ', 'Ⳍ' => 'ⳍ', 'Ⳏ' => 'ⳏ', 'Ⳑ' => 'ⳑ', 'Ⳓ' => 'ⳓ', 'Ⳕ' => 'ⳕ', 'Ⳗ' => 'ⳗ', 'Ⳙ' => 'ⳙ', 'Ⳛ' => 'ⳛ', 'Ⳝ' => 'ⳝ', 'Ⳟ' => 'ⳟ', 'Ⳡ' => 'ⳡ', 'Ⳣ' => 'ⳣ', 'Ⳬ' => 'ⳬ', 'Ⳮ' => 'ⳮ', 'Ⳳ' => 'ⳳ', 'Ꙁ' => 'ꙁ', 'Ꙃ' => 'ꙃ', 'Ꙅ' => 'ꙅ', 'Ꙇ' => 'ꙇ', 'Ꙉ' => 'ꙉ', 'Ꙋ' => 'ꙋ', 'Ꙍ' => 'ꙍ', 'Ꙏ' => 'ꙏ', 'Ꙑ' => 'ꙑ', 'Ꙓ' => 'ꙓ', 'Ꙕ' => 'ꙕ', 'Ꙗ' => 'ꙗ', 'Ꙙ' => 'ꙙ', 'Ꙛ' => 'ꙛ', 'Ꙝ' => 'ꙝ', 'Ꙟ' => 'ꙟ', 'Ꙡ' => 'ꙡ', 'Ꙣ' => 'ꙣ', 'Ꙥ' => 'ꙥ', 'Ꙧ' => 'ꙧ', 'Ꙩ' => 'ꙩ', 'Ꙫ' => 'ꙫ', 'Ꙭ' => 'ꙭ', 'Ꚁ' => 'ꚁ', 'Ꚃ' => 'ꚃ', 'Ꚅ' => 'ꚅ', 'Ꚇ' => 'ꚇ', 'Ꚉ' => 'ꚉ', 'Ꚋ' => 'ꚋ', 'Ꚍ' => 'ꚍ', 'Ꚏ' => 'ꚏ', 'Ꚑ' => 'ꚑ', 'Ꚓ' => 'ꚓ', 'Ꚕ' => 'ꚕ', 'Ꚗ' => 'ꚗ', 'Ꚙ' => 'ꚙ', 'Ꚛ' => 'ꚛ', 'Ꜣ' => 'ꜣ', 'Ꜥ' => 'ꜥ', 'Ꜧ' => 'ꜧ', 'Ꜩ' => 'ꜩ', 'Ꜫ' => 'ꜫ', 'Ꜭ' => 'ꜭ', 'Ꜯ' => 'ꜯ', 'Ꜳ' => 'ꜳ', 'Ꜵ' => 'ꜵ', 'Ꜷ' => 'ꜷ', 'Ꜹ' => 'ꜹ', 'Ꜻ' => 'ꜻ', 'Ꜽ' => 'ꜽ', 'Ꜿ' => 'ꜿ', 'Ꝁ' => 'ꝁ', 'Ꝃ' => 'ꝃ', 'Ꝅ' => 'ꝅ', 'Ꝇ' => 'ꝇ', 'Ꝉ' => 'ꝉ', 'Ꝋ' => 'ꝋ', 'Ꝍ' => 'ꝍ', 'Ꝏ' => 'ꝏ', 'Ꝑ' => 'ꝑ', 'Ꝓ' => 'ꝓ', 'Ꝕ' => 'ꝕ', 'Ꝗ' => 'ꝗ', 'Ꝙ' => 'ꝙ', 'Ꝛ' => 'ꝛ', 'Ꝝ' => 'ꝝ', 'Ꝟ' => 'ꝟ', 'Ꝡ' => 'ꝡ', 'Ꝣ' => 'ꝣ', 'Ꝥ' => 'ꝥ', 'Ꝧ' => 'ꝧ', 'Ꝩ' => 'ꝩ', 'Ꝫ' => 'ꝫ', 'Ꝭ' => 'ꝭ', 'Ꝯ' => 'ꝯ', 'Ꝺ' => 'ꝺ', 'Ꝼ' => 'ꝼ', 'Ᵹ' => 'ᵹ', 'Ꝿ' => 'ꝿ', 'Ꞁ' => 'ꞁ', 'Ꞃ' => 'ꞃ', 'Ꞅ' => 'ꞅ', 'Ꞇ' => 'ꞇ', 'Ꞌ' => 'ꞌ', 'Ɥ' => 'ɥ', 'Ꞑ' => 'ꞑ', 'Ꞓ' => 'ꞓ', 'Ꞗ' => 'ꞗ', 'Ꞙ' => 'ꞙ', 'Ꞛ' => 'ꞛ', 'Ꞝ' => 'ꞝ', 'Ꞟ' => 'ꞟ', 'Ꞡ' => 'ꞡ', 'Ꞣ' => 'ꞣ', 'Ꞥ' => 'ꞥ', 'Ꞧ' => 'ꞧ', 'Ꞩ' => 'ꞩ', 'Ɦ' => 'ɦ', 'Ɜ' => 'ɜ', 'Ɡ' => 'ɡ', 'Ɬ' => 'ɬ', 'Ɪ' => 'ɪ', 'Ʞ' => 'ʞ', 'Ʇ' => 'ʇ', 'Ʝ' => 'ʝ', 'Ꭓ' => 'ꭓ', 'Ꞵ' => 'ꞵ', 'Ꞷ' => 'ꞷ', 'Ꞹ' => 'ꞹ', 'Ꞻ' => 'ꞻ', 'Ꞽ' => 'ꞽ', 'Ꞿ' => 'ꞿ', 'Ꟃ' => 'ꟃ', 'Ꞔ' => 'ꞔ', 'Ʂ' => 'ʂ', 'Ᶎ' => 'ᶎ', 'Ꟈ' => 'ꟈ', 'Ꟊ' => 'ꟊ', 'Ꟶ' => 'ꟶ', 'A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', '𐐀' => '𐐨', '𐐁' => '𐐩', '𐐂' => '𐐪', '𐐃' => '𐐫', '𐐄' => '𐐬', '𐐅' => '𐐭', '𐐆' => '𐐮', '𐐇' => '𐐯', '𐐈' => '𐐰', '𐐉' => '𐐱', '𐐊' => '𐐲', '𐐋' => '𐐳', '𐐌' => '𐐴', '𐐍' => '𐐵', '𐐎' => '𐐶', '𐐏' => '𐐷', '𐐐' => '𐐸', '𐐑' => '𐐹', '𐐒' => '𐐺', '𐐓' => '𐐻', '𐐔' => '𐐼', '𐐕' => '𐐽', '𐐖' => '𐐾', '𐐗' => '𐐿', '𐐘' => '𐑀', '𐐙' => '𐑁', '𐐚' => '𐑂', '𐐛' => '𐑃', '𐐜' => '𐑄', '𐐝' => '𐑅', '𐐞' => '𐑆', '𐐟' => '𐑇', '𐐠' => '𐑈', '𐐡' => '𐑉', '𐐢' => '𐑊', '𐐣' => '𐑋', '𐐤' => '𐑌', '𐐥' => '𐑍', '𐐦' => '𐑎', '𐐧' => '𐑏', '𐒰' => '𐓘', '𐒱' => '𐓙', '𐒲' => '𐓚', '𐒳' => '𐓛', '𐒴' => '𐓜', '𐒵' => '𐓝', '𐒶' => '𐓞', '𐒷' => '𐓟', '𐒸' => '𐓠', '𐒹' => '𐓡', '𐒺' => '𐓢', '𐒻' => '𐓣', '𐒼' => '𐓤', '𐒽' => '𐓥', '𐒾' => '𐓦', '𐒿' => '𐓧', '𐓀' => '𐓨', '𐓁' => '𐓩', '𐓂' => '𐓪', '𐓃' => '𐓫', '𐓄' => '𐓬', '𐓅' => '𐓭', '𐓆' => '𐓮', '𐓇' => '𐓯', '𐓈' => '𐓰', '𐓉' => '𐓱', '𐓊' => '𐓲', '𐓋' => '𐓳', '𐓌' => '𐓴', '𐓍' => '𐓵', '𐓎' => '𐓶', '𐓏' => '𐓷', '𐓐' => '𐓸', '𐓑' => '𐓹', '𐓒' => '𐓺', '𐓓' => '𐓻', '𐲀' => '𐳀', '𐲁' => '𐳁', '𐲂' => '𐳂', '𐲃' => '𐳃', '𐲄' => '𐳄', '𐲅' => '𐳅', '𐲆' => '𐳆', '𐲇' => '𐳇', '𐲈' => '𐳈', '𐲉' => '𐳉', '𐲊' => '𐳊', '𐲋' => '𐳋', '𐲌' => '𐳌', '𐲍' => '𐳍', '𐲎' => '𐳎', '𐲏' => '𐳏', '𐲐' => '𐳐', '𐲑' => '𐳑', '𐲒' => '𐳒', '𐲓' => '𐳓', '𐲔' => '𐳔', '𐲕' => '𐳕', '𐲖' => '𐳖', '𐲗' => '𐳗', '𐲘' => '𐳘', '𐲙' => '𐳙', '𐲚' => '𐳚', '𐲛' => '𐳛', '𐲜' => '𐳜', '𐲝' => '𐳝', '𐲞' => '𐳞', '𐲟' => '𐳟', '𐲠' => '𐳠', '𐲡' => '𐳡', '𐲢' => '𐳢', '𐲣' => '𐳣', '𐲤' => '𐳤', '𐲥' => '𐳥', '𐲦' => '𐳦', '𐲧' => '𐳧', '𐲨' => '𐳨', '𐲩' => '𐳩', '𐲪' => '𐳪', '𐲫' => '𐳫', '𐲬' => '𐳬', '𐲭' => '𐳭', '𐲮' => '𐳮', '𐲯' => '𐳯', '𐲰' => '𐳰', '𐲱' => '𐳱', '𐲲' => '𐳲', '𑢠' => '𑣀', '𑢡' => '𑣁', '𑢢' => '𑣂', '𑢣' => '𑣃', '𑢤' => '𑣄', '𑢥' => '𑣅', '𑢦' => '𑣆', '𑢧' => '𑣇', '𑢨' => '𑣈', '𑢩' => '𑣉', '𑢪' => '𑣊', '𑢫' => '𑣋', '𑢬' => '𑣌', '𑢭' => '𑣍', '𑢮' => '𑣎', '𑢯' => '𑣏', '𑢰' => '𑣐', '𑢱' => '𑣑', '𑢲' => '𑣒', '𑢳' => '𑣓', '𑢴' => '𑣔', '𑢵' => '𑣕', '𑢶' => '𑣖', '𑢷' => '𑣗', '𑢸' => '𑣘', '𑢹' => '𑣙', '𑢺' => '𑣚', '𑢻' => '𑣛', '𑢼' => '𑣜', '𑢽' => '𑣝', '𑢾' => '𑣞', '𑢿' => '𑣟', '𖹀' => '𖹠', '𖹁' => '𖹡', '𖹂' => '𖹢', '𖹃' => '𖹣', '𖹄' => '𖹤', '𖹅' => '𖹥', '𖹆' => '𖹦', '𖹇' => '𖹧', '𖹈' => '𖹨', '𖹉' => '𖹩', '𖹊' => '𖹪', '𖹋' => '𖹫', '𖹌' => '𖹬', '𖹍' => '𖹭', '𖹎' => '𖹮', '𖹏' => '𖹯', '𖹐' => '𖹰', '𖹑' => '𖹱', '𖹒' => '𖹲', '𖹓' => '𖹳', '𖹔' => '𖹴', '𖹕' => '𖹵', '𖹖' => '𖹶', '𖹗' => '𖹷', '𖹘' => '𖹸', '𖹙' => '𖹹', '𖹚' => '𖹺', '𖹛' => '𖹻', '𖹜' => '𖹼', '𖹝' => '𖹽', '𖹞' => '𖹾', '𖹟' => '𖹿', '𞤀' => '𞤢', '𞤁' => '𞤣', '𞤂' => '𞤤', '𞤃' => '𞤥', '𞤄' => '𞤦', '𞤅' => '𞤧', '𞤆' => '𞤨', '𞤇' => '𞤩', '𞤈' => '𞤪', '𞤉' => '𞤫', '𞤊' => '𞤬', '𞤋' => '𞤭', '𞤌' => '𞤮', '𞤍' => '𞤯', '𞤎' => '𞤰', '𞤏' => '𞤱', '𞤐' => '𞤲', '𞤑' => '𞤳', '𞤒' => '𞤴', '𞤓' => '𞤵', '𞤔' => '𞤶', '𞤕' => '𞤷', '𞤖' => '𞤸', '𞤗' => '𞤹', '𞤘' => '𞤺', '𞤙' => '𞤻', '𞤚' => '𞤼', '𞤛' => '𞤽', '𞤜' => '𞤾', '𞤝' => '𞤿', '𞤞' => '𞥀', '𞤟' => '𞥁', '𞤠' => '𞥂', '𞤡' => '𞥃', ); polyfill-mbstring/Resources/unidata/upperCase.php000064400000063322150432043200016257 0ustar00 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', 'µ' => 'Μ', 'à' => 'À', 'á' => 'Á', 'â' => 'Â', 'ã' => 'Ã', 'ä' => 'Ä', 'å' => 'Å', 'æ' => 'Æ', 'ç' => 'Ç', 'è' => 'È', 'é' => 'É', 'ê' => 'Ê', 'ë' => 'Ë', 'ì' => 'Ì', 'í' => 'Í', 'î' => 'Î', 'ï' => 'Ï', 'ð' => 'Ð', 'ñ' => 'Ñ', 'ò' => 'Ò', 'ó' => 'Ó', 'ô' => 'Ô', 'õ' => 'Õ', 'ö' => 'Ö', 'ø' => 'Ø', 'ù' => 'Ù', 'ú' => 'Ú', 'û' => 'Û', 'ü' => 'Ü', 'ý' => 'Ý', 'þ' => 'Þ', 'ÿ' => 'Ÿ', 'ā' => 'Ā', 'ă' => 'Ă', 'ą' => 'Ą', 'ć' => 'Ć', 'ĉ' => 'Ĉ', 'ċ' => 'Ċ', 'č' => 'Č', 'ď' => 'Ď', 'đ' => 'Đ', 'ē' => 'Ē', 'ĕ' => 'Ĕ', 'ė' => 'Ė', 'ę' => 'Ę', 'ě' => 'Ě', 'ĝ' => 'Ĝ', 'ğ' => 'Ğ', 'ġ' => 'Ġ', 'ģ' => 'Ģ', 'ĥ' => 'Ĥ', 'ħ' => 'Ħ', 'ĩ' => 'Ĩ', 'ī' => 'Ī', 'ĭ' => 'Ĭ', 'į' => 'Į', 'ı' => 'I', 'ij' => 'IJ', 'ĵ' => 'Ĵ', 'ķ' => 'Ķ', 'ĺ' => 'Ĺ', 'ļ' => 'Ļ', 'ľ' => 'Ľ', 'ŀ' => 'Ŀ', 'ł' => 'Ł', 'ń' => 'Ń', 'ņ' => 'Ņ', 'ň' => 'Ň', 'ŋ' => 'Ŋ', 'ō' => 'Ō', 'ŏ' => 'Ŏ', 'ő' => 'Ő', 'œ' => 'Œ', 'ŕ' => 'Ŕ', 'ŗ' => 'Ŗ', 'ř' => 'Ř', 'ś' => 'Ś', 'ŝ' => 'Ŝ', 'ş' => 'Ş', 'š' => 'Š', 'ţ' => 'Ţ', 'ť' => 'Ť', 'ŧ' => 'Ŧ', 'ũ' => 'Ũ', 'ū' => 'Ū', 'ŭ' => 'Ŭ', 'ů' => 'Ů', 'ű' => 'Ű', 'ų' => 'Ų', 'ŵ' => 'Ŵ', 'ŷ' => 'Ŷ', 'ź' => 'Ź', 'ż' => 'Ż', 'ž' => 'Ž', 'ſ' => 'S', 'ƀ' => 'Ƀ', 'ƃ' => 'Ƃ', 'ƅ' => 'Ƅ', 'ƈ' => 'Ƈ', 'ƌ' => 'Ƌ', 'ƒ' => 'Ƒ', 'ƕ' => 'Ƕ', 'ƙ' => 'Ƙ', 'ƚ' => 'Ƚ', 'ƞ' => 'Ƞ', 'ơ' => 'Ơ', 'ƣ' => 'Ƣ', 'ƥ' => 'Ƥ', 'ƨ' => 'Ƨ', 'ƭ' => 'Ƭ', 'ư' => 'Ư', 'ƴ' => 'Ƴ', 'ƶ' => 'Ƶ', 'ƹ' => 'Ƹ', 'ƽ' => 'Ƽ', 'ƿ' => 'Ƿ', 'Dž' => 'DŽ', 'dž' => 'DŽ', 'Lj' => 'LJ', 'lj' => 'LJ', 'Nj' => 'NJ', 'nj' => 'NJ', 'ǎ' => 'Ǎ', 'ǐ' => 'Ǐ', 'ǒ' => 'Ǒ', 'ǔ' => 'Ǔ', 'ǖ' => 'Ǖ', 'ǘ' => 'Ǘ', 'ǚ' => 'Ǚ', 'ǜ' => 'Ǜ', 'ǝ' => 'Ǝ', 'ǟ' => 'Ǟ', 'ǡ' => 'Ǡ', 'ǣ' => 'Ǣ', 'ǥ' => 'Ǥ', 'ǧ' => 'Ǧ', 'ǩ' => 'Ǩ', 'ǫ' => 'Ǫ', 'ǭ' => 'Ǭ', 'ǯ' => 'Ǯ', 'Dz' => 'DZ', 'dz' => 'DZ', 'ǵ' => 'Ǵ', 'ǹ' => 'Ǹ', 'ǻ' => 'Ǻ', 'ǽ' => 'Ǽ', 'ǿ' => 'Ǿ', 'ȁ' => 'Ȁ', 'ȃ' => 'Ȃ', 'ȅ' => 'Ȅ', 'ȇ' => 'Ȇ', 'ȉ' => 'Ȉ', 'ȋ' => 'Ȋ', 'ȍ' => 'Ȍ', 'ȏ' => 'Ȏ', 'ȑ' => 'Ȑ', 'ȓ' => 'Ȓ', 'ȕ' => 'Ȕ', 'ȗ' => 'Ȗ', 'ș' => 'Ș', 'ț' => 'Ț', 'ȝ' => 'Ȝ', 'ȟ' => 'Ȟ', 'ȣ' => 'Ȣ', 'ȥ' => 'Ȥ', 'ȧ' => 'Ȧ', 'ȩ' => 'Ȩ', 'ȫ' => 'Ȫ', 'ȭ' => 'Ȭ', 'ȯ' => 'Ȯ', 'ȱ' => 'Ȱ', 'ȳ' => 'Ȳ', 'ȼ' => 'Ȼ', 'ȿ' => 'Ȿ', 'ɀ' => 'Ɀ', 'ɂ' => 'Ɂ', 'ɇ' => 'Ɇ', 'ɉ' => 'Ɉ', 'ɋ' => 'Ɋ', 'ɍ' => 'Ɍ', 'ɏ' => 'Ɏ', 'ɐ' => 'Ɐ', 'ɑ' => 'Ɑ', 'ɒ' => 'Ɒ', 'ɓ' => 'Ɓ', 'ɔ' => 'Ɔ', 'ɖ' => 'Ɖ', 'ɗ' => 'Ɗ', 'ə' => 'Ə', 'ɛ' => 'Ɛ', 'ɜ' => 'Ɜ', 'ɠ' => 'Ɠ', 'ɡ' => 'Ɡ', 'ɣ' => 'Ɣ', 'ɥ' => 'Ɥ', 'ɦ' => 'Ɦ', 'ɨ' => 'Ɨ', 'ɩ' => 'Ɩ', 'ɪ' => 'Ɪ', 'ɫ' => 'Ɫ', 'ɬ' => 'Ɬ', 'ɯ' => 'Ɯ', 'ɱ' => 'Ɱ', 'ɲ' => 'Ɲ', 'ɵ' => 'Ɵ', 'ɽ' => 'Ɽ', 'ʀ' => 'Ʀ', 'ʂ' => 'Ʂ', 'ʃ' => 'Ʃ', 'ʇ' => 'Ʇ', 'ʈ' => 'Ʈ', 'ʉ' => 'Ʉ', 'ʊ' => 'Ʊ', 'ʋ' => 'Ʋ', 'ʌ' => 'Ʌ', 'ʒ' => 'Ʒ', 'ʝ' => 'Ʝ', 'ʞ' => 'Ʞ', 'ͅ' => 'Ι', 'ͱ' => 'Ͱ', 'ͳ' => 'Ͳ', 'ͷ' => 'Ͷ', 'ͻ' => 'Ͻ', 'ͼ' => 'Ͼ', 'ͽ' => 'Ͽ', 'ά' => 'Ά', 'έ' => 'Έ', 'ή' => 'Ή', 'ί' => 'Ί', 'α' => 'Α', 'β' => 'Β', 'γ' => 'Γ', 'δ' => 'Δ', 'ε' => 'Ε', 'ζ' => 'Ζ', 'η' => 'Η', 'θ' => 'Θ', 'ι' => 'Ι', 'κ' => 'Κ', 'λ' => 'Λ', 'μ' => 'Μ', 'ν' => 'Ν', 'ξ' => 'Ξ', 'ο' => 'Ο', 'π' => 'Π', 'ρ' => 'Ρ', 'ς' => 'Σ', 'σ' => 'Σ', 'τ' => 'Τ', 'υ' => 'Υ', 'φ' => 'Φ', 'χ' => 'Χ', 'ψ' => 'Ψ', 'ω' => 'Ω', 'ϊ' => 'Ϊ', 'ϋ' => 'Ϋ', 'ό' => 'Ό', 'ύ' => 'Ύ', 'ώ' => 'Ώ', 'ϐ' => 'Β', 'ϑ' => 'Θ', 'ϕ' => 'Φ', 'ϖ' => 'Π', 'ϗ' => 'Ϗ', 'ϙ' => 'Ϙ', 'ϛ' => 'Ϛ', 'ϝ' => 'Ϝ', 'ϟ' => 'Ϟ', 'ϡ' => 'Ϡ', 'ϣ' => 'Ϣ', 'ϥ' => 'Ϥ', 'ϧ' => 'Ϧ', 'ϩ' => 'Ϩ', 'ϫ' => 'Ϫ', 'ϭ' => 'Ϭ', 'ϯ' => 'Ϯ', 'ϰ' => 'Κ', 'ϱ' => 'Ρ', 'ϲ' => 'Ϲ', 'ϳ' => 'Ϳ', 'ϵ' => 'Ε', 'ϸ' => 'Ϸ', 'ϻ' => 'Ϻ', 'а' => 'А', 'б' => 'Б', 'в' => 'В', 'г' => 'Г', 'д' => 'Д', 'е' => 'Е', 'ж' => 'Ж', 'з' => 'З', 'и' => 'И', 'й' => 'Й', 'к' => 'К', 'л' => 'Л', 'м' => 'М', 'н' => 'Н', 'о' => 'О', 'п' => 'П', 'р' => 'Р', 'с' => 'С', 'т' => 'Т', 'у' => 'У', 'ф' => 'Ф', 'х' => 'Х', 'ц' => 'Ц', 'ч' => 'Ч', 'ш' => 'Ш', 'щ' => 'Щ', 'ъ' => 'Ъ', 'ы' => 'Ы', 'ь' => 'Ь', 'э' => 'Э', 'ю' => 'Ю', 'я' => 'Я', 'ѐ' => 'Ѐ', 'ё' => 'Ё', 'ђ' => 'Ђ', 'ѓ' => 'Ѓ', 'є' => 'Є', 'ѕ' => 'Ѕ', 'і' => 'І', 'ї' => 'Ї', 'ј' => 'Ј', 'љ' => 'Љ', 'њ' => 'Њ', 'ћ' => 'Ћ', 'ќ' => 'Ќ', 'ѝ' => 'Ѝ', 'ў' => 'Ў', 'џ' => 'Џ', 'ѡ' => 'Ѡ', 'ѣ' => 'Ѣ', 'ѥ' => 'Ѥ', 'ѧ' => 'Ѧ', 'ѩ' => 'Ѩ', 'ѫ' => 'Ѫ', 'ѭ' => 'Ѭ', 'ѯ' => 'Ѯ', 'ѱ' => 'Ѱ', 'ѳ' => 'Ѳ', 'ѵ' => 'Ѵ', 'ѷ' => 'Ѷ', 'ѹ' => 'Ѹ', 'ѻ' => 'Ѻ', 'ѽ' => 'Ѽ', 'ѿ' => 'Ѿ', 'ҁ' => 'Ҁ', 'ҋ' => 'Ҋ', 'ҍ' => 'Ҍ', 'ҏ' => 'Ҏ', 'ґ' => 'Ґ', 'ғ' => 'Ғ', 'ҕ' => 'Ҕ', 'җ' => 'Җ', 'ҙ' => 'Ҙ', 'қ' => 'Қ', 'ҝ' => 'Ҝ', 'ҟ' => 'Ҟ', 'ҡ' => 'Ҡ', 'ң' => 'Ң', 'ҥ' => 'Ҥ', 'ҧ' => 'Ҧ', 'ҩ' => 'Ҩ', 'ҫ' => 'Ҫ', 'ҭ' => 'Ҭ', 'ү' => 'Ү', 'ұ' => 'Ұ', 'ҳ' => 'Ҳ', 'ҵ' => 'Ҵ', 'ҷ' => 'Ҷ', 'ҹ' => 'Ҹ', 'һ' => 'Һ', 'ҽ' => 'Ҽ', 'ҿ' => 'Ҿ', 'ӂ' => 'Ӂ', 'ӄ' => 'Ӄ', 'ӆ' => 'Ӆ', 'ӈ' => 'Ӈ', 'ӊ' => 'Ӊ', 'ӌ' => 'Ӌ', 'ӎ' => 'Ӎ', 'ӏ' => 'Ӏ', 'ӑ' => 'Ӑ', 'ӓ' => 'Ӓ', 'ӕ' => 'Ӕ', 'ӗ' => 'Ӗ', 'ә' => 'Ә', 'ӛ' => 'Ӛ', 'ӝ' => 'Ӝ', 'ӟ' => 'Ӟ', 'ӡ' => 'Ӡ', 'ӣ' => 'Ӣ', 'ӥ' => 'Ӥ', 'ӧ' => 'Ӧ', 'ө' => 'Ө', 'ӫ' => 'Ӫ', 'ӭ' => 'Ӭ', 'ӯ' => 'Ӯ', 'ӱ' => 'Ӱ', 'ӳ' => 'Ӳ', 'ӵ' => 'Ӵ', 'ӷ' => 'Ӷ', 'ӹ' => 'Ӹ', 'ӻ' => 'Ӻ', 'ӽ' => 'Ӽ', 'ӿ' => 'Ӿ', 'ԁ' => 'Ԁ', 'ԃ' => 'Ԃ', 'ԅ' => 'Ԅ', 'ԇ' => 'Ԇ', 'ԉ' => 'Ԉ', 'ԋ' => 'Ԋ', 'ԍ' => 'Ԍ', 'ԏ' => 'Ԏ', 'ԑ' => 'Ԑ', 'ԓ' => 'Ԓ', 'ԕ' => 'Ԕ', 'ԗ' => 'Ԗ', 'ԙ' => 'Ԙ', 'ԛ' => 'Ԛ', 'ԝ' => 'Ԝ', 'ԟ' => 'Ԟ', 'ԡ' => 'Ԡ', 'ԣ' => 'Ԣ', 'ԥ' => 'Ԥ', 'ԧ' => 'Ԧ', 'ԩ' => 'Ԩ', 'ԫ' => 'Ԫ', 'ԭ' => 'Ԭ', 'ԯ' => 'Ԯ', 'ա' => 'Ա', 'բ' => 'Բ', 'գ' => 'Գ', 'դ' => 'Դ', 'ե' => 'Ե', 'զ' => 'Զ', 'է' => 'Է', 'ը' => 'Ը', 'թ' => 'Թ', 'ժ' => 'Ժ', 'ի' => 'Ի', 'լ' => 'Լ', 'խ' => 'Խ', 'ծ' => 'Ծ', 'կ' => 'Կ', 'հ' => 'Հ', 'ձ' => 'Ձ', 'ղ' => 'Ղ', 'ճ' => 'Ճ', 'մ' => 'Մ', 'յ' => 'Յ', 'ն' => 'Ն', 'շ' => 'Շ', 'ո' => 'Ո', 'չ' => 'Չ', 'պ' => 'Պ', 'ջ' => 'Ջ', 'ռ' => 'Ռ', 'ս' => 'Ս', 'վ' => 'Վ', 'տ' => 'Տ', 'ր' => 'Ր', 'ց' => 'Ց', 'ւ' => 'Ւ', 'փ' => 'Փ', 'ք' => 'Ք', 'օ' => 'Օ', 'ֆ' => 'Ֆ', 'ა' => 'Ა', 'ბ' => 'Ბ', 'გ' => 'Გ', 'დ' => 'Დ', 'ე' => 'Ე', 'ვ' => 'Ვ', 'ზ' => 'Ზ', 'თ' => 'Თ', 'ი' => 'Ი', 'კ' => 'Კ', 'ლ' => 'Ლ', 'მ' => 'Მ', 'ნ' => 'Ნ', 'ო' => 'Ო', 'პ' => 'Პ', 'ჟ' => 'Ჟ', 'რ' => 'Რ', 'ს' => 'Ს', 'ტ' => 'Ტ', 'უ' => 'Უ', 'ფ' => 'Ფ', 'ქ' => 'Ქ', 'ღ' => 'Ღ', 'ყ' => 'Ყ', 'შ' => 'Შ', 'ჩ' => 'Ჩ', 'ც' => 'Ც', 'ძ' => 'Ძ', 'წ' => 'Წ', 'ჭ' => 'Ჭ', 'ხ' => 'Ხ', 'ჯ' => 'Ჯ', 'ჰ' => 'Ჰ', 'ჱ' => 'Ჱ', 'ჲ' => 'Ჲ', 'ჳ' => 'Ჳ', 'ჴ' => 'Ჴ', 'ჵ' => 'Ჵ', 'ჶ' => 'Ჶ', 'ჷ' => 'Ჷ', 'ჸ' => 'Ჸ', 'ჹ' => 'Ჹ', 'ჺ' => 'Ჺ', 'ჽ' => 'Ჽ', 'ჾ' => 'Ჾ', 'ჿ' => 'Ჿ', 'ᏸ' => 'Ᏸ', 'ᏹ' => 'Ᏹ', 'ᏺ' => 'Ᏺ', 'ᏻ' => 'Ᏻ', 'ᏼ' => 'Ᏼ', 'ᏽ' => 'Ᏽ', 'ᲀ' => 'В', 'ᲁ' => 'Д', 'ᲂ' => 'О', 'ᲃ' => 'С', 'ᲄ' => 'Т', 'ᲅ' => 'Т', 'ᲆ' => 'Ъ', 'ᲇ' => 'Ѣ', 'ᲈ' => 'Ꙋ', 'ᵹ' => 'Ᵹ', 'ᵽ' => 'Ᵽ', 'ᶎ' => 'Ᶎ', 'ḁ' => 'Ḁ', 'ḃ' => 'Ḃ', 'ḅ' => 'Ḅ', 'ḇ' => 'Ḇ', 'ḉ' => 'Ḉ', 'ḋ' => 'Ḋ', 'ḍ' => 'Ḍ', 'ḏ' => 'Ḏ', 'ḑ' => 'Ḑ', 'ḓ' => 'Ḓ', 'ḕ' => 'Ḕ', 'ḗ' => 'Ḗ', 'ḙ' => 'Ḙ', 'ḛ' => 'Ḛ', 'ḝ' => 'Ḝ', 'ḟ' => 'Ḟ', 'ḡ' => 'Ḡ', 'ḣ' => 'Ḣ', 'ḥ' => 'Ḥ', 'ḧ' => 'Ḧ', 'ḩ' => 'Ḩ', 'ḫ' => 'Ḫ', 'ḭ' => 'Ḭ', 'ḯ' => 'Ḯ', 'ḱ' => 'Ḱ', 'ḳ' => 'Ḳ', 'ḵ' => 'Ḵ', 'ḷ' => 'Ḷ', 'ḹ' => 'Ḹ', 'ḻ' => 'Ḻ', 'ḽ' => 'Ḽ', 'ḿ' => 'Ḿ', 'ṁ' => 'Ṁ', 'ṃ' => 'Ṃ', 'ṅ' => 'Ṅ', 'ṇ' => 'Ṇ', 'ṉ' => 'Ṉ', 'ṋ' => 'Ṋ', 'ṍ' => 'Ṍ', 'ṏ' => 'Ṏ', 'ṑ' => 'Ṑ', 'ṓ' => 'Ṓ', 'ṕ' => 'Ṕ', 'ṗ' => 'Ṗ', 'ṙ' => 'Ṙ', 'ṛ' => 'Ṛ', 'ṝ' => 'Ṝ', 'ṟ' => 'Ṟ', 'ṡ' => 'Ṡ', 'ṣ' => 'Ṣ', 'ṥ' => 'Ṥ', 'ṧ' => 'Ṧ', 'ṩ' => 'Ṩ', 'ṫ' => 'Ṫ', 'ṭ' => 'Ṭ', 'ṯ' => 'Ṯ', 'ṱ' => 'Ṱ', 'ṳ' => 'Ṳ', 'ṵ' => 'Ṵ', 'ṷ' => 'Ṷ', 'ṹ' => 'Ṹ', 'ṻ' => 'Ṻ', 'ṽ' => 'Ṽ', 'ṿ' => 'Ṿ', 'ẁ' => 'Ẁ', 'ẃ' => 'Ẃ', 'ẅ' => 'Ẅ', 'ẇ' => 'Ẇ', 'ẉ' => 'Ẉ', 'ẋ' => 'Ẋ', 'ẍ' => 'Ẍ', 'ẏ' => 'Ẏ', 'ẑ' => 'Ẑ', 'ẓ' => 'Ẓ', 'ẕ' => 'Ẕ', 'ẛ' => 'Ṡ', 'ạ' => 'Ạ', 'ả' => 'Ả', 'ấ' => 'Ấ', 'ầ' => 'Ầ', 'ẩ' => 'Ẩ', 'ẫ' => 'Ẫ', 'ậ' => 'Ậ', 'ắ' => 'Ắ', 'ằ' => 'Ằ', 'ẳ' => 'Ẳ', 'ẵ' => 'Ẵ', 'ặ' => 'Ặ', 'ẹ' => 'Ẹ', 'ẻ' => 'Ẻ', 'ẽ' => 'Ẽ', 'ế' => 'Ế', 'ề' => 'Ề', 'ể' => 'Ể', 'ễ' => 'Ễ', 'ệ' => 'Ệ', 'ỉ' => 'Ỉ', 'ị' => 'Ị', 'ọ' => 'Ọ', 'ỏ' => 'Ỏ', 'ố' => 'Ố', 'ồ' => 'Ồ', 'ổ' => 'Ổ', 'ỗ' => 'Ỗ', 'ộ' => 'Ộ', 'ớ' => 'Ớ', 'ờ' => 'Ờ', 'ở' => 'Ở', 'ỡ' => 'Ỡ', 'ợ' => 'Ợ', 'ụ' => 'Ụ', 'ủ' => 'Ủ', 'ứ' => 'Ứ', 'ừ' => 'Ừ', 'ử' => 'Ử', 'ữ' => 'Ữ', 'ự' => 'Ự', 'ỳ' => 'Ỳ', 'ỵ' => 'Ỵ', 'ỷ' => 'Ỷ', 'ỹ' => 'Ỹ', 'ỻ' => 'Ỻ', 'ỽ' => 'Ỽ', 'ỿ' => 'Ỿ', 'ἀ' => 'Ἀ', 'ἁ' => 'Ἁ', 'ἂ' => 'Ἂ', 'ἃ' => 'Ἃ', 'ἄ' => 'Ἄ', 'ἅ' => 'Ἅ', 'ἆ' => 'Ἆ', 'ἇ' => 'Ἇ', 'ἐ' => 'Ἐ', 'ἑ' => 'Ἑ', 'ἒ' => 'Ἒ', 'ἓ' => 'Ἓ', 'ἔ' => 'Ἔ', 'ἕ' => 'Ἕ', 'ἠ' => 'Ἠ', 'ἡ' => 'Ἡ', 'ἢ' => 'Ἢ', 'ἣ' => 'Ἣ', 'ἤ' => 'Ἤ', 'ἥ' => 'Ἥ', 'ἦ' => 'Ἦ', 'ἧ' => 'Ἧ', 'ἰ' => 'Ἰ', 'ἱ' => 'Ἱ', 'ἲ' => 'Ἲ', 'ἳ' => 'Ἳ', 'ἴ' => 'Ἴ', 'ἵ' => 'Ἵ', 'ἶ' => 'Ἶ', 'ἷ' => 'Ἷ', 'ὀ' => 'Ὀ', 'ὁ' => 'Ὁ', 'ὂ' => 'Ὂ', 'ὃ' => 'Ὃ', 'ὄ' => 'Ὄ', 'ὅ' => 'Ὅ', 'ὑ' => 'Ὑ', 'ὓ' => 'Ὓ', 'ὕ' => 'Ὕ', 'ὗ' => 'Ὗ', 'ὠ' => 'Ὠ', 'ὡ' => 'Ὡ', 'ὢ' => 'Ὢ', 'ὣ' => 'Ὣ', 'ὤ' => 'Ὤ', 'ὥ' => 'Ὥ', 'ὦ' => 'Ὦ', 'ὧ' => 'Ὧ', 'ὰ' => 'Ὰ', 'ά' => 'Ά', 'ὲ' => 'Ὲ', 'έ' => 'Έ', 'ὴ' => 'Ὴ', 'ή' => 'Ή', 'ὶ' => 'Ὶ', 'ί' => 'Ί', 'ὸ' => 'Ὸ', 'ό' => 'Ό', 'ὺ' => 'Ὺ', 'ύ' => 'Ύ', 'ὼ' => 'Ὼ', 'ώ' => 'Ώ', 'ᾀ' => 'ἈΙ', 'ᾁ' => 'ἉΙ', 'ᾂ' => 'ἊΙ', 'ᾃ' => 'ἋΙ', 'ᾄ' => 'ἌΙ', 'ᾅ' => 'ἍΙ', 'ᾆ' => 'ἎΙ', 'ᾇ' => 'ἏΙ', 'ᾐ' => 'ἨΙ', 'ᾑ' => 'ἩΙ', 'ᾒ' => 'ἪΙ', 'ᾓ' => 'ἫΙ', 'ᾔ' => 'ἬΙ', 'ᾕ' => 'ἭΙ', 'ᾖ' => 'ἮΙ', 'ᾗ' => 'ἯΙ', 'ᾠ' => 'ὨΙ', 'ᾡ' => 'ὩΙ', 'ᾢ' => 'ὪΙ', 'ᾣ' => 'ὫΙ', 'ᾤ' => 'ὬΙ', 'ᾥ' => 'ὭΙ', 'ᾦ' => 'ὮΙ', 'ᾧ' => 'ὯΙ', 'ᾰ' => 'Ᾰ', 'ᾱ' => 'Ᾱ', 'ᾳ' => 'ΑΙ', 'ι' => 'Ι', 'ῃ' => 'ΗΙ', 'ῐ' => 'Ῐ', 'ῑ' => 'Ῑ', 'ῠ' => 'Ῠ', 'ῡ' => 'Ῡ', 'ῥ' => 'Ῥ', 'ῳ' => 'ΩΙ', 'ⅎ' => 'Ⅎ', 'ⅰ' => 'Ⅰ', 'ⅱ' => 'Ⅱ', 'ⅲ' => 'Ⅲ', 'ⅳ' => 'Ⅳ', 'ⅴ' => 'Ⅴ', 'ⅵ' => 'Ⅵ', 'ⅶ' => 'Ⅶ', 'ⅷ' => 'Ⅷ', 'ⅸ' => 'Ⅸ', 'ⅹ' => 'Ⅹ', 'ⅺ' => 'Ⅺ', 'ⅻ' => 'Ⅻ', 'ⅼ' => 'Ⅼ', 'ⅽ' => 'Ⅽ', 'ⅾ' => 'Ⅾ', 'ⅿ' => 'Ⅿ', 'ↄ' => 'Ↄ', 'ⓐ' => 'Ⓐ', 'ⓑ' => 'Ⓑ', 'ⓒ' => 'Ⓒ', 'ⓓ' => 'Ⓓ', 'ⓔ' => 'Ⓔ', 'ⓕ' => 'Ⓕ', 'ⓖ' => 'Ⓖ', 'ⓗ' => 'Ⓗ', 'ⓘ' => 'Ⓘ', 'ⓙ' => 'Ⓙ', 'ⓚ' => 'Ⓚ', 'ⓛ' => 'Ⓛ', 'ⓜ' => 'Ⓜ', 'ⓝ' => 'Ⓝ', 'ⓞ' => 'Ⓞ', 'ⓟ' => 'Ⓟ', 'ⓠ' => 'Ⓠ', 'ⓡ' => 'Ⓡ', 'ⓢ' => 'Ⓢ', 'ⓣ' => 'Ⓣ', 'ⓤ' => 'Ⓤ', 'ⓥ' => 'Ⓥ', 'ⓦ' => 'Ⓦ', 'ⓧ' => 'Ⓧ', 'ⓨ' => 'Ⓨ', 'ⓩ' => 'Ⓩ', 'ⰰ' => 'Ⰰ', 'ⰱ' => 'Ⰱ', 'ⰲ' => 'Ⰲ', 'ⰳ' => 'Ⰳ', 'ⰴ' => 'Ⰴ', 'ⰵ' => 'Ⰵ', 'ⰶ' => 'Ⰶ', 'ⰷ' => 'Ⰷ', 'ⰸ' => 'Ⰸ', 'ⰹ' => 'Ⰹ', 'ⰺ' => 'Ⰺ', 'ⰻ' => 'Ⰻ', 'ⰼ' => 'Ⰼ', 'ⰽ' => 'Ⰽ', 'ⰾ' => 'Ⰾ', 'ⰿ' => 'Ⰿ', 'ⱀ' => 'Ⱀ', 'ⱁ' => 'Ⱁ', 'ⱂ' => 'Ⱂ', 'ⱃ' => 'Ⱃ', 'ⱄ' => 'Ⱄ', 'ⱅ' => 'Ⱅ', 'ⱆ' => 'Ⱆ', 'ⱇ' => 'Ⱇ', 'ⱈ' => 'Ⱈ', 'ⱉ' => 'Ⱉ', 'ⱊ' => 'Ⱊ', 'ⱋ' => 'Ⱋ', 'ⱌ' => 'Ⱌ', 'ⱍ' => 'Ⱍ', 'ⱎ' => 'Ⱎ', 'ⱏ' => 'Ⱏ', 'ⱐ' => 'Ⱐ', 'ⱑ' => 'Ⱑ', 'ⱒ' => 'Ⱒ', 'ⱓ' => 'Ⱓ', 'ⱔ' => 'Ⱔ', 'ⱕ' => 'Ⱕ', 'ⱖ' => 'Ⱖ', 'ⱗ' => 'Ⱗ', 'ⱘ' => 'Ⱘ', 'ⱙ' => 'Ⱙ', 'ⱚ' => 'Ⱚ', 'ⱛ' => 'Ⱛ', 'ⱜ' => 'Ⱜ', 'ⱝ' => 'Ⱝ', 'ⱞ' => 'Ⱞ', 'ⱡ' => 'Ⱡ', 'ⱥ' => 'Ⱥ', 'ⱦ' => 'Ⱦ', 'ⱨ' => 'Ⱨ', 'ⱪ' => 'Ⱪ', 'ⱬ' => 'Ⱬ', 'ⱳ' => 'Ⱳ', 'ⱶ' => 'Ⱶ', 'ⲁ' => 'Ⲁ', 'ⲃ' => 'Ⲃ', 'ⲅ' => 'Ⲅ', 'ⲇ' => 'Ⲇ', 'ⲉ' => 'Ⲉ', 'ⲋ' => 'Ⲋ', 'ⲍ' => 'Ⲍ', 'ⲏ' => 'Ⲏ', 'ⲑ' => 'Ⲑ', 'ⲓ' => 'Ⲓ', 'ⲕ' => 'Ⲕ', 'ⲗ' => 'Ⲗ', 'ⲙ' => 'Ⲙ', 'ⲛ' => 'Ⲛ', 'ⲝ' => 'Ⲝ', 'ⲟ' => 'Ⲟ', 'ⲡ' => 'Ⲡ', 'ⲣ' => 'Ⲣ', 'ⲥ' => 'Ⲥ', 'ⲧ' => 'Ⲧ', 'ⲩ' => 'Ⲩ', 'ⲫ' => 'Ⲫ', 'ⲭ' => 'Ⲭ', 'ⲯ' => 'Ⲯ', 'ⲱ' => 'Ⲱ', 'ⲳ' => 'Ⲳ', 'ⲵ' => 'Ⲵ', 'ⲷ' => 'Ⲷ', 'ⲹ' => 'Ⲹ', 'ⲻ' => 'Ⲻ', 'ⲽ' => 'Ⲽ', 'ⲿ' => 'Ⲿ', 'ⳁ' => 'Ⳁ', 'ⳃ' => 'Ⳃ', 'ⳅ' => 'Ⳅ', 'ⳇ' => 'Ⳇ', 'ⳉ' => 'Ⳉ', 'ⳋ' => 'Ⳋ', 'ⳍ' => 'Ⳍ', 'ⳏ' => 'Ⳏ', 'ⳑ' => 'Ⳑ', 'ⳓ' => 'Ⳓ', 'ⳕ' => 'Ⳕ', 'ⳗ' => 'Ⳗ', 'ⳙ' => 'Ⳙ', 'ⳛ' => 'Ⳛ', 'ⳝ' => 'Ⳝ', 'ⳟ' => 'Ⳟ', 'ⳡ' => 'Ⳡ', 'ⳣ' => 'Ⳣ', 'ⳬ' => 'Ⳬ', 'ⳮ' => 'Ⳮ', 'ⳳ' => 'Ⳳ', 'ⴀ' => 'Ⴀ', 'ⴁ' => 'Ⴁ', 'ⴂ' => 'Ⴂ', 'ⴃ' => 'Ⴃ', 'ⴄ' => 'Ⴄ', 'ⴅ' => 'Ⴅ', 'ⴆ' => 'Ⴆ', 'ⴇ' => 'Ⴇ', 'ⴈ' => 'Ⴈ', 'ⴉ' => 'Ⴉ', 'ⴊ' => 'Ⴊ', 'ⴋ' => 'Ⴋ', 'ⴌ' => 'Ⴌ', 'ⴍ' => 'Ⴍ', 'ⴎ' => 'Ⴎ', 'ⴏ' => 'Ⴏ', 'ⴐ' => 'Ⴐ', 'ⴑ' => 'Ⴑ', 'ⴒ' => 'Ⴒ', 'ⴓ' => 'Ⴓ', 'ⴔ' => 'Ⴔ', 'ⴕ' => 'Ⴕ', 'ⴖ' => 'Ⴖ', 'ⴗ' => 'Ⴗ', 'ⴘ' => 'Ⴘ', 'ⴙ' => 'Ⴙ', 'ⴚ' => 'Ⴚ', 'ⴛ' => 'Ⴛ', 'ⴜ' => 'Ⴜ', 'ⴝ' => 'Ⴝ', 'ⴞ' => 'Ⴞ', 'ⴟ' => 'Ⴟ', 'ⴠ' => 'Ⴠ', 'ⴡ' => 'Ⴡ', 'ⴢ' => 'Ⴢ', 'ⴣ' => 'Ⴣ', 'ⴤ' => 'Ⴤ', 'ⴥ' => 'Ⴥ', 'ⴧ' => 'Ⴧ', 'ⴭ' => 'Ⴭ', 'ꙁ' => 'Ꙁ', 'ꙃ' => 'Ꙃ', 'ꙅ' => 'Ꙅ', 'ꙇ' => 'Ꙇ', 'ꙉ' => 'Ꙉ', 'ꙋ' => 'Ꙋ', 'ꙍ' => 'Ꙍ', 'ꙏ' => 'Ꙏ', 'ꙑ' => 'Ꙑ', 'ꙓ' => 'Ꙓ', 'ꙕ' => 'Ꙕ', 'ꙗ' => 'Ꙗ', 'ꙙ' => 'Ꙙ', 'ꙛ' => 'Ꙛ', 'ꙝ' => 'Ꙝ', 'ꙟ' => 'Ꙟ', 'ꙡ' => 'Ꙡ', 'ꙣ' => 'Ꙣ', 'ꙥ' => 'Ꙥ', 'ꙧ' => 'Ꙧ', 'ꙩ' => 'Ꙩ', 'ꙫ' => 'Ꙫ', 'ꙭ' => 'Ꙭ', 'ꚁ' => 'Ꚁ', 'ꚃ' => 'Ꚃ', 'ꚅ' => 'Ꚅ', 'ꚇ' => 'Ꚇ', 'ꚉ' => 'Ꚉ', 'ꚋ' => 'Ꚋ', 'ꚍ' => 'Ꚍ', 'ꚏ' => 'Ꚏ', 'ꚑ' => 'Ꚑ', 'ꚓ' => 'Ꚓ', 'ꚕ' => 'Ꚕ', 'ꚗ' => 'Ꚗ', 'ꚙ' => 'Ꚙ', 'ꚛ' => 'Ꚛ', 'ꜣ' => 'Ꜣ', 'ꜥ' => 'Ꜥ', 'ꜧ' => 'Ꜧ', 'ꜩ' => 'Ꜩ', 'ꜫ' => 'Ꜫ', 'ꜭ' => 'Ꜭ', 'ꜯ' => 'Ꜯ', 'ꜳ' => 'Ꜳ', 'ꜵ' => 'Ꜵ', 'ꜷ' => 'Ꜷ', 'ꜹ' => 'Ꜹ', 'ꜻ' => 'Ꜻ', 'ꜽ' => 'Ꜽ', 'ꜿ' => 'Ꜿ', 'ꝁ' => 'Ꝁ', 'ꝃ' => 'Ꝃ', 'ꝅ' => 'Ꝅ', 'ꝇ' => 'Ꝇ', 'ꝉ' => 'Ꝉ', 'ꝋ' => 'Ꝋ', 'ꝍ' => 'Ꝍ', 'ꝏ' => 'Ꝏ', 'ꝑ' => 'Ꝑ', 'ꝓ' => 'Ꝓ', 'ꝕ' => 'Ꝕ', 'ꝗ' => 'Ꝗ', 'ꝙ' => 'Ꝙ', 'ꝛ' => 'Ꝛ', 'ꝝ' => 'Ꝝ', 'ꝟ' => 'Ꝟ', 'ꝡ' => 'Ꝡ', 'ꝣ' => 'Ꝣ', 'ꝥ' => 'Ꝥ', 'ꝧ' => 'Ꝧ', 'ꝩ' => 'Ꝩ', 'ꝫ' => 'Ꝫ', 'ꝭ' => 'Ꝭ', 'ꝯ' => 'Ꝯ', 'ꝺ' => 'Ꝺ', 'ꝼ' => 'Ꝼ', 'ꝿ' => 'Ꝿ', 'ꞁ' => 'Ꞁ', 'ꞃ' => 'Ꞃ', 'ꞅ' => 'Ꞅ', 'ꞇ' => 'Ꞇ', 'ꞌ' => 'Ꞌ', 'ꞑ' => 'Ꞑ', 'ꞓ' => 'Ꞓ', 'ꞔ' => 'Ꞔ', 'ꞗ' => 'Ꞗ', 'ꞙ' => 'Ꞙ', 'ꞛ' => 'Ꞛ', 'ꞝ' => 'Ꞝ', 'ꞟ' => 'Ꞟ', 'ꞡ' => 'Ꞡ', 'ꞣ' => 'Ꞣ', 'ꞥ' => 'Ꞥ', 'ꞧ' => 'Ꞧ', 'ꞩ' => 'Ꞩ', 'ꞵ' => 'Ꞵ', 'ꞷ' => 'Ꞷ', 'ꞹ' => 'Ꞹ', 'ꞻ' => 'Ꞻ', 'ꞽ' => 'Ꞽ', 'ꞿ' => 'Ꞿ', 'ꟃ' => 'Ꟃ', 'ꟈ' => 'Ꟈ', 'ꟊ' => 'Ꟊ', 'ꟶ' => 'Ꟶ', 'ꭓ' => 'Ꭓ', 'ꭰ' => 'Ꭰ', 'ꭱ' => 'Ꭱ', 'ꭲ' => 'Ꭲ', 'ꭳ' => 'Ꭳ', 'ꭴ' => 'Ꭴ', 'ꭵ' => 'Ꭵ', 'ꭶ' => 'Ꭶ', 'ꭷ' => 'Ꭷ', 'ꭸ' => 'Ꭸ', 'ꭹ' => 'Ꭹ', 'ꭺ' => 'Ꭺ', 'ꭻ' => 'Ꭻ', 'ꭼ' => 'Ꭼ', 'ꭽ' => 'Ꭽ', 'ꭾ' => 'Ꭾ', 'ꭿ' => 'Ꭿ', 'ꮀ' => 'Ꮀ', 'ꮁ' => 'Ꮁ', 'ꮂ' => 'Ꮂ', 'ꮃ' => 'Ꮃ', 'ꮄ' => 'Ꮄ', 'ꮅ' => 'Ꮅ', 'ꮆ' => 'Ꮆ', 'ꮇ' => 'Ꮇ', 'ꮈ' => 'Ꮈ', 'ꮉ' => 'Ꮉ', 'ꮊ' => 'Ꮊ', 'ꮋ' => 'Ꮋ', 'ꮌ' => 'Ꮌ', 'ꮍ' => 'Ꮍ', 'ꮎ' => 'Ꮎ', 'ꮏ' => 'Ꮏ', 'ꮐ' => 'Ꮐ', 'ꮑ' => 'Ꮑ', 'ꮒ' => 'Ꮒ', 'ꮓ' => 'Ꮓ', 'ꮔ' => 'Ꮔ', 'ꮕ' => 'Ꮕ', 'ꮖ' => 'Ꮖ', 'ꮗ' => 'Ꮗ', 'ꮘ' => 'Ꮘ', 'ꮙ' => 'Ꮙ', 'ꮚ' => 'Ꮚ', 'ꮛ' => 'Ꮛ', 'ꮜ' => 'Ꮜ', 'ꮝ' => 'Ꮝ', 'ꮞ' => 'Ꮞ', 'ꮟ' => 'Ꮟ', 'ꮠ' => 'Ꮠ', 'ꮡ' => 'Ꮡ', 'ꮢ' => 'Ꮢ', 'ꮣ' => 'Ꮣ', 'ꮤ' => 'Ꮤ', 'ꮥ' => 'Ꮥ', 'ꮦ' => 'Ꮦ', 'ꮧ' => 'Ꮧ', 'ꮨ' => 'Ꮨ', 'ꮩ' => 'Ꮩ', 'ꮪ' => 'Ꮪ', 'ꮫ' => 'Ꮫ', 'ꮬ' => 'Ꮬ', 'ꮭ' => 'Ꮭ', 'ꮮ' => 'Ꮮ', 'ꮯ' => 'Ꮯ', 'ꮰ' => 'Ꮰ', 'ꮱ' => 'Ꮱ', 'ꮲ' => 'Ꮲ', 'ꮳ' => 'Ꮳ', 'ꮴ' => 'Ꮴ', 'ꮵ' => 'Ꮵ', 'ꮶ' => 'Ꮶ', 'ꮷ' => 'Ꮷ', 'ꮸ' => 'Ꮸ', 'ꮹ' => 'Ꮹ', 'ꮺ' => 'Ꮺ', 'ꮻ' => 'Ꮻ', 'ꮼ' => 'Ꮼ', 'ꮽ' => 'Ꮽ', 'ꮾ' => 'Ꮾ', 'ꮿ' => 'Ꮿ', 'a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', '𐐨' => '𐐀', '𐐩' => '𐐁', '𐐪' => '𐐂', '𐐫' => '𐐃', '𐐬' => '𐐄', '𐐭' => '𐐅', '𐐮' => '𐐆', '𐐯' => '𐐇', '𐐰' => '𐐈', '𐐱' => '𐐉', '𐐲' => '𐐊', '𐐳' => '𐐋', '𐐴' => '𐐌', '𐐵' => '𐐍', '𐐶' => '𐐎', '𐐷' => '𐐏', '𐐸' => '𐐐', '𐐹' => '𐐑', '𐐺' => '𐐒', '𐐻' => '𐐓', '𐐼' => '𐐔', '𐐽' => '𐐕', '𐐾' => '𐐖', '𐐿' => '𐐗', '𐑀' => '𐐘', '𐑁' => '𐐙', '𐑂' => '𐐚', '𐑃' => '𐐛', '𐑄' => '𐐜', '𐑅' => '𐐝', '𐑆' => '𐐞', '𐑇' => '𐐟', '𐑈' => '𐐠', '𐑉' => '𐐡', '𐑊' => '𐐢', '𐑋' => '𐐣', '𐑌' => '𐐤', '𐑍' => '𐐥', '𐑎' => '𐐦', '𐑏' => '𐐧', '𐓘' => '𐒰', '𐓙' => '𐒱', '𐓚' => '𐒲', '𐓛' => '𐒳', '𐓜' => '𐒴', '𐓝' => '𐒵', '𐓞' => '𐒶', '𐓟' => '𐒷', '𐓠' => '𐒸', '𐓡' => '𐒹', '𐓢' => '𐒺', '𐓣' => '𐒻', '𐓤' => '𐒼', '𐓥' => '𐒽', '𐓦' => '𐒾', '𐓧' => '𐒿', '𐓨' => '𐓀', '𐓩' => '𐓁', '𐓪' => '𐓂', '𐓫' => '𐓃', '𐓬' => '𐓄', '𐓭' => '𐓅', '𐓮' => '𐓆', '𐓯' => '𐓇', '𐓰' => '𐓈', '𐓱' => '𐓉', '𐓲' => '𐓊', '𐓳' => '𐓋', '𐓴' => '𐓌', '𐓵' => '𐓍', '𐓶' => '𐓎', '𐓷' => '𐓏', '𐓸' => '𐓐', '𐓹' => '𐓑', '𐓺' => '𐓒', '𐓻' => '𐓓', '𐳀' => '𐲀', '𐳁' => '𐲁', '𐳂' => '𐲂', '𐳃' => '𐲃', '𐳄' => '𐲄', '𐳅' => '𐲅', '𐳆' => '𐲆', '𐳇' => '𐲇', '𐳈' => '𐲈', '𐳉' => '𐲉', '𐳊' => '𐲊', '𐳋' => '𐲋', '𐳌' => '𐲌', '𐳍' => '𐲍', '𐳎' => '𐲎', '𐳏' => '𐲏', '𐳐' => '𐲐', '𐳑' => '𐲑', '𐳒' => '𐲒', '𐳓' => '𐲓', '𐳔' => '𐲔', '𐳕' => '𐲕', '𐳖' => '𐲖', '𐳗' => '𐲗', '𐳘' => '𐲘', '𐳙' => '𐲙', '𐳚' => '𐲚', '𐳛' => '𐲛', '𐳜' => '𐲜', '𐳝' => '𐲝', '𐳞' => '𐲞', '𐳟' => '𐲟', '𐳠' => '𐲠', '𐳡' => '𐲡', '𐳢' => '𐲢', '𐳣' => '𐲣', '𐳤' => '𐲤', '𐳥' => '𐲥', '𐳦' => '𐲦', '𐳧' => '𐲧', '𐳨' => '𐲨', '𐳩' => '𐲩', '𐳪' => '𐲪', '𐳫' => '𐲫', '𐳬' => '𐲬', '𐳭' => '𐲭', '𐳮' => '𐲮', '𐳯' => '𐲯', '𐳰' => '𐲰', '𐳱' => '𐲱', '𐳲' => '𐲲', '𑣀' => '𑢠', '𑣁' => '𑢡', '𑣂' => '𑢢', '𑣃' => '𑢣', '𑣄' => '𑢤', '𑣅' => '𑢥', '𑣆' => '𑢦', '𑣇' => '𑢧', '𑣈' => '𑢨', '𑣉' => '𑢩', '𑣊' => '𑢪', '𑣋' => '𑢫', '𑣌' => '𑢬', '𑣍' => '𑢭', '𑣎' => '𑢮', '𑣏' => '𑢯', '𑣐' => '𑢰', '𑣑' => '𑢱', '𑣒' => '𑢲', '𑣓' => '𑢳', '𑣔' => '𑢴', '𑣕' => '𑢵', '𑣖' => '𑢶', '𑣗' => '𑢷', '𑣘' => '𑢸', '𑣙' => '𑢹', '𑣚' => '𑢺', '𑣛' => '𑢻', '𑣜' => '𑢼', '𑣝' => '𑢽', '𑣞' => '𑢾', '𑣟' => '𑢿', '𖹠' => '𖹀', '𖹡' => '𖹁', '𖹢' => '𖹂', '𖹣' => '𖹃', '𖹤' => '𖹄', '𖹥' => '𖹅', '𖹦' => '𖹆', '𖹧' => '𖹇', '𖹨' => '𖹈', '𖹩' => '𖹉', '𖹪' => '𖹊', '𖹫' => '𖹋', '𖹬' => '𖹌', '𖹭' => '𖹍', '𖹮' => '𖹎', '𖹯' => '𖹏', '𖹰' => '𖹐', '𖹱' => '𖹑', '𖹲' => '𖹒', '𖹳' => '𖹓', '𖹴' => '𖹔', '𖹵' => '𖹕', '𖹶' => '𖹖', '𖹷' => '𖹗', '𖹸' => '𖹘', '𖹹' => '𖹙', '𖹺' => '𖹚', '𖹻' => '𖹛', '𖹼' => '𖹜', '𖹽' => '𖹝', '𖹾' => '𖹞', '𖹿' => '𖹟', '𞤢' => '𞤀', '𞤣' => '𞤁', '𞤤' => '𞤂', '𞤥' => '𞤃', '𞤦' => '𞤄', '𞤧' => '𞤅', '𞤨' => '𞤆', '𞤩' => '𞤇', '𞤪' => '𞤈', '𞤫' => '𞤉', '𞤬' => '𞤊', '𞤭' => '𞤋', '𞤮' => '𞤌', '𞤯' => '𞤍', '𞤰' => '𞤎', '𞤱' => '𞤏', '𞤲' => '𞤐', '𞤳' => '𞤑', '𞤴' => '𞤒', '𞤵' => '𞤓', '𞤶' => '𞤔', '𞤷' => '𞤕', '𞤸' => '𞤖', '𞤹' => '𞤗', '𞤺' => '𞤘', '𞤻' => '𞤙', '𞤼' => '𞤚', '𞤽' => '𞤛', '𞤾' => '𞤜', '𞤿' => '𞤝', '𞥀' => '𞤞', '𞥁' => '𞤟', '𞥂' => '𞤠', '𞥃' => '𞤡', 'ß' => 'SS', 'ff' => 'FF', 'fi' => 'FI', 'fl' => 'FL', 'ffi' => 'FFI', 'ffl' => 'FFL', 'ſt' => 'ST', 'st' => 'ST', 'և' => 'ԵՒ', 'ﬓ' => 'ՄՆ', 'ﬔ' => 'ՄԵ', 'ﬕ' => 'ՄԻ', 'ﬖ' => 'ՎՆ', 'ﬗ' => 'ՄԽ', 'ʼn' => 'ʼN', 'ΐ' => 'Ϊ́', 'ΰ' => 'Ϋ́', 'ǰ' => 'J̌', 'ẖ' => 'H̱', 'ẗ' => 'T̈', 'ẘ' => 'W̊', 'ẙ' => 'Y̊', 'ẚ' => 'Aʾ', 'ὐ' => 'Υ̓', 'ὒ' => 'Υ̓̀', 'ὔ' => 'Υ̓́', 'ὖ' => 'Υ̓͂', 'ᾶ' => 'Α͂', 'ῆ' => 'Η͂', 'ῒ' => 'Ϊ̀', 'ΐ' => 'Ϊ́', 'ῖ' => 'Ι͂', 'ῗ' => 'Ϊ͂', 'ῢ' => 'Ϋ̀', 'ΰ' => 'Ϋ́', 'ῤ' => 'Ρ̓', 'ῦ' => 'Υ͂', 'ῧ' => 'Ϋ͂', 'ῶ' => 'Ω͂', 'ᾈ' => 'ἈΙ', 'ᾉ' => 'ἉΙ', 'ᾊ' => 'ἊΙ', 'ᾋ' => 'ἋΙ', 'ᾌ' => 'ἌΙ', 'ᾍ' => 'ἍΙ', 'ᾎ' => 'ἎΙ', 'ᾏ' => 'ἏΙ', 'ᾘ' => 'ἨΙ', 'ᾙ' => 'ἩΙ', 'ᾚ' => 'ἪΙ', 'ᾛ' => 'ἫΙ', 'ᾜ' => 'ἬΙ', 'ᾝ' => 'ἭΙ', 'ᾞ' => 'ἮΙ', 'ᾟ' => 'ἯΙ', 'ᾨ' => 'ὨΙ', 'ᾩ' => 'ὩΙ', 'ᾪ' => 'ὪΙ', 'ᾫ' => 'ὫΙ', 'ᾬ' => 'ὬΙ', 'ᾭ' => 'ὭΙ', 'ᾮ' => 'ὮΙ', 'ᾯ' => 'ὯΙ', 'ᾼ' => 'ΑΙ', 'ῌ' => 'ΗΙ', 'ῼ' => 'ΩΙ', 'ᾲ' => 'ᾺΙ', 'ᾴ' => 'ΆΙ', 'ῂ' => 'ῊΙ', 'ῄ' => 'ΉΙ', 'ῲ' => 'ῺΙ', 'ῴ' => 'ΏΙ', 'ᾷ' => 'Α͂Ι', 'ῇ' => 'Η͂Ι', 'ῷ' => 'Ω͂Ι', ); polyfill-mbstring/Resources/unidata/titleCaseRegexp.php000064400000014071150432043200017415 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Mbstring as p; if (!function_exists('mb_convert_encoding')) { function mb_convert_encoding(array|string|null $string, ?string $to_encoding, array|string|null $from_encoding = null): array|string|false { return p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding); } } if (!function_exists('mb_decode_mimeheader')) { function mb_decode_mimeheader(?string $string): string { return p\Mbstring::mb_decode_mimeheader((string) $string); } } if (!function_exists('mb_encode_mimeheader')) { function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0): string { return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent); } } if (!function_exists('mb_decode_numericentity')) { function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null): string { return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding); } } if (!function_exists('mb_encode_numericentity')) { function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false): string { return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex); } } if (!function_exists('mb_convert_case')) { function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null): string { return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding); } } if (!function_exists('mb_internal_encoding')) { function mb_internal_encoding(?string $encoding = null): string|bool { return p\Mbstring::mb_internal_encoding($encoding); } } if (!function_exists('mb_language')) { function mb_language(?string $language = null): string|bool { return p\Mbstring::mb_language($language); } } if (!function_exists('mb_list_encodings')) { function mb_list_encodings(): array { return p\Mbstring::mb_list_encodings(); } } if (!function_exists('mb_encoding_aliases')) { function mb_encoding_aliases(?string $encoding): array { return p\Mbstring::mb_encoding_aliases((string) $encoding); } } if (!function_exists('mb_check_encoding')) { function mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool { return p\Mbstring::mb_check_encoding($value, $encoding); } } if (!function_exists('mb_detect_encoding')) { function mb_detect_encoding(?string $string, array|string|null $encodings = null, ?bool $strict = false): string|false { return p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict); } } if (!function_exists('mb_detect_order')) { function mb_detect_order(array|string|null $encoding = null): array|bool { return p\Mbstring::mb_detect_order($encoding); } } if (!function_exists('mb_parse_str')) { function mb_parse_str(?string $string, &$result = []): bool { parse_str((string) $string, $result); return (bool) $result; } } if (!function_exists('mb_strlen')) { function mb_strlen(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strlen((string) $string, $encoding); } } if (!function_exists('mb_strpos')) { function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } } if (!function_exists('mb_strtolower')) { function mb_strtolower(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtolower((string) $string, $encoding); } } if (!function_exists('mb_strtoupper')) { function mb_strtoupper(?string $string, ?string $encoding = null): string { return p\Mbstring::mb_strtoupper((string) $string, $encoding); } } if (!function_exists('mb_substitute_character')) { function mb_substitute_character(string|int|null $substitute_character = null): string|int|bool { return p\Mbstring::mb_substitute_character($substitute_character); } } if (!function_exists('mb_substr')) { function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null): string { return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding); } } if (!function_exists('mb_stripos')) { function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } } if (!function_exists('mb_stristr')) { function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } } if (!function_exists('mb_strrchr')) { function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } } if (!function_exists('mb_strrichr')) { function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } } if (!function_exists('mb_strripos')) { function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding); } } if (!function_exists('mb_strrpos')) { function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null): int|false { return p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding); } } if (!function_exists('mb_strstr')) { function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null): string|false { return p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding); } } if (!function_exists('mb_get_info')) { function mb_get_info(?string $type = 'all'): array|string|int|false { return p\Mbstring::mb_get_info((string) $type); } } if (!function_exists('mb_http_output')) { function mb_http_output(?string $encoding = null): string|bool { return p\Mbstring::mb_http_output($encoding); } } if (!function_exists('mb_strwidth')) { function mb_strwidth(?string $string, ?string $encoding = null): int { return p\Mbstring::mb_strwidth((string) $string, $encoding); } } if (!function_exists('mb_substr_count')) { function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null): int { return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding); } } if (!function_exists('mb_output_handler')) { function mb_output_handler(?string $string, ?int $status): string { return p\Mbstring::mb_output_handler((string) $string, (int) $status); } } if (!function_exists('mb_http_input')) { function mb_http_input(?string $type = null): array|string|false { return p\Mbstring::mb_http_input($type); } } if (!function_exists('mb_convert_variables')) { function mb_convert_variables(?string $to_encoding, array|string|null $from_encoding, mixed &$var, mixed &...$vars): string|false { return p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars); } } if (!function_exists('mb_ord')) { function mb_ord(?string $string, ?string $encoding = null): int|false { return p\Mbstring::mb_ord((string) $string, $encoding); } } if (!function_exists('mb_chr')) { function mb_chr(?int $codepoint, ?string $encoding = null): string|false { return p\Mbstring::mb_chr((int) $codepoint, $encoding); } } if (!function_exists('mb_scrub')) { function mb_scrub(?string $string, ?string $encoding = null): string { $encoding ??= mb_internal_encoding(); return mb_convert_encoding((string) $string, $encoding, $encoding); } } if (!function_exists('mb_str_split')) { function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null): array { return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding); } } if (extension_loaded('mbstring')) { return; } if (!defined('MB_CASE_UPPER')) { define('MB_CASE_UPPER', 0); } if (!defined('MB_CASE_LOWER')) { define('MB_CASE_LOWER', 1); } if (!defined('MB_CASE_TITLE')) { define('MB_CASE_TITLE', 2); } polyfill-mbstring/bootstrap.php000064400000016105150432043200012743 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Mbstring as p; if (\PHP_VERSION_ID >= 80000) { return require __DIR__.'/bootstrap80.php'; } if (!function_exists('mb_convert_encoding')) { function mb_convert_encoding($string, $to_encoding, $from_encoding = null) { return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding); } } if (!function_exists('mb_decode_mimeheader')) { function mb_decode_mimeheader($string) { return p\Mbstring::mb_decode_mimeheader($string); } } if (!function_exists('mb_encode_mimeheader')) { function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0) { return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent); } } if (!function_exists('mb_decode_numericentity')) { function mb_decode_numericentity($string, $map, $encoding = null) { return p\Mbstring::mb_decode_numericentity($string, $map, $encoding); } } if (!function_exists('mb_encode_numericentity')) { function mb_encode_numericentity($string, $map, $encoding = null, $hex = false) { return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex); } } if (!function_exists('mb_convert_case')) { function mb_convert_case($string, $mode, $encoding = null) { return p\Mbstring::mb_convert_case($string, $mode, $encoding); } } if (!function_exists('mb_internal_encoding')) { function mb_internal_encoding($encoding = null) { return p\Mbstring::mb_internal_encoding($encoding); } } if (!function_exists('mb_language')) { function mb_language($language = null) { return p\Mbstring::mb_language($language); } } if (!function_exists('mb_list_encodings')) { function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); } } if (!function_exists('mb_encoding_aliases')) { function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); } } if (!function_exists('mb_check_encoding')) { function mb_check_encoding($value = null, $encoding = null) { return p\Mbstring::mb_check_encoding($value, $encoding); } } if (!function_exists('mb_detect_encoding')) { function mb_detect_encoding($string, $encodings = null, $strict = false) { return p\Mbstring::mb_detect_encoding($string, $encodings, $strict); } } if (!function_exists('mb_detect_order')) { function mb_detect_order($encoding = null) { return p\Mbstring::mb_detect_order($encoding); } } if (!function_exists('mb_parse_str')) { function mb_parse_str($string, &$result = []) { parse_str($string, $result); return (bool) $result; } } if (!function_exists('mb_strlen')) { function mb_strlen($string, $encoding = null) { return p\Mbstring::mb_strlen($string, $encoding); } } if (!function_exists('mb_strpos')) { function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding); } } if (!function_exists('mb_strtolower')) { function mb_strtolower($string, $encoding = null) { return p\Mbstring::mb_strtolower($string, $encoding); } } if (!function_exists('mb_strtoupper')) { function mb_strtoupper($string, $encoding = null) { return p\Mbstring::mb_strtoupper($string, $encoding); } } if (!function_exists('mb_substitute_character')) { function mb_substitute_character($substitute_character = null) { return p\Mbstring::mb_substitute_character($substitute_character); } } if (!function_exists('mb_substr')) { function mb_substr($string, $start, $length = 2147483647, $encoding = null) { return p\Mbstring::mb_substr($string, $start, $length, $encoding); } } if (!function_exists('mb_stripos')) { function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding); } } if (!function_exists('mb_stristr')) { function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding); } } if (!function_exists('mb_strrchr')) { function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding); } } if (!function_exists('mb_strrichr')) { function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding); } } if (!function_exists('mb_strripos')) { function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding); } } if (!function_exists('mb_strrpos')) { function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding); } } if (!function_exists('mb_strstr')) { function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null) { return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding); } } if (!function_exists('mb_get_info')) { function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); } } if (!function_exists('mb_http_output')) { function mb_http_output($encoding = null) { return p\Mbstring::mb_http_output($encoding); } } if (!function_exists('mb_strwidth')) { function mb_strwidth($string, $encoding = null) { return p\Mbstring::mb_strwidth($string, $encoding); } } if (!function_exists('mb_substr_count')) { function mb_substr_count($haystack, $needle, $encoding = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $encoding); } } if (!function_exists('mb_output_handler')) { function mb_output_handler($string, $status) { return p\Mbstring::mb_output_handler($string, $status); } } if (!function_exists('mb_http_input')) { function mb_http_input($type = null) { return p\Mbstring::mb_http_input($type); } } if (!function_exists('mb_convert_variables')) { function mb_convert_variables($to_encoding, $from_encoding, &...$vars) { return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars); } } if (!function_exists('mb_ord')) { function mb_ord($string, $encoding = null) { return p\Mbstring::mb_ord($string, $encoding); } } if (!function_exists('mb_chr')) { function mb_chr($codepoint, $encoding = null) { return p\Mbstring::mb_chr($codepoint, $encoding); } } if (!function_exists('mb_scrub')) { function mb_scrub($string, $encoding = null) { $encoding = null === $encoding ? mb_internal_encoding() : $encoding; return mb_convert_encoding($string, $encoding, $encoding); } } if (!function_exists('mb_str_split')) { function mb_str_split($string, $length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $length, $encoding); } } if (extension_loaded('mbstring')) { return; } if (!defined('MB_CASE_UPPER')) { define('MB_CASE_UPPER', 0); } if (!defined('MB_CASE_LOWER')) { define('MB_CASE_LOWER', 1); } if (!defined('MB_CASE_TITLE')) { define('MB_CASE_TITLE', 2); } polyfill-mbstring/composer.json000064400000001754150432043200012743 0ustar00{ "name": "symfony/polyfill-mbstring", "type": "library", "description": "Symfony polyfill for the Mbstring extension", "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, "files": [ "bootstrap.php" ] }, "suggest": { "ext-mbstring": "For best performance" }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-mbstring/LICENSE000064400000002051150432043200011215 0ustar00Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. polyfill-mbstring/Mbstring.php000064400000070560150432043200012520 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Mbstring; /** * Partial mbstring implementation in PHP, iconv based, UTF-8 centric. * * Implemented: * - mb_chr - Returns a specific character from its Unicode code point * - mb_convert_encoding - Convert character encoding * - mb_convert_variables - Convert character code in variable(s) * - mb_decode_mimeheader - Decode string in MIME header field * - mb_encode_mimeheader - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED * - mb_decode_numericentity - Decode HTML numeric string reference to character * - mb_encode_numericentity - Encode character to HTML numeric string reference * - mb_convert_case - Perform case folding on a string * - mb_detect_encoding - Detect character encoding * - mb_get_info - Get internal settings of mbstring * - mb_http_input - Detect HTTP input character encoding * - mb_http_output - Set/Get HTTP output character encoding * - mb_internal_encoding - Set/Get internal character encoding * - mb_list_encodings - Returns an array of all supported encodings * - mb_ord - Returns the Unicode code point of a character * - mb_output_handler - Callback function converts character encoding in output buffer * - mb_scrub - Replaces ill-formed byte sequences with substitute characters * - mb_strlen - Get string length * - mb_strpos - Find position of first occurrence of string in a string * - mb_strrpos - Find position of last occurrence of a string in a string * - mb_str_split - Convert a string to an array * - mb_strtolower - Make a string lowercase * - mb_strtoupper - Make a string uppercase * - mb_substitute_character - Set/Get substitution character * - mb_substr - Get part of string * - mb_stripos - Finds position of first occurrence of a string within another, case insensitive * - mb_stristr - Finds first occurrence of a string within another, case insensitive * - mb_strrchr - Finds the last occurrence of a character in a string within another * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive * - mb_strstr - Finds first occurrence of a string within another * - mb_strwidth - Return width of string * - mb_substr_count - Count the number of substring occurrences * * Not implemented: * - mb_convert_kana - Convert "kana" one from another ("zen-kaku", "han-kaku" and more) * - mb_ereg_* - Regular expression with multibyte support * - mb_parse_str - Parse GET/POST/COOKIE data and set global variable * - mb_preferred_mime_name - Get MIME charset string * - mb_regex_encoding - Returns current encoding for multibyte regex as string * - mb_regex_set_options - Set/Get the default options for mbregex functions * - mb_send_mail - Send encoded mail * - mb_split - Split multibyte string using regular expression * - mb_strcut - Get part of string * - mb_strimwidth - Get truncated string with specified width * * @author Nicolas Grekas * * @internal */ final class Mbstring { public const MB_CASE_FOLD = \PHP_INT_MAX; private const CASE_FOLD = [ ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], ]; private static $encodingList = ['ASCII', 'UTF-8']; private static $language = 'neutral'; private static $internalEncoding = 'UTF-8'; public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) { if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); } else { $fromEncoding = self::getEncoding($fromEncoding); } $toEncoding = self::getEncoding($toEncoding); if ('BASE64' === $fromEncoding) { $s = base64_decode($s); $fromEncoding = $toEncoding; } if ('BASE64' === $toEncoding) { return base64_encode($s); } if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) { if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) { $fromEncoding = 'Windows-1252'; } if ('UTF-8' !== $fromEncoding) { $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s); } return preg_replace_callback('/[\x80-\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s); } if ('HTML-ENTITIES' === $fromEncoding) { $s = html_entity_decode($s, \ENT_COMPAT, 'UTF-8'); $fromEncoding = 'UTF-8'; } return \iconv($fromEncoding, $toEncoding.'//IGNORE', $s); } public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) { $ok = true; array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { $ok = false; } }); return $ok ? $fromEncoding : false; } public static function mb_decode_mimeheader($s) { return \iconv_mime_decode($s, 2, self::$internalEncoding); } public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null) { trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING); } public static function mb_decode_numericentity($s, $convmap, $encoding = null) { if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; } if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { return false; } if (null !== $encoding && !is_scalar($encoding)) { trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); return ''; // Instead of null (cf. mb_encode_numericentity). } $s = (string) $s; if ('' === $s) { return ''; } $encoding = self::getEncoding($encoding); if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $cnt = floor(\count($convmap) / 4) * 4; for ($i = 0; $i < $cnt; $i += 4) { // collector_decode_htmlnumericentity ignores $convmap[$i + 3] $convmap[$i] += $convmap[$i + 2]; $convmap[$i + 1] += $convmap[$i + 2]; } $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; for ($i = 0; $i < $cnt; $i += 4) { if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { return self::mb_chr($c - $convmap[$i + 2]); } } return $m[0]; }, $s); if (null === $encoding) { return $s; } return \iconv('UTF-8', $encoding.'//IGNORE', $s); } public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) { if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) { trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; } if (!\is_array($convmap) || (80000 > \PHP_VERSION_ID && !$convmap)) { return false; } if (null !== $encoding && !is_scalar($encoding)) { trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', \E_USER_WARNING); return null; // Instead of '' (cf. mb_decode_numericentity). } if (null !== $is_hex && !is_scalar($is_hex)) { trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', \E_USER_WARNING); return null; } $s = (string) $s; if ('' === $s) { return ''; } $encoding = self::getEncoding($encoding); if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; $cnt = floor(\count($convmap) / 4) * 4; $i = 0; $len = \strlen($s); $result = ''; while ($i < $len) { $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; $uchr = substr($s, $i, $ulen); $i += $ulen; $c = self::mb_ord($uchr); for ($j = 0; $j < $cnt; $j += 4) { if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; continue 2; } } $result .= $uchr; } if (null === $encoding) { return $result; } return \iconv('UTF-8', $encoding.'//IGNORE', $result); } public static function mb_convert_case($s, $mode, $encoding = null) { $s = (string) $s; if ('' === $s) { return ''; } $encoding = self::getEncoding($encoding); if ('UTF-8' === $encoding) { $encoding = null; if (!preg_match('//u', $s)) { $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s); } } else { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } if (\MB_CASE_TITLE == $mode) { static $titleRegexp = null; if (null === $titleRegexp) { $titleRegexp = self::getData('titleCaseRegexp'); } $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s); } else { if (\MB_CASE_UPPER == $mode) { static $upper = null; if (null === $upper) { $upper = self::getData('upperCase'); } $map = $upper; } else { if (self::MB_CASE_FOLD === $mode) { $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); } static $lower = null; if (null === $lower) { $lower = self::getData('lowerCase'); } $map = $lower; } static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; $i = 0; $len = \strlen($s); while ($i < $len) { $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; $uchr = substr($s, $i, $ulen); $i += $ulen; if (isset($map[$uchr])) { $uchr = $map[$uchr]; $nlen = \strlen($uchr); if ($nlen == $ulen) { $nlen = $i; do { $s[--$nlen] = $uchr[--$ulen]; } while ($ulen); } else { $s = substr_replace($s, $uchr, $i - $ulen, $ulen); $len += $nlen - $ulen; $i += $nlen - $ulen; } } } } if (null === $encoding) { return $s; } return \iconv('UTF-8', $encoding.'//IGNORE', $s); } public static function mb_internal_encoding($encoding = null) { if (null === $encoding) { return self::$internalEncoding; } $normalizedEncoding = self::getEncoding($encoding); if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) { self::$internalEncoding = $normalizedEncoding; return true; } if (80000 > \PHP_VERSION_ID) { return false; } throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); } public static function mb_language($lang = null) { if (null === $lang) { return self::$language; } switch ($normalizedLang = strtolower($lang)) { case 'uni': case 'neutral': self::$language = $normalizedLang; return true; } if (80000 > \PHP_VERSION_ID) { return false; } throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); } public static function mb_list_encodings() { return ['UTF-8']; } public static function mb_encoding_aliases($encoding) { switch (strtoupper($encoding)) { case 'UTF8': case 'UTF-8': return ['utf8']; } return false; } public static function mb_check_encoding($var = null, $encoding = null) { if (null === $encoding) { if (null === $var) { return false; } $encoding = self::$internalEncoding; } return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var); } public static function mb_detect_encoding($str, $encodingList = null, $strict = false) { if (null === $encodingList) { $encodingList = self::$encodingList; } else { if (!\is_array($encodingList)) { $encodingList = array_map('trim', explode(',', $encodingList)); } $encodingList = array_map('strtoupper', $encodingList); } foreach ($encodingList as $enc) { switch ($enc) { case 'ASCII': if (!preg_match('/[\x80-\xFF]/', $str)) { return $enc; } break; case 'UTF8': case 'UTF-8': if (preg_match('//u', $str)) { return 'UTF-8'; } break; default: if (0 === strncmp($enc, 'ISO-8859-', 9)) { return $enc; } } } return false; } public static function mb_detect_order($encodingList = null) { if (null === $encodingList) { return self::$encodingList; } if (!\is_array($encodingList)) { $encodingList = array_map('trim', explode(',', $encodingList)); } $encodingList = array_map('strtoupper', $encodingList); foreach ($encodingList as $enc) { switch ($enc) { default: if (strncmp($enc, 'ISO-8859-', 9)) { return false; } // no break case 'ASCII': case 'UTF8': case 'UTF-8': } } self::$encodingList = $encodingList; return true; } public static function mb_strlen($s, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return \strlen($s); } return @\iconv_strlen($s, $encoding); } public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return strpos($haystack, $needle, $offset); } $needle = (string) $needle; if ('' === $needle) { if (80000 > \PHP_VERSION_ID) { trigger_error(__METHOD__.': Empty delimiter', \E_USER_WARNING); return false; } return 0; } return \iconv_strpos($haystack, $needle, $offset, $encoding); } public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return strrpos($haystack, $needle, $offset); } if ($offset != (int) $offset) { $offset = 0; } elseif ($offset = (int) $offset) { if ($offset < 0) { if (0 > $offset += self::mb_strlen($needle)) { $haystack = self::mb_substr($haystack, 0, $offset, $encoding); } $offset = 0; } else { $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding); } } $pos = '' !== $needle || 80000 > \PHP_VERSION_ID ? \iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding); return false !== $pos ? $offset + $pos : false; } public static function mb_str_split($string, $split_length = 1, $encoding = null) { if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) { trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', \E_USER_WARNING); return null; } if (1 > $split_length = (int) $split_length) { if (80000 > \PHP_VERSION_ID) { trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING); return false; } throw new \ValueError('Argument #2 ($length) must be greater than 0'); } if (null === $encoding) { $encoding = mb_internal_encoding(); } if ('UTF-8' === $encoding = self::getEncoding($encoding)) { $rx = '/('; while (65535 < $split_length) { $rx .= '.{65535}'; $split_length -= 65535; } $rx .= '.{'.$split_length.'})/us'; return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY); } $result = []; $length = mb_strlen($string, $encoding); for ($i = 0; $i < $length; $i += $split_length) { $result[] = mb_substr($string, $i, $split_length, $encoding); } return $result; } public static function mb_strtolower($s, $encoding = null) { return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding); } public static function mb_strtoupper($s, $encoding = null) { return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding); } public static function mb_substitute_character($c = null) { if (null === $c) { return 'none'; } if (0 === strcasecmp($c, 'none')) { return true; } if (80000 > \PHP_VERSION_ID) { return false; } throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint'); } public static function mb_substr($s, $start, $length = null, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { return (string) substr($s, $start, null === $length ? 2147483647 : $length); } if ($start < 0) { $start = \iconv_strlen($s, $encoding) + $start; if ($start < 0) { $start = 0; } } if (null === $length) { $length = 2147483647; } elseif ($length < 0) { $length = \iconv_strlen($s, $encoding) + $length - $start; if ($length < 0) { return ''; } } return (string) \iconv_substr($s, $start, $length, $encoding); } public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null) { $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strpos($haystack, $needle, $offset, $encoding); } public static function mb_stristr($haystack, $needle, $part = false, $encoding = null) { $pos = self::mb_stripos($haystack, $needle, 0, $encoding); return self::getSubpart($pos, $part, $haystack, $encoding); } public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null) { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { $pos = strrpos($haystack, $needle); } else { $needle = self::mb_substr($needle, 0, 1, $encoding); $pos = \iconv_strrpos($haystack, $needle, $encoding); } return self::getSubpart($pos, $part, $haystack, $encoding); } public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null) { $needle = self::mb_substr($needle, 0, 1, $encoding); $pos = self::mb_strripos($haystack, $needle, $encoding); return self::getSubpart($pos, $part, $haystack, $encoding); } public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null) { $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding); $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding); return self::mb_strrpos($haystack, $needle, $offset, $encoding); } public static function mb_strstr($haystack, $needle, $part = false, $encoding = null) { $pos = strpos($haystack, $needle); if (false === $pos) { return false; } if ($part) { return substr($haystack, 0, $pos); } return substr($haystack, $pos); } public static function mb_get_info($type = 'all') { $info = [ 'internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)', 'func_overload' => 0, 'func_overload_list' => 'no overload', 'mail_charset' => 'UTF-8', 'mail_header_encoding' => 'BASE64', 'mail_body_encoding' => 'BASE64', 'illegal_chars' => 0, 'encoding_translation' => 'Off', 'language' => self::$language, 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off', ]; if ('all' === $type) { return $info; } if (isset($info[$type])) { return $info[$type]; } return false; } public static function mb_http_input($type = '') { return false; } public static function mb_http_output($encoding = null) { return null !== $encoding ? 'pass' === $encoding : 'pass'; } public static function mb_strwidth($s, $encoding = null) { $encoding = self::getEncoding($encoding); if ('UTF-8' !== $encoding) { $s = \iconv($encoding, 'UTF-8//IGNORE', $s); } $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); return ($wide << 1) + \iconv_strlen($s, 'UTF-8'); } public static function mb_substr_count($haystack, $needle, $encoding = null) { return substr_count($haystack, $needle); } public static function mb_output_handler($contents, $status) { return $contents; } public static function mb_chr($code, $encoding = null) { if (0x80 > $code %= 0x200000) { $s = \chr($code); } elseif (0x800 > $code) { $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); } elseif (0x10000 > $code) { $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } else { $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { $s = mb_convert_encoding($s, $encoding, 'UTF-8'); } return $s; } public static function mb_ord($s, $encoding = null) { if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { $s = mb_convert_encoding($s, 'UTF-8', $encoding); } if (1 === \strlen($s)) { return \ord($s); } $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; if (0xF0 <= $code) { return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; } if (0xE0 <= $code) { return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; } if (0xC0 <= $code) { return (($code - 0xC0) << 6) + $s[2] - 0x80; } return $code; } private static function getSubpart($pos, $part, $haystack, $encoding) { if (false === $pos) { return false; } if ($part) { return self::mb_substr($haystack, 0, $pos, $encoding); } return self::mb_substr($haystack, $pos, null, $encoding); } private static function html_encoding_callback(array $m) { $i = 1; $entities = ''; $m = unpack('C*', htmlentities($m[0], \ENT_COMPAT, 'UTF-8')); while (isset($m[$i])) { if (0x80 > $m[$i]) { $entities .= \chr($m[$i++]); continue; } if (0xF0 <= $m[$i]) { $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; } elseif (0xE0 <= $m[$i]) { $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80; } else { $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80; } $entities .= '&#'.$c.';'; } return $entities; } private static function title_case(array $s) { return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8'); } private static function getData($file) { if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { return require $file; } return false; } private static function getEncoding($encoding) { if (null === $encoding) { return self::$internalEncoding; } if ('UTF-8' === $encoding) { return 'UTF-8'; } $encoding = strtoupper($encoding); if ('8BIT' === $encoding || 'BINARY' === $encoding) { return 'CP850'; } if ('UTF8' === $encoding) { return 'UTF-8'; } return $encoding; } } event-dispatcher/LegacyEventDispatcherProxy.php000064400000001562150432043200015776 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; trigger_deprecation('symfony/event-dispatcher', '5.1', '%s is deprecated, use the event dispatcher without the proxy.', LegacyEventDispatcherProxy::class); /** * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch(). * * @author Nicolas Grekas * * @deprecated since Symfony 5.1 */ final class LegacyEventDispatcherProxy { public static function decorate(?EventDispatcherInterface $dispatcher): ?EventDispatcherInterface { return $dispatcher; } } event-dispatcher/README.md000064400000001127150432043200011262 0ustar00EventDispatcher Component ========================= The EventDispatcher component provides tools that allow your application components to communicate with each other by dispatching events and listening to them. Resources --------- * [Documentation](https://symfony.com/doc/current/components/event_dispatcher.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) event-dispatcher/GenericEvent.php000064400000007414150432043200013077 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; use Symfony\Contracts\EventDispatcher\Event; /** * Event encapsulation class. * * Encapsulates events thus decoupling the observer from the subject they encapsulate. * * @author Drak * * @implements \ArrayAccess * @implements \IteratorAggregate */ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate { protected $subject; protected $arguments; /** * Encapsulate an event with $subject and $args. * * @param mixed $subject The subject of the event, usually an object or a callable * @param array $arguments Arguments to store in the event */ public function __construct($subject = null, array $arguments = []) { $this->subject = $subject; $this->arguments = $arguments; } /** * Getter for subject property. * * @return mixed */ public function getSubject() { return $this->subject; } /** * Get argument by key. * * @return mixed * * @throws \InvalidArgumentException if key is not found */ public function getArgument(string $key) { if ($this->hasArgument($key)) { return $this->arguments[$key]; } throw new \InvalidArgumentException(sprintf('Argument "%s" not found.', $key)); } /** * Add argument to event. * * @param mixed $value Value * * @return $this */ public function setArgument(string $key, $value) { $this->arguments[$key] = $value; return $this; } /** * Getter for all arguments. * * @return array */ public function getArguments() { return $this->arguments; } /** * Set args property. * * @return $this */ public function setArguments(array $args = []) { $this->arguments = $args; return $this; } /** * Has argument. * * @return bool */ public function hasArgument(string $key) { return \array_key_exists($key, $this->arguments); } /** * ArrayAccess for argument getter. * * @param string $key Array key * * @return mixed * * @throws \InvalidArgumentException if key does not exist in $this->args */ #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->getArgument($key); } /** * ArrayAccess for argument setter. * * @param string $key Array key to set * @param mixed $value Value * * @return void */ #[\ReturnTypeWillChange] public function offsetSet($key, $value) { $this->setArgument($key, $value); } /** * ArrayAccess for unset argument. * * @param string $key Array key * * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($key) { if ($this->hasArgument($key)) { unset($this->arguments[$key]); } } /** * ArrayAccess has argument. * * @param string $key Array key * * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($key) { return $this->hasArgument($key); } /** * IteratorAggregate for iterating over the object like an array. * * @return \ArrayIterator */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->arguments); } } event-dispatcher/Attribute/AsEventListener.php000064400000001324150432043200015531 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Attribute; /** * Service tag to autoconfigure event listeners. * * @author Alexander M. Turek */ #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class AsEventListener { public function __construct( public ?string $event = null, public ?string $method = null, public int $priority = 0, public ?string $dispatcher = null, ) { } } event-dispatcher/ImmutableEventDispatcher.php000064400000004265150432043200015452 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * A read-only proxy for an event dispatcher. * * @author Bernhard Schussek */ class ImmutableEventDispatcher implements EventDispatcherInterface { private $dispatcher; public function __construct(EventDispatcherInterface $dispatcher) { $this->dispatcher = $dispatcher; } /** * {@inheritdoc} */ public function dispatch(object $event, string $eventName = null): object { return $this->dispatcher->dispatch($event, $eventName); } /** * {@inheritdoc} */ public function addListener(string $eventName, $listener, int $priority = 0) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeListener(string $eventName, $listener) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } /** * {@inheritdoc} */ public function getListeners(string $eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function getListenerPriority(string $eventName, $listener) { return $this->dispatcher->getListenerPriority($eventName, $listener); } /** * {@inheritdoc} */ public function hasListeners(string $eventName = null) { return $this->dispatcher->hasListeners($eventName); } } event-dispatcher/EventDispatcherInterface.php000064400000004170150432043200015426 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Bernhard Schussek */ interface EventDispatcherInterface extends ContractsEventDispatcherInterface { /** * Adds an event listener that listens on the specified events. * * @param int $priority The higher this value, the earlier an event * listener will be triggered in the chain (defaults to 0) */ public function addListener(string $eventName, callable $listener, int $priority = 0); /** * Adds an event subscriber. * * The subscriber is asked for all the events it is * interested in and added as a listener for these events. */ public function addSubscriber(EventSubscriberInterface $subscriber); /** * Removes an event listener from the specified events. */ public function removeListener(string $eventName, callable $listener); public function removeSubscriber(EventSubscriberInterface $subscriber); /** * Gets the listeners of a specific event or all listeners sorted by descending priority. * * @return array */ public function getListeners(string $eventName = null); /** * Gets the listener priority for a specific event. * * Returns null if the event or the listener does not exist. * * @return int|null */ public function getListenerPriority(string $eventName, callable $listener); /** * Checks whether an event has any registered listeners. * * @return bool */ public function hasListeners(string $eventName = null); } event-dispatcher/DependencyInjection/AddEventAliasesPass.php000064400000002657150432043200020271 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This pass allows bundles to extend the list of event aliases. * * @author Alexander M. Turek */ class AddEventAliasesPass implements CompilerPassInterface { private $eventAliases; private $eventAliasesParameter; public function __construct(array $eventAliases, string $eventAliasesParameter = 'event_dispatcher.event_aliases') { if (1 < \func_num_args()) { trigger_deprecation('symfony/event-dispatcher', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->eventAliases = $eventAliases; $this->eventAliasesParameter = $eventAliasesParameter; } public function process(ContainerBuilder $container): void { $eventAliases = $container->hasParameter($this->eventAliasesParameter) ? $container->getParameter($this->eventAliasesParameter) : []; $container->setParameter( $this->eventAliasesParameter, array_merge($eventAliases, $this->eventAliases) ); } } event-dispatcher/DependencyInjection/RegisterListenersPass.php000064400000022315150432043200020743 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\DependencyInjection; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Contracts\EventDispatcher\Event; /** * Compiler pass to register tagged services for an event dispatcher. */ class RegisterListenersPass implements CompilerPassInterface { protected $dispatcherService; protected $listenerTag; protected $subscriberTag; protected $eventAliasesParameter; private $hotPathEvents = []; private $hotPathTagName = 'container.hot_path'; private $noPreloadEvents = []; private $noPreloadTagName = 'container.no_preload'; public function __construct(string $dispatcherService = 'event_dispatcher', string $listenerTag = 'kernel.event_listener', string $subscriberTag = 'kernel.event_subscriber', string $eventAliasesParameter = 'event_dispatcher.event_aliases') { if (0 < \func_num_args()) { trigger_deprecation('symfony/event-dispatcher', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->dispatcherService = $dispatcherService; $this->listenerTag = $listenerTag; $this->subscriberTag = $subscriberTag; $this->eventAliasesParameter = $eventAliasesParameter; } /** * @return $this */ public function setHotPathEvents(array $hotPathEvents) { $this->hotPathEvents = array_flip($hotPathEvents); if (1 < \func_num_args()) { trigger_deprecation('symfony/event-dispatcher', '5.4', 'Configuring "$tagName" in "%s" is deprecated.', __METHOD__); $this->hotPathTagName = func_get_arg(1); } return $this; } /** * @return $this */ public function setNoPreloadEvents(array $noPreloadEvents): self { $this->noPreloadEvents = array_flip($noPreloadEvents); if (1 < \func_num_args()) { trigger_deprecation('symfony/event-dispatcher', '5.4', 'Configuring "$tagName" in "%s" is deprecated.', __METHOD__); $this->noPreloadTagName = func_get_arg(1); } return $this; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) { return; } $aliases = []; if ($container->hasParameter($this->eventAliasesParameter)) { $aliases = $container->getParameter($this->eventAliasesParameter); } $globalDispatcherDefinition = $container->findDefinition($this->dispatcherService); foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { $noPreload = 0; foreach ($events as $event) { $priority = $event['priority'] ?? 0; if (!isset($event['event'])) { if ($container->getDefinition($id)->hasTag($this->subscriberTag)) { continue; } $event['method'] = $event['method'] ?? '__invoke'; $event['event'] = $this->getEventFromTypeDeclaration($container, $id, $event['method']); } $event['event'] = $aliases[$event['event']] ?? $event['event']; if (!isset($event['method'])) { $event['method'] = 'on'.preg_replace_callback([ '/(?<=\b|_)[a-z]/i', '/[^a-z0-9]/i', ], function ($matches) { return strtoupper($matches[0]); }, $event['event']); $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) { $event['method'] = '__invoke'; } } $dispatcherDefinition = $globalDispatcherDefinition; if (isset($event['dispatcher'])) { $dispatcherDefinition = $container->getDefinition($event['dispatcher']); } $dispatcherDefinition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); if (isset($this->hotPathEvents[$event['event']])) { $container->getDefinition($id)->addTag($this->hotPathTagName); } elseif (isset($this->noPreloadEvents[$event['event']])) { ++$noPreload; } } if ($noPreload && \count($events) === $noPreload) { $container->getDefinition($id)->addTag($this->noPreloadTagName); } } $extractingDispatcher = new ExtractingEventDispatcher(); foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $tags) { $def = $container->getDefinition($id); // We must assume that the class value has been correctly filled, even if the service is created by a factory $class = $def->getClass(); if (!$r = $container->getReflectionClass($class)) { throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } if (!$r->isSubclassOf(EventSubscriberInterface::class)) { throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class)); } $class = $r->name; $dispatcherDefinitions = []; foreach ($tags as $attributes) { if (!isset($attributes['dispatcher']) || isset($dispatcherDefinitions[$attributes['dispatcher']])) { continue; } $dispatcherDefinitions[$attributes['dispatcher']] = $container->getDefinition($attributes['dispatcher']); } if (!$dispatcherDefinitions) { $dispatcherDefinitions = [$globalDispatcherDefinition]; } $noPreload = 0; ExtractingEventDispatcher::$aliases = $aliases; ExtractingEventDispatcher::$subscriber = $class; $extractingDispatcher->addSubscriber($extractingDispatcher); foreach ($extractingDispatcher->listeners as $args) { $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]]; foreach ($dispatcherDefinitions as $dispatcherDefinition) { $dispatcherDefinition->addMethodCall('addListener', $args); } if (isset($this->hotPathEvents[$args[0]])) { $container->getDefinition($id)->addTag($this->hotPathTagName); } elseif (isset($this->noPreloadEvents[$args[0]])) { ++$noPreload; } } if ($noPreload && \count($extractingDispatcher->listeners) === $noPreload) { $container->getDefinition($id)->addTag($this->noPreloadTagName); } $extractingDispatcher->listeners = []; ExtractingEventDispatcher::$aliases = []; } } private function getEventFromTypeDeclaration(ContainerBuilder $container, string $id, string $method): string { if ( null === ($class = $container->getDefinition($id)->getClass()) || !($r = $container->getReflectionClass($class, false)) || !$r->hasMethod($method) || 1 > ($m = $r->getMethod($method))->getNumberOfParameters() || !($type = $m->getParameters()[0]->getType()) instanceof \ReflectionNamedType || $type->isBuiltin() || Event::class === ($name = $type->getName()) ) { throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); } return $name; } } /** * @internal */ class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface { public $listeners = []; public static $aliases = []; public static $subscriber; public function addListener(string $eventName, $listener, int $priority = 0) { $this->listeners[] = [$eventName, $listener[1], $priority]; } public static function getSubscribedEvents(): array { $events = []; foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) { $events[self::$aliases[$eventName] ?? $eventName] = $params; } return $events; } } event-dispatcher/CHANGELOG.md000064400000005454150432043200011623 0ustar00CHANGELOG ========= 5.4 --- * Allow `#[AsEventListener]` attribute on methods 5.3 --- * Add `#[AsEventListener]` attribute for declaring listeners on PHP 8 5.1.0 ----- * The `LegacyEventDispatcherProxy` class has been deprecated. * Added an optional `dispatcher` attribute to the listener and subscriber tags in `RegisterListenerPass`. 5.0.0 ----- * The signature of the `EventDispatcherInterface::dispatch()` method has been changed to `dispatch($event, string $eventName = null): object`. * The `Event` class has been removed in favor of `Symfony\Contracts\EventDispatcher\Event`. * The `TraceableEventDispatcherInterface` has been removed. * The `WrappedListener` class is now final. 4.4.0 ----- * `AddEventAliasesPass` has been added, allowing applications and bundles to extend the event alias mapping used by `RegisterListenersPass`. * Made the `event` attribute of the `kernel.event_listener` tag optional for FQCN events. 4.3.0 ----- * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated * deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead 4.1.0 ----- * added support for invokable event listeners tagged with `kernel.event_listener` by default * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added. * The `TraceableEventDispatcherInterface` has been deprecated. 4.0.0 ----- * removed the `ContainerAwareEventDispatcher` class * added the `reset()` method to the `TraceableEventDispatcherInterface` 3.4.0 ----- * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. 3.3.0 ----- * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. 3.0.0 ----- * The method `getListenerPriority($eventName, $listener)` has been added to the `EventDispatcherInterface`. * The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()` and `Event::getName()` have been removed. The event dispatcher and the event name are passed to the listener call. 2.5.0 ----- * added Debug\TraceableEventDispatcher (originally in HttpKernel) * changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface * added RegisterListenersPass (originally in HttpKernel) 2.1.0 ----- * added TraceableEventDispatcherInterface * added ContainerAwareEventDispatcher * added a reference to the EventDispatcher on the Event * added a reference to the Event name on the event * added fluid interface to the dispatch() method which now returns the Event object * added GenericEvent event class * added the possibility for subscribers to subscribe several times for the same event * added ImmutableEventDispatcher event-dispatcher/EventSubscriberInterface.php000064400000003344150432043200015445 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; /** * An EventSubscriber knows itself what events it is interested in. * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek */ interface EventSubscriberInterface { /** * Returns an array of event names this subscriber wants to listen to. * * The array keys are event names and the value can be: * * * The method name to call (priority defaults to 0) * * An array composed of the method name to call and the priority * * An array of arrays composed of the method names to call and respective * priorities, or 0 if unset * * For instance: * * * ['eventName' => 'methodName'] * * ['eventName' => ['methodName', $priority]] * * ['eventName' => [['methodName1', $priority], ['methodName2']]] * * The code must not depend on runtime state as it will only be called at compile time. * All logic depending on runtime state must be put into the individual methods handling the events. * * @return array> */ public static function getSubscribedEvents(); } event-dispatcher/composer.json000064400000003176150432043200012533 0ustar00{ "name": "symfony/event-dispatcher", "type": "library", "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/event-dispatcher-contracts": "^2|^3", "symfony/polyfill-php80": "^1.16" }, "require-dev": { "symfony/dependency-injection": "^4.4|^5.0|^6.0", "symfony/expression-language": "^4.4|^5.0|^6.0", "symfony/config": "^4.4|^5.0|^6.0", "symfony/error-handler": "^4.4|^5.0|^6.0", "symfony/http-foundation": "^4.4|^5.0|^6.0", "symfony/service-contracts": "^1.1|^2|^3", "symfony/stopwatch": "^4.4|^5.0|^6.0", "psr/log": "^1|^2|^3" }, "conflict": { "symfony/dependency-injection": "<4.4" }, "provide": { "psr/event-dispatcher-implementation": "1.0", "symfony/event-dispatcher-implementation": "2.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } event-dispatcher/EventDispatcher.php000064400000021603150432043200013605 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher; use Psr\EventDispatcher\StoppableEventInterface; use Symfony\Component\EventDispatcher\Debug\WrappedListener; /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * * Listeners are registered on the manager and events are dispatched through the * manager. * * @author Guilherme Blanco * @author Jonathan Wage * @author Roman Borschel * @author Bernhard Schussek * @author Fabien Potencier * @author Jordi Boggiano * @author Jordan Alliot * @author Nicolas Grekas */ class EventDispatcher implements EventDispatcherInterface { private $listeners = []; private $sorted = []; private $optimized; public function __construct() { if (__CLASS__ === static::class) { $this->optimized = []; } } /** * {@inheritdoc} */ public function dispatch(object $event, string $eventName = null): object { $eventName = $eventName ?? \get_class($event); if (null !== $this->optimized) { $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName)); } else { $listeners = $this->getListeners($eventName); } if ($listeners) { $this->callListeners($listeners, $eventName, $event); } return $event; } /** * {@inheritdoc} */ public function getListeners(string $eventName = null) { if (null !== $eventName) { if (empty($this->listeners[$eventName])) { return []; } if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } return $this->sorted[$eventName]; } foreach ($this->listeners as $eventName => $eventListeners) { if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } } return array_filter($this->sorted); } /** * {@inheritdoc} */ public function getListenerPriority(string $eventName, $listener) { if (empty($this->listeners[$eventName])) { return null; } if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { $listener[0] = $listener[0](); $listener[1] = $listener[1] ?? '__invoke'; } foreach ($this->listeners[$eventName] as $priority => &$listeners) { foreach ($listeners as &$v) { if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { $v[0] = $v[0](); $v[1] = $v[1] ?? '__invoke'; } if ($v === $listener) { return $priority; } } } return null; } /** * {@inheritdoc} */ public function hasListeners(string $eventName = null) { if (null !== $eventName) { return !empty($this->listeners[$eventName]); } foreach ($this->listeners as $eventListeners) { if ($eventListeners) { return true; } } return false; } /** * {@inheritdoc} */ public function addListener(string $eventName, $listener, int $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; unset($this->sorted[$eventName], $this->optimized[$eventName]); } /** * {@inheritdoc} */ public function removeListener(string $eventName, $listener) { if (empty($this->listeners[$eventName])) { return; } if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { $listener[0] = $listener[0](); $listener[1] = $listener[1] ?? '__invoke'; } foreach ($this->listeners[$eventName] as $priority => &$listeners) { foreach ($listeners as $k => &$v) { if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure && 2 >= \count($v)) { $v[0] = $v[0](); $v[1] = $v[1] ?? '__invoke'; } if ($v === $listener) { unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]); } } if (!$listeners) { unset($this->listeners[$eventName][$priority]); } } } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (\is_string($params)) { $this->addListener($eventName, [$subscriber, $params]); } elseif (\is_string($params[0])) { $this->addListener($eventName, [$subscriber, $params[0]], $params[1] ?? 0); } else { foreach ($params as $listener) { $this->addListener($eventName, [$subscriber, $listener[0]], $listener[1] ?? 0); } } } } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { if (\is_array($params) && \is_array($params[0])) { foreach ($params as $listener) { $this->removeListener($eventName, [$subscriber, $listener[0]]); } } else { $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]); } } } /** * Triggers the listeners of an event. * * This method can be overridden to add functionality that is executed * for each listener. * * @param callable[] $listeners The event listeners * @param string $eventName The name of the event to dispatch * @param object $event The event object to pass to the event handlers/listeners */ protected function callListeners(iterable $listeners, string $eventName, object $event) { $stoppable = $event instanceof StoppableEventInterface; foreach ($listeners as $listener) { if ($stoppable && $event->isPropagationStopped()) { break; } $listener($event, $eventName, $this); } } /** * Sorts the internal list of listeners for the given event by priority. */ private function sortListeners(string $eventName) { krsort($this->listeners[$eventName]); $this->sorted[$eventName] = []; foreach ($this->listeners[$eventName] as &$listeners) { foreach ($listeners as $k => &$listener) { if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { $listener[0] = $listener[0](); $listener[1] = $listener[1] ?? '__invoke'; } $this->sorted[$eventName][] = $listener; } } } /** * Optimizes the internal list of listeners for the given event by priority. */ private function optimizeListeners(string $eventName): array { krsort($this->listeners[$eventName]); $this->optimized[$eventName] = []; foreach ($this->listeners[$eventName] as &$listeners) { foreach ($listeners as &$listener) { $closure = &$this->optimized[$eventName][]; if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure && 2 >= \count($listener)) { $closure = static function (...$args) use (&$listener, &$closure) { if ($listener[0] instanceof \Closure) { $listener[0] = $listener[0](); $listener[1] = $listener[1] ?? '__invoke'; } ($closure = \Closure::fromCallable($listener))(...$args); }; } else { $closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener); } } } return $this->optimized[$eventName]; } } event-dispatcher/LICENSE000064400000002051150432043200011005 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. event-dispatcher/Debug/WrappedListener.php000064400000007637150432043200014666 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Debug; use Psr\EventDispatcher\StoppableEventInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\VarDumper\Caster\ClassStub; /** * @author Fabien Potencier */ final class WrappedListener { private $listener; private $optimizedListener; private $name; private $called; private $stoppedPropagation; private $stopwatch; private $dispatcher; private $pretty; private $stub; private $priority; private static $hasClassStub; public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { $this->listener = $listener; $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null); $this->stopwatch = $stopwatch; $this->dispatcher = $dispatcher; $this->called = false; $this->stoppedPropagation = false; if (\is_array($listener)) { $this->name = \is_object($listener[0]) ? get_debug_type($listener[0]) : $listener[0]; $this->pretty = $this->name.'::'.$listener[1]; } elseif ($listener instanceof \Closure) { $r = new \ReflectionFunction($listener); if (str_contains($r->name, '{closure}')) { $this->pretty = $this->name = 'closure'; } elseif ($class = $r->getClosureScopeClass()) { $this->name = $class->name; $this->pretty = $this->name.'::'.$r->name; } else { $this->pretty = $this->name = $r->name; } } elseif (\is_string($listener)) { $this->pretty = $this->name = $listener; } else { $this->name = get_debug_type($listener); $this->pretty = $this->name.'::__invoke'; } if (null !== $name) { $this->name = $name; } if (null === self::$hasClassStub) { self::$hasClassStub = class_exists(ClassStub::class); } } public function getWrappedListener() { return $this->listener; } public function wasCalled(): bool { return $this->called; } public function stoppedPropagation(): bool { return $this->stoppedPropagation; } public function getPretty(): string { return $this->pretty; } public function getInfo(string $eventName): array { if (null === $this->stub) { $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; } return [ 'event' => $eventName, 'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null), 'pretty' => $this->pretty, 'stub' => $this->stub, ]; } public function __invoke(object $event, string $eventName, EventDispatcherInterface $dispatcher): void { $dispatcher = $this->dispatcher ?: $dispatcher; $this->called = true; $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener); $e = $this->stopwatch->start($this->name, 'event_listener'); ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); if ($e->isStarted()) { $e->stop(); } if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) { $this->stoppedPropagation = true; } } } event-dispatcher/Debug/TraceableEventDispatcher.php000064400000026357150432043200016451 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\EventDispatcher\Debug; use Psr\EventDispatcher\StoppableEventInterface; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Contracts\Service\ResetInterface; /** * Collects some data about event listeners. * * This event dispatcher delegates the dispatching to another one. * * @author Fabien Potencier */ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterface { protected $logger; protected $stopwatch; /** * @var \SplObjectStorage */ private $callStack; private $dispatcher; private $wrappedListeners; private $orphanedEvents; private $requestStack; private $currentRequestHash = ''; public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) { $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; $this->logger = $logger; $this->wrappedListeners = []; $this->orphanedEvents = []; $this->requestStack = $requestStack; } /** * {@inheritdoc} */ public function addListener(string $eventName, $listener, int $priority = 0) { $this->dispatcher->addListener($eventName, $listener, $priority); } /** * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { $this->dispatcher->addSubscriber($subscriber); } /** * {@inheritdoc} */ public function removeListener(string $eventName, $listener) { if (isset($this->wrappedListeners[$eventName])) { foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { if ($wrappedListener->getWrappedListener() === $listener) { $listener = $wrappedListener; unset($this->wrappedListeners[$eventName][$index]); break; } } } return $this->dispatcher->removeListener($eventName, $listener); } /** * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { return $this->dispatcher->removeSubscriber($subscriber); } /** * {@inheritdoc} */ public function getListeners(string $eventName = null) { return $this->dispatcher->getListeners($eventName); } /** * {@inheritdoc} */ public function getListenerPriority(string $eventName, $listener) { // we might have wrapped listeners for the event (if called while dispatching) // in that case get the priority by wrapper if (isset($this->wrappedListeners[$eventName])) { foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) { if ($wrappedListener->getWrappedListener() === $listener) { return $this->dispatcher->getListenerPriority($eventName, $wrappedListener); } } } return $this->dispatcher->getListenerPriority($eventName, $listener); } /** * {@inheritdoc} */ public function hasListeners(string $eventName = null) { return $this->dispatcher->hasListeners($eventName); } /** * {@inheritdoc} */ public function dispatch(object $event, string $eventName = null): object { $eventName = $eventName ?? \get_class($event); if (null === $this->callStack) { $this->callStack = new \SplObjectStorage(); } $currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : ''; if (null !== $this->logger && $event instanceof StoppableEventInterface && $event->isPropagationStopped()) { $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName)); } $this->preProcess($eventName); try { $this->beforeDispatch($eventName, $event); try { $e = $this->stopwatch->start($eventName, 'section'); try { $this->dispatcher->dispatch($event, $eventName); } finally { if ($e->isStarted()) { $e->stop(); } } } finally { $this->afterDispatch($eventName, $event); } } finally { $this->currentRequestHash = $currentRequestHash; $this->postProcess($eventName); } return $event; } /** * @return array */ public function getCalledListeners(Request $request = null) { if (null === $this->callStack) { return []; } $hash = $request ? spl_object_hash($request) : null; $called = []; foreach ($this->callStack as $listener) { [$eventName, $requestHash] = $this->callStack->getInfo(); if (null === $hash || $hash === $requestHash) { $called[] = $listener->getInfo($eventName); } } return $called; } /** * @return array */ public function getNotCalledListeners(Request $request = null) { try { $allListeners = $this->getListeners(); } catch (\Exception $e) { if (null !== $this->logger) { $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]); } // unable to retrieve the uncalled listeners return []; } $hash = $request ? spl_object_hash($request) : null; $calledListeners = []; if (null !== $this->callStack) { foreach ($this->callStack as $calledListener) { [, $requestHash] = $this->callStack->getInfo(); if (null === $hash || $hash === $requestHash) { $calledListeners[] = $calledListener->getWrappedListener(); } } } $notCalled = []; foreach ($allListeners as $eventName => $listeners) { foreach ($listeners as $listener) { if (!\in_array($listener, $calledListeners, true)) { if (!$listener instanceof WrappedListener) { $listener = new WrappedListener($listener, null, $this->stopwatch, $this); } $notCalled[] = $listener->getInfo($eventName); } } } uasort($notCalled, [$this, 'sortNotCalledListeners']); return $notCalled; } public function getOrphanedEvents(Request $request = null): array { if ($request) { return $this->orphanedEvents[spl_object_hash($request)] ?? []; } if (!$this->orphanedEvents) { return []; } return array_merge(...array_values($this->orphanedEvents)); } public function reset() { $this->callStack = null; $this->orphanedEvents = []; $this->currentRequestHash = ''; } /** * Proxies all method calls to the original event dispatcher. * * @param string $method The method name * @param array $arguments The method arguments * * @return mixed */ public function __call(string $method, array $arguments) { return $this->dispatcher->{$method}(...$arguments); } /** * Called before dispatching the event. */ protected function beforeDispatch(string $eventName, object $event) { } /** * Called after dispatching the event. */ protected function afterDispatch(string $eventName, object $event) { } private function preProcess(string $eventName): void { if (!$this->dispatcher->hasListeners($eventName)) { $this->orphanedEvents[$this->currentRequestHash][] = $eventName; return; } foreach ($this->dispatcher->getListeners($eventName) as $listener) { $priority = $this->getListenerPriority($eventName, $listener); $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this); $this->wrappedListeners[$eventName][] = $wrappedListener; $this->dispatcher->removeListener($eventName, $listener); $this->dispatcher->addListener($eventName, $wrappedListener, $priority); $this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]); } } private function postProcess(string $eventName): void { unset($this->wrappedListeners[$eventName]); $skipped = false; foreach ($this->dispatcher->getListeners($eventName) as $listener) { if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch. continue; } // Unwrap listener $priority = $this->getListenerPriority($eventName, $listener); $this->dispatcher->removeListener($eventName, $listener); $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority); if (null !== $this->logger) { $context = ['event' => $eventName, 'listener' => $listener->getPretty()]; } if ($listener->wasCalled()) { if (null !== $this->logger) { $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context); } } else { $this->callStack->detach($listener); } if (null !== $this->logger && $skipped) { $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context); } if ($listener->stoppedPropagation()) { if (null !== $this->logger) { $this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context); } $skipped = true; } } } private function sortNotCalledListeners(array $a, array $b) { if (0 !== $cmp = strcmp($a['event'], $b['event'])) { return $cmp; } if (\is_int($a['priority']) && !\is_int($b['priority'])) { return 1; } if (!\is_int($a['priority']) && \is_int($b['priority'])) { return -1; } if ($a['priority'] === $b['priority']) { return 0; } if ($a['priority'] > $b['priority']) { return -1; } return 1; } } polyfill-intl-normalizer/Resources/stubs/Normalizer.php000064400000000624150432043200017462 0ustar00 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'ÿ' => 'ÿ', 'Ā' => 'Ā', 'ā' => 'ā', 'Ă' => 'Ă', 'ă' => 'ă', 'Ą' => 'Ą', 'ą' => 'ą', 'Ć' => 'Ć', 'ć' => 'ć', 'Ĉ' => 'Ĉ', 'ĉ' => 'ĉ', 'Ċ' => 'Ċ', 'ċ' => 'ċ', 'Č' => 'Č', 'č' => 'č', 'Ď' => 'Ď', 'ď' => 'ď', 'Ē' => 'Ē', 'ē' => 'ē', 'Ĕ' => 'Ĕ', 'ĕ' => 'ĕ', 'Ė' => 'Ė', 'ė' => 'ė', 'Ę' => 'Ę', 'ę' => 'ę', 'Ě' => 'Ě', 'ě' => 'ě', 'Ĝ' => 'Ĝ', 'ĝ' => 'ĝ', 'Ğ' => 'Ğ', 'ğ' => 'ğ', 'Ġ' => 'Ġ', 'ġ' => 'ġ', 'Ģ' => 'Ģ', 'ģ' => 'ģ', 'Ĥ' => 'Ĥ', 'ĥ' => 'ĥ', 'Ĩ' => 'Ĩ', 'ĩ' => 'ĩ', 'Ī' => 'Ī', 'ī' => 'ī', 'Ĭ' => 'Ĭ', 'ĭ' => 'ĭ', 'Į' => 'Į', 'į' => 'į', 'İ' => 'İ', 'Ĵ' => 'Ĵ', 'ĵ' => 'ĵ', 'Ķ' => 'Ķ', 'ķ' => 'ķ', 'Ĺ' => 'Ĺ', 'ĺ' => 'ĺ', 'Ļ' => 'Ļ', 'ļ' => 'ļ', 'Ľ' => 'Ľ', 'ľ' => 'ľ', 'Ń' => 'Ń', 'ń' => 'ń', 'Ņ' => 'Ņ', 'ņ' => 'ņ', 'Ň' => 'Ň', 'ň' => 'ň', 'Ō' => 'Ō', 'ō' => 'ō', 'Ŏ' => 'Ŏ', 'ŏ' => 'ŏ', 'Ő' => 'Ő', 'ő' => 'ő', 'Ŕ' => 'Ŕ', 'ŕ' => 'ŕ', 'Ŗ' => 'Ŗ', 'ŗ' => 'ŗ', 'Ř' => 'Ř', 'ř' => 'ř', 'Ś' => 'Ś', 'ś' => 'ś', 'Ŝ' => 'Ŝ', 'ŝ' => 'ŝ', 'Ş' => 'Ş', 'ş' => 'ş', 'Š' => 'Š', 'š' => 'š', 'Ţ' => 'Ţ', 'ţ' => 'ţ', 'Ť' => 'Ť', 'ť' => 'ť', 'Ũ' => 'Ũ', 'ũ' => 'ũ', 'Ū' => 'Ū', 'ū' => 'ū', 'Ŭ' => 'Ŭ', 'ŭ' => 'ŭ', 'Ů' => 'Ů', 'ů' => 'ů', 'Ű' => 'Ű', 'ű' => 'ű', 'Ų' => 'Ų', 'ų' => 'ų', 'Ŵ' => 'Ŵ', 'ŵ' => 'ŵ', 'Ŷ' => 'Ŷ', 'ŷ' => 'ŷ', 'Ÿ' => 'Ÿ', 'Ź' => 'Ź', 'ź' => 'ź', 'Ż' => 'Ż', 'ż' => 'ż', 'Ž' => 'Ž', 'ž' => 'ž', 'Ơ' => 'Ơ', 'ơ' => 'ơ', 'Ư' => 'Ư', 'ư' => 'ư', 'Ǎ' => 'Ǎ', 'ǎ' => 'ǎ', 'Ǐ' => 'Ǐ', 'ǐ' => 'ǐ', 'Ǒ' => 'Ǒ', 'ǒ' => 'ǒ', 'Ǔ' => 'Ǔ', 'ǔ' => 'ǔ', 'Ǖ' => 'Ǖ', 'ǖ' => 'ǖ', 'Ǘ' => 'Ǘ', 'ǘ' => 'ǘ', 'Ǚ' => 'Ǚ', 'ǚ' => 'ǚ', 'Ǜ' => 'Ǜ', 'ǜ' => 'ǜ', 'Ǟ' => 'Ǟ', 'ǟ' => 'ǟ', 'Ǡ' => 'Ǡ', 'ǡ' => 'ǡ', 'Ǣ' => 'Ǣ', 'ǣ' => 'ǣ', 'Ǧ' => 'Ǧ', 'ǧ' => 'ǧ', 'Ǩ' => 'Ǩ', 'ǩ' => 'ǩ', 'Ǫ' => 'Ǫ', 'ǫ' => 'ǫ', 'Ǭ' => 'Ǭ', 'ǭ' => 'ǭ', 'Ǯ' => 'Ǯ', 'ǯ' => 'ǯ', 'ǰ' => 'ǰ', 'Ǵ' => 'Ǵ', 'ǵ' => 'ǵ', 'Ǹ' => 'Ǹ', 'ǹ' => 'ǹ', 'Ǻ' => 'Ǻ', 'ǻ' => 'ǻ', 'Ǽ' => 'Ǽ', 'ǽ' => 'ǽ', 'Ǿ' => 'Ǿ', 'ǿ' => 'ǿ', 'Ȁ' => 'Ȁ', 'ȁ' => 'ȁ', 'Ȃ' => 'Ȃ', 'ȃ' => 'ȃ', 'Ȅ' => 'Ȅ', 'ȅ' => 'ȅ', 'Ȇ' => 'Ȇ', 'ȇ' => 'ȇ', 'Ȉ' => 'Ȉ', 'ȉ' => 'ȉ', 'Ȋ' => 'Ȋ', 'ȋ' => 'ȋ', 'Ȍ' => 'Ȍ', 'ȍ' => 'ȍ', 'Ȏ' => 'Ȏ', 'ȏ' => 'ȏ', 'Ȑ' => 'Ȑ', 'ȑ' => 'ȑ', 'Ȓ' => 'Ȓ', 'ȓ' => 'ȓ', 'Ȕ' => 'Ȕ', 'ȕ' => 'ȕ', 'Ȗ' => 'Ȗ', 'ȗ' => 'ȗ', 'Ș' => 'Ș', 'ș' => 'ș', 'Ț' => 'Ț', 'ț' => 'ț', 'Ȟ' => 'Ȟ', 'ȟ' => 'ȟ', 'Ȧ' => 'Ȧ', 'ȧ' => 'ȧ', 'Ȩ' => 'Ȩ', 'ȩ' => 'ȩ', 'Ȫ' => 'Ȫ', 'ȫ' => 'ȫ', 'Ȭ' => 'Ȭ', 'ȭ' => 'ȭ', 'Ȯ' => 'Ȯ', 'ȯ' => 'ȯ', 'Ȱ' => 'Ȱ', 'ȱ' => 'ȱ', 'Ȳ' => 'Ȳ', 'ȳ' => 'ȳ', '΅' => '΅', 'Ά' => 'Ά', 'Έ' => 'Έ', 'Ή' => 'Ή', 'Ί' => 'Ί', 'Ό' => 'Ό', 'Ύ' => 'Ύ', 'Ώ' => 'Ώ', 'ΐ' => 'ΐ', 'Ϊ' => 'Ϊ', 'Ϋ' => 'Ϋ', 'ά' => 'ά', 'έ' => 'έ', 'ή' => 'ή', 'ί' => 'ί', 'ΰ' => 'ΰ', 'ϊ' => 'ϊ', 'ϋ' => 'ϋ', 'ό' => 'ό', 'ύ' => 'ύ', 'ώ' => 'ώ', 'ϓ' => 'ϓ', 'ϔ' => 'ϔ', 'Ѐ' => 'Ѐ', 'Ё' => 'Ё', 'Ѓ' => 'Ѓ', 'Ї' => 'Ї', 'Ќ' => 'Ќ', 'Ѝ' => 'Ѝ', 'Ў' => 'Ў', 'Й' => 'Й', 'й' => 'й', 'ѐ' => 'ѐ', 'ё' => 'ё', 'ѓ' => 'ѓ', 'ї' => 'ї', 'ќ' => 'ќ', 'ѝ' => 'ѝ', 'ў' => 'ў', 'Ѷ' => 'Ѷ', 'ѷ' => 'ѷ', 'Ӂ' => 'Ӂ', 'ӂ' => 'ӂ', 'Ӑ' => 'Ӑ', 'ӑ' => 'ӑ', 'Ӓ' => 'Ӓ', 'ӓ' => 'ӓ', 'Ӗ' => 'Ӗ', 'ӗ' => 'ӗ', 'Ӛ' => 'Ӛ', 'ӛ' => 'ӛ', 'Ӝ' => 'Ӝ', 'ӝ' => 'ӝ', 'Ӟ' => 'Ӟ', 'ӟ' => 'ӟ', 'Ӣ' => 'Ӣ', 'ӣ' => 'ӣ', 'Ӥ' => 'Ӥ', 'ӥ' => 'ӥ', 'Ӧ' => 'Ӧ', 'ӧ' => 'ӧ', 'Ӫ' => 'Ӫ', 'ӫ' => 'ӫ', 'Ӭ' => 'Ӭ', 'ӭ' => 'ӭ', 'Ӯ' => 'Ӯ', 'ӯ' => 'ӯ', 'Ӱ' => 'Ӱ', 'ӱ' => 'ӱ', 'Ӳ' => 'Ӳ', 'ӳ' => 'ӳ', 'Ӵ' => 'Ӵ', 'ӵ' => 'ӵ', 'Ӹ' => 'Ӹ', 'ӹ' => 'ӹ', 'آ' => 'آ', 'أ' => 'أ', 'ؤ' => 'ؤ', 'إ' => 'إ', 'ئ' => 'ئ', 'ۀ' => 'ۀ', 'ۂ' => 'ۂ', 'ۓ' => 'ۓ', 'ऩ' => 'ऩ', 'ऱ' => 'ऱ', 'ऴ' => 'ऴ', 'ো' => 'ো', 'ৌ' => 'ৌ', 'ୈ' => 'ୈ', 'ୋ' => 'ୋ', 'ୌ' => 'ୌ', 'ஔ' => 'ஔ', 'ொ' => 'ொ', 'ோ' => 'ோ', 'ௌ' => 'ௌ', 'ై' => 'ై', 'ೀ' => 'ೀ', 'ೇ' => 'ೇ', 'ೈ' => 'ೈ', 'ೊ' => 'ೊ', 'ೋ' => 'ೋ', 'ൊ' => 'ൊ', 'ോ' => 'ോ', 'ൌ' => 'ൌ', 'ේ' => 'ේ', 'ො' => 'ො', 'ෝ' => 'ෝ', 'ෞ' => 'ෞ', 'ဦ' => 'ဦ', 'ᬆ' => 'ᬆ', 'ᬈ' => 'ᬈ', 'ᬊ' => 'ᬊ', 'ᬌ' => 'ᬌ', 'ᬎ' => 'ᬎ', 'ᬒ' => 'ᬒ', 'ᬻ' => 'ᬻ', 'ᬽ' => 'ᬽ', 'ᭀ' => 'ᭀ', 'ᭁ' => 'ᭁ', 'ᭃ' => 'ᭃ', 'Ḁ' => 'Ḁ', 'ḁ' => 'ḁ', 'Ḃ' => 'Ḃ', 'ḃ' => 'ḃ', 'Ḅ' => 'Ḅ', 'ḅ' => 'ḅ', 'Ḇ' => 'Ḇ', 'ḇ' => 'ḇ', 'Ḉ' => 'Ḉ', 'ḉ' => 'ḉ', 'Ḋ' => 'Ḋ', 'ḋ' => 'ḋ', 'Ḍ' => 'Ḍ', 'ḍ' => 'ḍ', 'Ḏ' => 'Ḏ', 'ḏ' => 'ḏ', 'Ḑ' => 'Ḑ', 'ḑ' => 'ḑ', 'Ḓ' => 'Ḓ', 'ḓ' => 'ḓ', 'Ḕ' => 'Ḕ', 'ḕ' => 'ḕ', 'Ḗ' => 'Ḗ', 'ḗ' => 'ḗ', 'Ḙ' => 'Ḙ', 'ḙ' => 'ḙ', 'Ḛ' => 'Ḛ', 'ḛ' => 'ḛ', 'Ḝ' => 'Ḝ', 'ḝ' => 'ḝ', 'Ḟ' => 'Ḟ', 'ḟ' => 'ḟ', 'Ḡ' => 'Ḡ', 'ḡ' => 'ḡ', 'Ḣ' => 'Ḣ', 'ḣ' => 'ḣ', 'Ḥ' => 'Ḥ', 'ḥ' => 'ḥ', 'Ḧ' => 'Ḧ', 'ḧ' => 'ḧ', 'Ḩ' => 'Ḩ', 'ḩ' => 'ḩ', 'Ḫ' => 'Ḫ', 'ḫ' => 'ḫ', 'Ḭ' => 'Ḭ', 'ḭ' => 'ḭ', 'Ḯ' => 'Ḯ', 'ḯ' => 'ḯ', 'Ḱ' => 'Ḱ', 'ḱ' => 'ḱ', 'Ḳ' => 'Ḳ', 'ḳ' => 'ḳ', 'Ḵ' => 'Ḵ', 'ḵ' => 'ḵ', 'Ḷ' => 'Ḷ', 'ḷ' => 'ḷ', 'Ḹ' => 'Ḹ', 'ḹ' => 'ḹ', 'Ḻ' => 'Ḻ', 'ḻ' => 'ḻ', 'Ḽ' => 'Ḽ', 'ḽ' => 'ḽ', 'Ḿ' => 'Ḿ', 'ḿ' => 'ḿ', 'Ṁ' => 'Ṁ', 'ṁ' => 'ṁ', 'Ṃ' => 'Ṃ', 'ṃ' => 'ṃ', 'Ṅ' => 'Ṅ', 'ṅ' => 'ṅ', 'Ṇ' => 'Ṇ', 'ṇ' => 'ṇ', 'Ṉ' => 'Ṉ', 'ṉ' => 'ṉ', 'Ṋ' => 'Ṋ', 'ṋ' => 'ṋ', 'Ṍ' => 'Ṍ', 'ṍ' => 'ṍ', 'Ṏ' => 'Ṏ', 'ṏ' => 'ṏ', 'Ṑ' => 'Ṑ', 'ṑ' => 'ṑ', 'Ṓ' => 'Ṓ', 'ṓ' => 'ṓ', 'Ṕ' => 'Ṕ', 'ṕ' => 'ṕ', 'Ṗ' => 'Ṗ', 'ṗ' => 'ṗ', 'Ṙ' => 'Ṙ', 'ṙ' => 'ṙ', 'Ṛ' => 'Ṛ', 'ṛ' => 'ṛ', 'Ṝ' => 'Ṝ', 'ṝ' => 'ṝ', 'Ṟ' => 'Ṟ', 'ṟ' => 'ṟ', 'Ṡ' => 'Ṡ', 'ṡ' => 'ṡ', 'Ṣ' => 'Ṣ', 'ṣ' => 'ṣ', 'Ṥ' => 'Ṥ', 'ṥ' => 'ṥ', 'Ṧ' => 'Ṧ', 'ṧ' => 'ṧ', 'Ṩ' => 'Ṩ', 'ṩ' => 'ṩ', 'Ṫ' => 'Ṫ', 'ṫ' => 'ṫ', 'Ṭ' => 'Ṭ', 'ṭ' => 'ṭ', 'Ṯ' => 'Ṯ', 'ṯ' => 'ṯ', 'Ṱ' => 'Ṱ', 'ṱ' => 'ṱ', 'Ṳ' => 'Ṳ', 'ṳ' => 'ṳ', 'Ṵ' => 'Ṵ', 'ṵ' => 'ṵ', 'Ṷ' => 'Ṷ', 'ṷ' => 'ṷ', 'Ṹ' => 'Ṹ', 'ṹ' => 'ṹ', 'Ṻ' => 'Ṻ', 'ṻ' => 'ṻ', 'Ṽ' => 'Ṽ', 'ṽ' => 'ṽ', 'Ṿ' => 'Ṿ', 'ṿ' => 'ṿ', 'Ẁ' => 'Ẁ', 'ẁ' => 'ẁ', 'Ẃ' => 'Ẃ', 'ẃ' => 'ẃ', 'Ẅ' => 'Ẅ', 'ẅ' => 'ẅ', 'Ẇ' => 'Ẇ', 'ẇ' => 'ẇ', 'Ẉ' => 'Ẉ', 'ẉ' => 'ẉ', 'Ẋ' => 'Ẋ', 'ẋ' => 'ẋ', 'Ẍ' => 'Ẍ', 'ẍ' => 'ẍ', 'Ẏ' => 'Ẏ', 'ẏ' => 'ẏ', 'Ẑ' => 'Ẑ', 'ẑ' => 'ẑ', 'Ẓ' => 'Ẓ', 'ẓ' => 'ẓ', 'Ẕ' => 'Ẕ', 'ẕ' => 'ẕ', 'ẖ' => 'ẖ', 'ẗ' => 'ẗ', 'ẘ' => 'ẘ', 'ẙ' => 'ẙ', 'ẛ' => 'ẛ', 'Ạ' => 'Ạ', 'ạ' => 'ạ', 'Ả' => 'Ả', 'ả' => 'ả', 'Ấ' => 'Ấ', 'ấ' => 'ấ', 'Ầ' => 'Ầ', 'ầ' => 'ầ', 'Ẩ' => 'Ẩ', 'ẩ' => 'ẩ', 'Ẫ' => 'Ẫ', 'ẫ' => 'ẫ', 'Ậ' => 'Ậ', 'ậ' => 'ậ', 'Ắ' => 'Ắ', 'ắ' => 'ắ', 'Ằ' => 'Ằ', 'ằ' => 'ằ', 'Ẳ' => 'Ẳ', 'ẳ' => 'ẳ', 'Ẵ' => 'Ẵ', 'ẵ' => 'ẵ', 'Ặ' => 'Ặ', 'ặ' => 'ặ', 'Ẹ' => 'Ẹ', 'ẹ' => 'ẹ', 'Ẻ' => 'Ẻ', 'ẻ' => 'ẻ', 'Ẽ' => 'Ẽ', 'ẽ' => 'ẽ', 'Ế' => 'Ế', 'ế' => 'ế', 'Ề' => 'Ề', 'ề' => 'ề', 'Ể' => 'Ể', 'ể' => 'ể', 'Ễ' => 'Ễ', 'ễ' => 'ễ', 'Ệ' => 'Ệ', 'ệ' => 'ệ', 'Ỉ' => 'Ỉ', 'ỉ' => 'ỉ', 'Ị' => 'Ị', 'ị' => 'ị', 'Ọ' => 'Ọ', 'ọ' => 'ọ', 'Ỏ' => 'Ỏ', 'ỏ' => 'ỏ', 'Ố' => 'Ố', 'ố' => 'ố', 'Ồ' => 'Ồ', 'ồ' => 'ồ', 'Ổ' => 'Ổ', 'ổ' => 'ổ', 'Ỗ' => 'Ỗ', 'ỗ' => 'ỗ', 'Ộ' => 'Ộ', 'ộ' => 'ộ', 'Ớ' => 'Ớ', 'ớ' => 'ớ', 'Ờ' => 'Ờ', 'ờ' => 'ờ', 'Ở' => 'Ở', 'ở' => 'ở', 'Ỡ' => 'Ỡ', 'ỡ' => 'ỡ', 'Ợ' => 'Ợ', 'ợ' => 'ợ', 'Ụ' => 'Ụ', 'ụ' => 'ụ', 'Ủ' => 'Ủ', 'ủ' => 'ủ', 'Ứ' => 'Ứ', 'ứ' => 'ứ', 'Ừ' => 'Ừ', 'ừ' => 'ừ', 'Ử' => 'Ử', 'ử' => 'ử', 'Ữ' => 'Ữ', 'ữ' => 'ữ', 'Ự' => 'Ự', 'ự' => 'ự', 'Ỳ' => 'Ỳ', 'ỳ' => 'ỳ', 'Ỵ' => 'Ỵ', 'ỵ' => 'ỵ', 'Ỷ' => 'Ỷ', 'ỷ' => 'ỷ', 'Ỹ' => 'Ỹ', 'ỹ' => 'ỹ', 'ἀ' => 'ἀ', 'ἁ' => 'ἁ', 'ἂ' => 'ἂ', 'ἃ' => 'ἃ', 'ἄ' => 'ἄ', 'ἅ' => 'ἅ', 'ἆ' => 'ἆ', 'ἇ' => 'ἇ', 'Ἀ' => 'Ἀ', 'Ἁ' => 'Ἁ', 'Ἂ' => 'Ἂ', 'Ἃ' => 'Ἃ', 'Ἄ' => 'Ἄ', 'Ἅ' => 'Ἅ', 'Ἆ' => 'Ἆ', 'Ἇ' => 'Ἇ', 'ἐ' => 'ἐ', 'ἑ' => 'ἑ', 'ἒ' => 'ἒ', 'ἓ' => 'ἓ', 'ἔ' => 'ἔ', 'ἕ' => 'ἕ', 'Ἐ' => 'Ἐ', 'Ἑ' => 'Ἑ', 'Ἒ' => 'Ἒ', 'Ἓ' => 'Ἓ', 'Ἔ' => 'Ἔ', 'Ἕ' => 'Ἕ', 'ἠ' => 'ἠ', 'ἡ' => 'ἡ', 'ἢ' => 'ἢ', 'ἣ' => 'ἣ', 'ἤ' => 'ἤ', 'ἥ' => 'ἥ', 'ἦ' => 'ἦ', 'ἧ' => 'ἧ', 'Ἠ' => 'Ἠ', 'Ἡ' => 'Ἡ', 'Ἢ' => 'Ἢ', 'Ἣ' => 'Ἣ', 'Ἤ' => 'Ἤ', 'Ἥ' => 'Ἥ', 'Ἦ' => 'Ἦ', 'Ἧ' => 'Ἧ', 'ἰ' => 'ἰ', 'ἱ' => 'ἱ', 'ἲ' => 'ἲ', 'ἳ' => 'ἳ', 'ἴ' => 'ἴ', 'ἵ' => 'ἵ', 'ἶ' => 'ἶ', 'ἷ' => 'ἷ', 'Ἰ' => 'Ἰ', 'Ἱ' => 'Ἱ', 'Ἲ' => 'Ἲ', 'Ἳ' => 'Ἳ', 'Ἴ' => 'Ἴ', 'Ἵ' => 'Ἵ', 'Ἶ' => 'Ἶ', 'Ἷ' => 'Ἷ', 'ὀ' => 'ὀ', 'ὁ' => 'ὁ', 'ὂ' => 'ὂ', 'ὃ' => 'ὃ', 'ὄ' => 'ὄ', 'ὅ' => 'ὅ', 'Ὀ' => 'Ὀ', 'Ὁ' => 'Ὁ', 'Ὂ' => 'Ὂ', 'Ὃ' => 'Ὃ', 'Ὄ' => 'Ὄ', 'Ὅ' => 'Ὅ', 'ὐ' => 'ὐ', 'ὑ' => 'ὑ', 'ὒ' => 'ὒ', 'ὓ' => 'ὓ', 'ὔ' => 'ὔ', 'ὕ' => 'ὕ', 'ὖ' => 'ὖ', 'ὗ' => 'ὗ', 'Ὑ' => 'Ὑ', 'Ὓ' => 'Ὓ', 'Ὕ' => 'Ὕ', 'Ὗ' => 'Ὗ', 'ὠ' => 'ὠ', 'ὡ' => 'ὡ', 'ὢ' => 'ὢ', 'ὣ' => 'ὣ', 'ὤ' => 'ὤ', 'ὥ' => 'ὥ', 'ὦ' => 'ὦ', 'ὧ' => 'ὧ', 'Ὠ' => 'Ὠ', 'Ὡ' => 'Ὡ', 'Ὢ' => 'Ὢ', 'Ὣ' => 'Ὣ', 'Ὤ' => 'Ὤ', 'Ὥ' => 'Ὥ', 'Ὦ' => 'Ὦ', 'Ὧ' => 'Ὧ', 'ὰ' => 'ὰ', 'ὲ' => 'ὲ', 'ὴ' => 'ὴ', 'ὶ' => 'ὶ', 'ὸ' => 'ὸ', 'ὺ' => 'ὺ', 'ὼ' => 'ὼ', 'ᾀ' => 'ᾀ', 'ᾁ' => 'ᾁ', 'ᾂ' => 'ᾂ', 'ᾃ' => 'ᾃ', 'ᾄ' => 'ᾄ', 'ᾅ' => 'ᾅ', 'ᾆ' => 'ᾆ', 'ᾇ' => 'ᾇ', 'ᾈ' => 'ᾈ', 'ᾉ' => 'ᾉ', 'ᾊ' => 'ᾊ', 'ᾋ' => 'ᾋ', 'ᾌ' => 'ᾌ', 'ᾍ' => 'ᾍ', 'ᾎ' => 'ᾎ', 'ᾏ' => 'ᾏ', 'ᾐ' => 'ᾐ', 'ᾑ' => 'ᾑ', 'ᾒ' => 'ᾒ', 'ᾓ' => 'ᾓ', 'ᾔ' => 'ᾔ', 'ᾕ' => 'ᾕ', 'ᾖ' => 'ᾖ', 'ᾗ' => 'ᾗ', 'ᾘ' => 'ᾘ', 'ᾙ' => 'ᾙ', 'ᾚ' => 'ᾚ', 'ᾛ' => 'ᾛ', 'ᾜ' => 'ᾜ', 'ᾝ' => 'ᾝ', 'ᾞ' => 'ᾞ', 'ᾟ' => 'ᾟ', 'ᾠ' => 'ᾠ', 'ᾡ' => 'ᾡ', 'ᾢ' => 'ᾢ', 'ᾣ' => 'ᾣ', 'ᾤ' => 'ᾤ', 'ᾥ' => 'ᾥ', 'ᾦ' => 'ᾦ', 'ᾧ' => 'ᾧ', 'ᾨ' => 'ᾨ', 'ᾩ' => 'ᾩ', 'ᾪ' => 'ᾪ', 'ᾫ' => 'ᾫ', 'ᾬ' => 'ᾬ', 'ᾭ' => 'ᾭ', 'ᾮ' => 'ᾮ', 'ᾯ' => 'ᾯ', 'ᾰ' => 'ᾰ', 'ᾱ' => 'ᾱ', 'ᾲ' => 'ᾲ', 'ᾳ' => 'ᾳ', 'ᾴ' => 'ᾴ', 'ᾶ' => 'ᾶ', 'ᾷ' => 'ᾷ', 'Ᾰ' => 'Ᾰ', 'Ᾱ' => 'Ᾱ', 'Ὰ' => 'Ὰ', 'ᾼ' => 'ᾼ', '῁' => '῁', 'ῂ' => 'ῂ', 'ῃ' => 'ῃ', 'ῄ' => 'ῄ', 'ῆ' => 'ῆ', 'ῇ' => 'ῇ', 'Ὲ' => 'Ὲ', 'Ὴ' => 'Ὴ', 'ῌ' => 'ῌ', '῍' => '῍', '῎' => '῎', '῏' => '῏', 'ῐ' => 'ῐ', 'ῑ' => 'ῑ', 'ῒ' => 'ῒ', 'ῖ' => 'ῖ', 'ῗ' => 'ῗ', 'Ῐ' => 'Ῐ', 'Ῑ' => 'Ῑ', 'Ὶ' => 'Ὶ', '῝' => '῝', '῞' => '῞', '῟' => '῟', 'ῠ' => 'ῠ', 'ῡ' => 'ῡ', 'ῢ' => 'ῢ', 'ῤ' => 'ῤ', 'ῥ' => 'ῥ', 'ῦ' => 'ῦ', 'ῧ' => 'ῧ', 'Ῠ' => 'Ῠ', 'Ῡ' => 'Ῡ', 'Ὺ' => 'Ὺ', 'Ῥ' => 'Ῥ', '῭' => '῭', 'ῲ' => 'ῲ', 'ῳ' => 'ῳ', 'ῴ' => 'ῴ', 'ῶ' => 'ῶ', 'ῷ' => 'ῷ', 'Ὸ' => 'Ὸ', 'Ὼ' => 'Ὼ', 'ῼ' => 'ῼ', '↚' => '↚', '↛' => '↛', '↮' => '↮', '⇍' => '⇍', '⇎' => '⇎', '⇏' => '⇏', '∄' => '∄', '∉' => '∉', '∌' => '∌', '∤' => '∤', '∦' => '∦', '≁' => '≁', '≄' => '≄', '≇' => '≇', '≉' => '≉', '≠' => '≠', '≢' => '≢', '≭' => '≭', '≮' => '≮', '≯' => '≯', '≰' => '≰', '≱' => '≱', '≴' => '≴', '≵' => '≵', '≸' => '≸', '≹' => '≹', '⊀' => '⊀', '⊁' => '⊁', '⊄' => '⊄', '⊅' => '⊅', '⊈' => '⊈', '⊉' => '⊉', '⊬' => '⊬', '⊭' => '⊭', '⊮' => '⊮', '⊯' => '⊯', '⋠' => '⋠', '⋡' => '⋡', '⋢' => '⋢', '⋣' => '⋣', '⋪' => '⋪', '⋫' => '⋫', '⋬' => '⋬', '⋭' => '⋭', 'が' => 'が', 'ぎ' => 'ぎ', 'ぐ' => 'ぐ', 'げ' => 'げ', 'ご' => 'ご', 'ざ' => 'ざ', 'じ' => 'じ', 'ず' => 'ず', 'ぜ' => 'ぜ', 'ぞ' => 'ぞ', 'だ' => 'だ', 'ぢ' => 'ぢ', 'づ' => 'づ', 'で' => 'で', 'ど' => 'ど', 'ば' => 'ば', 'ぱ' => 'ぱ', 'び' => 'び', 'ぴ' => 'ぴ', 'ぶ' => 'ぶ', 'ぷ' => 'ぷ', 'べ' => 'べ', 'ぺ' => 'ぺ', 'ぼ' => 'ぼ', 'ぽ' => 'ぽ', 'ゔ' => 'ゔ', 'ゞ' => 'ゞ', 'ガ' => 'ガ', 'ギ' => 'ギ', 'グ' => 'グ', 'ゲ' => 'ゲ', 'ゴ' => 'ゴ', 'ザ' => 'ザ', 'ジ' => 'ジ', 'ズ' => 'ズ', 'ゼ' => 'ゼ', 'ゾ' => 'ゾ', 'ダ' => 'ダ', 'ヂ' => 'ヂ', 'ヅ' => 'ヅ', 'デ' => 'デ', 'ド' => 'ド', 'バ' => 'バ', 'パ' => 'パ', 'ビ' => 'ビ', 'ピ' => 'ピ', 'ブ' => 'ブ', 'プ' => 'プ', 'ベ' => 'ベ', 'ペ' => 'ペ', 'ボ' => 'ボ', 'ポ' => 'ポ', 'ヴ' => 'ヴ', 'ヷ' => 'ヷ', 'ヸ' => 'ヸ', 'ヹ' => 'ヹ', 'ヺ' => 'ヺ', 'ヾ' => 'ヾ', '𑂚' => '𑂚', '𑂜' => '𑂜', '𑂫' => '𑂫', '𑄮' => '𑄮', '𑄯' => '𑄯', '𑍋' => '𑍋', '𑍌' => '𑍌', '𑒻' => '𑒻', '𑒼' => '𑒼', '𑒾' => '𑒾', '𑖺' => '𑖺', '𑖻' => '𑖻', '𑤸' => '𑤸', ); polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php000064400000114173150432043200022316 0ustar00 'À', 'Á' => 'Á', 'Â' => 'Â', 'Ã' => 'Ã', 'Ä' => 'Ä', 'Å' => 'Å', 'Ç' => 'Ç', 'È' => 'È', 'É' => 'É', 'Ê' => 'Ê', 'Ë' => 'Ë', 'Ì' => 'Ì', 'Í' => 'Í', 'Î' => 'Î', 'Ï' => 'Ï', 'Ñ' => 'Ñ', 'Ò' => 'Ò', 'Ó' => 'Ó', 'Ô' => 'Ô', 'Õ' => 'Õ', 'Ö' => 'Ö', 'Ù' => 'Ù', 'Ú' => 'Ú', 'Û' => 'Û', 'Ü' => 'Ü', 'Ý' => 'Ý', 'à' => 'à', 'á' => 'á', 'â' => 'â', 'ã' => 'ã', 'ä' => 'ä', 'å' => 'å', 'ç' => 'ç', 'è' => 'è', 'é' => 'é', 'ê' => 'ê', 'ë' => 'ë', 'ì' => 'ì', 'í' => 'í', 'î' => 'î', 'ï' => 'ï', 'ñ' => 'ñ', 'ò' => 'ò', 'ó' => 'ó', 'ô' => 'ô', 'õ' => 'õ', 'ö' => 'ö', 'ù' => 'ù', 'ú' => 'ú', 'û' => 'û', 'ü' => 'ü', 'ý' => 'ý', 'ÿ' => 'ÿ', 'Ā' => 'Ā', 'ā' => 'ā', 'Ă' => 'Ă', 'ă' => 'ă', 'Ą' => 'Ą', 'ą' => 'ą', 'Ć' => 'Ć', 'ć' => 'ć', 'Ĉ' => 'Ĉ', 'ĉ' => 'ĉ', 'Ċ' => 'Ċ', 'ċ' => 'ċ', 'Č' => 'Č', 'č' => 'č', 'Ď' => 'Ď', 'ď' => 'ď', 'Ē' => 'Ē', 'ē' => 'ē', 'Ĕ' => 'Ĕ', 'ĕ' => 'ĕ', 'Ė' => 'Ė', 'ė' => 'ė', 'Ę' => 'Ę', 'ę' => 'ę', 'Ě' => 'Ě', 'ě' => 'ě', 'Ĝ' => 'Ĝ', 'ĝ' => 'ĝ', 'Ğ' => 'Ğ', 'ğ' => 'ğ', 'Ġ' => 'Ġ', 'ġ' => 'ġ', 'Ģ' => 'Ģ', 'ģ' => 'ģ', 'Ĥ' => 'Ĥ', 'ĥ' => 'ĥ', 'Ĩ' => 'Ĩ', 'ĩ' => 'ĩ', 'Ī' => 'Ī', 'ī' => 'ī', 'Ĭ' => 'Ĭ', 'ĭ' => 'ĭ', 'Į' => 'Į', 'į' => 'į', 'İ' => 'İ', 'Ĵ' => 'Ĵ', 'ĵ' => 'ĵ', 'Ķ' => 'Ķ', 'ķ' => 'ķ', 'Ĺ' => 'Ĺ', 'ĺ' => 'ĺ', 'Ļ' => 'Ļ', 'ļ' => 'ļ', 'Ľ' => 'Ľ', 'ľ' => 'ľ', 'Ń' => 'Ń', 'ń' => 'ń', 'Ņ' => 'Ņ', 'ņ' => 'ņ', 'Ň' => 'Ň', 'ň' => 'ň', 'Ō' => 'Ō', 'ō' => 'ō', 'Ŏ' => 'Ŏ', 'ŏ' => 'ŏ', 'Ő' => 'Ő', 'ő' => 'ő', 'Ŕ' => 'Ŕ', 'ŕ' => 'ŕ', 'Ŗ' => 'Ŗ', 'ŗ' => 'ŗ', 'Ř' => 'Ř', 'ř' => 'ř', 'Ś' => 'Ś', 'ś' => 'ś', 'Ŝ' => 'Ŝ', 'ŝ' => 'ŝ', 'Ş' => 'Ş', 'ş' => 'ş', 'Š' => 'Š', 'š' => 'š', 'Ţ' => 'Ţ', 'ţ' => 'ţ', 'Ť' => 'Ť', 'ť' => 'ť', 'Ũ' => 'Ũ', 'ũ' => 'ũ', 'Ū' => 'Ū', 'ū' => 'ū', 'Ŭ' => 'Ŭ', 'ŭ' => 'ŭ', 'Ů' => 'Ů', 'ů' => 'ů', 'Ű' => 'Ű', 'ű' => 'ű', 'Ų' => 'Ų', 'ų' => 'ų', 'Ŵ' => 'Ŵ', 'ŵ' => 'ŵ', 'Ŷ' => 'Ŷ', 'ŷ' => 'ŷ', 'Ÿ' => 'Ÿ', 'Ź' => 'Ź', 'ź' => 'ź', 'Ż' => 'Ż', 'ż' => 'ż', 'Ž' => 'Ž', 'ž' => 'ž', 'Ơ' => 'Ơ', 'ơ' => 'ơ', 'Ư' => 'Ư', 'ư' => 'ư', 'Ǎ' => 'Ǎ', 'ǎ' => 'ǎ', 'Ǐ' => 'Ǐ', 'ǐ' => 'ǐ', 'Ǒ' => 'Ǒ', 'ǒ' => 'ǒ', 'Ǔ' => 'Ǔ', 'ǔ' => 'ǔ', 'Ǖ' => 'Ǖ', 'ǖ' => 'ǖ', 'Ǘ' => 'Ǘ', 'ǘ' => 'ǘ', 'Ǚ' => 'Ǚ', 'ǚ' => 'ǚ', 'Ǜ' => 'Ǜ', 'ǜ' => 'ǜ', 'Ǟ' => 'Ǟ', 'ǟ' => 'ǟ', 'Ǡ' => 'Ǡ', 'ǡ' => 'ǡ', 'Ǣ' => 'Ǣ', 'ǣ' => 'ǣ', 'Ǧ' => 'Ǧ', 'ǧ' => 'ǧ', 'Ǩ' => 'Ǩ', 'ǩ' => 'ǩ', 'Ǫ' => 'Ǫ', 'ǫ' => 'ǫ', 'Ǭ' => 'Ǭ', 'ǭ' => 'ǭ', 'Ǯ' => 'Ǯ', 'ǯ' => 'ǯ', 'ǰ' => 'ǰ', 'Ǵ' => 'Ǵ', 'ǵ' => 'ǵ', 'Ǹ' => 'Ǹ', 'ǹ' => 'ǹ', 'Ǻ' => 'Ǻ', 'ǻ' => 'ǻ', 'Ǽ' => 'Ǽ', 'ǽ' => 'ǽ', 'Ǿ' => 'Ǿ', 'ǿ' => 'ǿ', 'Ȁ' => 'Ȁ', 'ȁ' => 'ȁ', 'Ȃ' => 'Ȃ', 'ȃ' => 'ȃ', 'Ȅ' => 'Ȅ', 'ȅ' => 'ȅ', 'Ȇ' => 'Ȇ', 'ȇ' => 'ȇ', 'Ȉ' => 'Ȉ', 'ȉ' => 'ȉ', 'Ȋ' => 'Ȋ', 'ȋ' => 'ȋ', 'Ȍ' => 'Ȍ', 'ȍ' => 'ȍ', 'Ȏ' => 'Ȏ', 'ȏ' => 'ȏ', 'Ȑ' => 'Ȑ', 'ȑ' => 'ȑ', 'Ȓ' => 'Ȓ', 'ȓ' => 'ȓ', 'Ȕ' => 'Ȕ', 'ȕ' => 'ȕ', 'Ȗ' => 'Ȗ', 'ȗ' => 'ȗ', 'Ș' => 'Ș', 'ș' => 'ș', 'Ț' => 'Ț', 'ț' => 'ț', 'Ȟ' => 'Ȟ', 'ȟ' => 'ȟ', 'Ȧ' => 'Ȧ', 'ȧ' => 'ȧ', 'Ȩ' => 'Ȩ', 'ȩ' => 'ȩ', 'Ȫ' => 'Ȫ', 'ȫ' => 'ȫ', 'Ȭ' => 'Ȭ', 'ȭ' => 'ȭ', 'Ȯ' => 'Ȯ', 'ȯ' => 'ȯ', 'Ȱ' => 'Ȱ', 'ȱ' => 'ȱ', 'Ȳ' => 'Ȳ', 'ȳ' => 'ȳ', '̀' => '̀', '́' => '́', '̓' => '̓', '̈́' => '̈́', 'ʹ' => 'ʹ', ';' => ';', '΅' => '΅', 'Ά' => 'Ά', '·' => '·', 'Έ' => 'Έ', 'Ή' => 'Ή', 'Ί' => 'Ί', 'Ό' => 'Ό', 'Ύ' => 'Ύ', 'Ώ' => 'Ώ', 'ΐ' => 'ΐ', 'Ϊ' => 'Ϊ', 'Ϋ' => 'Ϋ', 'ά' => 'ά', 'έ' => 'έ', 'ή' => 'ή', 'ί' => 'ί', 'ΰ' => 'ΰ', 'ϊ' => 'ϊ', 'ϋ' => 'ϋ', 'ό' => 'ό', 'ύ' => 'ύ', 'ώ' => 'ώ', 'ϓ' => 'ϓ', 'ϔ' => 'ϔ', 'Ѐ' => 'Ѐ', 'Ё' => 'Ё', 'Ѓ' => 'Ѓ', 'Ї' => 'Ї', 'Ќ' => 'Ќ', 'Ѝ' => 'Ѝ', 'Ў' => 'Ў', 'Й' => 'Й', 'й' => 'й', 'ѐ' => 'ѐ', 'ё' => 'ё', 'ѓ' => 'ѓ', 'ї' => 'ї', 'ќ' => 'ќ', 'ѝ' => 'ѝ', 'ў' => 'ў', 'Ѷ' => 'Ѷ', 'ѷ' => 'ѷ', 'Ӂ' => 'Ӂ', 'ӂ' => 'ӂ', 'Ӑ' => 'Ӑ', 'ӑ' => 'ӑ', 'Ӓ' => 'Ӓ', 'ӓ' => 'ӓ', 'Ӗ' => 'Ӗ', 'ӗ' => 'ӗ', 'Ӛ' => 'Ӛ', 'ӛ' => 'ӛ', 'Ӝ' => 'Ӝ', 'ӝ' => 'ӝ', 'Ӟ' => 'Ӟ', 'ӟ' => 'ӟ', 'Ӣ' => 'Ӣ', 'ӣ' => 'ӣ', 'Ӥ' => 'Ӥ', 'ӥ' => 'ӥ', 'Ӧ' => 'Ӧ', 'ӧ' => 'ӧ', 'Ӫ' => 'Ӫ', 'ӫ' => 'ӫ', 'Ӭ' => 'Ӭ', 'ӭ' => 'ӭ', 'Ӯ' => 'Ӯ', 'ӯ' => 'ӯ', 'Ӱ' => 'Ӱ', 'ӱ' => 'ӱ', 'Ӳ' => 'Ӳ', 'ӳ' => 'ӳ', 'Ӵ' => 'Ӵ', 'ӵ' => 'ӵ', 'Ӹ' => 'Ӹ', 'ӹ' => 'ӹ', 'آ' => 'آ', 'أ' => 'أ', 'ؤ' => 'ؤ', 'إ' => 'إ', 'ئ' => 'ئ', 'ۀ' => 'ۀ', 'ۂ' => 'ۂ', 'ۓ' => 'ۓ', 'ऩ' => 'ऩ', 'ऱ' => 'ऱ', 'ऴ' => 'ऴ', 'क़' => 'क़', 'ख़' => 'ख़', 'ग़' => 'ग़', 'ज़' => 'ज़', 'ड़' => 'ड़', 'ढ़' => 'ढ़', 'फ़' => 'फ़', 'य़' => 'य़', 'ো' => 'ো', 'ৌ' => 'ৌ', 'ড়' => 'ড়', 'ঢ়' => 'ঢ়', 'য়' => 'য়', 'ਲ਼' => 'ਲ਼', 'ਸ਼' => 'ਸ਼', 'ਖ਼' => 'ਖ਼', 'ਗ਼' => 'ਗ਼', 'ਜ਼' => 'ਜ਼', 'ਫ਼' => 'ਫ਼', 'ୈ' => 'ୈ', 'ୋ' => 'ୋ', 'ୌ' => 'ୌ', 'ଡ଼' => 'ଡ଼', 'ଢ଼' => 'ଢ଼', 'ஔ' => 'ஔ', 'ொ' => 'ொ', 'ோ' => 'ோ', 'ௌ' => 'ௌ', 'ై' => 'ై', 'ೀ' => 'ೀ', 'ೇ' => 'ೇ', 'ೈ' => 'ೈ', 'ೊ' => 'ೊ', 'ೋ' => 'ೋ', 'ൊ' => 'ൊ', 'ോ' => 'ോ', 'ൌ' => 'ൌ', 'ේ' => 'ේ', 'ො' => 'ො', 'ෝ' => 'ෝ', 'ෞ' => 'ෞ', 'གྷ' => 'གྷ', 'ཌྷ' => 'ཌྷ', 'དྷ' => 'དྷ', 'བྷ' => 'བྷ', 'ཛྷ' => 'ཛྷ', 'ཀྵ' => 'ཀྵ', 'ཱི' => 'ཱི', 'ཱུ' => 'ཱུ', 'ྲྀ' => 'ྲྀ', 'ླྀ' => 'ླྀ', 'ཱྀ' => 'ཱྀ', 'ྒྷ' => 'ྒྷ', 'ྜྷ' => 'ྜྷ', 'ྡྷ' => 'ྡྷ', 'ྦྷ' => 'ྦྷ', 'ྫྷ' => 'ྫྷ', 'ྐྵ' => 'ྐྵ', 'ဦ' => 'ဦ', 'ᬆ' => 'ᬆ', 'ᬈ' => 'ᬈ', 'ᬊ' => 'ᬊ', 'ᬌ' => 'ᬌ', 'ᬎ' => 'ᬎ', 'ᬒ' => 'ᬒ', 'ᬻ' => 'ᬻ', 'ᬽ' => 'ᬽ', 'ᭀ' => 'ᭀ', 'ᭁ' => 'ᭁ', 'ᭃ' => 'ᭃ', 'Ḁ' => 'Ḁ', 'ḁ' => 'ḁ', 'Ḃ' => 'Ḃ', 'ḃ' => 'ḃ', 'Ḅ' => 'Ḅ', 'ḅ' => 'ḅ', 'Ḇ' => 'Ḇ', 'ḇ' => 'ḇ', 'Ḉ' => 'Ḉ', 'ḉ' => 'ḉ', 'Ḋ' => 'Ḋ', 'ḋ' => 'ḋ', 'Ḍ' => 'Ḍ', 'ḍ' => 'ḍ', 'Ḏ' => 'Ḏ', 'ḏ' => 'ḏ', 'Ḑ' => 'Ḑ', 'ḑ' => 'ḑ', 'Ḓ' => 'Ḓ', 'ḓ' => 'ḓ', 'Ḕ' => 'Ḕ', 'ḕ' => 'ḕ', 'Ḗ' => 'Ḗ', 'ḗ' => 'ḗ', 'Ḙ' => 'Ḙ', 'ḙ' => 'ḙ', 'Ḛ' => 'Ḛ', 'ḛ' => 'ḛ', 'Ḝ' => 'Ḝ', 'ḝ' => 'ḝ', 'Ḟ' => 'Ḟ', 'ḟ' => 'ḟ', 'Ḡ' => 'Ḡ', 'ḡ' => 'ḡ', 'Ḣ' => 'Ḣ', 'ḣ' => 'ḣ', 'Ḥ' => 'Ḥ', 'ḥ' => 'ḥ', 'Ḧ' => 'Ḧ', 'ḧ' => 'ḧ', 'Ḩ' => 'Ḩ', 'ḩ' => 'ḩ', 'Ḫ' => 'Ḫ', 'ḫ' => 'ḫ', 'Ḭ' => 'Ḭ', 'ḭ' => 'ḭ', 'Ḯ' => 'Ḯ', 'ḯ' => 'ḯ', 'Ḱ' => 'Ḱ', 'ḱ' => 'ḱ', 'Ḳ' => 'Ḳ', 'ḳ' => 'ḳ', 'Ḵ' => 'Ḵ', 'ḵ' => 'ḵ', 'Ḷ' => 'Ḷ', 'ḷ' => 'ḷ', 'Ḹ' => 'Ḹ', 'ḹ' => 'ḹ', 'Ḻ' => 'Ḻ', 'ḻ' => 'ḻ', 'Ḽ' => 'Ḽ', 'ḽ' => 'ḽ', 'Ḿ' => 'Ḿ', 'ḿ' => 'ḿ', 'Ṁ' => 'Ṁ', 'ṁ' => 'ṁ', 'Ṃ' => 'Ṃ', 'ṃ' => 'ṃ', 'Ṅ' => 'Ṅ', 'ṅ' => 'ṅ', 'Ṇ' => 'Ṇ', 'ṇ' => 'ṇ', 'Ṉ' => 'Ṉ', 'ṉ' => 'ṉ', 'Ṋ' => 'Ṋ', 'ṋ' => 'ṋ', 'Ṍ' => 'Ṍ', 'ṍ' => 'ṍ', 'Ṏ' => 'Ṏ', 'ṏ' => 'ṏ', 'Ṑ' => 'Ṑ', 'ṑ' => 'ṑ', 'Ṓ' => 'Ṓ', 'ṓ' => 'ṓ', 'Ṕ' => 'Ṕ', 'ṕ' => 'ṕ', 'Ṗ' => 'Ṗ', 'ṗ' => 'ṗ', 'Ṙ' => 'Ṙ', 'ṙ' => 'ṙ', 'Ṛ' => 'Ṛ', 'ṛ' => 'ṛ', 'Ṝ' => 'Ṝ', 'ṝ' => 'ṝ', 'Ṟ' => 'Ṟ', 'ṟ' => 'ṟ', 'Ṡ' => 'Ṡ', 'ṡ' => 'ṡ', 'Ṣ' => 'Ṣ', 'ṣ' => 'ṣ', 'Ṥ' => 'Ṥ', 'ṥ' => 'ṥ', 'Ṧ' => 'Ṧ', 'ṧ' => 'ṧ', 'Ṩ' => 'Ṩ', 'ṩ' => 'ṩ', 'Ṫ' => 'Ṫ', 'ṫ' => 'ṫ', 'Ṭ' => 'Ṭ', 'ṭ' => 'ṭ', 'Ṯ' => 'Ṯ', 'ṯ' => 'ṯ', 'Ṱ' => 'Ṱ', 'ṱ' => 'ṱ', 'Ṳ' => 'Ṳ', 'ṳ' => 'ṳ', 'Ṵ' => 'Ṵ', 'ṵ' => 'ṵ', 'Ṷ' => 'Ṷ', 'ṷ' => 'ṷ', 'Ṹ' => 'Ṹ', 'ṹ' => 'ṹ', 'Ṻ' => 'Ṻ', 'ṻ' => 'ṻ', 'Ṽ' => 'Ṽ', 'ṽ' => 'ṽ', 'Ṿ' => 'Ṿ', 'ṿ' => 'ṿ', 'Ẁ' => 'Ẁ', 'ẁ' => 'ẁ', 'Ẃ' => 'Ẃ', 'ẃ' => 'ẃ', 'Ẅ' => 'Ẅ', 'ẅ' => 'ẅ', 'Ẇ' => 'Ẇ', 'ẇ' => 'ẇ', 'Ẉ' => 'Ẉ', 'ẉ' => 'ẉ', 'Ẋ' => 'Ẋ', 'ẋ' => 'ẋ', 'Ẍ' => 'Ẍ', 'ẍ' => 'ẍ', 'Ẏ' => 'Ẏ', 'ẏ' => 'ẏ', 'Ẑ' => 'Ẑ', 'ẑ' => 'ẑ', 'Ẓ' => 'Ẓ', 'ẓ' => 'ẓ', 'Ẕ' => 'Ẕ', 'ẕ' => 'ẕ', 'ẖ' => 'ẖ', 'ẗ' => 'ẗ', 'ẘ' => 'ẘ', 'ẙ' => 'ẙ', 'ẛ' => 'ẛ', 'Ạ' => 'Ạ', 'ạ' => 'ạ', 'Ả' => 'Ả', 'ả' => 'ả', 'Ấ' => 'Ấ', 'ấ' => 'ấ', 'Ầ' => 'Ầ', 'ầ' => 'ầ', 'Ẩ' => 'Ẩ', 'ẩ' => 'ẩ', 'Ẫ' => 'Ẫ', 'ẫ' => 'ẫ', 'Ậ' => 'Ậ', 'ậ' => 'ậ', 'Ắ' => 'Ắ', 'ắ' => 'ắ', 'Ằ' => 'Ằ', 'ằ' => 'ằ', 'Ẳ' => 'Ẳ', 'ẳ' => 'ẳ', 'Ẵ' => 'Ẵ', 'ẵ' => 'ẵ', 'Ặ' => 'Ặ', 'ặ' => 'ặ', 'Ẹ' => 'Ẹ', 'ẹ' => 'ẹ', 'Ẻ' => 'Ẻ', 'ẻ' => 'ẻ', 'Ẽ' => 'Ẽ', 'ẽ' => 'ẽ', 'Ế' => 'Ế', 'ế' => 'ế', 'Ề' => 'Ề', 'ề' => 'ề', 'Ể' => 'Ể', 'ể' => 'ể', 'Ễ' => 'Ễ', 'ễ' => 'ễ', 'Ệ' => 'Ệ', 'ệ' => 'ệ', 'Ỉ' => 'Ỉ', 'ỉ' => 'ỉ', 'Ị' => 'Ị', 'ị' => 'ị', 'Ọ' => 'Ọ', 'ọ' => 'ọ', 'Ỏ' => 'Ỏ', 'ỏ' => 'ỏ', 'Ố' => 'Ố', 'ố' => 'ố', 'Ồ' => 'Ồ', 'ồ' => 'ồ', 'Ổ' => 'Ổ', 'ổ' => 'ổ', 'Ỗ' => 'Ỗ', 'ỗ' => 'ỗ', 'Ộ' => 'Ộ', 'ộ' => 'ộ', 'Ớ' => 'Ớ', 'ớ' => 'ớ', 'Ờ' => 'Ờ', 'ờ' => 'ờ', 'Ở' => 'Ở', 'ở' => 'ở', 'Ỡ' => 'Ỡ', 'ỡ' => 'ỡ', 'Ợ' => 'Ợ', 'ợ' => 'ợ', 'Ụ' => 'Ụ', 'ụ' => 'ụ', 'Ủ' => 'Ủ', 'ủ' => 'ủ', 'Ứ' => 'Ứ', 'ứ' => 'ứ', 'Ừ' => 'Ừ', 'ừ' => 'ừ', 'Ử' => 'Ử', 'ử' => 'ử', 'Ữ' => 'Ữ', 'ữ' => 'ữ', 'Ự' => 'Ự', 'ự' => 'ự', 'Ỳ' => 'Ỳ', 'ỳ' => 'ỳ', 'Ỵ' => 'Ỵ', 'ỵ' => 'ỵ', 'Ỷ' => 'Ỷ', 'ỷ' => 'ỷ', 'Ỹ' => 'Ỹ', 'ỹ' => 'ỹ', 'ἀ' => 'ἀ', 'ἁ' => 'ἁ', 'ἂ' => 'ἂ', 'ἃ' => 'ἃ', 'ἄ' => 'ἄ', 'ἅ' => 'ἅ', 'ἆ' => 'ἆ', 'ἇ' => 'ἇ', 'Ἀ' => 'Ἀ', 'Ἁ' => 'Ἁ', 'Ἂ' => 'Ἂ', 'Ἃ' => 'Ἃ', 'Ἄ' => 'Ἄ', 'Ἅ' => 'Ἅ', 'Ἆ' => 'Ἆ', 'Ἇ' => 'Ἇ', 'ἐ' => 'ἐ', 'ἑ' => 'ἑ', 'ἒ' => 'ἒ', 'ἓ' => 'ἓ', 'ἔ' => 'ἔ', 'ἕ' => 'ἕ', 'Ἐ' => 'Ἐ', 'Ἑ' => 'Ἑ', 'Ἒ' => 'Ἒ', 'Ἓ' => 'Ἓ', 'Ἔ' => 'Ἔ', 'Ἕ' => 'Ἕ', 'ἠ' => 'ἠ', 'ἡ' => 'ἡ', 'ἢ' => 'ἢ', 'ἣ' => 'ἣ', 'ἤ' => 'ἤ', 'ἥ' => 'ἥ', 'ἦ' => 'ἦ', 'ἧ' => 'ἧ', 'Ἠ' => 'Ἠ', 'Ἡ' => 'Ἡ', 'Ἢ' => 'Ἢ', 'Ἣ' => 'Ἣ', 'Ἤ' => 'Ἤ', 'Ἥ' => 'Ἥ', 'Ἦ' => 'Ἦ', 'Ἧ' => 'Ἧ', 'ἰ' => 'ἰ', 'ἱ' => 'ἱ', 'ἲ' => 'ἲ', 'ἳ' => 'ἳ', 'ἴ' => 'ἴ', 'ἵ' => 'ἵ', 'ἶ' => 'ἶ', 'ἷ' => 'ἷ', 'Ἰ' => 'Ἰ', 'Ἱ' => 'Ἱ', 'Ἲ' => 'Ἲ', 'Ἳ' => 'Ἳ', 'Ἴ' => 'Ἴ', 'Ἵ' => 'Ἵ', 'Ἶ' => 'Ἶ', 'Ἷ' => 'Ἷ', 'ὀ' => 'ὀ', 'ὁ' => 'ὁ', 'ὂ' => 'ὂ', 'ὃ' => 'ὃ', 'ὄ' => 'ὄ', 'ὅ' => 'ὅ', 'Ὀ' => 'Ὀ', 'Ὁ' => 'Ὁ', 'Ὂ' => 'Ὂ', 'Ὃ' => 'Ὃ', 'Ὄ' => 'Ὄ', 'Ὅ' => 'Ὅ', 'ὐ' => 'ὐ', 'ὑ' => 'ὑ', 'ὒ' => 'ὒ', 'ὓ' => 'ὓ', 'ὔ' => 'ὔ', 'ὕ' => 'ὕ', 'ὖ' => 'ὖ', 'ὗ' => 'ὗ', 'Ὑ' => 'Ὑ', 'Ὓ' => 'Ὓ', 'Ὕ' => 'Ὕ', 'Ὗ' => 'Ὗ', 'ὠ' => 'ὠ', 'ὡ' => 'ὡ', 'ὢ' => 'ὢ', 'ὣ' => 'ὣ', 'ὤ' => 'ὤ', 'ὥ' => 'ὥ', 'ὦ' => 'ὦ', 'ὧ' => 'ὧ', 'Ὠ' => 'Ὠ', 'Ὡ' => 'Ὡ', 'Ὢ' => 'Ὢ', 'Ὣ' => 'Ὣ', 'Ὤ' => 'Ὤ', 'Ὥ' => 'Ὥ', 'Ὦ' => 'Ὦ', 'Ὧ' => 'Ὧ', 'ὰ' => 'ὰ', 'ά' => 'ά', 'ὲ' => 'ὲ', 'έ' => 'έ', 'ὴ' => 'ὴ', 'ή' => 'ή', 'ὶ' => 'ὶ', 'ί' => 'ί', 'ὸ' => 'ὸ', 'ό' => 'ό', 'ὺ' => 'ὺ', 'ύ' => 'ύ', 'ὼ' => 'ὼ', 'ώ' => 'ώ', 'ᾀ' => 'ᾀ', 'ᾁ' => 'ᾁ', 'ᾂ' => 'ᾂ', 'ᾃ' => 'ᾃ', 'ᾄ' => 'ᾄ', 'ᾅ' => 'ᾅ', 'ᾆ' => 'ᾆ', 'ᾇ' => 'ᾇ', 'ᾈ' => 'ᾈ', 'ᾉ' => 'ᾉ', 'ᾊ' => 'ᾊ', 'ᾋ' => 'ᾋ', 'ᾌ' => 'ᾌ', 'ᾍ' => 'ᾍ', 'ᾎ' => 'ᾎ', 'ᾏ' => 'ᾏ', 'ᾐ' => 'ᾐ', 'ᾑ' => 'ᾑ', 'ᾒ' => 'ᾒ', 'ᾓ' => 'ᾓ', 'ᾔ' => 'ᾔ', 'ᾕ' => 'ᾕ', 'ᾖ' => 'ᾖ', 'ᾗ' => 'ᾗ', 'ᾘ' => 'ᾘ', 'ᾙ' => 'ᾙ', 'ᾚ' => 'ᾚ', 'ᾛ' => 'ᾛ', 'ᾜ' => 'ᾜ', 'ᾝ' => 'ᾝ', 'ᾞ' => 'ᾞ', 'ᾟ' => 'ᾟ', 'ᾠ' => 'ᾠ', 'ᾡ' => 'ᾡ', 'ᾢ' => 'ᾢ', 'ᾣ' => 'ᾣ', 'ᾤ' => 'ᾤ', 'ᾥ' => 'ᾥ', 'ᾦ' => 'ᾦ', 'ᾧ' => 'ᾧ', 'ᾨ' => 'ᾨ', 'ᾩ' => 'ᾩ', 'ᾪ' => 'ᾪ', 'ᾫ' => 'ᾫ', 'ᾬ' => 'ᾬ', 'ᾭ' => 'ᾭ', 'ᾮ' => 'ᾮ', 'ᾯ' => 'ᾯ', 'ᾰ' => 'ᾰ', 'ᾱ' => 'ᾱ', 'ᾲ' => 'ᾲ', 'ᾳ' => 'ᾳ', 'ᾴ' => 'ᾴ', 'ᾶ' => 'ᾶ', 'ᾷ' => 'ᾷ', 'Ᾰ' => 'Ᾰ', 'Ᾱ' => 'Ᾱ', 'Ὰ' => 'Ὰ', 'Ά' => 'Ά', 'ᾼ' => 'ᾼ', 'ι' => 'ι', '῁' => '῁', 'ῂ' => 'ῂ', 'ῃ' => 'ῃ', 'ῄ' => 'ῄ', 'ῆ' => 'ῆ', 'ῇ' => 'ῇ', 'Ὲ' => 'Ὲ', 'Έ' => 'Έ', 'Ὴ' => 'Ὴ', 'Ή' => 'Ή', 'ῌ' => 'ῌ', '῍' => '῍', '῎' => '῎', '῏' => '῏', 'ῐ' => 'ῐ', 'ῑ' => 'ῑ', 'ῒ' => 'ῒ', 'ΐ' => 'ΐ', 'ῖ' => 'ῖ', 'ῗ' => 'ῗ', 'Ῐ' => 'Ῐ', 'Ῑ' => 'Ῑ', 'Ὶ' => 'Ὶ', 'Ί' => 'Ί', '῝' => '῝', '῞' => '῞', '῟' => '῟', 'ῠ' => 'ῠ', 'ῡ' => 'ῡ', 'ῢ' => 'ῢ', 'ΰ' => 'ΰ', 'ῤ' => 'ῤ', 'ῥ' => 'ῥ', 'ῦ' => 'ῦ', 'ῧ' => 'ῧ', 'Ῠ' => 'Ῠ', 'Ῡ' => 'Ῡ', 'Ὺ' => 'Ὺ', 'Ύ' => 'Ύ', 'Ῥ' => 'Ῥ', '῭' => '῭', '΅' => '΅', '`' => '`', 'ῲ' => 'ῲ', 'ῳ' => 'ῳ', 'ῴ' => 'ῴ', 'ῶ' => 'ῶ', 'ῷ' => 'ῷ', 'Ὸ' => 'Ὸ', 'Ό' => 'Ό', 'Ὼ' => 'Ὼ', 'Ώ' => 'Ώ', 'ῼ' => 'ῼ', '´' => '´', ' ' => ' ', ' ' => ' ', 'Ω' => 'Ω', 'K' => 'K', 'Å' => 'Å', '↚' => '↚', '↛' => '↛', '↮' => '↮', '⇍' => '⇍', '⇎' => '⇎', '⇏' => '⇏', '∄' => '∄', '∉' => '∉', '∌' => '∌', '∤' => '∤', '∦' => '∦', '≁' => '≁', '≄' => '≄', '≇' => '≇', '≉' => '≉', '≠' => '≠', '≢' => '≢', '≭' => '≭', '≮' => '≮', '≯' => '≯', '≰' => '≰', '≱' => '≱', '≴' => '≴', '≵' => '≵', '≸' => '≸', '≹' => '≹', '⊀' => '⊀', '⊁' => '⊁', '⊄' => '⊄', '⊅' => '⊅', '⊈' => '⊈', '⊉' => '⊉', '⊬' => '⊬', '⊭' => '⊭', '⊮' => '⊮', '⊯' => '⊯', '⋠' => '⋠', '⋡' => '⋡', '⋢' => '⋢', '⋣' => '⋣', '⋪' => '⋪', '⋫' => '⋫', '⋬' => '⋬', '⋭' => '⋭', '〈' => '〈', '〉' => '〉', '⫝̸' => '⫝̸', 'が' => 'が', 'ぎ' => 'ぎ', 'ぐ' => 'ぐ', 'げ' => 'げ', 'ご' => 'ご', 'ざ' => 'ざ', 'じ' => 'じ', 'ず' => 'ず', 'ぜ' => 'ぜ', 'ぞ' => 'ぞ', 'だ' => 'だ', 'ぢ' => 'ぢ', 'づ' => 'づ', 'で' => 'で', 'ど' => 'ど', 'ば' => 'ば', 'ぱ' => 'ぱ', 'び' => 'び', 'ぴ' => 'ぴ', 'ぶ' => 'ぶ', 'ぷ' => 'ぷ', 'べ' => 'べ', 'ぺ' => 'ぺ', 'ぼ' => 'ぼ', 'ぽ' => 'ぽ', 'ゔ' => 'ゔ', 'ゞ' => 'ゞ', 'ガ' => 'ガ', 'ギ' => 'ギ', 'グ' => 'グ', 'ゲ' => 'ゲ', 'ゴ' => 'ゴ', 'ザ' => 'ザ', 'ジ' => 'ジ', 'ズ' => 'ズ', 'ゼ' => 'ゼ', 'ゾ' => 'ゾ', 'ダ' => 'ダ', 'ヂ' => 'ヂ', 'ヅ' => 'ヅ', 'デ' => 'デ', 'ド' => 'ド', 'バ' => 'バ', 'パ' => 'パ', 'ビ' => 'ビ', 'ピ' => 'ピ', 'ブ' => 'ブ', 'プ' => 'プ', 'ベ' => 'ベ', 'ペ' => 'ペ', 'ボ' => 'ボ', 'ポ' => 'ポ', 'ヴ' => 'ヴ', 'ヷ' => 'ヷ', 'ヸ' => 'ヸ', 'ヹ' => 'ヹ', 'ヺ' => 'ヺ', 'ヾ' => 'ヾ', '豈' => '豈', '更' => '更', '車' => '車', '賈' => '賈', '滑' => '滑', '串' => '串', '句' => '句', '龜' => '龜', '龜' => '龜', '契' => '契', '金' => '金', '喇' => '喇', '奈' => '奈', '懶' => '懶', '癩' => '癩', '羅' => '羅', '蘿' => '蘿', '螺' => '螺', '裸' => '裸', '邏' => '邏', '樂' => '樂', '洛' => '洛', '烙' => '烙', '珞' => '珞', '落' => '落', '酪' => '酪', '駱' => '駱', '亂' => '亂', '卵' => '卵', '欄' => '欄', '爛' => '爛', '蘭' => '蘭', '鸞' => '鸞', '嵐' => '嵐', '濫' => '濫', '藍' => '藍', '襤' => '襤', '拉' => '拉', '臘' => '臘', '蠟' => '蠟', '廊' => '廊', '朗' => '朗', '浪' => '浪', '狼' => '狼', '郎' => '郎', '來' => '來', '冷' => '冷', '勞' => '勞', '擄' => '擄', '櫓' => '櫓', '爐' => '爐', '盧' => '盧', '老' => '老', '蘆' => '蘆', '虜' => '虜', '路' => '路', '露' => '露', '魯' => '魯', '鷺' => '鷺', '碌' => '碌', '祿' => '祿', '綠' => '綠', '菉' => '菉', '錄' => '錄', '鹿' => '鹿', '論' => '論', '壟' => '壟', '弄' => '弄', '籠' => '籠', '聾' => '聾', '牢' => '牢', '磊' => '磊', '賂' => '賂', '雷' => '雷', '壘' => '壘', '屢' => '屢', '樓' => '樓', '淚' => '淚', '漏' => '漏', '累' => '累', '縷' => '縷', '陋' => '陋', '勒' => '勒', '肋' => '肋', '凜' => '凜', '凌' => '凌', '稜' => '稜', '綾' => '綾', '菱' => '菱', '陵' => '陵', '讀' => '讀', '拏' => '拏', '樂' => '樂', '諾' => '諾', '丹' => '丹', '寧' => '寧', '怒' => '怒', '率' => '率', '異' => '異', '北' => '北', '磻' => '磻', '便' => '便', '復' => '復', '不' => '不', '泌' => '泌', '數' => '數', '索' => '索', '參' => '參', '塞' => '塞', '省' => '省', '葉' => '葉', '說' => '說', '殺' => '殺', '辰' => '辰', '沈' => '沈', '拾' => '拾', '若' => '若', '掠' => '掠', '略' => '略', '亮' => '亮', '兩' => '兩', '凉' => '凉', '梁' => '梁', '糧' => '糧', '良' => '良', '諒' => '諒', '量' => '量', '勵' => '勵', '呂' => '呂', '女' => '女', '廬' => '廬', '旅' => '旅', '濾' => '濾', '礪' => '礪', '閭' => '閭', '驪' => '驪', '麗' => '麗', '黎' => '黎', '力' => '力', '曆' => '曆', '歷' => '歷', '轢' => '轢', '年' => '年', '憐' => '憐', '戀' => '戀', '撚' => '撚', '漣' => '漣', '煉' => '煉', '璉' => '璉', '秊' => '秊', '練' => '練', '聯' => '聯', '輦' => '輦', '蓮' => '蓮', '連' => '連', '鍊' => '鍊', '列' => '列', '劣' => '劣', '咽' => '咽', '烈' => '烈', '裂' => '裂', '說' => '說', '廉' => '廉', '念' => '念', '捻' => '捻', '殮' => '殮', '簾' => '簾', '獵' => '獵', '令' => '令', '囹' => '囹', '寧' => '寧', '嶺' => '嶺', '怜' => '怜', '玲' => '玲', '瑩' => '瑩', '羚' => '羚', '聆' => '聆', '鈴' => '鈴', '零' => '零', '靈' => '靈', '領' => '領', '例' => '例', '禮' => '禮', '醴' => '醴', '隸' => '隸', '惡' => '惡', '了' => '了', '僚' => '僚', '寮' => '寮', '尿' => '尿', '料' => '料', '樂' => '樂', '燎' => '燎', '療' => '療', '蓼' => '蓼', '遼' => '遼', '龍' => '龍', '暈' => '暈', '阮' => '阮', '劉' => '劉', '杻' => '杻', '柳' => '柳', '流' => '流', '溜' => '溜', '琉' => '琉', '留' => '留', '硫' => '硫', '紐' => '紐', '類' => '類', '六' => '六', '戮' => '戮', '陸' => '陸', '倫' => '倫', '崙' => '崙', '淪' => '淪', '輪' => '輪', '律' => '律', '慄' => '慄', '栗' => '栗', '率' => '率', '隆' => '隆', '利' => '利', '吏' => '吏', '履' => '履', '易' => '易', '李' => '李', '梨' => '梨', '泥' => '泥', '理' => '理', '痢' => '痢', '罹' => '罹', '裏' => '裏', '裡' => '裡', '里' => '里', '離' => '離', '匿' => '匿', '溺' => '溺', '吝' => '吝', '燐' => '燐', '璘' => '璘', '藺' => '藺', '隣' => '隣', '鱗' => '鱗', '麟' => '麟', '林' => '林', '淋' => '淋', '臨' => '臨', '立' => '立', '笠' => '笠', '粒' => '粒', '狀' => '狀', '炙' => '炙', '識' => '識', '什' => '什', '茶' => '茶', '刺' => '刺', '切' => '切', '度' => '度', '拓' => '拓', '糖' => '糖', '宅' => '宅', '洞' => '洞', '暴' => '暴', '輻' => '輻', '行' => '行', '降' => '降', '見' => '見', '廓' => '廓', '兀' => '兀', '嗀' => '嗀', '塚' => '塚', '晴' => '晴', '凞' => '凞', '猪' => '猪', '益' => '益', '礼' => '礼', '神' => '神', '祥' => '祥', '福' => '福', '靖' => '靖', '精' => '精', '羽' => '羽', '蘒' => '蘒', '諸' => '諸', '逸' => '逸', '都' => '都', '飯' => '飯', '飼' => '飼', '館' => '館', '鶴' => '鶴', '郞' => '郞', '隷' => '隷', '侮' => '侮', '僧' => '僧', '免' => '免', '勉' => '勉', '勤' => '勤', '卑' => '卑', '喝' => '喝', '嘆' => '嘆', '器' => '器', '塀' => '塀', '墨' => '墨', '層' => '層', '屮' => '屮', '悔' => '悔', '慨' => '慨', '憎' => '憎', '懲' => '懲', '敏' => '敏', '既' => '既', '暑' => '暑', '梅' => '梅', '海' => '海', '渚' => '渚', '漢' => '漢', '煮' => '煮', '爫' => '爫', '琢' => '琢', '碑' => '碑', '社' => '社', '祉' => '祉', '祈' => '祈', '祐' => '祐', '祖' => '祖', '祝' => '祝', '禍' => '禍', '禎' => '禎', '穀' => '穀', '突' => '突', '節' => '節', '練' => '練', '縉' => '縉', '繁' => '繁', '署' => '署', '者' => '者', '臭' => '臭', '艹' => '艹', '艹' => '艹', '著' => '著', '褐' => '褐', '視' => '視', '謁' => '謁', '謹' => '謹', '賓' => '賓', '贈' => '贈', '辶' => '辶', '逸' => '逸', '難' => '難', '響' => '響', '頻' => '頻', '恵' => '恵', '𤋮' => '𤋮', '舘' => '舘', '並' => '並', '况' => '况', '全' => '全', '侀' => '侀', '充' => '充', '冀' => '冀', '勇' => '勇', '勺' => '勺', '喝' => '喝', '啕' => '啕', '喙' => '喙', '嗢' => '嗢', '塚' => '塚', '墳' => '墳', '奄' => '奄', '奔' => '奔', '婢' => '婢', '嬨' => '嬨', '廒' => '廒', '廙' => '廙', '彩' => '彩', '徭' => '徭', '惘' => '惘', '慎' => '慎', '愈' => '愈', '憎' => '憎', '慠' => '慠', '懲' => '懲', '戴' => '戴', '揄' => '揄', '搜' => '搜', '摒' => '摒', '敖' => '敖', '晴' => '晴', '朗' => '朗', '望' => '望', '杖' => '杖', '歹' => '歹', '殺' => '殺', '流' => '流', '滛' => '滛', '滋' => '滋', '漢' => '漢', '瀞' => '瀞', '煮' => '煮', '瞧' => '瞧', '爵' => '爵', '犯' => '犯', '猪' => '猪', '瑱' => '瑱', '甆' => '甆', '画' => '画', '瘝' => '瘝', '瘟' => '瘟', '益' => '益', '盛' => '盛', '直' => '直', '睊' => '睊', '着' => '着', '磌' => '磌', '窱' => '窱', '節' => '節', '类' => '类', '絛' => '絛', '練' => '練', '缾' => '缾', '者' => '者', '荒' => '荒', '華' => '華', '蝹' => '蝹', '襁' => '襁', '覆' => '覆', '視' => '視', '調' => '調', '諸' => '諸', '請' => '請', '謁' => '謁', '諾' => '諾', '諭' => '諭', '謹' => '謹', '變' => '變', '贈' => '贈', '輸' => '輸', '遲' => '遲', '醙' => '醙', '鉶' => '鉶', '陼' => '陼', '難' => '難', '靖' => '靖', '韛' => '韛', '響' => '響', '頋' => '頋', '頻' => '頻', '鬒' => '鬒', '龜' => '龜', '𢡊' => '𢡊', '𢡄' => '𢡄', '𣏕' => '𣏕', '㮝' => '㮝', '䀘' => '䀘', '䀹' => '䀹', '𥉉' => '𥉉', '𥳐' => '𥳐', '𧻓' => '𧻓', '齃' => '齃', '龎' => '龎', 'יִ' => 'יִ', 'ײַ' => 'ײַ', 'שׁ' => 'שׁ', 'שׂ' => 'שׂ', 'שּׁ' => 'שּׁ', 'שּׂ' => 'שּׂ', 'אַ' => 'אַ', 'אָ' => 'אָ', 'אּ' => 'אּ', 'בּ' => 'בּ', 'גּ' => 'גּ', 'דּ' => 'דּ', 'הּ' => 'הּ', 'וּ' => 'וּ', 'זּ' => 'זּ', 'טּ' => 'טּ', 'יּ' => 'יּ', 'ךּ' => 'ךּ', 'כּ' => 'כּ', 'לּ' => 'לּ', 'מּ' => 'מּ', 'נּ' => 'נּ', 'סּ' => 'סּ', 'ףּ' => 'ףּ', 'פּ' => 'פּ', 'צּ' => 'צּ', 'קּ' => 'קּ', 'רּ' => 'רּ', 'שּ' => 'שּ', 'תּ' => 'תּ', 'וֹ' => 'וֹ', 'בֿ' => 'בֿ', 'כֿ' => 'כֿ', 'פֿ' => 'פֿ', '𑂚' => '𑂚', '𑂜' => '𑂜', '𑂫' => '𑂫', '𑄮' => '𑄮', '𑄯' => '𑄯', '𑍋' => '𑍋', '𑍌' => '𑍌', '𑒻' => '𑒻', '𑒼' => '𑒼', '𑒾' => '𑒾', '𑖺' => '𑖺', '𑖻' => '𑖻', '𑤸' => '𑤸', '𝅗𝅥' => '𝅗𝅥', '𝅘𝅥' => '𝅘𝅥', '𝅘𝅥𝅮' => '𝅘𝅥𝅮', '𝅘𝅥𝅯' => '𝅘𝅥𝅯', '𝅘𝅥𝅰' => '𝅘𝅥𝅰', '𝅘𝅥𝅱' => '𝅘𝅥𝅱', '𝅘𝅥𝅲' => '𝅘𝅥𝅲', '𝆹𝅥' => '𝆹𝅥', '𝆺𝅥' => '𝆺𝅥', '𝆹𝅥𝅮' => '𝆹𝅥𝅮', '𝆺𝅥𝅮' => '𝆺𝅥𝅮', '𝆹𝅥𝅯' => '𝆹𝅥𝅯', '𝆺𝅥𝅯' => '𝆺𝅥𝅯', '丽' => '丽', '丸' => '丸', '乁' => '乁', '𠄢' => '𠄢', '你' => '你', '侮' => '侮', '侻' => '侻', '倂' => '倂', '偺' => '偺', '備' => '備', '僧' => '僧', '像' => '像', '㒞' => '㒞', '𠘺' => '𠘺', '免' => '免', '兔' => '兔', '兤' => '兤', '具' => '具', '𠔜' => '𠔜', '㒹' => '㒹', '內' => '內', '再' => '再', '𠕋' => '𠕋', '冗' => '冗', '冤' => '冤', '仌' => '仌', '冬' => '冬', '况' => '况', '𩇟' => '𩇟', '凵' => '凵', '刃' => '刃', '㓟' => '㓟', '刻' => '刻', '剆' => '剆', '割' => '割', '剷' => '剷', '㔕' => '㔕', '勇' => '勇', '勉' => '勉', '勤' => '勤', '勺' => '勺', '包' => '包', '匆' => '匆', '北' => '北', '卉' => '卉', '卑' => '卑', '博' => '博', '即' => '即', '卽' => '卽', '卿' => '卿', '卿' => '卿', '卿' => '卿', '𠨬' => '𠨬', '灰' => '灰', '及' => '及', '叟' => '叟', '𠭣' => '𠭣', '叫' => '叫', '叱' => '叱', '吆' => '吆', '咞' => '咞', '吸' => '吸', '呈' => '呈', '周' => '周', '咢' => '咢', '哶' => '哶', '唐' => '唐', '啓' => '啓', '啣' => '啣', '善' => '善', '善' => '善', '喙' => '喙', '喫' => '喫', '喳' => '喳', '嗂' => '嗂', '圖' => '圖', '嘆' => '嘆', '圗' => '圗', '噑' => '噑', '噴' => '噴', '切' => '切', '壮' => '壮', '城' => '城', '埴' => '埴', '堍' => '堍', '型' => '型', '堲' => '堲', '報' => '報', '墬' => '墬', '𡓤' => '𡓤', '売' => '売', '壷' => '壷', '夆' => '夆', '多' => '多', '夢' => '夢', '奢' => '奢', '𡚨' => '𡚨', '𡛪' => '𡛪', '姬' => '姬', '娛' => '娛', '娧' => '娧', '姘' => '姘', '婦' => '婦', '㛮' => '㛮', '㛼' => '㛼', '嬈' => '嬈', '嬾' => '嬾', '嬾' => '嬾', '𡧈' => '𡧈', '寃' => '寃', '寘' => '寘', '寧' => '寧', '寳' => '寳', '𡬘' => '𡬘', '寿' => '寿', '将' => '将', '当' => '当', '尢' => '尢', '㞁' => '㞁', '屠' => '屠', '屮' => '屮', '峀' => '峀', '岍' => '岍', '𡷤' => '𡷤', '嵃' => '嵃', '𡷦' => '𡷦', '嵮' => '嵮', '嵫' => '嵫', '嵼' => '嵼', '巡' => '巡', '巢' => '巢', '㠯' => '㠯', '巽' => '巽', '帨' => '帨', '帽' => '帽', '幩' => '幩', '㡢' => '㡢', '𢆃' => '𢆃', '㡼' => '㡼', '庰' => '庰', '庳' => '庳', '庶' => '庶', '廊' => '廊', '𪎒' => '𪎒', '廾' => '廾', '𢌱' => '𢌱', '𢌱' => '𢌱', '舁' => '舁', '弢' => '弢', '弢' => '弢', '㣇' => '㣇', '𣊸' => '𣊸', '𦇚' => '𦇚', '形' => '形', '彫' => '彫', '㣣' => '㣣', '徚' => '徚', '忍' => '忍', '志' => '志', '忹' => '忹', '悁' => '悁', '㤺' => '㤺', '㤜' => '㤜', '悔' => '悔', '𢛔' => '𢛔', '惇' => '惇', '慈' => '慈', '慌' => '慌', '慎' => '慎', '慌' => '慌', '慺' => '慺', '憎' => '憎', '憲' => '憲', '憤' => '憤', '憯' => '憯', '懞' => '懞', '懲' => '懲', '懶' => '懶', '成' => '成', '戛' => '戛', '扝' => '扝', '抱' => '抱', '拔' => '拔', '捐' => '捐', '𢬌' => '𢬌', '挽' => '挽', '拼' => '拼', '捨' => '捨', '掃' => '掃', '揤' => '揤', '𢯱' => '𢯱', '搢' => '搢', '揅' => '揅', '掩' => '掩', '㨮' => '㨮', '摩' => '摩', '摾' => '摾', '撝' => '撝', '摷' => '摷', '㩬' => '㩬', '敏' => '敏', '敬' => '敬', '𣀊' => '𣀊', '旣' => '旣', '書' => '書', '晉' => '晉', '㬙' => '㬙', '暑' => '暑', '㬈' => '㬈', '㫤' => '㫤', '冒' => '冒', '冕' => '冕', '最' => '最', '暜' => '暜', '肭' => '肭', '䏙' => '䏙', '朗' => '朗', '望' => '望', '朡' => '朡', '杞' => '杞', '杓' => '杓', '𣏃' => '𣏃', '㭉' => '㭉', '柺' => '柺', '枅' => '枅', '桒' => '桒', '梅' => '梅', '𣑭' => '𣑭', '梎' => '梎', '栟' => '栟', '椔' => '椔', '㮝' => '㮝', '楂' => '楂', '榣' => '榣', '槪' => '槪', '檨' => '檨', '𣚣' => '𣚣', '櫛' => '櫛', '㰘' => '㰘', '次' => '次', '𣢧' => '𣢧', '歔' => '歔', '㱎' => '㱎', '歲' => '歲', '殟' => '殟', '殺' => '殺', '殻' => '殻', '𣪍' => '𣪍', '𡴋' => '𡴋', '𣫺' => '𣫺', '汎' => '汎', '𣲼' => '𣲼', '沿' => '沿', '泍' => '泍', '汧' => '汧', '洖' => '洖', '派' => '派', '海' => '海', '流' => '流', '浩' => '浩', '浸' => '浸', '涅' => '涅', '𣴞' => '𣴞', '洴' => '洴', '港' => '港', '湮' => '湮', '㴳' => '㴳', '滋' => '滋', '滇' => '滇', '𣻑' => '𣻑', '淹' => '淹', '潮' => '潮', '𣽞' => '𣽞', '𣾎' => '𣾎', '濆' => '濆', '瀹' => '瀹', '瀞' => '瀞', '瀛' => '瀛', '㶖' => '㶖', '灊' => '灊', '災' => '災', '灷' => '灷', '炭' => '炭', '𠔥' => '𠔥', '煅' => '煅', '𤉣' => '𤉣', '熜' => '熜', '𤎫' => '𤎫', '爨' => '爨', '爵' => '爵', '牐' => '牐', '𤘈' => '𤘈', '犀' => '犀', '犕' => '犕', '𤜵' => '𤜵', '𤠔' => '𤠔', '獺' => '獺', '王' => '王', '㺬' => '㺬', '玥' => '玥', '㺸' => '㺸', '㺸' => '㺸', '瑇' => '瑇', '瑜' => '瑜', '瑱' => '瑱', '璅' => '璅', '瓊' => '瓊', '㼛' => '㼛', '甤' => '甤', '𤰶' => '𤰶', '甾' => '甾', '𤲒' => '𤲒', '異' => '異', '𢆟' => '𢆟', '瘐' => '瘐', '𤾡' => '𤾡', '𤾸' => '𤾸', '𥁄' => '𥁄', '㿼' => '㿼', '䀈' => '䀈', '直' => '直', '𥃳' => '𥃳', '𥃲' => '𥃲', '𥄙' => '𥄙', '𥄳' => '𥄳', '眞' => '眞', '真' => '真', '真' => '真', '睊' => '睊', '䀹' => '䀹', '瞋' => '瞋', '䁆' => '䁆', '䂖' => '䂖', '𥐝' => '𥐝', '硎' => '硎', '碌' => '碌', '磌' => '磌', '䃣' => '䃣', '𥘦' => '𥘦', '祖' => '祖', '𥚚' => '𥚚', '𥛅' => '𥛅', '福' => '福', '秫' => '秫', '䄯' => '䄯', '穀' => '穀', '穊' => '穊', '穏' => '穏', '𥥼' => '𥥼', '𥪧' => '𥪧', '𥪧' => '𥪧', '竮' => '竮', '䈂' => '䈂', '𥮫' => '𥮫', '篆' => '篆', '築' => '築', '䈧' => '䈧', '𥲀' => '𥲀', '糒' => '糒', '䊠' => '䊠', '糨' => '糨', '糣' => '糣', '紀' => '紀', '𥾆' => '𥾆', '絣' => '絣', '䌁' => '䌁', '緇' => '緇', '縂' => '縂', '繅' => '繅', '䌴' => '䌴', '𦈨' => '𦈨', '𦉇' => '𦉇', '䍙' => '䍙', '𦋙' => '𦋙', '罺' => '罺', '𦌾' => '𦌾', '羕' => '羕', '翺' => '翺', '者' => '者', '𦓚' => '𦓚', '𦔣' => '𦔣', '聠' => '聠', '𦖨' => '𦖨', '聰' => '聰', '𣍟' => '𣍟', '䏕' => '䏕', '育' => '育', '脃' => '脃', '䐋' => '䐋', '脾' => '脾', '媵' => '媵', '𦞧' => '𦞧', '𦞵' => '𦞵', '𣎓' => '𣎓', '𣎜' => '𣎜', '舁' => '舁', '舄' => '舄', '辞' => '辞', '䑫' => '䑫', '芑' => '芑', '芋' => '芋', '芝' => '芝', '劳' => '劳', '花' => '花', '芳' => '芳', '芽' => '芽', '苦' => '苦', '𦬼' => '𦬼', '若' => '若', '茝' => '茝', '荣' => '荣', '莭' => '莭', '茣' => '茣', '莽' => '莽', '菧' => '菧', '著' => '著', '荓' => '荓', '菊' => '菊', '菌' => '菌', '菜' => '菜', '𦰶' => '𦰶', '𦵫' => '𦵫', '𦳕' => '𦳕', '䔫' => '䔫', '蓱' => '蓱', '蓳' => '蓳', '蔖' => '蔖', '𧏊' => '𧏊', '蕤' => '蕤', '𦼬' => '𦼬', '䕝' => '䕝', '䕡' => '䕡', '𦾱' => '𦾱', '𧃒' => '𧃒', '䕫' => '䕫', '虐' => '虐', '虜' => '虜', '虧' => '虧', '虩' => '虩', '蚩' => '蚩', '蚈' => '蚈', '蜎' => '蜎', '蛢' => '蛢', '蝹' => '蝹', '蜨' => '蜨', '蝫' => '蝫', '螆' => '螆', '䗗' => '䗗', '蟡' => '蟡', '蠁' => '蠁', '䗹' => '䗹', '衠' => '衠', '衣' => '衣', '𧙧' => '𧙧', '裗' => '裗', '裞' => '裞', '䘵' => '䘵', '裺' => '裺', '㒻' => '㒻', '𧢮' => '𧢮', '𧥦' => '𧥦', '䚾' => '䚾', '䛇' => '䛇', '誠' => '誠', '諭' => '諭', '變' => '變', '豕' => '豕', '𧲨' => '𧲨', '貫' => '貫', '賁' => '賁', '贛' => '贛', '起' => '起', '𧼯' => '𧼯', '𠠄' => '𠠄', '跋' => '跋', '趼' => '趼', '跰' => '跰', '𠣞' => '𠣞', '軔' => '軔', '輸' => '輸', '𨗒' => '𨗒', '𨗭' => '𨗭', '邔' => '邔', '郱' => '郱', '鄑' => '鄑', '𨜮' => '𨜮', '鄛' => '鄛', '鈸' => '鈸', '鋗' => '鋗', '鋘' => '鋘', '鉼' => '鉼', '鏹' => '鏹', '鐕' => '鐕', '𨯺' => '𨯺', '開' => '開', '䦕' => '䦕', '閷' => '閷', '𨵷' => '𨵷', '䧦' => '䧦', '雃' => '雃', '嶲' => '嶲', '霣' => '霣', '𩅅' => '𩅅', '𩈚' => '𩈚', '䩮' => '䩮', '䩶' => '䩶', '韠' => '韠', '𩐊' => '𩐊', '䪲' => '䪲', '𩒖' => '𩒖', '頋' => '頋', '頋' => '頋', '頩' => '頩', '𩖶' => '𩖶', '飢' => '飢', '䬳' => '䬳', '餩' => '餩', '馧' => '馧', '駂' => '駂', '駾' => '駾', '䯎' => '䯎', '𩬰' => '𩬰', '鬒' => '鬒', '鱀' => '鱀', '鳽' => '鳽', '䳎' => '䳎', '䳭' => '䳭', '鵧' => '鵧', '𪃎' => '𪃎', '䳸' => '䳸', '𪄅' => '𪄅', '𪈎' => '𪈎', '𪊑' => '𪊑', '麻' => '麻', '䵖' => '䵖', '黹' => '黹', '黾' => '黾', '鼅' => '鼅', '鼏' => '鼏', '鼖' => '鼖', '鼻' => '鼻', '𪘀' => '𪘀', ); polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php000064400000202557150432043200023244 0ustar00 ' ', '¨' => ' ̈', 'ª' => 'a', '¯' => ' ̄', '²' => '2', '³' => '3', '´' => ' ́', 'µ' => 'μ', '¸' => ' ̧', '¹' => '1', 'º' => 'o', '¼' => '1⁄4', '½' => '1⁄2', '¾' => '3⁄4', 'IJ' => 'IJ', 'ij' => 'ij', 'Ŀ' => 'L·', 'ŀ' => 'l·', 'ʼn' => 'ʼn', 'ſ' => 's', 'DŽ' => 'DŽ', 'Dž' => 'Dž', 'dž' => 'dž', 'LJ' => 'LJ', 'Lj' => 'Lj', 'lj' => 'lj', 'NJ' => 'NJ', 'Nj' => 'Nj', 'nj' => 'nj', 'DZ' => 'DZ', 'Dz' => 'Dz', 'dz' => 'dz', 'ʰ' => 'h', 'ʱ' => 'ɦ', 'ʲ' => 'j', 'ʳ' => 'r', 'ʴ' => 'ɹ', 'ʵ' => 'ɻ', 'ʶ' => 'ʁ', 'ʷ' => 'w', 'ʸ' => 'y', '˘' => ' ̆', '˙' => ' ̇', '˚' => ' ̊', '˛' => ' ̨', '˜' => ' ̃', '˝' => ' ̋', 'ˠ' => 'ɣ', 'ˡ' => 'l', 'ˢ' => 's', 'ˣ' => 'x', 'ˤ' => 'ʕ', 'ͺ' => ' ͅ', '΄' => ' ́', '΅' => ' ̈́', 'ϐ' => 'β', 'ϑ' => 'θ', 'ϒ' => 'Υ', 'ϓ' => 'Ύ', 'ϔ' => 'Ϋ', 'ϕ' => 'φ', 'ϖ' => 'π', 'ϰ' => 'κ', 'ϱ' => 'ρ', 'ϲ' => 'ς', 'ϴ' => 'Θ', 'ϵ' => 'ε', 'Ϲ' => 'Σ', 'և' => 'եւ', 'ٵ' => 'اٴ', 'ٶ' => 'وٴ', 'ٷ' => 'ۇٴ', 'ٸ' => 'يٴ', 'ำ' => 'ํา', 'ຳ' => 'ໍາ', 'ໜ' => 'ຫນ', 'ໝ' => 'ຫມ', '༌' => '་', 'ཷ' => 'ྲཱྀ', 'ཹ' => 'ླཱྀ', 'ჼ' => 'ნ', 'ᴬ' => 'A', 'ᴭ' => 'Æ', 'ᴮ' => 'B', 'ᴰ' => 'D', 'ᴱ' => 'E', 'ᴲ' => 'Ǝ', 'ᴳ' => 'G', 'ᴴ' => 'H', 'ᴵ' => 'I', 'ᴶ' => 'J', 'ᴷ' => 'K', 'ᴸ' => 'L', 'ᴹ' => 'M', 'ᴺ' => 'N', 'ᴼ' => 'O', 'ᴽ' => 'Ȣ', 'ᴾ' => 'P', 'ᴿ' => 'R', 'ᵀ' => 'T', 'ᵁ' => 'U', 'ᵂ' => 'W', 'ᵃ' => 'a', 'ᵄ' => 'ɐ', 'ᵅ' => 'ɑ', 'ᵆ' => 'ᴂ', 'ᵇ' => 'b', 'ᵈ' => 'd', 'ᵉ' => 'e', 'ᵊ' => 'ə', 'ᵋ' => 'ɛ', 'ᵌ' => 'ɜ', 'ᵍ' => 'g', 'ᵏ' => 'k', 'ᵐ' => 'm', 'ᵑ' => 'ŋ', 'ᵒ' => 'o', 'ᵓ' => 'ɔ', 'ᵔ' => 'ᴖ', 'ᵕ' => 'ᴗ', 'ᵖ' => 'p', 'ᵗ' => 't', 'ᵘ' => 'u', 'ᵙ' => 'ᴝ', 'ᵚ' => 'ɯ', 'ᵛ' => 'v', 'ᵜ' => 'ᴥ', 'ᵝ' => 'β', 'ᵞ' => 'γ', 'ᵟ' => 'δ', 'ᵠ' => 'φ', 'ᵡ' => 'χ', 'ᵢ' => 'i', 'ᵣ' => 'r', 'ᵤ' => 'u', 'ᵥ' => 'v', 'ᵦ' => 'β', 'ᵧ' => 'γ', 'ᵨ' => 'ρ', 'ᵩ' => 'φ', 'ᵪ' => 'χ', 'ᵸ' => 'н', 'ᶛ' => 'ɒ', 'ᶜ' => 'c', 'ᶝ' => 'ɕ', 'ᶞ' => 'ð', 'ᶟ' => 'ɜ', 'ᶠ' => 'f', 'ᶡ' => 'ɟ', 'ᶢ' => 'ɡ', 'ᶣ' => 'ɥ', 'ᶤ' => 'ɨ', 'ᶥ' => 'ɩ', 'ᶦ' => 'ɪ', 'ᶧ' => 'ᵻ', 'ᶨ' => 'ʝ', 'ᶩ' => 'ɭ', 'ᶪ' => 'ᶅ', 'ᶫ' => 'ʟ', 'ᶬ' => 'ɱ', 'ᶭ' => 'ɰ', 'ᶮ' => 'ɲ', 'ᶯ' => 'ɳ', 'ᶰ' => 'ɴ', 'ᶱ' => 'ɵ', 'ᶲ' => 'ɸ', 'ᶳ' => 'ʂ', 'ᶴ' => 'ʃ', 'ᶵ' => 'ƫ', 'ᶶ' => 'ʉ', 'ᶷ' => 'ʊ', 'ᶸ' => 'ᴜ', 'ᶹ' => 'ʋ', 'ᶺ' => 'ʌ', 'ᶻ' => 'z', 'ᶼ' => 'ʐ', 'ᶽ' => 'ʑ', 'ᶾ' => 'ʒ', 'ᶿ' => 'θ', 'ẚ' => 'aʾ', 'ẛ' => 'ṡ', '᾽' => ' ̓', '᾿' => ' ̓', '῀' => ' ͂', '῁' => ' ̈͂', '῍' => ' ̓̀', '῎' => ' ̓́', '῏' => ' ̓͂', '῝' => ' ̔̀', '῞' => ' ̔́', '῟' => ' ̔͂', '῭' => ' ̈̀', '΅' => ' ̈́', '´' => ' ́', '῾' => ' ̔', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', ' ' => ' ', '‑' => '‐', '‗' => ' ̳', '․' => '.', '‥' => '..', '…' => '...', ' ' => ' ', '″' => '′′', '‴' => '′′′', '‶' => '‵‵', '‷' => '‵‵‵', '‼' => '!!', '‾' => ' ̅', '⁇' => '??', '⁈' => '?!', '⁉' => '!?', '⁗' => '′′′′', ' ' => ' ', '⁰' => '0', 'ⁱ' => 'i', '⁴' => '4', '⁵' => '5', '⁶' => '6', '⁷' => '7', '⁸' => '8', '⁹' => '9', '⁺' => '+', '⁻' => '−', '⁼' => '=', '⁽' => '(', '⁾' => ')', 'ⁿ' => 'n', '₀' => '0', '₁' => '1', '₂' => '2', '₃' => '3', '₄' => '4', '₅' => '5', '₆' => '6', '₇' => '7', '₈' => '8', '₉' => '9', '₊' => '+', '₋' => '−', '₌' => '=', '₍' => '(', '₎' => ')', 'ₐ' => 'a', 'ₑ' => 'e', 'ₒ' => 'o', 'ₓ' => 'x', 'ₔ' => 'ə', 'ₕ' => 'h', 'ₖ' => 'k', 'ₗ' => 'l', 'ₘ' => 'm', 'ₙ' => 'n', 'ₚ' => 'p', 'ₛ' => 's', 'ₜ' => 't', '₨' => 'Rs', '℀' => 'a/c', '℁' => 'a/s', 'ℂ' => 'C', '℃' => '°C', '℅' => 'c/o', '℆' => 'c/u', 'ℇ' => 'Ɛ', '℉' => '°F', 'ℊ' => 'g', 'ℋ' => 'H', 'ℌ' => 'H', 'ℍ' => 'H', 'ℎ' => 'h', 'ℏ' => 'ħ', 'ℐ' => 'I', 'ℑ' => 'I', 'ℒ' => 'L', 'ℓ' => 'l', 'ℕ' => 'N', '№' => 'No', 'ℙ' => 'P', 'ℚ' => 'Q', 'ℛ' => 'R', 'ℜ' => 'R', 'ℝ' => 'R', '℠' => 'SM', '℡' => 'TEL', '™' => 'TM', 'ℤ' => 'Z', 'ℨ' => 'Z', 'ℬ' => 'B', 'ℭ' => 'C', 'ℯ' => 'e', 'ℰ' => 'E', 'ℱ' => 'F', 'ℳ' => 'M', 'ℴ' => 'o', 'ℵ' => 'א', 'ℶ' => 'ב', 'ℷ' => 'ג', 'ℸ' => 'ד', 'ℹ' => 'i', '℻' => 'FAX', 'ℼ' => 'π', 'ℽ' => 'γ', 'ℾ' => 'Γ', 'ℿ' => 'Π', '⅀' => '∑', 'ⅅ' => 'D', 'ⅆ' => 'd', 'ⅇ' => 'e', 'ⅈ' => 'i', 'ⅉ' => 'j', '⅐' => '1⁄7', '⅑' => '1⁄9', '⅒' => '1⁄10', '⅓' => '1⁄3', '⅔' => '2⁄3', '⅕' => '1⁄5', '⅖' => '2⁄5', '⅗' => '3⁄5', '⅘' => '4⁄5', '⅙' => '1⁄6', '⅚' => '5⁄6', '⅛' => '1⁄8', '⅜' => '3⁄8', '⅝' => '5⁄8', '⅞' => '7⁄8', '⅟' => '1⁄', 'Ⅰ' => 'I', 'Ⅱ' => 'II', 'Ⅲ' => 'III', 'Ⅳ' => 'IV', 'Ⅴ' => 'V', 'Ⅵ' => 'VI', 'Ⅶ' => 'VII', 'Ⅷ' => 'VIII', 'Ⅸ' => 'IX', 'Ⅹ' => 'X', 'Ⅺ' => 'XI', 'Ⅻ' => 'XII', 'Ⅼ' => 'L', 'Ⅽ' => 'C', 'Ⅾ' => 'D', 'Ⅿ' => 'M', 'ⅰ' => 'i', 'ⅱ' => 'ii', 'ⅲ' => 'iii', 'ⅳ' => 'iv', 'ⅴ' => 'v', 'ⅵ' => 'vi', 'ⅶ' => 'vii', 'ⅷ' => 'viii', 'ⅸ' => 'ix', 'ⅹ' => 'x', 'ⅺ' => 'xi', 'ⅻ' => 'xii', 'ⅼ' => 'l', 'ⅽ' => 'c', 'ⅾ' => 'd', 'ⅿ' => 'm', '↉' => '0⁄3', '∬' => '∫∫', '∭' => '∫∫∫', '∯' => '∮∮', '∰' => '∮∮∮', '①' => '1', '②' => '2', '③' => '3', '④' => '4', '⑤' => '5', '⑥' => '6', '⑦' => '7', '⑧' => '8', '⑨' => '9', '⑩' => '10', '⑪' => '11', '⑫' => '12', '⑬' => '13', '⑭' => '14', '⑮' => '15', '⑯' => '16', '⑰' => '17', '⑱' => '18', '⑲' => '19', '⑳' => '20', '⑴' => '(1)', '⑵' => '(2)', '⑶' => '(3)', '⑷' => '(4)', '⑸' => '(5)', '⑹' => '(6)', '⑺' => '(7)', '⑻' => '(8)', '⑼' => '(9)', '⑽' => '(10)', '⑾' => '(11)', '⑿' => '(12)', '⒀' => '(13)', '⒁' => '(14)', '⒂' => '(15)', '⒃' => '(16)', '⒄' => '(17)', '⒅' => '(18)', '⒆' => '(19)', '⒇' => '(20)', '⒈' => '1.', '⒉' => '2.', '⒊' => '3.', '⒋' => '4.', '⒌' => '5.', '⒍' => '6.', '⒎' => '7.', '⒏' => '8.', '⒐' => '9.', '⒑' => '10.', '⒒' => '11.', '⒓' => '12.', '⒔' => '13.', '⒕' => '14.', '⒖' => '15.', '⒗' => '16.', '⒘' => '17.', '⒙' => '18.', '⒚' => '19.', '⒛' => '20.', '⒜' => '(a)', '⒝' => '(b)', '⒞' => '(c)', '⒟' => '(d)', '⒠' => '(e)', '⒡' => '(f)', '⒢' => '(g)', '⒣' => '(h)', '⒤' => '(i)', '⒥' => '(j)', '⒦' => '(k)', '⒧' => '(l)', '⒨' => '(m)', '⒩' => '(n)', '⒪' => '(o)', '⒫' => '(p)', '⒬' => '(q)', '⒭' => '(r)', '⒮' => '(s)', '⒯' => '(t)', '⒰' => '(u)', '⒱' => '(v)', '⒲' => '(w)', '⒳' => '(x)', '⒴' => '(y)', '⒵' => '(z)', 'Ⓐ' => 'A', 'Ⓑ' => 'B', 'Ⓒ' => 'C', 'Ⓓ' => 'D', 'Ⓔ' => 'E', 'Ⓕ' => 'F', 'Ⓖ' => 'G', 'Ⓗ' => 'H', 'Ⓘ' => 'I', 'Ⓙ' => 'J', 'Ⓚ' => 'K', 'Ⓛ' => 'L', 'Ⓜ' => 'M', 'Ⓝ' => 'N', 'Ⓞ' => 'O', 'Ⓟ' => 'P', 'Ⓠ' => 'Q', 'Ⓡ' => 'R', 'Ⓢ' => 'S', 'Ⓣ' => 'T', 'Ⓤ' => 'U', 'Ⓥ' => 'V', 'Ⓦ' => 'W', 'Ⓧ' => 'X', 'Ⓨ' => 'Y', 'Ⓩ' => 'Z', 'ⓐ' => 'a', 'ⓑ' => 'b', 'ⓒ' => 'c', 'ⓓ' => 'd', 'ⓔ' => 'e', 'ⓕ' => 'f', 'ⓖ' => 'g', 'ⓗ' => 'h', 'ⓘ' => 'i', 'ⓙ' => 'j', 'ⓚ' => 'k', 'ⓛ' => 'l', 'ⓜ' => 'm', 'ⓝ' => 'n', 'ⓞ' => 'o', 'ⓟ' => 'p', 'ⓠ' => 'q', 'ⓡ' => 'r', 'ⓢ' => 's', 'ⓣ' => 't', 'ⓤ' => 'u', 'ⓥ' => 'v', 'ⓦ' => 'w', 'ⓧ' => 'x', 'ⓨ' => 'y', 'ⓩ' => 'z', '⓪' => '0', '⨌' => '∫∫∫∫', '⩴' => '::=', '⩵' => '==', '⩶' => '===', 'ⱼ' => 'j', 'ⱽ' => 'V', 'ⵯ' => 'ⵡ', '⺟' => '母', '⻳' => '龟', '⼀' => '一', '⼁' => '丨', '⼂' => '丶', '⼃' => '丿', '⼄' => '乙', '⼅' => '亅', '⼆' => '二', '⼇' => '亠', '⼈' => '人', '⼉' => '儿', '⼊' => '入', '⼋' => '八', '⼌' => '冂', '⼍' => '冖', '⼎' => '冫', '⼏' => '几', '⼐' => '凵', '⼑' => '刀', '⼒' => '力', '⼓' => '勹', '⼔' => '匕', '⼕' => '匚', '⼖' => '匸', '⼗' => '十', '⼘' => '卜', '⼙' => '卩', '⼚' => '厂', '⼛' => '厶', '⼜' => '又', '⼝' => '口', '⼞' => '囗', '⼟' => '土', '⼠' => '士', '⼡' => '夂', '⼢' => '夊', '⼣' => '夕', '⼤' => '大', '⼥' => '女', '⼦' => '子', '⼧' => '宀', '⼨' => '寸', '⼩' => '小', '⼪' => '尢', '⼫' => '尸', '⼬' => '屮', '⼭' => '山', '⼮' => '巛', '⼯' => '工', '⼰' => '己', '⼱' => '巾', '⼲' => '干', '⼳' => '幺', '⼴' => '广', '⼵' => '廴', '⼶' => '廾', '⼷' => '弋', '⼸' => '弓', '⼹' => '彐', '⼺' => '彡', '⼻' => '彳', '⼼' => '心', '⼽' => '戈', '⼾' => '戶', '⼿' => '手', '⽀' => '支', '⽁' => '攴', '⽂' => '文', '⽃' => '斗', '⽄' => '斤', '⽅' => '方', '⽆' => '无', '⽇' => '日', '⽈' => '曰', '⽉' => '月', '⽊' => '木', '⽋' => '欠', '⽌' => '止', '⽍' => '歹', '⽎' => '殳', '⽏' => '毋', '⽐' => '比', '⽑' => '毛', '⽒' => '氏', '⽓' => '气', '⽔' => '水', '⽕' => '火', '⽖' => '爪', '⽗' => '父', '⽘' => '爻', '⽙' => '爿', '⽚' => '片', '⽛' => '牙', '⽜' => '牛', '⽝' => '犬', '⽞' => '玄', '⽟' => '玉', '⽠' => '瓜', '⽡' => '瓦', '⽢' => '甘', '⽣' => '生', '⽤' => '用', '⽥' => '田', '⽦' => '疋', '⽧' => '疒', '⽨' => '癶', '⽩' => '白', '⽪' => '皮', '⽫' => '皿', '⽬' => '目', '⽭' => '矛', '⽮' => '矢', '⽯' => '石', '⽰' => '示', '⽱' => '禸', '⽲' => '禾', '⽳' => '穴', '⽴' => '立', '⽵' => '竹', '⽶' => '米', '⽷' => '糸', '⽸' => '缶', '⽹' => '网', '⽺' => '羊', '⽻' => '羽', '⽼' => '老', '⽽' => '而', '⽾' => '耒', '⽿' => '耳', '⾀' => '聿', '⾁' => '肉', '⾂' => '臣', '⾃' => '自', '⾄' => '至', '⾅' => '臼', '⾆' => '舌', '⾇' => '舛', '⾈' => '舟', '⾉' => '艮', '⾊' => '色', '⾋' => '艸', '⾌' => '虍', '⾍' => '虫', '⾎' => '血', '⾏' => '行', '⾐' => '衣', '⾑' => '襾', '⾒' => '見', '⾓' => '角', '⾔' => '言', '⾕' => '谷', '⾖' => '豆', '⾗' => '豕', '⾘' => '豸', '⾙' => '貝', '⾚' => '赤', '⾛' => '走', '⾜' => '足', '⾝' => '身', '⾞' => '車', '⾟' => '辛', '⾠' => '辰', '⾡' => '辵', '⾢' => '邑', '⾣' => '酉', '⾤' => '釆', '⾥' => '里', '⾦' => '金', '⾧' => '長', '⾨' => '門', '⾩' => '阜', '⾪' => '隶', '⾫' => '隹', '⾬' => '雨', '⾭' => '靑', '⾮' => '非', '⾯' => '面', '⾰' => '革', '⾱' => '韋', '⾲' => '韭', '⾳' => '音', '⾴' => '頁', '⾵' => '風', '⾶' => '飛', '⾷' => '食', '⾸' => '首', '⾹' => '香', '⾺' => '馬', '⾻' => '骨', '⾼' => '高', '⾽' => '髟', '⾾' => '鬥', '⾿' => '鬯', '⿀' => '鬲', '⿁' => '鬼', '⿂' => '魚', '⿃' => '鳥', '⿄' => '鹵', '⿅' => '鹿', '⿆' => '麥', '⿇' => '麻', '⿈' => '黃', '⿉' => '黍', '⿊' => '黑', '⿋' => '黹', '⿌' => '黽', '⿍' => '鼎', '⿎' => '鼓', '⿏' => '鼠', '⿐' => '鼻', '⿑' => '齊', '⿒' => '齒', '⿓' => '龍', '⿔' => '龜', '⿕' => '龠', ' ' => ' ', '〶' => '〒', '〸' => '十', '〹' => '卄', '〺' => '卅', '゛' => ' ゙', '゜' => ' ゚', 'ゟ' => 'より', 'ヿ' => 'コト', 'ㄱ' => 'ᄀ', 'ㄲ' => 'ᄁ', 'ㄳ' => 'ᆪ', 'ㄴ' => 'ᄂ', 'ㄵ' => 'ᆬ', 'ㄶ' => 'ᆭ', 'ㄷ' => 'ᄃ', 'ㄸ' => 'ᄄ', 'ㄹ' => 'ᄅ', 'ㄺ' => 'ᆰ', 'ㄻ' => 'ᆱ', 'ㄼ' => 'ᆲ', 'ㄽ' => 'ᆳ', 'ㄾ' => 'ᆴ', 'ㄿ' => 'ᆵ', 'ㅀ' => 'ᄚ', 'ㅁ' => 'ᄆ', 'ㅂ' => 'ᄇ', 'ㅃ' => 'ᄈ', 'ㅄ' => 'ᄡ', 'ㅅ' => 'ᄉ', 'ㅆ' => 'ᄊ', 'ㅇ' => 'ᄋ', 'ㅈ' => 'ᄌ', 'ㅉ' => 'ᄍ', 'ㅊ' => 'ᄎ', 'ㅋ' => 'ᄏ', 'ㅌ' => 'ᄐ', 'ㅍ' => 'ᄑ', 'ㅎ' => 'ᄒ', 'ㅏ' => 'ᅡ', 'ㅐ' => 'ᅢ', 'ㅑ' => 'ᅣ', 'ㅒ' => 'ᅤ', 'ㅓ' => 'ᅥ', 'ㅔ' => 'ᅦ', 'ㅕ' => 'ᅧ', 'ㅖ' => 'ᅨ', 'ㅗ' => 'ᅩ', 'ㅘ' => 'ᅪ', 'ㅙ' => 'ᅫ', 'ㅚ' => 'ᅬ', 'ㅛ' => 'ᅭ', 'ㅜ' => 'ᅮ', 'ㅝ' => 'ᅯ', 'ㅞ' => 'ᅰ', 'ㅟ' => 'ᅱ', 'ㅠ' => 'ᅲ', 'ㅡ' => 'ᅳ', 'ㅢ' => 'ᅴ', 'ㅣ' => 'ᅵ', 'ㅤ' => 'ᅠ', 'ㅥ' => 'ᄔ', 'ㅦ' => 'ᄕ', 'ㅧ' => 'ᇇ', 'ㅨ' => 'ᇈ', 'ㅩ' => 'ᇌ', 'ㅪ' => 'ᇎ', 'ㅫ' => 'ᇓ', 'ㅬ' => 'ᇗ', 'ㅭ' => 'ᇙ', 'ㅮ' => 'ᄜ', 'ㅯ' => 'ᇝ', 'ㅰ' => 'ᇟ', 'ㅱ' => 'ᄝ', 'ㅲ' => 'ᄞ', 'ㅳ' => 'ᄠ', 'ㅴ' => 'ᄢ', 'ㅵ' => 'ᄣ', 'ㅶ' => 'ᄧ', 'ㅷ' => 'ᄩ', 'ㅸ' => 'ᄫ', 'ㅹ' => 'ᄬ', 'ㅺ' => 'ᄭ', 'ㅻ' => 'ᄮ', 'ㅼ' => 'ᄯ', 'ㅽ' => 'ᄲ', 'ㅾ' => 'ᄶ', 'ㅿ' => 'ᅀ', 'ㆀ' => 'ᅇ', 'ㆁ' => 'ᅌ', 'ㆂ' => 'ᇱ', 'ㆃ' => 'ᇲ', 'ㆄ' => 'ᅗ', 'ㆅ' => 'ᅘ', 'ㆆ' => 'ᅙ', 'ㆇ' => 'ᆄ', 'ㆈ' => 'ᆅ', 'ㆉ' => 'ᆈ', 'ㆊ' => 'ᆑ', 'ㆋ' => 'ᆒ', 'ㆌ' => 'ᆔ', 'ㆍ' => 'ᆞ', 'ㆎ' => 'ᆡ', '㆒' => '一', '㆓' => '二', '㆔' => '三', '㆕' => '四', '㆖' => '上', '㆗' => '中', '㆘' => '下', '㆙' => '甲', '㆚' => '乙', '㆛' => '丙', '㆜' => '丁', '㆝' => '天', '㆞' => '地', '㆟' => '人', '㈀' => '(ᄀ)', '㈁' => '(ᄂ)', '㈂' => '(ᄃ)', '㈃' => '(ᄅ)', '㈄' => '(ᄆ)', '㈅' => '(ᄇ)', '㈆' => '(ᄉ)', '㈇' => '(ᄋ)', '㈈' => '(ᄌ)', '㈉' => '(ᄎ)', '㈊' => '(ᄏ)', '㈋' => '(ᄐ)', '㈌' => '(ᄑ)', '㈍' => '(ᄒ)', '㈎' => '(가)', '㈏' => '(나)', '㈐' => '(다)', '㈑' => '(라)', '㈒' => '(마)', '㈓' => '(바)', '㈔' => '(사)', '㈕' => '(아)', '㈖' => '(자)', '㈗' => '(차)', '㈘' => '(카)', '㈙' => '(타)', '㈚' => '(파)', '㈛' => '(하)', '㈜' => '(주)', '㈝' => '(오전)', '㈞' => '(오후)', '㈠' => '(一)', '㈡' => '(二)', '㈢' => '(三)', '㈣' => '(四)', '㈤' => '(五)', '㈥' => '(六)', '㈦' => '(七)', '㈧' => '(八)', '㈨' => '(九)', '㈩' => '(十)', '㈪' => '(月)', '㈫' => '(火)', '㈬' => '(水)', '㈭' => '(木)', '㈮' => '(金)', '㈯' => '(土)', '㈰' => '(日)', '㈱' => '(株)', '㈲' => '(有)', '㈳' => '(社)', '㈴' => '(名)', '㈵' => '(特)', '㈶' => '(財)', '㈷' => '(祝)', '㈸' => '(労)', '㈹' => '(代)', '㈺' => '(呼)', '㈻' => '(学)', '㈼' => '(監)', '㈽' => '(企)', '㈾' => '(資)', '㈿' => '(協)', '㉀' => '(祭)', '㉁' => '(休)', '㉂' => '(自)', '㉃' => '(至)', '㉄' => '問', '㉅' => '幼', '㉆' => '文', '㉇' => '箏', '㉐' => 'PTE', '㉑' => '21', '㉒' => '22', '㉓' => '23', '㉔' => '24', '㉕' => '25', '㉖' => '26', '㉗' => '27', '㉘' => '28', '㉙' => '29', '㉚' => '30', '㉛' => '31', '㉜' => '32', '㉝' => '33', '㉞' => '34', '㉟' => '35', '㉠' => 'ᄀ', '㉡' => 'ᄂ', '㉢' => 'ᄃ', '㉣' => 'ᄅ', '㉤' => 'ᄆ', '㉥' => 'ᄇ', '㉦' => 'ᄉ', '㉧' => 'ᄋ', '㉨' => 'ᄌ', '㉩' => 'ᄎ', '㉪' => 'ᄏ', '㉫' => 'ᄐ', '㉬' => 'ᄑ', '㉭' => 'ᄒ', '㉮' => '가', '㉯' => '나', '㉰' => '다', '㉱' => '라', '㉲' => '마', '㉳' => '바', '㉴' => '사', '㉵' => '아', '㉶' => '자', '㉷' => '차', '㉸' => '카', '㉹' => '타', '㉺' => '파', '㉻' => '하', '㉼' => '참고', '㉽' => '주의', '㉾' => '우', '㊀' => '一', '㊁' => '二', '㊂' => '三', '㊃' => '四', '㊄' => '五', '㊅' => '六', '㊆' => '七', '㊇' => '八', '㊈' => '九', '㊉' => '十', '㊊' => '月', '㊋' => '火', '㊌' => '水', '㊍' => '木', '㊎' => '金', '㊏' => '土', '㊐' => '日', '㊑' => '株', '㊒' => '有', '㊓' => '社', '㊔' => '名', '㊕' => '特', '㊖' => '財', '㊗' => '祝', '㊘' => '労', '㊙' => '秘', '㊚' => '男', '㊛' => '女', '㊜' => '適', '㊝' => '優', '㊞' => '印', '㊟' => '注', '㊠' => '項', '㊡' => '休', '㊢' => '写', '㊣' => '正', '㊤' => '上', '㊥' => '中', '㊦' => '下', '㊧' => '左', '㊨' => '右', '㊩' => '医', '㊪' => '宗', '㊫' => '学', '㊬' => '監', '㊭' => '企', '㊮' => '資', '㊯' => '協', '㊰' => '夜', '㊱' => '36', '㊲' => '37', '㊳' => '38', '㊴' => '39', '㊵' => '40', '㊶' => '41', '㊷' => '42', '㊸' => '43', '㊹' => '44', '㊺' => '45', '㊻' => '46', '㊼' => '47', '㊽' => '48', '㊾' => '49', '㊿' => '50', '㋀' => '1月', '㋁' => '2月', '㋂' => '3月', '㋃' => '4月', '㋄' => '5月', '㋅' => '6月', '㋆' => '7月', '㋇' => '8月', '㋈' => '9月', '㋉' => '10月', '㋊' => '11月', '㋋' => '12月', '㋌' => 'Hg', '㋍' => 'erg', '㋎' => 'eV', '㋏' => 'LTD', '㋐' => 'ア', '㋑' => 'イ', '㋒' => 'ウ', '㋓' => 'エ', '㋔' => 'オ', '㋕' => 'カ', '㋖' => 'キ', '㋗' => 'ク', '㋘' => 'ケ', '㋙' => 'コ', '㋚' => 'サ', '㋛' => 'シ', '㋜' => 'ス', '㋝' => 'セ', '㋞' => 'ソ', '㋟' => 'タ', '㋠' => 'チ', '㋡' => 'ツ', '㋢' => 'テ', '㋣' => 'ト', '㋤' => 'ナ', '㋥' => 'ニ', '㋦' => 'ヌ', '㋧' => 'ネ', '㋨' => 'ノ', '㋩' => 'ハ', '㋪' => 'ヒ', '㋫' => 'フ', '㋬' => 'ヘ', '㋭' => 'ホ', '㋮' => 'マ', '㋯' => 'ミ', '㋰' => 'ム', '㋱' => 'メ', '㋲' => 'モ', '㋳' => 'ヤ', '㋴' => 'ユ', '㋵' => 'ヨ', '㋶' => 'ラ', '㋷' => 'リ', '㋸' => 'ル', '㋹' => 'レ', '㋺' => 'ロ', '㋻' => 'ワ', '㋼' => 'ヰ', '㋽' => 'ヱ', '㋾' => 'ヲ', '㋿' => '令和', '㌀' => 'アパート', '㌁' => 'アルファ', '㌂' => 'アンペア', '㌃' => 'アール', '㌄' => 'イニング', '㌅' => 'インチ', '㌆' => 'ウォン', '㌇' => 'エスクード', '㌈' => 'エーカー', '㌉' => 'オンス', '㌊' => 'オーム', '㌋' => 'カイリ', '㌌' => 'カラット', '㌍' => 'カロリー', '㌎' => 'ガロン', '㌏' => 'ガンマ', '㌐' => 'ギガ', '㌑' => 'ギニー', '㌒' => 'キュリー', '㌓' => 'ギルダー', '㌔' => 'キロ', '㌕' => 'キログラム', '㌖' => 'キロメートル', '㌗' => 'キロワット', '㌘' => 'グラム', '㌙' => 'グラムトン', '㌚' => 'クルゼイロ', '㌛' => 'クローネ', '㌜' => 'ケース', '㌝' => 'コルナ', '㌞' => 'コーポ', '㌟' => 'サイクル', '㌠' => 'サンチーム', '㌡' => 'シリング', '㌢' => 'センチ', '㌣' => 'セント', '㌤' => 'ダース', '㌥' => 'デシ', '㌦' => 'ドル', '㌧' => 'トン', '㌨' => 'ナノ', '㌩' => 'ノット', '㌪' => 'ハイツ', '㌫' => 'パーセント', '㌬' => 'パーツ', '㌭' => 'バーレル', '㌮' => 'ピアストル', '㌯' => 'ピクル', '㌰' => 'ピコ', '㌱' => 'ビル', '㌲' => 'ファラッド', '㌳' => 'フィート', '㌴' => 'ブッシェル', '㌵' => 'フラン', '㌶' => 'ヘクタール', '㌷' => 'ペソ', '㌸' => 'ペニヒ', '㌹' => 'ヘルツ', '㌺' => 'ペンス', '㌻' => 'ページ', '㌼' => 'ベータ', '㌽' => 'ポイント', '㌾' => 'ボルト', '㌿' => 'ホン', '㍀' => 'ポンド', '㍁' => 'ホール', '㍂' => 'ホーン', '㍃' => 'マイクロ', '㍄' => 'マイル', '㍅' => 'マッハ', '㍆' => 'マルク', '㍇' => 'マンション', '㍈' => 'ミクロン', '㍉' => 'ミリ', '㍊' => 'ミリバール', '㍋' => 'メガ', '㍌' => 'メガトン', '㍍' => 'メートル', '㍎' => 'ヤード', '㍏' => 'ヤール', '㍐' => 'ユアン', '㍑' => 'リットル', '㍒' => 'リラ', '㍓' => 'ルピー', '㍔' => 'ルーブル', '㍕' => 'レム', '㍖' => 'レントゲン', '㍗' => 'ワット', '㍘' => '0点', '㍙' => '1点', '㍚' => '2点', '㍛' => '3点', '㍜' => '4点', '㍝' => '5点', '㍞' => '6点', '㍟' => '7点', '㍠' => '8点', '㍡' => '9点', '㍢' => '10点', '㍣' => '11点', '㍤' => '12点', '㍥' => '13点', '㍦' => '14点', '㍧' => '15点', '㍨' => '16点', '㍩' => '17点', '㍪' => '18点', '㍫' => '19点', '㍬' => '20点', '㍭' => '21点', '㍮' => '22点', '㍯' => '23点', '㍰' => '24点', '㍱' => 'hPa', '㍲' => 'da', '㍳' => 'AU', '㍴' => 'bar', '㍵' => 'oV', '㍶' => 'pc', '㍷' => 'dm', '㍸' => 'dm2', '㍹' => 'dm3', '㍺' => 'IU', '㍻' => '平成', '㍼' => '昭和', '㍽' => '大正', '㍾' => '明治', '㍿' => '株式会社', '㎀' => 'pA', '㎁' => 'nA', '㎂' => 'μA', '㎃' => 'mA', '㎄' => 'kA', '㎅' => 'KB', '㎆' => 'MB', '㎇' => 'GB', '㎈' => 'cal', '㎉' => 'kcal', '㎊' => 'pF', '㎋' => 'nF', '㎌' => 'μF', '㎍' => 'μg', '㎎' => 'mg', '㎏' => 'kg', '㎐' => 'Hz', '㎑' => 'kHz', '㎒' => 'MHz', '㎓' => 'GHz', '㎔' => 'THz', '㎕' => 'μl', '㎖' => 'ml', '㎗' => 'dl', '㎘' => 'kl', '㎙' => 'fm', '㎚' => 'nm', '㎛' => 'μm', '㎜' => 'mm', '㎝' => 'cm', '㎞' => 'km', '㎟' => 'mm2', '㎠' => 'cm2', '㎡' => 'm2', '㎢' => 'km2', '㎣' => 'mm3', '㎤' => 'cm3', '㎥' => 'm3', '㎦' => 'km3', '㎧' => 'm∕s', '㎨' => 'm∕s2', '㎩' => 'Pa', '㎪' => 'kPa', '㎫' => 'MPa', '㎬' => 'GPa', '㎭' => 'rad', '㎮' => 'rad∕s', '㎯' => 'rad∕s2', '㎰' => 'ps', '㎱' => 'ns', '㎲' => 'μs', '㎳' => 'ms', '㎴' => 'pV', '㎵' => 'nV', '㎶' => 'μV', '㎷' => 'mV', '㎸' => 'kV', '㎹' => 'MV', '㎺' => 'pW', '㎻' => 'nW', '㎼' => 'μW', '㎽' => 'mW', '㎾' => 'kW', '㎿' => 'MW', '㏀' => 'kΩ', '㏁' => 'MΩ', '㏂' => 'a.m.', '㏃' => 'Bq', '㏄' => 'cc', '㏅' => 'cd', '㏆' => 'C∕kg', '㏇' => 'Co.', '㏈' => 'dB', '㏉' => 'Gy', '㏊' => 'ha', '㏋' => 'HP', '㏌' => 'in', '㏍' => 'KK', '㏎' => 'KM', '㏏' => 'kt', '㏐' => 'lm', '㏑' => 'ln', '㏒' => 'log', '㏓' => 'lx', '㏔' => 'mb', '㏕' => 'mil', '㏖' => 'mol', '㏗' => 'PH', '㏘' => 'p.m.', '㏙' => 'PPM', '㏚' => 'PR', '㏛' => 'sr', '㏜' => 'Sv', '㏝' => 'Wb', '㏞' => 'V∕m', '㏟' => 'A∕m', '㏠' => '1日', '㏡' => '2日', '㏢' => '3日', '㏣' => '4日', '㏤' => '5日', '㏥' => '6日', '㏦' => '7日', '㏧' => '8日', '㏨' => '9日', '㏩' => '10日', '㏪' => '11日', '㏫' => '12日', '㏬' => '13日', '㏭' => '14日', '㏮' => '15日', '㏯' => '16日', '㏰' => '17日', '㏱' => '18日', '㏲' => '19日', '㏳' => '20日', '㏴' => '21日', '㏵' => '22日', '㏶' => '23日', '㏷' => '24日', '㏸' => '25日', '㏹' => '26日', '㏺' => '27日', '㏻' => '28日', '㏼' => '29日', '㏽' => '30日', '㏾' => '31日', '㏿' => 'gal', 'ꚜ' => 'ъ', 'ꚝ' => 'ь', 'ꝰ' => 'ꝯ', 'ꟸ' => 'Ħ', 'ꟹ' => 'œ', 'ꭜ' => 'ꜧ', 'ꭝ' => 'ꬷ', 'ꭞ' => 'ɫ', 'ꭟ' => 'ꭒ', 'ꭩ' => 'ʍ', 'ff' => 'ff', 'fi' => 'fi', 'fl' => 'fl', 'ffi' => 'ffi', 'ffl' => 'ffl', 'ſt' => 'st', 'st' => 'st', 'ﬓ' => 'մն', 'ﬔ' => 'մե', 'ﬕ' => 'մի', 'ﬖ' => 'վն', 'ﬗ' => 'մխ', 'ﬠ' => 'ע', 'ﬡ' => 'א', 'ﬢ' => 'ד', 'ﬣ' => 'ה', 'ﬤ' => 'כ', 'ﬥ' => 'ל', 'ﬦ' => 'ם', 'ﬧ' => 'ר', 'ﬨ' => 'ת', '﬩' => '+', 'ﭏ' => 'אל', 'ﭐ' => 'ٱ', 'ﭑ' => 'ٱ', 'ﭒ' => 'ٻ', 'ﭓ' => 'ٻ', 'ﭔ' => 'ٻ', 'ﭕ' => 'ٻ', 'ﭖ' => 'پ', 'ﭗ' => 'پ', 'ﭘ' => 'پ', 'ﭙ' => 'پ', 'ﭚ' => 'ڀ', 'ﭛ' => 'ڀ', 'ﭜ' => 'ڀ', 'ﭝ' => 'ڀ', 'ﭞ' => 'ٺ', 'ﭟ' => 'ٺ', 'ﭠ' => 'ٺ', 'ﭡ' => 'ٺ', 'ﭢ' => 'ٿ', 'ﭣ' => 'ٿ', 'ﭤ' => 'ٿ', 'ﭥ' => 'ٿ', 'ﭦ' => 'ٹ', 'ﭧ' => 'ٹ', 'ﭨ' => 'ٹ', 'ﭩ' => 'ٹ', 'ﭪ' => 'ڤ', 'ﭫ' => 'ڤ', 'ﭬ' => 'ڤ', 'ﭭ' => 'ڤ', 'ﭮ' => 'ڦ', 'ﭯ' => 'ڦ', 'ﭰ' => 'ڦ', 'ﭱ' => 'ڦ', 'ﭲ' => 'ڄ', 'ﭳ' => 'ڄ', 'ﭴ' => 'ڄ', 'ﭵ' => 'ڄ', 'ﭶ' => 'ڃ', 'ﭷ' => 'ڃ', 'ﭸ' => 'ڃ', 'ﭹ' => 'ڃ', 'ﭺ' => 'چ', 'ﭻ' => 'چ', 'ﭼ' => 'چ', 'ﭽ' => 'چ', 'ﭾ' => 'ڇ', 'ﭿ' => 'ڇ', 'ﮀ' => 'ڇ', 'ﮁ' => 'ڇ', 'ﮂ' => 'ڍ', 'ﮃ' => 'ڍ', 'ﮄ' => 'ڌ', 'ﮅ' => 'ڌ', 'ﮆ' => 'ڎ', 'ﮇ' => 'ڎ', 'ﮈ' => 'ڈ', 'ﮉ' => 'ڈ', 'ﮊ' => 'ژ', 'ﮋ' => 'ژ', 'ﮌ' => 'ڑ', 'ﮍ' => 'ڑ', 'ﮎ' => 'ک', 'ﮏ' => 'ک', 'ﮐ' => 'ک', 'ﮑ' => 'ک', 'ﮒ' => 'گ', 'ﮓ' => 'گ', 'ﮔ' => 'گ', 'ﮕ' => 'گ', 'ﮖ' => 'ڳ', 'ﮗ' => 'ڳ', 'ﮘ' => 'ڳ', 'ﮙ' => 'ڳ', 'ﮚ' => 'ڱ', 'ﮛ' => 'ڱ', 'ﮜ' => 'ڱ', 'ﮝ' => 'ڱ', 'ﮞ' => 'ں', 'ﮟ' => 'ں', 'ﮠ' => 'ڻ', 'ﮡ' => 'ڻ', 'ﮢ' => 'ڻ', 'ﮣ' => 'ڻ', 'ﮤ' => 'ۀ', 'ﮥ' => 'ۀ', 'ﮦ' => 'ہ', 'ﮧ' => 'ہ', 'ﮨ' => 'ہ', 'ﮩ' => 'ہ', 'ﮪ' => 'ھ', 'ﮫ' => 'ھ', 'ﮬ' => 'ھ', 'ﮭ' => 'ھ', 'ﮮ' => 'ے', 'ﮯ' => 'ے', 'ﮰ' => 'ۓ', 'ﮱ' => 'ۓ', 'ﯓ' => 'ڭ', 'ﯔ' => 'ڭ', 'ﯕ' => 'ڭ', 'ﯖ' => 'ڭ', 'ﯗ' => 'ۇ', 'ﯘ' => 'ۇ', 'ﯙ' => 'ۆ', 'ﯚ' => 'ۆ', 'ﯛ' => 'ۈ', 'ﯜ' => 'ۈ', 'ﯝ' => 'ۇٴ', 'ﯞ' => 'ۋ', 'ﯟ' => 'ۋ', 'ﯠ' => 'ۅ', 'ﯡ' => 'ۅ', 'ﯢ' => 'ۉ', 'ﯣ' => 'ۉ', 'ﯤ' => 'ې', 'ﯥ' => 'ې', 'ﯦ' => 'ې', 'ﯧ' => 'ې', 'ﯨ' => 'ى', 'ﯩ' => 'ى', 'ﯪ' => 'ئا', 'ﯫ' => 'ئا', 'ﯬ' => 'ئە', 'ﯭ' => 'ئە', 'ﯮ' => 'ئو', 'ﯯ' => 'ئو', 'ﯰ' => 'ئۇ', 'ﯱ' => 'ئۇ', 'ﯲ' => 'ئۆ', 'ﯳ' => 'ئۆ', 'ﯴ' => 'ئۈ', 'ﯵ' => 'ئۈ', 'ﯶ' => 'ئې', 'ﯷ' => 'ئې', 'ﯸ' => 'ئې', 'ﯹ' => 'ئى', 'ﯺ' => 'ئى', 'ﯻ' => 'ئى', 'ﯼ' => 'ی', 'ﯽ' => 'ی', 'ﯾ' => 'ی', 'ﯿ' => 'ی', 'ﰀ' => 'ئج', 'ﰁ' => 'ئح', 'ﰂ' => 'ئم', 'ﰃ' => 'ئى', 'ﰄ' => 'ئي', 'ﰅ' => 'بج', 'ﰆ' => 'بح', 'ﰇ' => 'بخ', 'ﰈ' => 'بم', 'ﰉ' => 'بى', 'ﰊ' => 'بي', 'ﰋ' => 'تج', 'ﰌ' => 'تح', 'ﰍ' => 'تخ', 'ﰎ' => 'تم', 'ﰏ' => 'تى', 'ﰐ' => 'تي', 'ﰑ' => 'ثج', 'ﰒ' => 'ثم', 'ﰓ' => 'ثى', 'ﰔ' => 'ثي', 'ﰕ' => 'جح', 'ﰖ' => 'جم', 'ﰗ' => 'حج', 'ﰘ' => 'حم', 'ﰙ' => 'خج', 'ﰚ' => 'خح', 'ﰛ' => 'خم', 'ﰜ' => 'سج', 'ﰝ' => 'سح', 'ﰞ' => 'سخ', 'ﰟ' => 'سم', 'ﰠ' => 'صح', 'ﰡ' => 'صم', 'ﰢ' => 'ضج', 'ﰣ' => 'ضح', 'ﰤ' => 'ضخ', 'ﰥ' => 'ضم', 'ﰦ' => 'طح', 'ﰧ' => 'طم', 'ﰨ' => 'ظم', 'ﰩ' => 'عج', 'ﰪ' => 'عم', 'ﰫ' => 'غج', 'ﰬ' => 'غم', 'ﰭ' => 'فج', 'ﰮ' => 'فح', 'ﰯ' => 'فخ', 'ﰰ' => 'فم', 'ﰱ' => 'فى', 'ﰲ' => 'في', 'ﰳ' => 'قح', 'ﰴ' => 'قم', 'ﰵ' => 'قى', 'ﰶ' => 'قي', 'ﰷ' => 'كا', 'ﰸ' => 'كج', 'ﰹ' => 'كح', 'ﰺ' => 'كخ', 'ﰻ' => 'كل', 'ﰼ' => 'كم', 'ﰽ' => 'كى', 'ﰾ' => 'كي', 'ﰿ' => 'لج', 'ﱀ' => 'لح', 'ﱁ' => 'لخ', 'ﱂ' => 'لم', 'ﱃ' => 'لى', 'ﱄ' => 'لي', 'ﱅ' => 'مج', 'ﱆ' => 'مح', 'ﱇ' => 'مخ', 'ﱈ' => 'مم', 'ﱉ' => 'مى', 'ﱊ' => 'مي', 'ﱋ' => 'نج', 'ﱌ' => 'نح', 'ﱍ' => 'نخ', 'ﱎ' => 'نم', 'ﱏ' => 'نى', 'ﱐ' => 'ني', 'ﱑ' => 'هج', 'ﱒ' => 'هم', 'ﱓ' => 'هى', 'ﱔ' => 'هي', 'ﱕ' => 'يج', 'ﱖ' => 'يح', 'ﱗ' => 'يخ', 'ﱘ' => 'يم', 'ﱙ' => 'يى', 'ﱚ' => 'يي', 'ﱛ' => 'ذٰ', 'ﱜ' => 'رٰ', 'ﱝ' => 'ىٰ', 'ﱞ' => ' ٌّ', 'ﱟ' => ' ٍّ', 'ﱠ' => ' َّ', 'ﱡ' => ' ُّ', 'ﱢ' => ' ِّ', 'ﱣ' => ' ّٰ', 'ﱤ' => 'ئر', 'ﱥ' => 'ئز', 'ﱦ' => 'ئم', 'ﱧ' => 'ئن', 'ﱨ' => 'ئى', 'ﱩ' => 'ئي', 'ﱪ' => 'بر', 'ﱫ' => 'بز', 'ﱬ' => 'بم', 'ﱭ' => 'بن', 'ﱮ' => 'بى', 'ﱯ' => 'بي', 'ﱰ' => 'تر', 'ﱱ' => 'تز', 'ﱲ' => 'تم', 'ﱳ' => 'تن', 'ﱴ' => 'تى', 'ﱵ' => 'تي', 'ﱶ' => 'ثر', 'ﱷ' => 'ثز', 'ﱸ' => 'ثم', 'ﱹ' => 'ثن', 'ﱺ' => 'ثى', 'ﱻ' => 'ثي', 'ﱼ' => 'فى', 'ﱽ' => 'في', 'ﱾ' => 'قى', 'ﱿ' => 'قي', 'ﲀ' => 'كا', 'ﲁ' => 'كل', 'ﲂ' => 'كم', 'ﲃ' => 'كى', 'ﲄ' => 'كي', 'ﲅ' => 'لم', 'ﲆ' => 'لى', 'ﲇ' => 'لي', 'ﲈ' => 'ما', 'ﲉ' => 'مم', 'ﲊ' => 'نر', 'ﲋ' => 'نز', 'ﲌ' => 'نم', 'ﲍ' => 'نن', 'ﲎ' => 'نى', 'ﲏ' => 'ني', 'ﲐ' => 'ىٰ', 'ﲑ' => 'ير', 'ﲒ' => 'يز', 'ﲓ' => 'يم', 'ﲔ' => 'ين', 'ﲕ' => 'يى', 'ﲖ' => 'يي', 'ﲗ' => 'ئج', 'ﲘ' => 'ئح', 'ﲙ' => 'ئخ', 'ﲚ' => 'ئم', 'ﲛ' => 'ئه', 'ﲜ' => 'بج', 'ﲝ' => 'بح', 'ﲞ' => 'بخ', 'ﲟ' => 'بم', 'ﲠ' => 'به', 'ﲡ' => 'تج', 'ﲢ' => 'تح', 'ﲣ' => 'تخ', 'ﲤ' => 'تم', 'ﲥ' => 'ته', 'ﲦ' => 'ثم', 'ﲧ' => 'جح', 'ﲨ' => 'جم', 'ﲩ' => 'حج', 'ﲪ' => 'حم', 'ﲫ' => 'خج', 'ﲬ' => 'خم', 'ﲭ' => 'سج', 'ﲮ' => 'سح', 'ﲯ' => 'سخ', 'ﲰ' => 'سم', 'ﲱ' => 'صح', 'ﲲ' => 'صخ', 'ﲳ' => 'صم', 'ﲴ' => 'ضج', 'ﲵ' => 'ضح', 'ﲶ' => 'ضخ', 'ﲷ' => 'ضم', 'ﲸ' => 'طح', 'ﲹ' => 'ظم', 'ﲺ' => 'عج', 'ﲻ' => 'عم', 'ﲼ' => 'غج', 'ﲽ' => 'غم', 'ﲾ' => 'فج', 'ﲿ' => 'فح', 'ﳀ' => 'فخ', 'ﳁ' => 'فم', 'ﳂ' => 'قح', 'ﳃ' => 'قم', 'ﳄ' => 'كج', 'ﳅ' => 'كح', 'ﳆ' => 'كخ', 'ﳇ' => 'كل', 'ﳈ' => 'كم', 'ﳉ' => 'لج', 'ﳊ' => 'لح', 'ﳋ' => 'لخ', 'ﳌ' => 'لم', 'ﳍ' => 'له', 'ﳎ' => 'مج', 'ﳏ' => 'مح', 'ﳐ' => 'مخ', 'ﳑ' => 'مم', 'ﳒ' => 'نج', 'ﳓ' => 'نح', 'ﳔ' => 'نخ', 'ﳕ' => 'نم', 'ﳖ' => 'نه', 'ﳗ' => 'هج', 'ﳘ' => 'هم', 'ﳙ' => 'هٰ', 'ﳚ' => 'يج', 'ﳛ' => 'يح', 'ﳜ' => 'يخ', 'ﳝ' => 'يم', 'ﳞ' => 'يه', 'ﳟ' => 'ئم', 'ﳠ' => 'ئه', 'ﳡ' => 'بم', 'ﳢ' => 'به', 'ﳣ' => 'تم', 'ﳤ' => 'ته', 'ﳥ' => 'ثم', 'ﳦ' => 'ثه', 'ﳧ' => 'سم', 'ﳨ' => 'سه', 'ﳩ' => 'شم', 'ﳪ' => 'شه', 'ﳫ' => 'كل', 'ﳬ' => 'كم', 'ﳭ' => 'لم', 'ﳮ' => 'نم', 'ﳯ' => 'نه', 'ﳰ' => 'يم', 'ﳱ' => 'يه', 'ﳲ' => 'ـَّ', 'ﳳ' => 'ـُّ', 'ﳴ' => 'ـِّ', 'ﳵ' => 'طى', 'ﳶ' => 'طي', 'ﳷ' => 'عى', 'ﳸ' => 'عي', 'ﳹ' => 'غى', 'ﳺ' => 'غي', 'ﳻ' => 'سى', 'ﳼ' => 'سي', 'ﳽ' => 'شى', 'ﳾ' => 'شي', 'ﳿ' => 'حى', 'ﴀ' => 'حي', 'ﴁ' => 'جى', 'ﴂ' => 'جي', 'ﴃ' => 'خى', 'ﴄ' => 'خي', 'ﴅ' => 'صى', 'ﴆ' => 'صي', 'ﴇ' => 'ضى', 'ﴈ' => 'ضي', 'ﴉ' => 'شج', 'ﴊ' => 'شح', 'ﴋ' => 'شخ', 'ﴌ' => 'شم', 'ﴍ' => 'شر', 'ﴎ' => 'سر', 'ﴏ' => 'صر', 'ﴐ' => 'ضر', 'ﴑ' => 'طى', 'ﴒ' => 'طي', 'ﴓ' => 'عى', 'ﴔ' => 'عي', 'ﴕ' => 'غى', 'ﴖ' => 'غي', 'ﴗ' => 'سى', 'ﴘ' => 'سي', 'ﴙ' => 'شى', 'ﴚ' => 'شي', 'ﴛ' => 'حى', 'ﴜ' => 'حي', 'ﴝ' => 'جى', 'ﴞ' => 'جي', 'ﴟ' => 'خى', 'ﴠ' => 'خي', 'ﴡ' => 'صى', 'ﴢ' => 'صي', 'ﴣ' => 'ضى', 'ﴤ' => 'ضي', 'ﴥ' => 'شج', 'ﴦ' => 'شح', 'ﴧ' => 'شخ', 'ﴨ' => 'شم', 'ﴩ' => 'شر', 'ﴪ' => 'سر', 'ﴫ' => 'صر', 'ﴬ' => 'ضر', 'ﴭ' => 'شج', 'ﴮ' => 'شح', 'ﴯ' => 'شخ', 'ﴰ' => 'شم', 'ﴱ' => 'سه', 'ﴲ' => 'شه', 'ﴳ' => 'طم', 'ﴴ' => 'سج', 'ﴵ' => 'سح', 'ﴶ' => 'سخ', 'ﴷ' => 'شج', 'ﴸ' => 'شح', 'ﴹ' => 'شخ', 'ﴺ' => 'طم', 'ﴻ' => 'ظم', 'ﴼ' => 'اً', 'ﴽ' => 'اً', 'ﵐ' => 'تجم', 'ﵑ' => 'تحج', 'ﵒ' => 'تحج', 'ﵓ' => 'تحم', 'ﵔ' => 'تخم', 'ﵕ' => 'تمج', 'ﵖ' => 'تمح', 'ﵗ' => 'تمخ', 'ﵘ' => 'جمح', 'ﵙ' => 'جمح', 'ﵚ' => 'حمي', 'ﵛ' => 'حمى', 'ﵜ' => 'سحج', 'ﵝ' => 'سجح', 'ﵞ' => 'سجى', 'ﵟ' => 'سمح', 'ﵠ' => 'سمح', 'ﵡ' => 'سمج', 'ﵢ' => 'سمم', 'ﵣ' => 'سمم', 'ﵤ' => 'صحح', 'ﵥ' => 'صحح', 'ﵦ' => 'صمم', 'ﵧ' => 'شحم', 'ﵨ' => 'شحم', 'ﵩ' => 'شجي', 'ﵪ' => 'شمخ', 'ﵫ' => 'شمخ', 'ﵬ' => 'شمم', 'ﵭ' => 'شمم', 'ﵮ' => 'ضحى', 'ﵯ' => 'ضخم', 'ﵰ' => 'ضخم', 'ﵱ' => 'طمح', 'ﵲ' => 'طمح', 'ﵳ' => 'طمم', 'ﵴ' => 'طمي', 'ﵵ' => 'عجم', 'ﵶ' => 'عمم', 'ﵷ' => 'عمم', 'ﵸ' => 'عمى', 'ﵹ' => 'غمم', 'ﵺ' => 'غمي', 'ﵻ' => 'غمى', 'ﵼ' => 'فخم', 'ﵽ' => 'فخم', 'ﵾ' => 'قمح', 'ﵿ' => 'قمم', 'ﶀ' => 'لحم', 'ﶁ' => 'لحي', 'ﶂ' => 'لحى', 'ﶃ' => 'لجج', 'ﶄ' => 'لجج', 'ﶅ' => 'لخم', 'ﶆ' => 'لخم', 'ﶇ' => 'لمح', 'ﶈ' => 'لمح', 'ﶉ' => 'محج', 'ﶊ' => 'محم', 'ﶋ' => 'محي', 'ﶌ' => 'مجح', 'ﶍ' => 'مجم', 'ﶎ' => 'مخج', 'ﶏ' => 'مخم', 'ﶒ' => 'مجخ', 'ﶓ' => 'همج', 'ﶔ' => 'همم', 'ﶕ' => 'نحم', 'ﶖ' => 'نحى', 'ﶗ' => 'نجم', 'ﶘ' => 'نجم', 'ﶙ' => 'نجى', 'ﶚ' => 'نمي', 'ﶛ' => 'نمى', 'ﶜ' => 'يمم', 'ﶝ' => 'يمم', 'ﶞ' => 'بخي', 'ﶟ' => 'تجي', 'ﶠ' => 'تجى', 'ﶡ' => 'تخي', 'ﶢ' => 'تخى', 'ﶣ' => 'تمي', 'ﶤ' => 'تمى', 'ﶥ' => 'جمي', 'ﶦ' => 'جحى', 'ﶧ' => 'جمى', 'ﶨ' => 'سخى', 'ﶩ' => 'صحي', 'ﶪ' => 'شحي', 'ﶫ' => 'ضحي', 'ﶬ' => 'لجي', 'ﶭ' => 'لمي', 'ﶮ' => 'يحي', 'ﶯ' => 'يجي', 'ﶰ' => 'يمي', 'ﶱ' => 'ممي', 'ﶲ' => 'قمي', 'ﶳ' => 'نحي', 'ﶴ' => 'قمح', 'ﶵ' => 'لحم', 'ﶶ' => 'عمي', 'ﶷ' => 'كمي', 'ﶸ' => 'نجح', 'ﶹ' => 'مخي', 'ﶺ' => 'لجم', 'ﶻ' => 'كمم', 'ﶼ' => 'لجم', 'ﶽ' => 'نجح', 'ﶾ' => 'جحي', 'ﶿ' => 'حجي', 'ﷀ' => 'مجي', 'ﷁ' => 'فمي', 'ﷂ' => 'بحي', 'ﷃ' => 'كمم', 'ﷄ' => 'عجم', 'ﷅ' => 'صمم', 'ﷆ' => 'سخي', 'ﷇ' => 'نجي', 'ﷰ' => 'صلے', 'ﷱ' => 'قلے', 'ﷲ' => 'الله', 'ﷳ' => 'اكبر', 'ﷴ' => 'محمد', 'ﷵ' => 'صلعم', 'ﷶ' => 'رسول', 'ﷷ' => 'عليه', 'ﷸ' => 'وسلم', 'ﷹ' => 'صلى', 'ﷺ' => 'صلى الله عليه وسلم', 'ﷻ' => 'جل جلاله', '﷼' => 'ریال', '︐' => ',', '︑' => '、', '︒' => '。', '︓' => ':', '︔' => ';', '︕' => '!', '︖' => '?', '︗' => '〖', '︘' => '〗', '︙' => '...', '︰' => '..', '︱' => '—', '︲' => '–', '︳' => '_', '︴' => '_', '︵' => '(', '︶' => ')', '︷' => '{', '︸' => '}', '︹' => '〔', '︺' => '〕', '︻' => '【', '︼' => '】', '︽' => '《', '︾' => '》', '︿' => '〈', '﹀' => '〉', '﹁' => '「', '﹂' => '」', '﹃' => '『', '﹄' => '』', '﹇' => '[', '﹈' => ']', '﹉' => ' ̅', '﹊' => ' ̅', '﹋' => ' ̅', '﹌' => ' ̅', '﹍' => '_', '﹎' => '_', '﹏' => '_', '﹐' => ',', '﹑' => '、', '﹒' => '.', '﹔' => ';', '﹕' => ':', '﹖' => '?', '﹗' => '!', '﹘' => '—', '﹙' => '(', '﹚' => ')', '﹛' => '{', '﹜' => '}', '﹝' => '〔', '﹞' => '〕', '﹟' => '#', '﹠' => '&', '﹡' => '*', '﹢' => '+', '﹣' => '-', '﹤' => '<', '﹥' => '>', '﹦' => '=', '﹨' => '\\', '﹩' => '$', '﹪' => '%', '﹫' => '@', 'ﹰ' => ' ً', 'ﹱ' => 'ـً', 'ﹲ' => ' ٌ', 'ﹴ' => ' ٍ', 'ﹶ' => ' َ', 'ﹷ' => 'ـَ', 'ﹸ' => ' ُ', 'ﹹ' => 'ـُ', 'ﹺ' => ' ِ', 'ﹻ' => 'ـِ', 'ﹼ' => ' ّ', 'ﹽ' => 'ـّ', 'ﹾ' => ' ْ', 'ﹿ' => 'ـْ', 'ﺀ' => 'ء', 'ﺁ' => 'آ', 'ﺂ' => 'آ', 'ﺃ' => 'أ', 'ﺄ' => 'أ', 'ﺅ' => 'ؤ', 'ﺆ' => 'ؤ', 'ﺇ' => 'إ', 'ﺈ' => 'إ', 'ﺉ' => 'ئ', 'ﺊ' => 'ئ', 'ﺋ' => 'ئ', 'ﺌ' => 'ئ', 'ﺍ' => 'ا', 'ﺎ' => 'ا', 'ﺏ' => 'ب', 'ﺐ' => 'ب', 'ﺑ' => 'ب', 'ﺒ' => 'ب', 'ﺓ' => 'ة', 'ﺔ' => 'ة', 'ﺕ' => 'ت', 'ﺖ' => 'ت', 'ﺗ' => 'ت', 'ﺘ' => 'ت', 'ﺙ' => 'ث', 'ﺚ' => 'ث', 'ﺛ' => 'ث', 'ﺜ' => 'ث', 'ﺝ' => 'ج', 'ﺞ' => 'ج', 'ﺟ' => 'ج', 'ﺠ' => 'ج', 'ﺡ' => 'ح', 'ﺢ' => 'ح', 'ﺣ' => 'ح', 'ﺤ' => 'ح', 'ﺥ' => 'خ', 'ﺦ' => 'خ', 'ﺧ' => 'خ', 'ﺨ' => 'خ', 'ﺩ' => 'د', 'ﺪ' => 'د', 'ﺫ' => 'ذ', 'ﺬ' => 'ذ', 'ﺭ' => 'ر', 'ﺮ' => 'ر', 'ﺯ' => 'ز', 'ﺰ' => 'ز', 'ﺱ' => 'س', 'ﺲ' => 'س', 'ﺳ' => 'س', 'ﺴ' => 'س', 'ﺵ' => 'ش', 'ﺶ' => 'ش', 'ﺷ' => 'ش', 'ﺸ' => 'ش', 'ﺹ' => 'ص', 'ﺺ' => 'ص', 'ﺻ' => 'ص', 'ﺼ' => 'ص', 'ﺽ' => 'ض', 'ﺾ' => 'ض', 'ﺿ' => 'ض', 'ﻀ' => 'ض', 'ﻁ' => 'ط', 'ﻂ' => 'ط', 'ﻃ' => 'ط', 'ﻄ' => 'ط', 'ﻅ' => 'ظ', 'ﻆ' => 'ظ', 'ﻇ' => 'ظ', 'ﻈ' => 'ظ', 'ﻉ' => 'ع', 'ﻊ' => 'ع', 'ﻋ' => 'ع', 'ﻌ' => 'ع', 'ﻍ' => 'غ', 'ﻎ' => 'غ', 'ﻏ' => 'غ', 'ﻐ' => 'غ', 'ﻑ' => 'ف', 'ﻒ' => 'ف', 'ﻓ' => 'ف', 'ﻔ' => 'ف', 'ﻕ' => 'ق', 'ﻖ' => 'ق', 'ﻗ' => 'ق', 'ﻘ' => 'ق', 'ﻙ' => 'ك', 'ﻚ' => 'ك', 'ﻛ' => 'ك', 'ﻜ' => 'ك', 'ﻝ' => 'ل', 'ﻞ' => 'ل', 'ﻟ' => 'ل', 'ﻠ' => 'ل', 'ﻡ' => 'م', 'ﻢ' => 'م', 'ﻣ' => 'م', 'ﻤ' => 'م', 'ﻥ' => 'ن', 'ﻦ' => 'ن', 'ﻧ' => 'ن', 'ﻨ' => 'ن', 'ﻩ' => 'ه', 'ﻪ' => 'ه', 'ﻫ' => 'ه', 'ﻬ' => 'ه', 'ﻭ' => 'و', 'ﻮ' => 'و', 'ﻯ' => 'ى', 'ﻰ' => 'ى', 'ﻱ' => 'ي', 'ﻲ' => 'ي', 'ﻳ' => 'ي', 'ﻴ' => 'ي', 'ﻵ' => 'لآ', 'ﻶ' => 'لآ', 'ﻷ' => 'لأ', 'ﻸ' => 'لأ', 'ﻹ' => 'لإ', 'ﻺ' => 'لإ', 'ﻻ' => 'لا', 'ﻼ' => 'لا', '!' => '!', '"' => '"', '#' => '#', '$' => '$', '%' => '%', '&' => '&', ''' => '\'', '(' => '(', ')' => ')', '*' => '*', '+' => '+', ',' => ',', '-' => '-', '.' => '.', '/' => '/', '0' => '0', '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', ':' => ':', ';' => ';', '<' => '<', '=' => '=', '>' => '>', '?' => '?', '@' => '@', 'A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 'F' => 'F', 'G' => 'G', 'H' => 'H', 'I' => 'I', 'J' => 'J', 'K' => 'K', 'L' => 'L', 'M' => 'M', 'N' => 'N', 'O' => 'O', 'P' => 'P', 'Q' => 'Q', 'R' => 'R', 'S' => 'S', 'T' => 'T', 'U' => 'U', 'V' => 'V', 'W' => 'W', 'X' => 'X', 'Y' => 'Y', 'Z' => 'Z', '[' => '[', '\' => '\\', ']' => ']', '^' => '^', '_' => '_', '`' => '`', 'a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', 'e' => 'e', 'f' => 'f', 'g' => 'g', 'h' => 'h', 'i' => 'i', 'j' => 'j', 'k' => 'k', 'l' => 'l', 'm' => 'm', 'n' => 'n', 'o' => 'o', 'p' => 'p', 'q' => 'q', 'r' => 'r', 's' => 's', 't' => 't', 'u' => 'u', 'v' => 'v', 'w' => 'w', 'x' => 'x', 'y' => 'y', 'z' => 'z', '{' => '{', '|' => '|', '}' => '}', '~' => '~', '⦅' => '⦅', '⦆' => '⦆', '。' => '。', '「' => '「', '」' => '」', '、' => '、', '・' => '・', 'ヲ' => 'ヲ', 'ァ' => 'ァ', 'ィ' => 'ィ', 'ゥ' => 'ゥ', 'ェ' => 'ェ', 'ォ' => 'ォ', 'ャ' => 'ャ', 'ュ' => 'ュ', 'ョ' => 'ョ', 'ッ' => 'ッ', 'ー' => 'ー', 'ア' => 'ア', 'イ' => 'イ', 'ウ' => 'ウ', 'エ' => 'エ', 'オ' => 'オ', 'カ' => 'カ', 'キ' => 'キ', 'ク' => 'ク', 'ケ' => 'ケ', 'コ' => 'コ', 'サ' => 'サ', 'シ' => 'シ', 'ス' => 'ス', 'セ' => 'セ', 'ソ' => 'ソ', 'タ' => 'タ', 'チ' => 'チ', 'ツ' => 'ツ', 'テ' => 'テ', 'ト' => 'ト', 'ナ' => 'ナ', 'ニ' => 'ニ', 'ヌ' => 'ヌ', 'ネ' => 'ネ', 'ノ' => 'ノ', 'ハ' => 'ハ', 'ヒ' => 'ヒ', 'フ' => 'フ', 'ヘ' => 'ヘ', 'ホ' => 'ホ', 'マ' => 'マ', 'ミ' => 'ミ', 'ム' => 'ム', 'メ' => 'メ', 'モ' => 'モ', 'ヤ' => 'ヤ', 'ユ' => 'ユ', 'ヨ' => 'ヨ', 'ラ' => 'ラ', 'リ' => 'リ', 'ル' => 'ル', 'レ' => 'レ', 'ロ' => 'ロ', 'ワ' => 'ワ', 'ン' => 'ン', '゙' => '゙', '゚' => '゚', 'ᅠ' => 'ᅠ', 'ᄀ' => 'ᄀ', 'ᄁ' => 'ᄁ', 'ᆪ' => 'ᆪ', 'ᄂ' => 'ᄂ', 'ᆬ' => 'ᆬ', 'ᆭ' => 'ᆭ', 'ᄃ' => 'ᄃ', 'ᄄ' => 'ᄄ', 'ᄅ' => 'ᄅ', 'ᆰ' => 'ᆰ', 'ᆱ' => 'ᆱ', 'ᆲ' => 'ᆲ', 'ᆳ' => 'ᆳ', 'ᆴ' => 'ᆴ', 'ᆵ' => 'ᆵ', 'ᄚ' => 'ᄚ', 'ᄆ' => 'ᄆ', 'ᄇ' => 'ᄇ', 'ᄈ' => 'ᄈ', 'ᄡ' => 'ᄡ', 'ᄉ' => 'ᄉ', 'ᄊ' => 'ᄊ', 'ᄋ' => 'ᄋ', 'ᄌ' => 'ᄌ', 'ᄍ' => 'ᄍ', 'ᄎ' => 'ᄎ', 'ᄏ' => 'ᄏ', 'ᄐ' => 'ᄐ', 'ᄑ' => 'ᄑ', 'ᄒ' => 'ᄒ', 'ᅡ' => 'ᅡ', 'ᅢ' => 'ᅢ', 'ᅣ' => 'ᅣ', 'ᅤ' => 'ᅤ', 'ᅥ' => 'ᅥ', 'ᅦ' => 'ᅦ', 'ᅧ' => 'ᅧ', 'ᅨ' => 'ᅨ', 'ᅩ' => 'ᅩ', 'ᅪ' => 'ᅪ', 'ᅫ' => 'ᅫ', 'ᅬ' => 'ᅬ', 'ᅭ' => 'ᅭ', 'ᅮ' => 'ᅮ', 'ᅯ' => 'ᅯ', 'ᅰ' => 'ᅰ', 'ᅱ' => 'ᅱ', 'ᅲ' => 'ᅲ', 'ᅳ' => 'ᅳ', 'ᅴ' => 'ᅴ', 'ᅵ' => 'ᅵ', '¢' => '¢', '£' => '£', '¬' => '¬', ' ̄' => ' ̄', '¦' => '¦', '¥' => '¥', '₩' => '₩', '│' => '│', '←' => '←', '↑' => '↑', '→' => '→', '↓' => '↓', '■' => '■', '○' => '○', '𝐀' => 'A', '𝐁' => 'B', '𝐂' => 'C', '𝐃' => 'D', '𝐄' => 'E', '𝐅' => 'F', '𝐆' => 'G', '𝐇' => 'H', '𝐈' => 'I', '𝐉' => 'J', '𝐊' => 'K', '𝐋' => 'L', '𝐌' => 'M', '𝐍' => 'N', '𝐎' => 'O', '𝐏' => 'P', '𝐐' => 'Q', '𝐑' => 'R', '𝐒' => 'S', '𝐓' => 'T', '𝐔' => 'U', '𝐕' => 'V', '𝐖' => 'W', '𝐗' => 'X', '𝐘' => 'Y', '𝐙' => 'Z', '𝐚' => 'a', '𝐛' => 'b', '𝐜' => 'c', '𝐝' => 'd', '𝐞' => 'e', '𝐟' => 'f', '𝐠' => 'g', '𝐡' => 'h', '𝐢' => 'i', '𝐣' => 'j', '𝐤' => 'k', '𝐥' => 'l', '𝐦' => 'm', '𝐧' => 'n', '𝐨' => 'o', '𝐩' => 'p', '𝐪' => 'q', '𝐫' => 'r', '𝐬' => 's', '𝐭' => 't', '𝐮' => 'u', '𝐯' => 'v', '𝐰' => 'w', '𝐱' => 'x', '𝐲' => 'y', '𝐳' => 'z', '𝐴' => 'A', '𝐵' => 'B', '𝐶' => 'C', '𝐷' => 'D', '𝐸' => 'E', '𝐹' => 'F', '𝐺' => 'G', '𝐻' => 'H', '𝐼' => 'I', '𝐽' => 'J', '𝐾' => 'K', '𝐿' => 'L', '𝑀' => 'M', '𝑁' => 'N', '𝑂' => 'O', '𝑃' => 'P', '𝑄' => 'Q', '𝑅' => 'R', '𝑆' => 'S', '𝑇' => 'T', '𝑈' => 'U', '𝑉' => 'V', '𝑊' => 'W', '𝑋' => 'X', '𝑌' => 'Y', '𝑍' => 'Z', '𝑎' => 'a', '𝑏' => 'b', '𝑐' => 'c', '𝑑' => 'd', '𝑒' => 'e', '𝑓' => 'f', '𝑔' => 'g', '𝑖' => 'i', '𝑗' => 'j', '𝑘' => 'k', '𝑙' => 'l', '𝑚' => 'm', '𝑛' => 'n', '𝑜' => 'o', '𝑝' => 'p', '𝑞' => 'q', '𝑟' => 'r', '𝑠' => 's', '𝑡' => 't', '𝑢' => 'u', '𝑣' => 'v', '𝑤' => 'w', '𝑥' => 'x', '𝑦' => 'y', '𝑧' => 'z', '𝑨' => 'A', '𝑩' => 'B', '𝑪' => 'C', '𝑫' => 'D', '𝑬' => 'E', '𝑭' => 'F', '𝑮' => 'G', '𝑯' => 'H', '𝑰' => 'I', '𝑱' => 'J', '𝑲' => 'K', '𝑳' => 'L', '𝑴' => 'M', '𝑵' => 'N', '𝑶' => 'O', '𝑷' => 'P', '𝑸' => 'Q', '𝑹' => 'R', '𝑺' => 'S', '𝑻' => 'T', '𝑼' => 'U', '𝑽' => 'V', '𝑾' => 'W', '𝑿' => 'X', '𝒀' => 'Y', '𝒁' => 'Z', '𝒂' => 'a', '𝒃' => 'b', '𝒄' => 'c', '𝒅' => 'd', '𝒆' => 'e', '𝒇' => 'f', '𝒈' => 'g', '𝒉' => 'h', '𝒊' => 'i', '𝒋' => 'j', '𝒌' => 'k', '𝒍' => 'l', '𝒎' => 'm', '𝒏' => 'n', '𝒐' => 'o', '𝒑' => 'p', '𝒒' => 'q', '𝒓' => 'r', '𝒔' => 's', '𝒕' => 't', '𝒖' => 'u', '𝒗' => 'v', '𝒘' => 'w', '𝒙' => 'x', '𝒚' => 'y', '𝒛' => 'z', '𝒜' => 'A', '𝒞' => 'C', '𝒟' => 'D', '𝒢' => 'G', '𝒥' => 'J', '𝒦' => 'K', '𝒩' => 'N', '𝒪' => 'O', '𝒫' => 'P', '𝒬' => 'Q', '𝒮' => 'S', '𝒯' => 'T', '𝒰' => 'U', '𝒱' => 'V', '𝒲' => 'W', '𝒳' => 'X', '𝒴' => 'Y', '𝒵' => 'Z', '𝒶' => 'a', '𝒷' => 'b', '𝒸' => 'c', '𝒹' => 'd', '𝒻' => 'f', '𝒽' => 'h', '𝒾' => 'i', '𝒿' => 'j', '𝓀' => 'k', '𝓁' => 'l', '𝓂' => 'm', '𝓃' => 'n', '𝓅' => 'p', '𝓆' => 'q', '𝓇' => 'r', '𝓈' => 's', '𝓉' => 't', '𝓊' => 'u', '𝓋' => 'v', '𝓌' => 'w', '𝓍' => 'x', '𝓎' => 'y', '𝓏' => 'z', '𝓐' => 'A', '𝓑' => 'B', '𝓒' => 'C', '𝓓' => 'D', '𝓔' => 'E', '𝓕' => 'F', '𝓖' => 'G', '𝓗' => 'H', '𝓘' => 'I', '𝓙' => 'J', '𝓚' => 'K', '𝓛' => 'L', '𝓜' => 'M', '𝓝' => 'N', '𝓞' => 'O', '𝓟' => 'P', '𝓠' => 'Q', '𝓡' => 'R', '𝓢' => 'S', '𝓣' => 'T', '𝓤' => 'U', '𝓥' => 'V', '𝓦' => 'W', '𝓧' => 'X', '𝓨' => 'Y', '𝓩' => 'Z', '𝓪' => 'a', '𝓫' => 'b', '𝓬' => 'c', '𝓭' => 'd', '𝓮' => 'e', '𝓯' => 'f', '𝓰' => 'g', '𝓱' => 'h', '𝓲' => 'i', '𝓳' => 'j', '𝓴' => 'k', '𝓵' => 'l', '𝓶' => 'm', '𝓷' => 'n', '𝓸' => 'o', '𝓹' => 'p', '𝓺' => 'q', '𝓻' => 'r', '𝓼' => 's', '𝓽' => 't', '𝓾' => 'u', '𝓿' => 'v', '𝔀' => 'w', '𝔁' => 'x', '𝔂' => 'y', '𝔃' => 'z', '𝔄' => 'A', '𝔅' => 'B', '𝔇' => 'D', '𝔈' => 'E', '𝔉' => 'F', '𝔊' => 'G', '𝔍' => 'J', '𝔎' => 'K', '𝔏' => 'L', '𝔐' => 'M', '𝔑' => 'N', '𝔒' => 'O', '𝔓' => 'P', '𝔔' => 'Q', '𝔖' => 'S', '𝔗' => 'T', '𝔘' => 'U', '𝔙' => 'V', '𝔚' => 'W', '𝔛' => 'X', '𝔜' => 'Y', '𝔞' => 'a', '𝔟' => 'b', '𝔠' => 'c', '𝔡' => 'd', '𝔢' => 'e', '𝔣' => 'f', '𝔤' => 'g', '𝔥' => 'h', '𝔦' => 'i', '𝔧' => 'j', '𝔨' => 'k', '𝔩' => 'l', '𝔪' => 'm', '𝔫' => 'n', '𝔬' => 'o', '𝔭' => 'p', '𝔮' => 'q', '𝔯' => 'r', '𝔰' => 's', '𝔱' => 't', '𝔲' => 'u', '𝔳' => 'v', '𝔴' => 'w', '𝔵' => 'x', '𝔶' => 'y', '𝔷' => 'z', '𝔸' => 'A', '𝔹' => 'B', '𝔻' => 'D', '𝔼' => 'E', '𝔽' => 'F', '𝔾' => 'G', '𝕀' => 'I', '𝕁' => 'J', '𝕂' => 'K', '𝕃' => 'L', '𝕄' => 'M', '𝕆' => 'O', '𝕊' => 'S', '𝕋' => 'T', '𝕌' => 'U', '𝕍' => 'V', '𝕎' => 'W', '𝕏' => 'X', '𝕐' => 'Y', '𝕒' => 'a', '𝕓' => 'b', '𝕔' => 'c', '𝕕' => 'd', '𝕖' => 'e', '𝕗' => 'f', '𝕘' => 'g', '𝕙' => 'h', '𝕚' => 'i', '𝕛' => 'j', '𝕜' => 'k', '𝕝' => 'l', '𝕞' => 'm', '𝕟' => 'n', '𝕠' => 'o', '𝕡' => 'p', '𝕢' => 'q', '𝕣' => 'r', '𝕤' => 's', '𝕥' => 't', '𝕦' => 'u', '𝕧' => 'v', '𝕨' => 'w', '𝕩' => 'x', '𝕪' => 'y', '𝕫' => 'z', '𝕬' => 'A', '𝕭' => 'B', '𝕮' => 'C', '𝕯' => 'D', '𝕰' => 'E', '𝕱' => 'F', '𝕲' => 'G', '𝕳' => 'H', '𝕴' => 'I', '𝕵' => 'J', '𝕶' => 'K', '𝕷' => 'L', '𝕸' => 'M', '𝕹' => 'N', '𝕺' => 'O', '𝕻' => 'P', '𝕼' => 'Q', '𝕽' => 'R', '𝕾' => 'S', '𝕿' => 'T', '𝖀' => 'U', '𝖁' => 'V', '𝖂' => 'W', '𝖃' => 'X', '𝖄' => 'Y', '𝖅' => 'Z', '𝖆' => 'a', '𝖇' => 'b', '𝖈' => 'c', '𝖉' => 'd', '𝖊' => 'e', '𝖋' => 'f', '𝖌' => 'g', '𝖍' => 'h', '𝖎' => 'i', '𝖏' => 'j', '𝖐' => 'k', '𝖑' => 'l', '𝖒' => 'm', '𝖓' => 'n', '𝖔' => 'o', '𝖕' => 'p', '𝖖' => 'q', '𝖗' => 'r', '𝖘' => 's', '𝖙' => 't', '𝖚' => 'u', '𝖛' => 'v', '𝖜' => 'w', '𝖝' => 'x', '𝖞' => 'y', '𝖟' => 'z', '𝖠' => 'A', '𝖡' => 'B', '𝖢' => 'C', '𝖣' => 'D', '𝖤' => 'E', '𝖥' => 'F', '𝖦' => 'G', '𝖧' => 'H', '𝖨' => 'I', '𝖩' => 'J', '𝖪' => 'K', '𝖫' => 'L', '𝖬' => 'M', '𝖭' => 'N', '𝖮' => 'O', '𝖯' => 'P', '𝖰' => 'Q', '𝖱' => 'R', '𝖲' => 'S', '𝖳' => 'T', '𝖴' => 'U', '𝖵' => 'V', '𝖶' => 'W', '𝖷' => 'X', '𝖸' => 'Y', '𝖹' => 'Z', '𝖺' => 'a', '𝖻' => 'b', '𝖼' => 'c', '𝖽' => 'd', '𝖾' => 'e', '𝖿' => 'f', '𝗀' => 'g', '𝗁' => 'h', '𝗂' => 'i', '𝗃' => 'j', '𝗄' => 'k', '𝗅' => 'l', '𝗆' => 'm', '𝗇' => 'n', '𝗈' => 'o', '𝗉' => 'p', '𝗊' => 'q', '𝗋' => 'r', '𝗌' => 's', '𝗍' => 't', '𝗎' => 'u', '𝗏' => 'v', '𝗐' => 'w', '𝗑' => 'x', '𝗒' => 'y', '𝗓' => 'z', '𝗔' => 'A', '𝗕' => 'B', '𝗖' => 'C', '𝗗' => 'D', '𝗘' => 'E', '𝗙' => 'F', '𝗚' => 'G', '𝗛' => 'H', '𝗜' => 'I', '𝗝' => 'J', '𝗞' => 'K', '𝗟' => 'L', '𝗠' => 'M', '𝗡' => 'N', '𝗢' => 'O', '𝗣' => 'P', '𝗤' => 'Q', '𝗥' => 'R', '𝗦' => 'S', '𝗧' => 'T', '𝗨' => 'U', '𝗩' => 'V', '𝗪' => 'W', '𝗫' => 'X', '𝗬' => 'Y', '𝗭' => 'Z', '𝗮' => 'a', '𝗯' => 'b', '𝗰' => 'c', '𝗱' => 'd', '𝗲' => 'e', '𝗳' => 'f', '𝗴' => 'g', '𝗵' => 'h', '𝗶' => 'i', '𝗷' => 'j', '𝗸' => 'k', '𝗹' => 'l', '𝗺' => 'm', '𝗻' => 'n', '𝗼' => 'o', '𝗽' => 'p', '𝗾' => 'q', '𝗿' => 'r', '𝘀' => 's', '𝘁' => 't', '𝘂' => 'u', '𝘃' => 'v', '𝘄' => 'w', '𝘅' => 'x', '𝘆' => 'y', '𝘇' => 'z', '𝘈' => 'A', '𝘉' => 'B', '𝘊' => 'C', '𝘋' => 'D', '𝘌' => 'E', '𝘍' => 'F', '𝘎' => 'G', '𝘏' => 'H', '𝘐' => 'I', '𝘑' => 'J', '𝘒' => 'K', '𝘓' => 'L', '𝘔' => 'M', '𝘕' => 'N', '𝘖' => 'O', '𝘗' => 'P', '𝘘' => 'Q', '𝘙' => 'R', '𝘚' => 'S', '𝘛' => 'T', '𝘜' => 'U', '𝘝' => 'V', '𝘞' => 'W', '𝘟' => 'X', '𝘠' => 'Y', '𝘡' => 'Z', '𝘢' => 'a', '𝘣' => 'b', '𝘤' => 'c', '𝘥' => 'd', '𝘦' => 'e', '𝘧' => 'f', '𝘨' => 'g', '𝘩' => 'h', '𝘪' => 'i', '𝘫' => 'j', '𝘬' => 'k', '𝘭' => 'l', '𝘮' => 'm', '𝘯' => 'n', '𝘰' => 'o', '𝘱' => 'p', '𝘲' => 'q', '𝘳' => 'r', '𝘴' => 's', '𝘵' => 't', '𝘶' => 'u', '𝘷' => 'v', '𝘸' => 'w', '𝘹' => 'x', '𝘺' => 'y', '𝘻' => 'z', '𝘼' => 'A', '𝘽' => 'B', '𝘾' => 'C', '𝘿' => 'D', '𝙀' => 'E', '𝙁' => 'F', '𝙂' => 'G', '𝙃' => 'H', '𝙄' => 'I', '𝙅' => 'J', '𝙆' => 'K', '𝙇' => 'L', '𝙈' => 'M', '𝙉' => 'N', '𝙊' => 'O', '𝙋' => 'P', '𝙌' => 'Q', '𝙍' => 'R', '𝙎' => 'S', '𝙏' => 'T', '𝙐' => 'U', '𝙑' => 'V', '𝙒' => 'W', '𝙓' => 'X', '𝙔' => 'Y', '𝙕' => 'Z', '𝙖' => 'a', '𝙗' => 'b', '𝙘' => 'c', '𝙙' => 'd', '𝙚' => 'e', '𝙛' => 'f', '𝙜' => 'g', '𝙝' => 'h', '𝙞' => 'i', '𝙟' => 'j', '𝙠' => 'k', '𝙡' => 'l', '𝙢' => 'm', '𝙣' => 'n', '𝙤' => 'o', '𝙥' => 'p', '𝙦' => 'q', '𝙧' => 'r', '𝙨' => 's', '𝙩' => 't', '𝙪' => 'u', '𝙫' => 'v', '𝙬' => 'w', '𝙭' => 'x', '𝙮' => 'y', '𝙯' => 'z', '𝙰' => 'A', '𝙱' => 'B', '𝙲' => 'C', '𝙳' => 'D', '𝙴' => 'E', '𝙵' => 'F', '𝙶' => 'G', '𝙷' => 'H', '𝙸' => 'I', '𝙹' => 'J', '𝙺' => 'K', '𝙻' => 'L', '𝙼' => 'M', '𝙽' => 'N', '𝙾' => 'O', '𝙿' => 'P', '𝚀' => 'Q', '𝚁' => 'R', '𝚂' => 'S', '𝚃' => 'T', '𝚄' => 'U', '𝚅' => 'V', '𝚆' => 'W', '𝚇' => 'X', '𝚈' => 'Y', '𝚉' => 'Z', '𝚊' => 'a', '𝚋' => 'b', '𝚌' => 'c', '𝚍' => 'd', '𝚎' => 'e', '𝚏' => 'f', '𝚐' => 'g', '𝚑' => 'h', '𝚒' => 'i', '𝚓' => 'j', '𝚔' => 'k', '𝚕' => 'l', '𝚖' => 'm', '𝚗' => 'n', '𝚘' => 'o', '𝚙' => 'p', '𝚚' => 'q', '𝚛' => 'r', '𝚜' => 's', '𝚝' => 't', '𝚞' => 'u', '𝚟' => 'v', '𝚠' => 'w', '𝚡' => 'x', '𝚢' => 'y', '𝚣' => 'z', '𝚤' => 'ı', '𝚥' => 'ȷ', '𝚨' => 'Α', '𝚩' => 'Β', '𝚪' => 'Γ', '𝚫' => 'Δ', '𝚬' => 'Ε', '𝚭' => 'Ζ', '𝚮' => 'Η', '𝚯' => 'Θ', '𝚰' => 'Ι', '𝚱' => 'Κ', '𝚲' => 'Λ', '𝚳' => 'Μ', '𝚴' => 'Ν', '𝚵' => 'Ξ', '𝚶' => 'Ο', '𝚷' => 'Π', '𝚸' => 'Ρ', '𝚹' => 'Θ', '𝚺' => 'Σ', '𝚻' => 'Τ', '𝚼' => 'Υ', '𝚽' => 'Φ', '𝚾' => 'Χ', '𝚿' => 'Ψ', '𝛀' => 'Ω', '𝛁' => '∇', '𝛂' => 'α', '𝛃' => 'β', '𝛄' => 'γ', '𝛅' => 'δ', '𝛆' => 'ε', '𝛇' => 'ζ', '𝛈' => 'η', '𝛉' => 'θ', '𝛊' => 'ι', '𝛋' => 'κ', '𝛌' => 'λ', '𝛍' => 'μ', '𝛎' => 'ν', '𝛏' => 'ξ', '𝛐' => 'ο', '𝛑' => 'π', '𝛒' => 'ρ', '𝛓' => 'ς', '𝛔' => 'σ', '𝛕' => 'τ', '𝛖' => 'υ', '𝛗' => 'φ', '𝛘' => 'χ', '𝛙' => 'ψ', '𝛚' => 'ω', '𝛛' => '∂', '𝛜' => 'ε', '𝛝' => 'θ', '𝛞' => 'κ', '𝛟' => 'φ', '𝛠' => 'ρ', '𝛡' => 'π', '𝛢' => 'Α', '𝛣' => 'Β', '𝛤' => 'Γ', '𝛥' => 'Δ', '𝛦' => 'Ε', '𝛧' => 'Ζ', '𝛨' => 'Η', '𝛩' => 'Θ', '𝛪' => 'Ι', '𝛫' => 'Κ', '𝛬' => 'Λ', '𝛭' => 'Μ', '𝛮' => 'Ν', '𝛯' => 'Ξ', '𝛰' => 'Ο', '𝛱' => 'Π', '𝛲' => 'Ρ', '𝛳' => 'Θ', '𝛴' => 'Σ', '𝛵' => 'Τ', '𝛶' => 'Υ', '𝛷' => 'Φ', '𝛸' => 'Χ', '𝛹' => 'Ψ', '𝛺' => 'Ω', '𝛻' => '∇', '𝛼' => 'α', '𝛽' => 'β', '𝛾' => 'γ', '𝛿' => 'δ', '𝜀' => 'ε', '𝜁' => 'ζ', '𝜂' => 'η', '𝜃' => 'θ', '𝜄' => 'ι', '𝜅' => 'κ', '𝜆' => 'λ', '𝜇' => 'μ', '𝜈' => 'ν', '𝜉' => 'ξ', '𝜊' => 'ο', '𝜋' => 'π', '𝜌' => 'ρ', '𝜍' => 'ς', '𝜎' => 'σ', '𝜏' => 'τ', '𝜐' => 'υ', '𝜑' => 'φ', '𝜒' => 'χ', '𝜓' => 'ψ', '𝜔' => 'ω', '𝜕' => '∂', '𝜖' => 'ε', '𝜗' => 'θ', '𝜘' => 'κ', '𝜙' => 'φ', '𝜚' => 'ρ', '𝜛' => 'π', '𝜜' => 'Α', '𝜝' => 'Β', '𝜞' => 'Γ', '𝜟' => 'Δ', '𝜠' => 'Ε', '𝜡' => 'Ζ', '𝜢' => 'Η', '𝜣' => 'Θ', '𝜤' => 'Ι', '𝜥' => 'Κ', '𝜦' => 'Λ', '𝜧' => 'Μ', '𝜨' => 'Ν', '𝜩' => 'Ξ', '𝜪' => 'Ο', '𝜫' => 'Π', '𝜬' => 'Ρ', '𝜭' => 'Θ', '𝜮' => 'Σ', '𝜯' => 'Τ', '𝜰' => 'Υ', '𝜱' => 'Φ', '𝜲' => 'Χ', '𝜳' => 'Ψ', '𝜴' => 'Ω', '𝜵' => '∇', '𝜶' => 'α', '𝜷' => 'β', '𝜸' => 'γ', '𝜹' => 'δ', '𝜺' => 'ε', '𝜻' => 'ζ', '𝜼' => 'η', '𝜽' => 'θ', '𝜾' => 'ι', '𝜿' => 'κ', '𝝀' => 'λ', '𝝁' => 'μ', '𝝂' => 'ν', '𝝃' => 'ξ', '𝝄' => 'ο', '𝝅' => 'π', '𝝆' => 'ρ', '𝝇' => 'ς', '𝝈' => 'σ', '𝝉' => 'τ', '𝝊' => 'υ', '𝝋' => 'φ', '𝝌' => 'χ', '𝝍' => 'ψ', '𝝎' => 'ω', '𝝏' => '∂', '𝝐' => 'ε', '𝝑' => 'θ', '𝝒' => 'κ', '𝝓' => 'φ', '𝝔' => 'ρ', '𝝕' => 'π', '𝝖' => 'Α', '𝝗' => 'Β', '𝝘' => 'Γ', '𝝙' => 'Δ', '𝝚' => 'Ε', '𝝛' => 'Ζ', '𝝜' => 'Η', '𝝝' => 'Θ', '𝝞' => 'Ι', '𝝟' => 'Κ', '𝝠' => 'Λ', '𝝡' => 'Μ', '𝝢' => 'Ν', '𝝣' => 'Ξ', '𝝤' => 'Ο', '𝝥' => 'Π', '𝝦' => 'Ρ', '𝝧' => 'Θ', '𝝨' => 'Σ', '𝝩' => 'Τ', '𝝪' => 'Υ', '𝝫' => 'Φ', '𝝬' => 'Χ', '𝝭' => 'Ψ', '𝝮' => 'Ω', '𝝯' => '∇', '𝝰' => 'α', '𝝱' => 'β', '𝝲' => 'γ', '𝝳' => 'δ', '𝝴' => 'ε', '𝝵' => 'ζ', '𝝶' => 'η', '𝝷' => 'θ', '𝝸' => 'ι', '𝝹' => 'κ', '𝝺' => 'λ', '𝝻' => 'μ', '𝝼' => 'ν', '𝝽' => 'ξ', '𝝾' => 'ο', '𝝿' => 'π', '𝞀' => 'ρ', '𝞁' => 'ς', '𝞂' => 'σ', '𝞃' => 'τ', '𝞄' => 'υ', '𝞅' => 'φ', '𝞆' => 'χ', '𝞇' => 'ψ', '𝞈' => 'ω', '𝞉' => '∂', '𝞊' => 'ε', '𝞋' => 'θ', '𝞌' => 'κ', '𝞍' => 'φ', '𝞎' => 'ρ', '𝞏' => 'π', '𝞐' => 'Α', '𝞑' => 'Β', '𝞒' => 'Γ', '𝞓' => 'Δ', '𝞔' => 'Ε', '𝞕' => 'Ζ', '𝞖' => 'Η', '𝞗' => 'Θ', '𝞘' => 'Ι', '𝞙' => 'Κ', '𝞚' => 'Λ', '𝞛' => 'Μ', '𝞜' => 'Ν', '𝞝' => 'Ξ', '𝞞' => 'Ο', '𝞟' => 'Π', '𝞠' => 'Ρ', '𝞡' => 'Θ', '𝞢' => 'Σ', '𝞣' => 'Τ', '𝞤' => 'Υ', '𝞥' => 'Φ', '𝞦' => 'Χ', '𝞧' => 'Ψ', '𝞨' => 'Ω', '𝞩' => '∇', '𝞪' => 'α', '𝞫' => 'β', '𝞬' => 'γ', '𝞭' => 'δ', '𝞮' => 'ε', '𝞯' => 'ζ', '𝞰' => 'η', '𝞱' => 'θ', '𝞲' => 'ι', '𝞳' => 'κ', '𝞴' => 'λ', '𝞵' => 'μ', '𝞶' => 'ν', '𝞷' => 'ξ', '𝞸' => 'ο', '𝞹' => 'π', '𝞺' => 'ρ', '𝞻' => 'ς', '𝞼' => 'σ', '𝞽' => 'τ', '𝞾' => 'υ', '𝞿' => 'φ', '𝟀' => 'χ', '𝟁' => 'ψ', '𝟂' => 'ω', '𝟃' => '∂', '𝟄' => 'ε', '𝟅' => 'θ', '𝟆' => 'κ', '𝟇' => 'φ', '𝟈' => 'ρ', '𝟉' => 'π', '𝟊' => 'Ϝ', '𝟋' => 'ϝ', '𝟎' => '0', '𝟏' => '1', '𝟐' => '2', '𝟑' => '3', '𝟒' => '4', '𝟓' => '5', '𝟔' => '6', '𝟕' => '7', '𝟖' => '8', '𝟗' => '9', '𝟘' => '0', '𝟙' => '1', '𝟚' => '2', '𝟛' => '3', '𝟜' => '4', '𝟝' => '5', '𝟞' => '6', '𝟟' => '7', '𝟠' => '8', '𝟡' => '9', '𝟢' => '0', '𝟣' => '1', '𝟤' => '2', '𝟥' => '3', '𝟦' => '4', '𝟧' => '5', '𝟨' => '6', '𝟩' => '7', '𝟪' => '8', '𝟫' => '9', '𝟬' => '0', '𝟭' => '1', '𝟮' => '2', '𝟯' => '3', '𝟰' => '4', '𝟱' => '5', '𝟲' => '6', '𝟳' => '7', '𝟴' => '8', '𝟵' => '9', '𝟶' => '0', '𝟷' => '1', '𝟸' => '2', '𝟹' => '3', '𝟺' => '4', '𝟻' => '5', '𝟼' => '6', '𝟽' => '7', '𝟾' => '8', '𝟿' => '9', '𞸀' => 'ا', '𞸁' => 'ب', '𞸂' => 'ج', '𞸃' => 'د', '𞸅' => 'و', '𞸆' => 'ز', '𞸇' => 'ح', '𞸈' => 'ط', '𞸉' => 'ي', '𞸊' => 'ك', '𞸋' => 'ل', '𞸌' => 'م', '𞸍' => 'ن', '𞸎' => 'س', '𞸏' => 'ع', '𞸐' => 'ف', '𞸑' => 'ص', '𞸒' => 'ق', '𞸓' => 'ر', '𞸔' => 'ش', '𞸕' => 'ت', '𞸖' => 'ث', '𞸗' => 'خ', '𞸘' => 'ذ', '𞸙' => 'ض', '𞸚' => 'ظ', '𞸛' => 'غ', '𞸜' => 'ٮ', '𞸝' => 'ں', '𞸞' => 'ڡ', '𞸟' => 'ٯ', '𞸡' => 'ب', '𞸢' => 'ج', '𞸤' => 'ه', '𞸧' => 'ح', '𞸩' => 'ي', '𞸪' => 'ك', '𞸫' => 'ل', '𞸬' => 'م', '𞸭' => 'ن', '𞸮' => 'س', '𞸯' => 'ع', '𞸰' => 'ف', '𞸱' => 'ص', '𞸲' => 'ق', '𞸴' => 'ش', '𞸵' => 'ت', '𞸶' => 'ث', '𞸷' => 'خ', '𞸹' => 'ض', '𞸻' => 'غ', '𞹂' => 'ج', '𞹇' => 'ح', '𞹉' => 'ي', '𞹋' => 'ل', '𞹍' => 'ن', '𞹎' => 'س', '𞹏' => 'ع', '𞹑' => 'ص', '𞹒' => 'ق', '𞹔' => 'ش', '𞹗' => 'خ', '𞹙' => 'ض', '𞹛' => 'غ', '𞹝' => 'ں', '𞹟' => 'ٯ', '𞹡' => 'ب', '𞹢' => 'ج', '𞹤' => 'ه', '𞹧' => 'ح', '𞹨' => 'ط', '𞹩' => 'ي', '𞹪' => 'ك', '𞹬' => 'م', '𞹭' => 'ن', '𞹮' => 'س', '𞹯' => 'ع', '𞹰' => 'ف', '𞹱' => 'ص', '𞹲' => 'ق', '𞹴' => 'ش', '𞹵' => 'ت', '𞹶' => 'ث', '𞹷' => 'خ', '𞹹' => 'ض', '𞹺' => 'ظ', '𞹻' => 'غ', '𞹼' => 'ٮ', '𞹾' => 'ڡ', '𞺀' => 'ا', '𞺁' => 'ب', '𞺂' => 'ج', '𞺃' => 'د', '𞺄' => 'ه', '𞺅' => 'و', '𞺆' => 'ز', '𞺇' => 'ح', '𞺈' => 'ط', '𞺉' => 'ي', '𞺋' => 'ل', '𞺌' => 'م', '𞺍' => 'ن', '𞺎' => 'س', '𞺏' => 'ع', '𞺐' => 'ف', '𞺑' => 'ص', '𞺒' => 'ق', '𞺓' => 'ر', '𞺔' => 'ش', '𞺕' => 'ت', '𞺖' => 'ث', '𞺗' => 'خ', '𞺘' => 'ذ', '𞺙' => 'ض', '𞺚' => 'ظ', '𞺛' => 'غ', '𞺡' => 'ب', '𞺢' => 'ج', '𞺣' => 'د', '𞺥' => 'و', '𞺦' => 'ز', '𞺧' => 'ح', '𞺨' => 'ط', '𞺩' => 'ي', '𞺫' => 'ل', '𞺬' => 'م', '𞺭' => 'ن', '𞺮' => 'س', '𞺯' => 'ع', '𞺰' => 'ف', '𞺱' => 'ص', '𞺲' => 'ق', '𞺳' => 'ر', '𞺴' => 'ش', '𞺵' => 'ت', '𞺶' => 'ث', '𞺷' => 'خ', '𞺸' => 'ذ', '𞺹' => 'ض', '𞺺' => 'ظ', '𞺻' => 'غ', '🄀' => '0.', '🄁' => '0,', '🄂' => '1,', '🄃' => '2,', '🄄' => '3,', '🄅' => '4,', '🄆' => '5,', '🄇' => '6,', '🄈' => '7,', '🄉' => '8,', '🄊' => '9,', '🄐' => '(A)', '🄑' => '(B)', '🄒' => '(C)', '🄓' => '(D)', '🄔' => '(E)', '🄕' => '(F)', '🄖' => '(G)', '🄗' => '(H)', '🄘' => '(I)', '🄙' => '(J)', '🄚' => '(K)', '🄛' => '(L)', '🄜' => '(M)', '🄝' => '(N)', '🄞' => '(O)', '🄟' => '(P)', '🄠' => '(Q)', '🄡' => '(R)', '🄢' => '(S)', '🄣' => '(T)', '🄤' => '(U)', '🄥' => '(V)', '🄦' => '(W)', '🄧' => '(X)', '🄨' => '(Y)', '🄩' => '(Z)', '🄪' => '〔S〕', '🄫' => 'C', '🄬' => 'R', '🄭' => 'CD', '🄮' => 'WZ', '🄰' => 'A', '🄱' => 'B', '🄲' => 'C', '🄳' => 'D', '🄴' => 'E', '🄵' => 'F', '🄶' => 'G', '🄷' => 'H', '🄸' => 'I', '🄹' => 'J', '🄺' => 'K', '🄻' => 'L', '🄼' => 'M', '🄽' => 'N', '🄾' => 'O', '🄿' => 'P', '🅀' => 'Q', '🅁' => 'R', '🅂' => 'S', '🅃' => 'T', '🅄' => 'U', '🅅' => 'V', '🅆' => 'W', '🅇' => 'X', '🅈' => 'Y', '🅉' => 'Z', '🅊' => 'HV', '🅋' => 'MV', '🅌' => 'SD', '🅍' => 'SS', '🅎' => 'PPV', '🅏' => 'WC', '🅪' => 'MC', '🅫' => 'MD', '🅬' => 'MR', '🆐' => 'DJ', '🈀' => 'ほか', '🈁' => 'ココ', '🈂' => 'サ', '🈐' => '手', '🈑' => '字', '🈒' => '双', '🈓' => 'デ', '🈔' => '二', '🈕' => '多', '🈖' => '解', '🈗' => '天', '🈘' => '交', '🈙' => '映', '🈚' => '無', '🈛' => '料', '🈜' => '前', '🈝' => '後', '🈞' => '再', '🈟' => '新', '🈠' => '初', '🈡' => '終', '🈢' => '生', '🈣' => '販', '🈤' => '声', '🈥' => '吹', '🈦' => '演', '🈧' => '投', '🈨' => '捕', '🈩' => '一', '🈪' => '三', '🈫' => '遊', '🈬' => '左', '🈭' => '中', '🈮' => '右', '🈯' => '指', '🈰' => '走', '🈱' => '打', '🈲' => '禁', '🈳' => '空', '🈴' => '合', '🈵' => '満', '🈶' => '有', '🈷' => '月', '🈸' => '申', '🈹' => '割', '🈺' => '営', '🈻' => '配', '🉀' => '〔本〕', '🉁' => '〔三〕', '🉂' => '〔二〕', '🉃' => '〔安〕', '🉄' => '〔点〕', '🉅' => '〔打〕', '🉆' => '〔盗〕', '🉇' => '〔勝〕', '🉈' => '〔敗〕', '🉐' => '得', '🉑' => '可', '🯰' => '0', '🯱' => '1', '🯲' => '2', '🯳' => '3', '🯴' => '4', '🯵' => '5', '🯶' => '6', '🯷' => '7', '🯸' => '8', '🯹' => '9', ); polyfill-intl-normalizer/Resources/unidata/combiningClass.php000064400000032504150432043200020562 0ustar00 230, '́' => 230, '̂' => 230, '̃' => 230, '̄' => 230, '̅' => 230, '̆' => 230, '̇' => 230, '̈' => 230, '̉' => 230, '̊' => 230, '̋' => 230, '̌' => 230, '̍' => 230, '̎' => 230, '̏' => 230, '̐' => 230, '̑' => 230, '̒' => 230, '̓' => 230, '̔' => 230, '̕' => 232, '̖' => 220, '̗' => 220, '̘' => 220, '̙' => 220, '̚' => 232, '̛' => 216, '̜' => 220, '̝' => 220, '̞' => 220, '̟' => 220, '̠' => 220, '̡' => 202, '̢' => 202, '̣' => 220, '̤' => 220, '̥' => 220, '̦' => 220, '̧' => 202, '̨' => 202, '̩' => 220, '̪' => 220, '̫' => 220, '̬' => 220, '̭' => 220, '̮' => 220, '̯' => 220, '̰' => 220, '̱' => 220, '̲' => 220, '̳' => 220, '̴' => 1, '̵' => 1, '̶' => 1, '̷' => 1, '̸' => 1, '̹' => 220, '̺' => 220, '̻' => 220, '̼' => 220, '̽' => 230, '̾' => 230, '̿' => 230, '̀' => 230, '́' => 230, '͂' => 230, '̓' => 230, '̈́' => 230, 'ͅ' => 240, '͆' => 230, '͇' => 220, '͈' => 220, '͉' => 220, '͊' => 230, '͋' => 230, '͌' => 230, '͍' => 220, '͎' => 220, '͐' => 230, '͑' => 230, '͒' => 230, '͓' => 220, '͔' => 220, '͕' => 220, '͖' => 220, '͗' => 230, '͘' => 232, '͙' => 220, '͚' => 220, '͛' => 230, '͜' => 233, '͝' => 234, '͞' => 234, '͟' => 233, '͠' => 234, '͡' => 234, '͢' => 233, 'ͣ' => 230, 'ͤ' => 230, 'ͥ' => 230, 'ͦ' => 230, 'ͧ' => 230, 'ͨ' => 230, 'ͩ' => 230, 'ͪ' => 230, 'ͫ' => 230, 'ͬ' => 230, 'ͭ' => 230, 'ͮ' => 230, 'ͯ' => 230, '҃' => 230, '҄' => 230, '҅' => 230, '҆' => 230, '҇' => 230, '֑' => 220, '֒' => 230, '֓' => 230, '֔' => 230, '֕' => 230, '֖' => 220, '֗' => 230, '֘' => 230, '֙' => 230, '֚' => 222, '֛' => 220, '֜' => 230, '֝' => 230, '֞' => 230, '֟' => 230, '֠' => 230, '֡' => 230, '֢' => 220, '֣' => 220, '֤' => 220, '֥' => 220, '֦' => 220, '֧' => 220, '֨' => 230, '֩' => 230, '֪' => 220, '֫' => 230, '֬' => 230, '֭' => 222, '֮' => 228, '֯' => 230, 'ְ' => 10, 'ֱ' => 11, 'ֲ' => 12, 'ֳ' => 13, 'ִ' => 14, 'ֵ' => 15, 'ֶ' => 16, 'ַ' => 17, 'ָ' => 18, 'ֹ' => 19, 'ֺ' => 19, 'ֻ' => 20, 'ּ' => 21, 'ֽ' => 22, 'ֿ' => 23, 'ׁ' => 24, 'ׂ' => 25, 'ׄ' => 230, 'ׅ' => 220, 'ׇ' => 18, 'ؐ' => 230, 'ؑ' => 230, 'ؒ' => 230, 'ؓ' => 230, 'ؔ' => 230, 'ؕ' => 230, 'ؖ' => 230, 'ؗ' => 230, 'ؘ' => 30, 'ؙ' => 31, 'ؚ' => 32, 'ً' => 27, 'ٌ' => 28, 'ٍ' => 29, 'َ' => 30, 'ُ' => 31, 'ِ' => 32, 'ّ' => 33, 'ْ' => 34, 'ٓ' => 230, 'ٔ' => 230, 'ٕ' => 220, 'ٖ' => 220, 'ٗ' => 230, '٘' => 230, 'ٙ' => 230, 'ٚ' => 230, 'ٛ' => 230, 'ٜ' => 220, 'ٝ' => 230, 'ٞ' => 230, 'ٟ' => 220, 'ٰ' => 35, 'ۖ' => 230, 'ۗ' => 230, 'ۘ' => 230, 'ۙ' => 230, 'ۚ' => 230, 'ۛ' => 230, 'ۜ' => 230, '۟' => 230, '۠' => 230, 'ۡ' => 230, 'ۢ' => 230, 'ۣ' => 220, 'ۤ' => 230, 'ۧ' => 230, 'ۨ' => 230, '۪' => 220, '۫' => 230, '۬' => 230, 'ۭ' => 220, 'ܑ' => 36, 'ܰ' => 230, 'ܱ' => 220, 'ܲ' => 230, 'ܳ' => 230, 'ܴ' => 220, 'ܵ' => 230, 'ܶ' => 230, 'ܷ' => 220, 'ܸ' => 220, 'ܹ' => 220, 'ܺ' => 230, 'ܻ' => 220, 'ܼ' => 220, 'ܽ' => 230, 'ܾ' => 220, 'ܿ' => 230, '݀' => 230, '݁' => 230, '݂' => 220, '݃' => 230, '݄' => 220, '݅' => 230, '݆' => 220, '݇' => 230, '݈' => 220, '݉' => 230, '݊' => 230, '߫' => 230, '߬' => 230, '߭' => 230, '߮' => 230, '߯' => 230, '߰' => 230, '߱' => 230, '߲' => 220, '߳' => 230, '߽' => 220, 'ࠖ' => 230, 'ࠗ' => 230, '࠘' => 230, '࠙' => 230, 'ࠛ' => 230, 'ࠜ' => 230, 'ࠝ' => 230, 'ࠞ' => 230, 'ࠟ' => 230, 'ࠠ' => 230, 'ࠡ' => 230, 'ࠢ' => 230, 'ࠣ' => 230, 'ࠥ' => 230, 'ࠦ' => 230, 'ࠧ' => 230, 'ࠩ' => 230, 'ࠪ' => 230, 'ࠫ' => 230, 'ࠬ' => 230, '࠭' => 230, '࡙' => 220, '࡚' => 220, '࡛' => 220, '࣓' => 220, 'ࣔ' => 230, 'ࣕ' => 230, 'ࣖ' => 230, 'ࣗ' => 230, 'ࣘ' => 230, 'ࣙ' => 230, 'ࣚ' => 230, 'ࣛ' => 230, 'ࣜ' => 230, 'ࣝ' => 230, 'ࣞ' => 230, 'ࣟ' => 230, '࣠' => 230, '࣡' => 230, 'ࣣ' => 220, 'ࣤ' => 230, 'ࣥ' => 230, 'ࣦ' => 220, 'ࣧ' => 230, 'ࣨ' => 230, 'ࣩ' => 220, '࣪' => 230, '࣫' => 230, '࣬' => 230, '࣭' => 220, '࣮' => 220, '࣯' => 220, 'ࣰ' => 27, 'ࣱ' => 28, 'ࣲ' => 29, 'ࣳ' => 230, 'ࣴ' => 230, 'ࣵ' => 230, 'ࣶ' => 220, 'ࣷ' => 230, 'ࣸ' => 230, 'ࣹ' => 220, 'ࣺ' => 220, 'ࣻ' => 230, 'ࣼ' => 230, 'ࣽ' => 230, 'ࣾ' => 230, 'ࣿ' => 230, '़' => 7, '्' => 9, '॑' => 230, '॒' => 220, '॓' => 230, '॔' => 230, '়' => 7, '্' => 9, '৾' => 230, '਼' => 7, '੍' => 9, '઼' => 7, '્' => 9, '଼' => 7, '୍' => 9, '்' => 9, '్' => 9, 'ౕ' => 84, 'ౖ' => 91, '಼' => 7, '್' => 9, '഻' => 9, '഼' => 9, '്' => 9, '්' => 9, 'ุ' => 103, 'ู' => 103, 'ฺ' => 9, '่' => 107, '้' => 107, '๊' => 107, '๋' => 107, 'ຸ' => 118, 'ູ' => 118, '຺' => 9, '່' => 122, '້' => 122, '໊' => 122, '໋' => 122, '༘' => 220, '༙' => 220, '༵' => 220, '༷' => 220, '༹' => 216, 'ཱ' => 129, 'ི' => 130, 'ུ' => 132, 'ེ' => 130, 'ཻ' => 130, 'ོ' => 130, 'ཽ' => 130, 'ྀ' => 130, 'ྂ' => 230, 'ྃ' => 230, '྄' => 9, '྆' => 230, '྇' => 230, '࿆' => 220, '့' => 7, '္' => 9, '်' => 9, 'ႍ' => 220, '፝' => 230, '፞' => 230, '፟' => 230, '᜔' => 9, '᜴' => 9, '្' => 9, '៝' => 230, 'ᢩ' => 228, '᤹' => 222, '᤺' => 230, '᤻' => 220, 'ᨗ' => 230, 'ᨘ' => 220, '᩠' => 9, '᩵' => 230, '᩶' => 230, '᩷' => 230, '᩸' => 230, '᩹' => 230, '᩺' => 230, '᩻' => 230, '᩼' => 230, '᩿' => 220, '᪰' => 230, '᪱' => 230, '᪲' => 230, '᪳' => 230, '᪴' => 230, '᪵' => 220, '᪶' => 220, '᪷' => 220, '᪸' => 220, '᪹' => 220, '᪺' => 220, '᪻' => 230, '᪼' => 230, '᪽' => 220, 'ᪿ' => 220, 'ᫀ' => 220, '᬴' => 7, '᭄' => 9, '᭫' => 230, '᭬' => 220, '᭭' => 230, '᭮' => 230, '᭯' => 230, '᭰' => 230, '᭱' => 230, '᭲' => 230, '᭳' => 230, '᮪' => 9, '᮫' => 9, '᯦' => 7, '᯲' => 9, '᯳' => 9, '᰷' => 7, '᳐' => 230, '᳑' => 230, '᳒' => 230, '᳔' => 1, '᳕' => 220, '᳖' => 220, '᳗' => 220, '᳘' => 220, '᳙' => 220, '᳚' => 230, '᳛' => 230, '᳜' => 220, '᳝' => 220, '᳞' => 220, '᳟' => 220, '᳠' => 230, '᳢' => 1, '᳣' => 1, '᳤' => 1, '᳥' => 1, '᳦' => 1, '᳧' => 1, '᳨' => 1, '᳭' => 220, '᳴' => 230, '᳸' => 230, '᳹' => 230, '᷀' => 230, '᷁' => 230, '᷂' => 220, '᷃' => 230, '᷄' => 230, '᷅' => 230, '᷆' => 230, '᷇' => 230, '᷈' => 230, '᷉' => 230, '᷊' => 220, '᷋' => 230, '᷌' => 230, '᷍' => 234, '᷎' => 214, '᷏' => 220, '᷐' => 202, '᷑' => 230, '᷒' => 230, 'ᷓ' => 230, 'ᷔ' => 230, 'ᷕ' => 230, 'ᷖ' => 230, 'ᷗ' => 230, 'ᷘ' => 230, 'ᷙ' => 230, 'ᷚ' => 230, 'ᷛ' => 230, 'ᷜ' => 230, 'ᷝ' => 230, 'ᷞ' => 230, 'ᷟ' => 230, 'ᷠ' => 230, 'ᷡ' => 230, 'ᷢ' => 230, 'ᷣ' => 230, 'ᷤ' => 230, 'ᷥ' => 230, 'ᷦ' => 230, 'ᷧ' => 230, 'ᷨ' => 230, 'ᷩ' => 230, 'ᷪ' => 230, 'ᷫ' => 230, 'ᷬ' => 230, 'ᷭ' => 230, 'ᷮ' => 230, 'ᷯ' => 230, 'ᷰ' => 230, 'ᷱ' => 230, 'ᷲ' => 230, 'ᷳ' => 230, 'ᷴ' => 230, '᷵' => 230, '᷶' => 232, '᷷' => 228, '᷸' => 228, '᷹' => 220, '᷻' => 230, '᷼' => 233, '᷽' => 220, '᷾' => 230, '᷿' => 220, '⃐' => 230, '⃑' => 230, '⃒' => 1, '⃓' => 1, '⃔' => 230, '⃕' => 230, '⃖' => 230, '⃗' => 230, '⃘' => 1, '⃙' => 1, '⃚' => 1, '⃛' => 230, '⃜' => 230, '⃡' => 230, '⃥' => 1, '⃦' => 1, '⃧' => 230, '⃨' => 220, '⃩' => 230, '⃪' => 1, '⃫' => 1, '⃬' => 220, '⃭' => 220, '⃮' => 220, '⃯' => 220, '⃰' => 230, '⳯' => 230, '⳰' => 230, '⳱' => 230, '⵿' => 9, 'ⷠ' => 230, 'ⷡ' => 230, 'ⷢ' => 230, 'ⷣ' => 230, 'ⷤ' => 230, 'ⷥ' => 230, 'ⷦ' => 230, 'ⷧ' => 230, 'ⷨ' => 230, 'ⷩ' => 230, 'ⷪ' => 230, 'ⷫ' => 230, 'ⷬ' => 230, 'ⷭ' => 230, 'ⷮ' => 230, 'ⷯ' => 230, 'ⷰ' => 230, 'ⷱ' => 230, 'ⷲ' => 230, 'ⷳ' => 230, 'ⷴ' => 230, 'ⷵ' => 230, 'ⷶ' => 230, 'ⷷ' => 230, 'ⷸ' => 230, 'ⷹ' => 230, 'ⷺ' => 230, 'ⷻ' => 230, 'ⷼ' => 230, 'ⷽ' => 230, 'ⷾ' => 230, 'ⷿ' => 230, '〪' => 218, '〫' => 228, '〬' => 232, '〭' => 222, '〮' => 224, '〯' => 224, '゙' => 8, '゚' => 8, '꙯' => 230, 'ꙴ' => 230, 'ꙵ' => 230, 'ꙶ' => 230, 'ꙷ' => 230, 'ꙸ' => 230, 'ꙹ' => 230, 'ꙺ' => 230, 'ꙻ' => 230, '꙼' => 230, '꙽' => 230, 'ꚞ' => 230, 'ꚟ' => 230, '꛰' => 230, '꛱' => 230, '꠆' => 9, '꠬' => 9, '꣄' => 9, '꣠' => 230, '꣡' => 230, '꣢' => 230, '꣣' => 230, '꣤' => 230, '꣥' => 230, '꣦' => 230, '꣧' => 230, '꣨' => 230, '꣩' => 230, '꣪' => 230, '꣫' => 230, '꣬' => 230, '꣭' => 230, '꣮' => 230, '꣯' => 230, '꣰' => 230, '꣱' => 230, '꤫' => 220, '꤬' => 220, '꤭' => 220, '꥓' => 9, '꦳' => 7, '꧀' => 9, 'ꪰ' => 230, 'ꪲ' => 230, 'ꪳ' => 230, 'ꪴ' => 220, 'ꪷ' => 230, 'ꪸ' => 230, 'ꪾ' => 230, '꪿' => 230, '꫁' => 230, '꫶' => 9, '꯭' => 9, 'ﬞ' => 26, '︠' => 230, '︡' => 230, '︢' => 230, '︣' => 230, '︤' => 230, '︥' => 230, '︦' => 230, '︧' => 220, '︨' => 220, '︩' => 220, '︪' => 220, '︫' => 220, '︬' => 220, '︭' => 220, '︮' => 230, '︯' => 230, '𐇽' => 220, '𐋠' => 220, '𐍶' => 230, '𐍷' => 230, '𐍸' => 230, '𐍹' => 230, '𐍺' => 230, '𐨍' => 220, '𐨏' => 230, '𐨸' => 230, '𐨹' => 1, '𐨺' => 220, '𐨿' => 9, '𐫥' => 230, '𐫦' => 220, '𐴤' => 230, '𐴥' => 230, '𐴦' => 230, '𐴧' => 230, '𐺫' => 230, '𐺬' => 230, '𐽆' => 220, '𐽇' => 220, '𐽈' => 230, '𐽉' => 230, '𐽊' => 230, '𐽋' => 220, '𐽌' => 230, '𐽍' => 220, '𐽎' => 220, '𐽏' => 220, '𐽐' => 220, '𑁆' => 9, '𑁿' => 9, '𑂹' => 9, '𑂺' => 7, '𑄀' => 230, '𑄁' => 230, '𑄂' => 230, '𑄳' => 9, '𑄴' => 9, '𑅳' => 7, '𑇀' => 9, '𑇊' => 7, '𑈵' => 9, '𑈶' => 7, '𑋩' => 7, '𑋪' => 9, '𑌻' => 7, '𑌼' => 7, '𑍍' => 9, '𑍦' => 230, '𑍧' => 230, '𑍨' => 230, '𑍩' => 230, '𑍪' => 230, '𑍫' => 230, '𑍬' => 230, '𑍰' => 230, '𑍱' => 230, '𑍲' => 230, '𑍳' => 230, '𑍴' => 230, '𑑂' => 9, '𑑆' => 7, '𑑞' => 230, '𑓂' => 9, '𑓃' => 7, '𑖿' => 9, '𑗀' => 7, '𑘿' => 9, '𑚶' => 9, '𑚷' => 7, '𑜫' => 9, '𑠹' => 9, '𑠺' => 7, '𑤽' => 9, '𑤾' => 9, '𑥃' => 7, '𑧠' => 9, '𑨴' => 9, '𑩇' => 9, '𑪙' => 9, '𑰿' => 9, '𑵂' => 7, '𑵄' => 9, '𑵅' => 9, '𑶗' => 9, '𖫰' => 1, '𖫱' => 1, '𖫲' => 1, '𖫳' => 1, '𖫴' => 1, '𖬰' => 230, '𖬱' => 230, '𖬲' => 230, '𖬳' => 230, '𖬴' => 230, '𖬵' => 230, '𖬶' => 230, '𖿰' => 6, '𖿱' => 6, '𛲞' => 1, '𝅥' => 216, '𝅦' => 216, '𝅧' => 1, '𝅨' => 1, '𝅩' => 1, '𝅭' => 226, '𝅮' => 216, '𝅯' => 216, '𝅰' => 216, '𝅱' => 216, '𝅲' => 216, '𝅻' => 220, '𝅼' => 220, '𝅽' => 220, '𝅾' => 220, '𝅿' => 220, '𝆀' => 220, '𝆁' => 220, '𝆂' => 220, '𝆅' => 230, '𝆆' => 230, '𝆇' => 230, '𝆈' => 230, '𝆉' => 230, '𝆊' => 220, '𝆋' => 220, '𝆪' => 230, '𝆫' => 230, '𝆬' => 230, '𝆭' => 230, '𝉂' => 230, '𝉃' => 230, '𝉄' => 230, '𞀀' => 230, '𞀁' => 230, '𞀂' => 230, '𞀃' => 230, '𞀄' => 230, '𞀅' => 230, '𞀆' => 230, '𞀈' => 230, '𞀉' => 230, '𞀊' => 230, '𞀋' => 230, '𞀌' => 230, '𞀍' => 230, '𞀎' => 230, '𞀏' => 230, '𞀐' => 230, '𞀑' => 230, '𞀒' => 230, '𞀓' => 230, '𞀔' => 230, '𞀕' => 230, '𞀖' => 230, '𞀗' => 230, '𞀘' => 230, '𞀛' => 230, '𞀜' => 230, '𞀝' => 230, '𞀞' => 230, '𞀟' => 230, '𞀠' => 230, '𞀡' => 230, '𞀣' => 230, '𞀤' => 230, '𞀦' => 230, '𞀧' => 230, '𞀨' => 230, '𞀩' => 230, '𞀪' => 230, '𞄰' => 230, '𞄱' => 230, '𞄲' => 230, '𞄳' => 230, '𞄴' => 230, '𞄵' => 230, '𞄶' => 230, '𞋬' => 230, '𞋭' => 230, '𞋮' => 230, '𞋯' => 230, '𞣐' => 220, '𞣑' => 220, '𞣒' => 220, '𞣓' => 220, '𞣔' => 220, '𞣕' => 220, '𞣖' => 220, '𞥄' => 230, '𞥅' => 230, '𞥆' => 230, '𞥇' => 230, '𞥈' => 230, '𞥉' => 230, '𞥊' => 7, ); polyfill-intl-normalizer/README.md000064400000000662150432043200012776 0ustar00Symfony Polyfill / Intl: Normalizer =================================== This component provides a fallback implementation for the [`Normalizer`](https://php.net/Normalizer) class provided by the [Intl](https://php.net/intl) extension. More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= This library is released under the [MIT license](LICENSE). polyfill-intl-normalizer/bootstrap80.php000064400000001317150432043200014413 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Intl\Normalizer as p; if (!function_exists('normalizer_is_normalized')) { function normalizer_is_normalized(?string $string, ?int $form = p\Normalizer::FORM_C): bool { return p\Normalizer::isNormalized((string) $string, (int) $form); } } if (!function_exists('normalizer_normalize')) { function normalizer_normalize(?string $string, ?int $form = p\Normalizer::FORM_C): string|false { return p\Normalizer::normalize((string) $string, (int) $form); } } polyfill-intl-normalizer/Normalizer.php000064400000022543150432043200014354 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Intl\Normalizer; /** * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension. * * It has been validated with Unicode 6.3 Normalization Conformance Test. * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations. * * @author Nicolas Grekas * * @internal */ class Normalizer { public const FORM_D = \Normalizer::FORM_D; public const FORM_KD = \Normalizer::FORM_KD; public const FORM_C = \Normalizer::FORM_C; public const FORM_KC = \Normalizer::FORM_KC; public const NFD = \Normalizer::NFD; public const NFKD = \Normalizer::NFKD; public const NFC = \Normalizer::NFC; public const NFKC = \Normalizer::NFKC; private static $C; private static $D; private static $KD; private static $cC; private static $ulenMask = ["\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4]; private static $ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; public static function isNormalized(string $s, int $form = self::FORM_C) { if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) { return false; } if (!isset($s[strspn($s, self::$ASCII)])) { return true; } if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\x00-\x{2FF}]/u', $s)) { return true; } return self::normalize($s, $form) === $s; } public static function normalize(string $s, int $form = self::FORM_C) { if (!preg_match('//u', $s)) { return false; } switch ($form) { case self::NFC: $C = true; $K = false; break; case self::NFD: $C = false; $K = false; break; case self::NFKC: $C = true; $K = true; break; case self::NFKD: $C = false; $K = true; break; default: if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) { return $s; } if (80000 > \PHP_VERSION_ID) { return false; } throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form'); } if ('' === $s) { return ''; } if ($K && null === self::$KD) { self::$KD = self::getData('compatibilityDecomposition'); } if (null === self::$D) { self::$D = self::getData('canonicalDecomposition'); self::$cC = self::getData('combiningClass'); } if (null !== $mbEncoding = (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) ? mb_internal_encoding() : null) { mb_internal_encoding('8bit'); } $r = self::decompose($s, $K); if ($C) { if (null === self::$C) { self::$C = self::getData('canonicalComposition'); } $r = self::recompose($r); } if (null !== $mbEncoding) { mb_internal_encoding($mbEncoding); } return $r; } private static function recompose($s) { $ASCII = self::$ASCII; $compMap = self::$C; $combClass = self::$cC; $ulenMask = self::$ulenMask; $result = $tail = ''; $i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xF0"]; $len = \strlen($s); $lastUchr = substr($s, 0, $i); $lastUcls = isset($combClass[$lastUchr]) ? 256 : 0; while ($i < $len) { if ($s[$i] < "\x80") { // ASCII chars if ($tail) { $lastUchr .= $tail; $tail = ''; } if ($j = strspn($s, $ASCII, $i + 1)) { $lastUchr .= substr($s, $i, $j); $i += $j; } $result .= $lastUchr; $lastUchr = $s[$i]; $lastUcls = 0; ++$i; continue; } $ulen = $ulenMask[$s[$i] & "\xF0"]; $uchr = substr($s, $i, $ulen); if ($lastUchr < "\xE1\x84\x80" || "\xE1\x84\x92" < $lastUchr || $uchr < "\xE1\x85\xA1" || "\xE1\x85\xB5" < $uchr || $lastUcls) { // Table lookup and combining chars composition $ucls = $combClass[$uchr] ?? 0; if (isset($compMap[$lastUchr.$uchr]) && (!$lastUcls || $lastUcls < $ucls)) { $lastUchr = $compMap[$lastUchr.$uchr]; } elseif ($lastUcls = $ucls) { $tail .= $uchr; } else { if ($tail) { $lastUchr .= $tail; $tail = ''; } $result .= $lastUchr; $lastUchr = $uchr; } } else { // Hangul chars $L = \ord($lastUchr[2]) - 0x80; $V = \ord($uchr[2]) - 0xA1; $T = 0; $uchr = substr($s, $i + $ulen, 3); if ("\xE1\x86\xA7" <= $uchr && $uchr <= "\xE1\x87\x82") { $T = \ord($uchr[2]) - 0xA7; 0 > $T && $T += 0x40; $ulen += 3; } $L = 0xAC00 + ($L * 21 + $V) * 28 + $T; $lastUchr = \chr(0xE0 | $L >> 12).\chr(0x80 | $L >> 6 & 0x3F).\chr(0x80 | $L & 0x3F); } $i += $ulen; } return $result.$lastUchr.$tail; } private static function decompose($s, $c) { $result = ''; $ASCII = self::$ASCII; $decompMap = self::$D; $combClass = self::$cC; $ulenMask = self::$ulenMask; if ($c) { $compatMap = self::$KD; } $c = []; $i = 0; $len = \strlen($s); while ($i < $len) { if ($s[$i] < "\x80") { // ASCII chars if ($c) { ksort($c); $result .= implode('', $c); $c = []; } $j = 1 + strspn($s, $ASCII, $i + 1); $result .= substr($s, $i, $j); $i += $j; continue; } $ulen = $ulenMask[$s[$i] & "\xF0"]; $uchr = substr($s, $i, $ulen); $i += $ulen; if ($uchr < "\xEA\xB0\x80" || "\xED\x9E\xA3" < $uchr) { // Table lookup if ($uchr !== $j = $compatMap[$uchr] ?? ($decompMap[$uchr] ?? $uchr)) { $uchr = $j; $j = \strlen($uchr); $ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xF0"]; if ($ulen != $j) { // Put trailing chars in $s $j -= $ulen; $i -= $j; if (0 > $i) { $s = str_repeat(' ', -$i).$s; $len -= $i; $i = 0; } while ($j--) { $s[$i + $j] = $uchr[$ulen + $j]; } $uchr = substr($uchr, 0, $ulen); } } if (isset($combClass[$uchr])) { // Combining chars, for sorting if (!isset($c[$combClass[$uchr]])) { $c[$combClass[$uchr]] = ''; } $c[$combClass[$uchr]] .= $uchr; continue; } } else { // Hangul chars $uchr = unpack('C*', $uchr); $j = (($uchr[1] - 224) << 12) + (($uchr[2] - 128) << 6) + $uchr[3] - 0xAC80; $uchr = "\xE1\x84".\chr(0x80 + (int) ($j / 588)) ."\xE1\x85".\chr(0xA1 + (int) (($j % 588) / 28)); if ($j %= 28) { $uchr .= $j < 25 ? ("\xE1\x86".\chr(0xA7 + $j)) : ("\xE1\x87".\chr(0x67 + $j)); } } if ($c) { ksort($c); $result .= implode('', $c); $c = []; } $result .= $uchr; } if ($c) { ksort($c); $result .= implode('', $c); } return $result; } private static function getData($file) { if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) { return require $file; } return false; } } polyfill-intl-normalizer/bootstrap.php000064400000001325150432043200014242 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Intl\Normalizer as p; if (\PHP_VERSION_ID >= 80000) { return require __DIR__.'/bootstrap80.php'; } if (!function_exists('normalizer_is_normalized')) { function normalizer_is_normalized($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::isNormalized($string, $form); } } if (!function_exists('normalizer_normalize')) { function normalizer_normalize($string, $form = p\Normalizer::FORM_C) { return p\Normalizer::normalize($string, $form); } } polyfill-intl-normalizer/composer.json000064400000002103150432043200014231 0ustar00{ "name": "symfony/polyfill-intl-normalizer", "type": "library", "description": "Symfony polyfill for intl's Normalizer class and related functions", "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "normalizer"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, "files": [ "bootstrap.php" ], "classmap": [ "Resources/stubs" ] }, "suggest": { "ext-intl": "For best performance" }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-intl-normalizer/LICENSE000064400000002051150432043200012516 0ustar00Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var-dumper/Resources/functions/dump.php000064400000001741150432043200014262 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Component\VarDumper\VarDumper; if (!function_exists('dump')) { /** * @author Nicolas Grekas */ function dump($var, ...$moreVars) { VarDumper::dump($var); foreach ($moreVars as $v) { VarDumper::dump($v); } if (1 < func_num_args()) { return func_get_args(); } return $var; } } if (!function_exists('dd')) { /** * @return never */ function dd(...$vars) { if (!in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !headers_sent()) { header('HTTP/1.1 500 Internal Server Error'); } foreach ($vars as $v) { VarDumper::dump($v); } exit(1); } } var-dumper/Resources/bin/var-dump-server000064400000003766150432043200014337 0ustar00#!/usr/bin/env php * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ /** * Starts a dump server to collect and output dumps on a single place with multiple formats support. * * @author Maxime Steinhausser */ use Psr\Log\LoggerInterface; use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Logger\ConsoleLogger; use Symfony\Component\Console\Output\ConsoleOutput; use Symfony\Component\VarDumper\Command\ServerDumpCommand; use Symfony\Component\VarDumper\Server\DumpServer; function includeIfExists(string $file): bool { return file_exists($file) && include $file; } if ( !includeIfExists(__DIR__ . '/../../../../autoload.php') && !includeIfExists(__DIR__ . '/../../vendor/autoload.php') && !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php') ) { fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL); exit(1); } if (!class_exists(Application::class)) { fwrite(STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.'.PHP_EOL); exit(1); } $input = new ArgvInput(); $output = new ConsoleOutput(); $defaultHost = '127.0.0.1:9912'; $host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true); $logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null; $app = new Application(); $app->getDefinition()->addOption( new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost) ); $app->add($command = new ServerDumpCommand(new DumpServer($host, $logger))) ->getApplication() ->setDefaultCommand($command->getName(), true) ->run($input, $output) ; var-dumper/Resources/css/htmlDescriptor.css000064400000005702150432043200015102 0ustar00body { display: flex; flex-direction: column-reverse; justify-content: flex-end; max-width: 1140px; margin: auto; padding: 15px; word-wrap: break-word; background-color: #F9F9F9; color: #222; font-family: Helvetica, Arial, sans-serif; font-size: 14px; line-height: 1.4; } p { margin: 0; } a { color: #218BC3; text-decoration: none; } a:hover { text-decoration: underline; } .text-small { font-size: 12px !important; } article { margin: 5px; margin-bottom: 10px; } article > header > .row { display: flex; flex-direction: row; align-items: baseline; margin-bottom: 10px; } article > header > .row > .col { flex: 1; display: flex; align-items: baseline; } article > header > .row > h2 { font-size: 14px; color: #222; font-weight: normal; font-family: "Lucida Console", monospace, sans-serif; word-break: break-all; margin: 20px 5px 0 0; user-select: all; } article > header > .row > h2 > code { white-space: nowrap; user-select: none; color: #cc2255; background-color: #f7f7f9; border: 1px solid #e1e1e8; border-radius: 3px; margin-right: 5px; padding: 0 3px; } article > header > .row > time.col { flex: 0; text-align: right; white-space: nowrap; color: #999; font-style: italic; } article > header ul.tags { list-style: none; padding: 0; margin: 0; font-size: 12px; } article > header ul.tags > li { user-select: all; margin-bottom: 2px; } article > header ul.tags > li > span.badge { display: inline-block; padding: .25em .4em; margin-right: 5px; border-radius: 4px; background-color: #6c757d3b; color: #524d4d; font-size: 12px; text-align: center; font-weight: 700; line-height: 1; white-space: nowrap; vertical-align: baseline; user-select: none; } article > section.body { border: 1px solid #d8d8d8; background: #FFF; padding: 10px; border-radius: 3px; } pre.sf-dump { border-radius: 3px; margin-bottom: 0; } .hidden { display: none !important; } .dumped-tag > .sf-dump { display: inline-block; margin: 0; padding: 1px 5px; line-height: 1.4; vertical-align: top; background-color: transparent; user-select: auto; } .dumped-tag > pre.sf-dump, .dumped-tag > .sf-dump-default { color: #CC7832; background: none; } .dumped-tag > .sf-dump .sf-dump-str { color: #629755; } .dumped-tag > .sf-dump .sf-dump-private, .dumped-tag > .sf-dump .sf-dump-protected, .dumped-tag > .sf-dump .sf-dump-public { color: #262626; } .dumped-tag > .sf-dump .sf-dump-note { color: #6897BB; } .dumped-tag > .sf-dump .sf-dump-key { color: #789339; } .dumped-tag > .sf-dump .sf-dump-ref { color: #6E6E6E; } .dumped-tag > .sf-dump .sf-dump-ellipsis { color: #CC7832; max-width: 100em; } .dumped-tag > .sf-dump .sf-dump-ellipsis-path { max-width: 5em; } .dumped-tag > .sf-dump .sf-dump-ns { user-select: none; } var-dumper/Resources/js/htmlDescriptor.js000064400000000542150432043200014547 0ustar00document.addEventListener('DOMContentLoaded', function() { let prev = null; Array.from(document.getElementsByTagName('article')).reverse().forEach(function (article) { const dedupId = article.dataset.dedupId; if (dedupId === prev) { article.getElementsByTagName('header')[0].classList.add('hidden'); } prev = dedupId; }); }); var-dumper/README.md000064400000001137150432043200010100 0ustar00VarDumper Component =================== The VarDumper component provides mechanisms for walking through any arbitrary PHP variable. It provides a better `dump()` function that you can use instead of `var_dump()`. Resources --------- * [Documentation](https://symfony.com/doc/current/components/var_dumper/introduction.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) var-dumper/Cloner/Stub.php000064400000003024150432043210011467 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Cloner; /** * Represents the main properties of a PHP variable. * * @author Nicolas Grekas */ class Stub { public const TYPE_REF = 1; public const TYPE_STRING = 2; public const TYPE_ARRAY = 3; public const TYPE_OBJECT = 4; public const TYPE_RESOURCE = 5; public const STRING_BINARY = 1; public const STRING_UTF8 = 2; public const ARRAY_ASSOC = 1; public const ARRAY_INDEXED = 2; public $type = self::TYPE_REF; public $class = ''; public $value; public $cut = 0; public $handle = 0; public $refCount = 0; public $position = 0; public $attr = []; private static $defaultProperties = []; /** * @internal */ public function __sleep(): array { $properties = []; if (!isset(self::$defaultProperties[$c = static::class])) { self::$defaultProperties[$c] = get_class_vars($c); foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) { unset(self::$defaultProperties[$c][$k]); } } foreach (self::$defaultProperties[$c] as $k => $v) { if ($this->$k !== $v) { $properties[] = $k; } } return $properties; } } var-dumper/Cloner/VarCloner.php000064400000032733150432043210012456 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Cloner; /** * @author Nicolas Grekas */ class VarCloner extends AbstractCloner { private static $gid; private static $arrayCache = []; /** * {@inheritdoc} */ protected function doClone($var) { $len = 1; // Length of $queue $pos = 0; // Number of cloned items past the minimum depth $refsCounter = 0; // Hard references counter $queue = [[$var]]; // This breadth-first queue is the return value $hardRefs = []; // Map of original zval ids to stub objects $objRefs = []; // Map of original object handles to their stub object counterpart $objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning $resRefs = []; // Map of original resource handles to their stub object counterpart $values = []; // Map of stub objects' ids to original values $maxItems = $this->maxItems; $maxString = $this->maxString; $minDepth = $this->minDepth; $currentDepth = 0; // Current tree depth $currentDepthFinalIndex = 0; // Final $queue index for current tree depth $minimumDepthReached = 0 === $minDepth; // Becomes true when minimum tree depth has been reached $cookie = (object) []; // Unique object used to detect hard references $a = null; // Array cast for nested structures $stub = null; // Stub capturing the main properties of an original item value // or null if the original value is used directly if (!$gid = self::$gid) { $gid = self::$gid = md5(random_bytes(6)); // Unique string used to detect the special $GLOBALS variable } $arrayStub = new Stub(); $arrayStub->type = Stub::TYPE_ARRAY; $fromObjCast = false; for ($i = 0; $i < $len; ++$i) { // Detect when we move on to the next tree depth if ($i > $currentDepthFinalIndex) { ++$currentDepth; $currentDepthFinalIndex = $len - 1; if ($currentDepth >= $minDepth) { $minimumDepthReached = true; } } $refs = $vals = $queue[$i]; foreach ($vals as $k => $v) { // $v is the original value or a stub object in case of hard references if (\PHP_VERSION_ID >= 70400) { $zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null; } else { $refs[$k] = $cookie; $zvalRef = $vals[$k] === $cookie; } if ($zvalRef) { $vals[$k] = &$stub; // Break hard references to make $queue completely unset($stub); // independent from the original structure if (\PHP_VERSION_ID >= 70400 ? null !== $vals[$k] = $hardRefs[$zvalRef] ?? null : $v instanceof Stub && isset($hardRefs[spl_object_id($v)])) { if (\PHP_VERSION_ID >= 70400) { $v = $vals[$k]; } else { $refs[$k] = $vals[$k] = $v; } if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { ++$v->value->refCount; } ++$v->refCount; continue; } $vals[$k] = new Stub(); $vals[$k]->value = $v; $vals[$k]->handle = ++$refsCounter; if (\PHP_VERSION_ID >= 70400) { $hardRefs[$zvalRef] = $vals[$k]; } else { $refs[$k] = $vals[$k]; $h = spl_object_id($refs[$k]); $hardRefs[$h] = &$refs[$k]; $values[$h] = $v; } } // Create $stub when the original value $v cannot be used directly // If $v is a nested structure, put that structure in array $a switch (true) { case null === $v: case \is_bool($v): case \is_int($v): case \is_float($v): continue 2; case \is_string($v): if ('' === $v) { continue 2; } if (!preg_match('//u', $v)) { $stub = new Stub(); $stub->type = Stub::TYPE_STRING; $stub->class = Stub::STRING_BINARY; if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) { $stub->cut = $cut; $stub->value = substr($v, 0, -$cut); } else { $stub->value = $v; } } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) { $stub = new Stub(); $stub->type = Stub::TYPE_STRING; $stub->class = Stub::STRING_UTF8; $stub->cut = $cut; $stub->value = mb_substr($v, 0, $maxString, 'UTF-8'); } else { continue 2; } $a = null; break; case \is_array($v): if (!$v) { continue 2; } $stub = $arrayStub; if (\PHP_VERSION_ID >= 80100) { $stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC; $a = $v; break; } $stub->class = Stub::ARRAY_INDEXED; $j = -1; foreach ($v as $gk => $gv) { if ($gk !== ++$j) { $stub->class = Stub::ARRAY_ASSOC; $a = $v; $a[$gid] = true; break; } } // Copies of $GLOBALS have very strange behavior, // let's detect them with some black magic if (isset($v[$gid])) { unset($v[$gid]); $a = []; foreach ($v as $gk => &$gv) { if ($v === $gv && (\PHP_VERSION_ID < 70400 || !isset($hardRefs[\ReflectionReference::fromArrayElement($v, $gk)->getId()]))) { unset($v); $v = new Stub(); $v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0]; $v->handle = -1; if (\PHP_VERSION_ID >= 70400) { $gv = &$a[$gk]; $hardRefs[\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv; } else { $gv = &$hardRefs[spl_object_id($v)]; } $gv = $v; } $a[$gk] = &$gv; } unset($gv); } else { $a = $v; } break; case \is_object($v): if (empty($objRefs[$h = spl_object_id($v)])) { $stub = new Stub(); $stub->type = Stub::TYPE_OBJECT; $stub->class = \get_class($v); $stub->value = $v; $stub->handle = $h; $a = $this->castObject($stub, 0 < $i); if ($v !== $stub->value) { if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { break; } $stub->handle = $h = spl_object_id($stub->value); } $stub->value = null; if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { $stub->cut = \count($a); $a = null; } } if (empty($objRefs[$h])) { $objRefs[$h] = $stub; $objects[] = $v; } else { $stub = $objRefs[$h]; ++$stub->refCount; $a = null; } break; default: // resource if (empty($resRefs[$h = (int) $v])) { $stub = new Stub(); $stub->type = Stub::TYPE_RESOURCE; if ('Unknown' === $stub->class = @get_resource_type($v)) { $stub->class = 'Closed'; } $stub->value = $v; $stub->handle = $h; $a = $this->castResource($stub, 0 < $i); $stub->value = null; if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { $stub->cut = \count($a); $a = null; } } if (empty($resRefs[$h])) { $resRefs[$h] = $stub; } else { $stub = $resRefs[$h]; ++$stub->refCount; $a = null; } break; } if ($a) { if (!$minimumDepthReached || 0 > $maxItems) { $queue[$len] = $a; $stub->position = $len++; } elseif ($pos < $maxItems) { if ($maxItems < $pos += \count($a)) { $a = \array_slice($a, 0, $maxItems - $pos, true); if ($stub->cut >= 0) { $stub->cut += $pos - $maxItems; } } $queue[$len] = $a; $stub->position = $len++; } elseif ($stub->cut >= 0) { $stub->cut += \count($a); $stub->position = 0; } } if ($arrayStub === $stub) { if ($arrayStub->cut) { $stub = [$arrayStub->cut, $arrayStub->class => $arrayStub->position]; $arrayStub->cut = 0; } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) { $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position]; } else { self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = [$arrayStub->class => $arrayStub->position]; } } if (!$zvalRef) { $vals[$k] = $stub; } elseif (\PHP_VERSION_ID >= 70400) { $hardRefs[$zvalRef]->value = $stub; } else { $refs[$k]->value = $stub; } } if ($fromObjCast) { $fromObjCast = false; $refs = $vals; $vals = []; $j = -1; foreach ($queue[$i] as $k => $v) { foreach ([$k => true] as $gk => $gv) { } if ($gk !== $k) { $vals = (object) $vals; $vals->{$k} = $refs[++$j]; $vals = (array) $vals; } else { $vals[$k] = $refs[++$j]; } } } $queue[$i] = $vals; } foreach ($values as $h => $v) { $hardRefs[$h] = $v; } return $queue; } } var-dumper/Cloner/AbstractCloner.php000064400000051115150432043210013464 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Cloner; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Exception\ThrowingCasterException; /** * AbstractCloner implements a generic caster mechanism for objects and resources. * * @author Nicolas Grekas */ abstract class AbstractCloner implements ClonerInterface { public static $defaultCasters = [ '__PHP_Incomplete_Class' => ['Symfony\Component\VarDumper\Caster\Caster', 'castPhpIncompleteClass'], 'Symfony\Component\VarDumper\Caster\CutStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], 'Symfony\Component\VarDumper\Caster\CutArrayStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castCutArray'], 'Symfony\Component\VarDumper\Caster\ConstStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castStub'], 'Symfony\Component\VarDumper\Caster\EnumStub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'castEnum'], 'Fiber' => ['Symfony\Component\VarDumper\Caster\FiberCaster', 'castFiber'], 'Closure' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClosure'], 'Generator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castGenerator'], 'ReflectionType' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castType'], 'ReflectionAttribute' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castAttribute'], 'ReflectionGenerator' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReflectionGenerator'], 'ReflectionClass' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClass'], 'ReflectionClassConstant' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castClassConstant'], 'ReflectionFunctionAbstract' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castFunctionAbstract'], 'ReflectionMethod' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castMethod'], 'ReflectionParameter' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castParameter'], 'ReflectionProperty' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castProperty'], 'ReflectionReference' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castReference'], 'ReflectionExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castExtension'], 'ReflectionZendExtension' => ['Symfony\Component\VarDumper\Caster\ReflectionCaster', 'castZendExtension'], 'Doctrine\Common\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'Doctrine\Common\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castCommonProxy'], 'Doctrine\ORM\Proxy\Proxy' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castOrmProxy'], 'Doctrine\ORM\PersistentCollection' => ['Symfony\Component\VarDumper\Caster\DoctrineCaster', 'castPersistentCollection'], 'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'], 'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'], 'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'], 'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'], 'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'], 'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'], 'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'], 'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'], 'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'], 'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'], 'DOMTypeinfo' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castTypeinfo'], 'DOMDomError' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDomError'], 'DOMLocator' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLocator'], 'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'], 'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'], 'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'], 'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'], 'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'], 'XMLReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'], 'ErrorException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castErrorException'], 'Exception' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castException'], 'Error' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castError'], 'Symfony\Bridge\Monolog\Logger' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'Symfony\Component\DependencyInjection\ContainerInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'Symfony\Component\EventDispatcher\EventDispatcherInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'Symfony\Component\HttpClient\AmpHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], 'Symfony\Component\HttpClient\CurlHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], 'Symfony\Component\HttpClient\NativeHttpClient' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClient'], 'Symfony\Component\HttpClient\Response\AmpResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], 'Symfony\Component\HttpClient\Response\CurlResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], 'Symfony\Component\HttpClient\Response\NativeResponse' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castHttpClientResponse'], 'Symfony\Component\HttpFoundation\Request' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castRequest'], 'Symfony\Component\Uid\Ulid' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUlid'], 'Symfony\Component\Uid\Uuid' => ['Symfony\Component\VarDumper\Caster\SymfonyCaster', 'castUuid'], 'Symfony\Component\VarDumper\Exception\ThrowingCasterException' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castThrowingCasterException'], 'Symfony\Component\VarDumper\Caster\TraceStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castTraceStub'], 'Symfony\Component\VarDumper\Caster\FrameStub' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castFrameStub'], 'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'], 'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'], 'Ramsey\Uuid\UuidInterface' => ['Symfony\Component\VarDumper\Caster\UuidCaster', 'castRamseyUuid'], 'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'], 'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'PHPUnit\Framework\MockObject\MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'PHPUnit\Framework\MockObject\Stub' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'Mockery\MockInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'], 'PDO' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdo'], 'PDOStatement' => ['Symfony\Component\VarDumper\Caster\PdoCaster', 'castPdoStatement'], 'AMQPConnection' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castConnection'], 'AMQPChannel' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castChannel'], 'AMQPQueue' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castQueue'], 'AMQPExchange' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castExchange'], 'AMQPEnvelope' => ['Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'], 'ArrayObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'], 'ArrayIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'], 'SplDoublyLinkedList' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'], 'SplFileInfo' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'], 'SplFileObject' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'], 'SplHeap' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], 'SplObjectStorage' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castObjectStorage'], 'SplPriorityQueue' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'], 'OuterIterator' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'], 'WeakReference' => ['Symfony\Component\VarDumper\Caster\SplCaster', 'castWeakReference'], 'Redis' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'], 'RedisArray' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'], 'RedisCluster' => ['Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisCluster'], 'DateTimeInterface' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'], 'DateInterval' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'], 'DateTimeZone' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'], 'DatePeriod' => ['Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'], 'GMP' => ['Symfony\Component\VarDumper\Caster\GmpCaster', 'castGmp'], 'MessageFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castMessageFormatter'], 'NumberFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castNumberFormatter'], 'IntlTimeZone' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlTimeZone'], 'IntlCalendar' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlCalendar'], 'IntlDateFormatter' => ['Symfony\Component\VarDumper\Caster\IntlCaster', 'castIntlDateFormatter'], 'Memcached' => ['Symfony\Component\VarDumper\Caster\MemcachedCaster', 'castMemcached'], 'Ds\Collection' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castCollection'], 'Ds\Map' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castMap'], 'Ds\Pair' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPair'], 'Symfony\Component\VarDumper\Caster\DsPairStub' => ['Symfony\Component\VarDumper\Caster\DsCaster', 'castPairStub'], 'CurlHandle' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], ':curl' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'], ':dba' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], ':dba persistent' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'], 'GdImage' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], ':gd' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castGd'], ':mysql link' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castMysqlLink'], ':pgsql large object' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLargeObject'], ':pgsql link' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], ':pgsql link persistent' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castLink'], ':pgsql result' => ['Symfony\Component\VarDumper\Caster\PgSqlCaster', 'castResult'], ':process' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castProcess'], ':stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], 'OpenSSLCertificate' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], ':OpenSSL X.509' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castOpensslX509'], ':persistent stream' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStream'], ':stream-context' => ['Symfony\Component\VarDumper\Caster\ResourceCaster', 'castStreamContext'], 'XmlParser' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], ':xml' => ['Symfony\Component\VarDumper\Caster\XmlResourceCaster', 'castXml'], 'RdKafka' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castRdKafka'], 'RdKafka\Conf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castConf'], 'RdKafka\KafkaConsumer' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castKafkaConsumer'], 'RdKafka\Metadata\Broker' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castBrokerMetadata'], 'RdKafka\Metadata\Collection' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castCollectionMetadata'], 'RdKafka\Metadata\Partition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castPartitionMetadata'], 'RdKafka\Metadata\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicMetadata'], 'RdKafka\Message' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castMessage'], 'RdKafka\Topic' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopic'], 'RdKafka\TopicPartition' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicPartition'], 'RdKafka\TopicConf' => ['Symfony\Component\VarDumper\Caster\RdKafkaCaster', 'castTopicConf'], ]; protected $maxItems = 2500; protected $maxString = -1; protected $minDepth = 1; /** * @var array> */ private $casters = []; /** * @var callable|null */ private $prevErrorHandler; private $classInfo = []; private $filter = 0; /** * @param callable[]|null $casters A map of casters * * @see addCasters */ public function __construct(array $casters = null) { if (null === $casters) { $casters = static::$defaultCasters; } $this->addCasters($casters); } /** * Adds casters for resources and objects. * * Maps resources or objects types to a callback. * Types are in the key, with a callable caster for value. * Resource types are to be prefixed with a `:`, * see e.g. static::$defaultCasters. * * @param callable[] $casters A map of casters */ public function addCasters(array $casters) { foreach ($casters as $type => $callback) { $this->casters[$type][] = $callback; } } /** * Sets the maximum number of items to clone past the minimum depth in nested structures. */ public function setMaxItems(int $maxItems) { $this->maxItems = $maxItems; } /** * Sets the maximum cloned length for strings. */ public function setMaxString(int $maxString) { $this->maxString = $maxString; } /** * Sets the minimum tree depth where we are guaranteed to clone all the items. After this * depth is reached, only setMaxItems items will be cloned. */ public function setMinDepth(int $minDepth) { $this->minDepth = $minDepth; } /** * Clones a PHP variable. * * @param mixed $var Any PHP variable * @param int $filter A bit field of Caster::EXCLUDE_* constants * * @return Data */ public function cloneVar($var, int $filter = 0) { $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) { if (\E_RECOVERABLE_ERROR === $type || \E_USER_ERROR === $type) { // Cloner never dies throw new \ErrorException($msg, 0, $type, $file, $line); } if ($this->prevErrorHandler) { return ($this->prevErrorHandler)($type, $msg, $file, $line, $context); } return false; }); $this->filter = $filter; if ($gc = gc_enabled()) { gc_disable(); } try { return new Data($this->doClone($var)); } finally { if ($gc) { gc_enable(); } restore_error_handler(); $this->prevErrorHandler = null; } } /** * Effectively clones the PHP variable. * * @param mixed $var Any PHP variable * * @return array */ abstract protected function doClone($var); /** * Casts an object to an array representation. * * @param bool $isNested True if the object is nested in the dumped structure * * @return array */ protected function castObject(Stub $stub, bool $isNested) { $obj = $stub->value; $class = $stub->class; if (\PHP_VERSION_ID < 80000 ? "\0" === ($class[15] ?? null) : str_contains($class, "@anonymous\0")) { $stub->class = get_debug_type($obj); } if (isset($this->classInfo[$class])) { [$i, $parents, $hasDebugInfo, $fileInfo] = $this->classInfo[$class]; } else { $i = 2; $parents = [$class]; $hasDebugInfo = method_exists($class, '__debugInfo'); foreach (class_parents($class) as $p) { $parents[] = $p; ++$i; } foreach (class_implements($class) as $p) { $parents[] = $p; ++$i; } $parents[] = '*'; $r = new \ReflectionClass($class); $fileInfo = $r->isInternal() || $r->isSubclassOf(Stub::class) ? [] : [ 'file' => $r->getFileName(), 'line' => $r->getStartLine(), ]; $this->classInfo[$class] = [$i, $parents, $hasDebugInfo, $fileInfo]; } $stub->attr += $fileInfo; $a = Caster::castObject($obj, $class, $hasDebugInfo, $stub->class); try { while ($i--) { if (!empty($this->casters[$p = $parents[$i]])) { foreach ($this->casters[$p] as $callback) { $a = $callback($obj, $a, $stub, $isNested, $this->filter); } } } } catch (\Exception $e) { $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; } return $a; } /** * Casts a resource to an array representation. * * @param bool $isNested True if the object is nested in the dumped structure * * @return array */ protected function castResource(Stub $stub, bool $isNested) { $a = []; $res = $stub->value; $type = $stub->class; try { if (!empty($this->casters[':'.$type])) { foreach ($this->casters[':'.$type] as $callback) { $a = $callback($res, $a, $stub, $isNested, $this->filter); } } } catch (\Exception $e) { $a = [(Stub::TYPE_OBJECT === $stub->type ? Caster::PREFIX_VIRTUAL : '').'⚠' => new ThrowingCasterException($e)] + $a; } return $a; } } var-dumper/Cloner/ClonerInterface.php000064400000001013150432043210013611 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Cloner; /** * @author Nicolas Grekas */ interface ClonerInterface { /** * Clones a PHP variable. * * @param mixed $var Any PHP variable * * @return Data */ public function cloneVar($var); } var-dumper/Cloner/Cursor.php000064400000002071150432043210012030 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Cloner; /** * Represents the current state of a dumper while dumping. * * @author Nicolas Grekas */ class Cursor { public const HASH_INDEXED = Stub::ARRAY_INDEXED; public const HASH_ASSOC = Stub::ARRAY_ASSOC; public const HASH_OBJECT = Stub::TYPE_OBJECT; public const HASH_RESOURCE = Stub::TYPE_RESOURCE; public $depth = 0; public $refIndex = 0; public $softRefTo = 0; public $softRefCount = 0; public $softRefHandle = 0; public $hardRefTo = 0; public $hardRefCount = 0; public $hardRefHandle = 0; public $hashType; public $hashKey; public $hashKeyIsBinary; public $hashIndex = 0; public $hashLength = 0; public $hashCut = 0; public $stop = false; public $attr = []; public $skipChildren = false; } var-dumper/Cloner/Data.php000064400000033164150432043210011433 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Cloner; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; /** * @author Nicolas Grekas */ class Data implements \ArrayAccess, \Countable, \IteratorAggregate { private $data; private $position = 0; private $key = 0; private $maxDepth = 20; private $maxItemsPerDepth = -1; private $useRefHandles = -1; private $context = []; /** * @param array $data An array as returned by ClonerInterface::cloneVar() */ public function __construct(array $data) { $this->data = $data; } /** * @return string|null */ public function getType() { $item = $this->data[$this->position][$this->key]; if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { $item = $item->value; } if (!$item instanceof Stub) { return \gettype($item); } if (Stub::TYPE_STRING === $item->type) { return 'string'; } if (Stub::TYPE_ARRAY === $item->type) { return 'array'; } if (Stub::TYPE_OBJECT === $item->type) { return $item->class; } if (Stub::TYPE_RESOURCE === $item->type) { return $item->class.' resource'; } return null; } /** * Returns a native representation of the original value. * * @param array|bool $recursive Whether values should be resolved recursively or not * * @return string|int|float|bool|array|Data[]|null */ public function getValue($recursive = false) { $item = $this->data[$this->position][$this->key]; if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { $item = $item->value; } if (!($item = $this->getStub($item)) instanceof Stub) { return $item; } if (Stub::TYPE_STRING === $item->type) { return $item->value; } $children = $item->position ? $this->data[$item->position] : []; foreach ($children as $k => $v) { if ($recursive && !($v = $this->getStub($v)) instanceof Stub) { continue; } $children[$k] = clone $this; $children[$k]->key = $k; $children[$k]->position = $item->position; if ($recursive) { if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) { $recursive = (array) $recursive; if (isset($recursive[$v->position])) { continue; } $recursive[$v->position] = true; } $children[$k] = $children[$k]->getValue($recursive); } } return $children; } /** * @return int */ #[\ReturnTypeWillChange] public function count() { return \count($this->getValue()); } /** * @return \Traversable */ #[\ReturnTypeWillChange] public function getIterator() { if (!\is_array($value = $this->getValue())) { throw new \LogicException(sprintf('"%s" object holds non-iterable type "%s".', self::class, get_debug_type($value))); } yield from $value; } public function __get(string $key) { if (null !== $data = $this->seek($key)) { $item = $this->getStub($data->data[$data->position][$data->key]); return $item instanceof Stub || [] === $item ? $data : $item; } return null; } /** * @return bool */ public function __isset(string $key) { return null !== $this->seek($key); } /** * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($key) { return $this->__isset($key); } /** * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->__get($key); } /** * @return void */ #[\ReturnTypeWillChange] public function offsetSet($key, $value) { throw new \BadMethodCallException(self::class.' objects are immutable.'); } /** * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($key) { throw new \BadMethodCallException(self::class.' objects are immutable.'); } /** * @return string */ public function __toString() { $value = $this->getValue(); if (!\is_array($value)) { return (string) $value; } return sprintf('%s (count=%d)', $this->getType(), \count($value)); } /** * Returns a depth limited clone of $this. * * @return static */ public function withMaxDepth(int $maxDepth) { $data = clone $this; $data->maxDepth = $maxDepth; return $data; } /** * Limits the number of elements per depth level. * * @return static */ public function withMaxItemsPerDepth(int $maxItemsPerDepth) { $data = clone $this; $data->maxItemsPerDepth = $maxItemsPerDepth; return $data; } /** * Enables/disables objects' identifiers tracking. * * @param bool $useRefHandles False to hide global ref. handles * * @return static */ public function withRefHandles(bool $useRefHandles) { $data = clone $this; $data->useRefHandles = $useRefHandles ? -1 : 0; return $data; } /** * @return static */ public function withContext(array $context) { $data = clone $this; $data->context = $context; return $data; } /** * Seeks to a specific key in nested data structures. * * @param string|int $key The key to seek to * * @return static|null */ public function seek($key) { $item = $this->data[$this->position][$this->key]; if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { $item = $item->value; } if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) { return null; } $keys = [$key]; switch ($item->type) { case Stub::TYPE_OBJECT: $keys[] = Caster::PREFIX_DYNAMIC.$key; $keys[] = Caster::PREFIX_PROTECTED.$key; $keys[] = Caster::PREFIX_VIRTUAL.$key; $keys[] = "\0$item->class\0$key"; // no break case Stub::TYPE_ARRAY: case Stub::TYPE_RESOURCE: break; default: return null; } $data = null; $children = $this->data[$item->position]; foreach ($keys as $key) { if (isset($children[$key]) || \array_key_exists($key, $children)) { $data = clone $this; $data->key = $key; $data->position = $item->position; break; } } return $data; } /** * Dumps data with a DumperInterface dumper. */ public function dump(DumperInterface $dumper) { $refs = [0]; $cursor = new Cursor(); if ($cursor->attr = $this->context[SourceContextProvider::class] ?? []) { $cursor->attr['if_links'] = true; $cursor->hashType = -1; $dumper->dumpScalar($cursor, 'default', '^'); $cursor->attr = ['if_links' => true]; $dumper->dumpScalar($cursor, 'default', ' '); $cursor->hashType = 0; } $this->dumpItem($dumper, $cursor, $refs, $this->data[$this->position][$this->key]); } /** * Depth-first dumping of items. * * @param mixed $item A Stub object or the original value being dumped */ private function dumpItem(DumperInterface $dumper, Cursor $cursor, array &$refs, $item) { $cursor->refIndex = 0; $cursor->softRefTo = $cursor->softRefHandle = $cursor->softRefCount = 0; $cursor->hardRefTo = $cursor->hardRefHandle = $cursor->hardRefCount = 0; $firstSeen = true; if (!$item instanceof Stub) { $cursor->attr = []; $type = \gettype($item); if ($item && 'array' === $type) { $item = $this->getStub($item); } } elseif (Stub::TYPE_REF === $item->type) { if ($item->handle) { if (!isset($refs[$r = $item->handle - (\PHP_INT_MAX >> 1)])) { $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; } else { $firstSeen = false; } $cursor->hardRefTo = $refs[$r]; $cursor->hardRefHandle = $this->useRefHandles & $item->handle; $cursor->hardRefCount = 0 < $item->handle ? $item->refCount : 0; } $cursor->attr = $item->attr; $type = $item->class ?: \gettype($item->value); $item = $this->getStub($item->value); } if ($item instanceof Stub) { if ($item->refCount) { if (!isset($refs[$r = $item->handle])) { $cursor->refIndex = $refs[$r] = $cursor->refIndex ?: ++$refs[0]; } else { $firstSeen = false; } $cursor->softRefTo = $refs[$r]; } $cursor->softRefHandle = $this->useRefHandles & $item->handle; $cursor->softRefCount = $item->refCount; $cursor->attr = $item->attr; $cut = $item->cut; if ($item->position && $firstSeen) { $children = $this->data[$item->position]; if ($cursor->stop) { if ($cut >= 0) { $cut += \count($children); } $children = []; } } else { $children = []; } switch ($item->type) { case Stub::TYPE_STRING: $dumper->dumpString($cursor, $item->value, Stub::STRING_BINARY === $item->class, $cut); break; case Stub::TYPE_ARRAY: $item = clone $item; $item->type = $item->class; $item->class = $item->value; // no break case Stub::TYPE_OBJECT: case Stub::TYPE_RESOURCE: $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; $dumper->enterHash($cursor, $item->type, $item->class, $withChildren); if ($withChildren) { if ($cursor->skipChildren) { $withChildren = false; $cut = -1; } else { $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); } } elseif ($children && 0 <= $cut) { $cut += \count($children); } $cursor->skipChildren = false; $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut); break; default: throw new \RuntimeException(sprintf('Unexpected Stub type: "%s".', $item->type)); } } elseif ('array' === $type) { $dumper->enterHash($cursor, Cursor::HASH_INDEXED, 0, false); $dumper->leaveHash($cursor, Cursor::HASH_INDEXED, 0, false, 0); } elseif ('string' === $type) { $dumper->dumpString($cursor, $item, false, 0); } else { $dumper->dumpScalar($cursor, $type, $item); } } /** * Dumps children of hash structures. * * @return int The final number of removed items */ private function dumpChildren(DumperInterface $dumper, Cursor $parentCursor, array &$refs, array $children, int $hashCut, int $hashType, bool $dumpKeys): int { $cursor = clone $parentCursor; ++$cursor->depth; $cursor->hashType = $hashType; $cursor->hashIndex = 0; $cursor->hashLength = \count($children); $cursor->hashCut = $hashCut; foreach ($children as $key => $child) { $cursor->hashKeyIsBinary = isset($key[0]) && !preg_match('//u', $key); $cursor->hashKey = $dumpKeys ? $key : null; $this->dumpItem($dumper, $cursor, $refs, $child); if (++$cursor->hashIndex === $this->maxItemsPerDepth || $cursor->stop) { $parentCursor->stop = true; return $hashCut >= 0 ? $hashCut + $cursor->hashLength - $cursor->hashIndex : $hashCut; } } return $hashCut; } private function getStub($item) { if (!$item || !\is_array($item)) { return $item; } $stub = new Stub(); $stub->type = Stub::TYPE_ARRAY; foreach ($item as $stub->class => $stub->position) { } if (isset($item[0])) { $stub->cut = $item[0]; } $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0); return $stub; } } var-dumper/Cloner/DumperInterface.php000064400000003474150432043210013640 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Cloner; /** * DumperInterface used by Data objects. * * @author Nicolas Grekas */ interface DumperInterface { /** * Dumps a scalar value. * * @param string $type The PHP type of the value being dumped * @param string|int|float|bool $value The scalar value being dumped */ public function dumpScalar(Cursor $cursor, string $type, $value); /** * Dumps a string. * * @param string $str The string being dumped * @param bool $bin Whether $str is UTF-8 or binary encoded * @param int $cut The number of characters $str has been cut by */ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut); /** * Dumps while entering an hash. * * @param int $type A Cursor::HASH_* const for the type of hash * @param string|int $class The object class, resource type or array count * @param bool $hasChild When the dump of the hash has child item */ public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild); /** * Dumps while leaving an hash. * * @param int $type A Cursor::HASH_* const for the type of hash * @param string|int $class The object class, resource type or array count * @param bool $hasChild When the dump of the hash has child item * @param int $cut The number of items the hash has been cut by */ public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut); } var-dumper/CHANGELOG.md000064400000004225150432043210010434 0ustar00CHANGELOG ========= 5.4 --- * Add ability to style integer and double values independently * Add casters for Symfony's UUIDs and ULIDs * Add support for `Fiber` 5.2.0 ----- * added support for PHPUnit `--colors` option * added `VAR_DUMPER_FORMAT=server` env var value support * prevent replacing the handler when the `VAR_DUMPER_FORMAT` env var is set 5.1.0 ----- * added `RdKafka` support 4.4.0 ----- * added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()` to configure casters & flags to use in tests * added `ImagineCaster` and infrastructure to dump images * added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data * added `UuidCaster` * made all casters final * added support for the `NO_COLOR` env var (https://no-color.org/) 4.3.0 ----- * added `DsCaster` to support dumping the contents of data structures from the Ds extension 4.2.0 ----- * support selecting the format to use by setting the environment variable `VAR_DUMPER_FORMAT` to `html` or `cli` 4.1.0 ----- * added a `ServerDumper` to send serialized Data clones to a server * added a `ServerDumpCommand` and `DumpServer` to run a server collecting and displaying dumps on a single place with multiple formats support * added `CliDescriptor` and `HtmlDescriptor` descriptors for `server:dump` CLI and HTML formats support 4.0.0 ----- * support for passing `\ReflectionClass` instances to the `Caster::castObject()` method has been dropped, pass class names as strings instead * the `Data::getRawData()` method has been removed * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$filter = 0` argument and moves `$message = ''` argument at 4th position. * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$filter = 0` argument and moves `$message = ''` argument at 4th position. 3.4.0 ----- * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth * deprecated `MongoCaster` 2.7.0 ----- * deprecated `Cloner\Data::getLimitedClone()`. Use `withMaxDepth`, `withMaxItemsPerDepth` or `withRefHandles` instead. var-dumper/Dumper/DataDumperInterface.php000064400000000771150432043210014441 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper; use Symfony\Component\VarDumper\Cloner\Data; /** * DataDumperInterface for dumping Data objects. * * @author Nicolas Grekas */ interface DataDumperInterface { public function dump(Data $data); } var-dumper/Dumper/ContextProvider/RequestContextProvider.php000064400000002701150432043210020434 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper\ContextProvider; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\VarDumper\Caster\ReflectionCaster; use Symfony\Component\VarDumper\Cloner\VarCloner; /** * Tries to provide context from a request. * * @author Maxime Steinhausser */ final class RequestContextProvider implements ContextProviderInterface { private $requestStack; private $cloner; public function __construct(RequestStack $requestStack) { $this->requestStack = $requestStack; $this->cloner = new VarCloner(); $this->cloner->setMaxItems(0); $this->cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); } public function getContext(): ?array { if (null === $request = $this->requestStack->getCurrentRequest()) { return null; } $controller = $request->attributes->get('_controller'); return [ 'uri' => $request->getUri(), 'method' => $request->getMethod(), 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller, 'identifier' => spl_object_hash($request), ]; } } var-dumper/Dumper/ContextProvider/SourceContextProvider.php000064400000011442150432043210020246 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper\ContextProvider; use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Symfony\Component\VarDumper\VarDumper; use Twig\Template; /** * Tries to provide context from sources (class name, file, line, code excerpt, ...). * * @author Nicolas Grekas * @author Maxime Steinhausser */ final class SourceContextProvider implements ContextProviderInterface { private $limit; private $charset; private $projectDir; private $fileLinkFormatter; public function __construct(string $charset = null, string $projectDir = null, FileLinkFormatter $fileLinkFormatter = null, int $limit = 9) { $this->charset = $charset; $this->projectDir = $projectDir; $this->fileLinkFormatter = $fileLinkFormatter; $this->limit = $limit; } public function getContext(): ?array { $trace = debug_backtrace(\DEBUG_BACKTRACE_PROVIDE_OBJECT | \DEBUG_BACKTRACE_IGNORE_ARGS, $this->limit); $file = $trace[1]['file']; $line = $trace[1]['line']; $name = false; $fileExcerpt = false; for ($i = 2; $i < $this->limit; ++$i) { if (isset($trace[$i]['class'], $trace[$i]['function']) && 'dump' === $trace[$i]['function'] && VarDumper::class === $trace[$i]['class'] ) { $file = $trace[$i]['file'] ?? $file; $line = $trace[$i]['line'] ?? $line; while (++$i < $this->limit) { if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) { $file = $trace[$i]['file']; $line = $trace[$i]['line']; break; } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) { $template = $trace[$i]['object']; $name = $template->getTemplateName(); $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false); $info = $template->getDebugInfo(); if (isset($info[$trace[$i - 1]['line']])) { $line = $info[$trace[$i - 1]['line']]; $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null; if ($src) { $src = explode("\n", $src); $fileExcerpt = []; for ($i = max($line - 3, 1), $max = min($line + 3, \count($src)); $i <= $max; ++$i) { $fileExcerpt[] = ''.$this->htmlEncode($src[$i - 1]).''; } $fileExcerpt = '
      '.implode("\n", $fileExcerpt).'
    '; } } break; } } break; } } if (false === $name) { $name = str_replace('\\', '/', $file); $name = substr($name, strrpos($name, '/') + 1); } $context = ['name' => $name, 'file' => $file, 'line' => $line]; $context['file_excerpt'] = $fileExcerpt; if (null !== $this->projectDir) { $context['project_dir'] = $this->projectDir; if (str_starts_with($file, $this->projectDir)) { $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); } } if ($this->fileLinkFormatter && $fileLink = $this->fileLinkFormatter->format($context['file'], $context['line'])) { $context['file_link'] = $fileLink; } return $context; } private function htmlEncode(string $s): string { $html = ''; $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset); $dumper->setDumpHeader(''); $dumper->setDumpBoundaries('', ''); $cloner = new VarCloner(); $dumper->dump($cloner->cloneVar($s)); return substr(strip_tags($html), 1, -1); } } var-dumper/Dumper/ContextProvider/ContextProviderInterface.php000064400000001103150432043210020677 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper\ContextProvider; /** * Interface to provide contextual data about dump data clones sent to a server. * * @author Maxime Steinhausser */ interface ContextProviderInterface { /** * @return array|null */ public function getContext(): ?array; } var-dumper/Dumper/ContextProvider/CliContextProvider.php000064400000001446150432043210017520 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper\ContextProvider; /** * Tries to provide context on CLI. * * @author Maxime Steinhausser */ final class CliContextProvider implements ContextProviderInterface { public function getContext(): ?array { if ('cli' !== \PHP_SAPI) { return null; } return [ 'command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []), 'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']), ]; } } var-dumper/Dumper/CliDumper.php000064400000052536150432043210012464 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper; use Symfony\Component\VarDumper\Cloner\Cursor; use Symfony\Component\VarDumper\Cloner\Stub; /** * CliDumper dumps variables for command line output. * * @author Nicolas Grekas */ class CliDumper extends AbstractDumper { public static $defaultColors; public static $defaultOutput = 'php://stdout'; protected $colors; protected $maxStringWidth = 0; protected $styles = [ // See http://en.wikipedia.org/wiki/ANSI_escape_code#graphics 'default' => '0;38;5;208', 'num' => '1;38;5;38', 'const' => '1;38;5;208', 'str' => '1;38;5;113', 'note' => '38;5;38', 'ref' => '38;5;247', 'public' => '', 'protected' => '', 'private' => '', 'meta' => '38;5;170', 'key' => '38;5;113', 'index' => '38;5;38', ]; protected static $controlCharsRx = '/[\x00-\x1F\x7F]+/'; protected static $controlCharsMap = [ "\t" => '\t', "\n" => '\n', "\v" => '\v', "\f" => '\f', "\r" => '\r', "\033" => '\e', ]; protected $collapseNextHash = false; protected $expandNextHash = false; private $displayOptions = [ 'fileLinkFormat' => null, ]; private $handlesHrefGracefully; /** * {@inheritdoc} */ public function __construct($output = null, string $charset = null, int $flags = 0) { parent::__construct($output, $charset, $flags); if ('\\' === \DIRECTORY_SEPARATOR && !$this->isWindowsTrueColor()) { // Use only the base 16 xterm colors when using ANSICON or standard Windows 10 CLI $this->setStyles([ 'default' => '31', 'num' => '1;34', 'const' => '1;31', 'str' => '1;32', 'note' => '34', 'ref' => '1;30', 'meta' => '35', 'key' => '32', 'index' => '34', ]); } $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l'; } /** * Enables/disables colored output. */ public function setColors(bool $colors) { $this->colors = $colors; } /** * Sets the maximum number of characters per line for dumped strings. */ public function setMaxStringWidth(int $maxStringWidth) { $this->maxStringWidth = $maxStringWidth; } /** * Configures styles. * * @param array $styles A map of style names to style definitions */ public function setStyles(array $styles) { $this->styles = $styles + $this->styles; } /** * Configures display options. * * @param array $displayOptions A map of display options to customize the behavior */ public function setDisplayOptions(array $displayOptions) { $this->displayOptions = $displayOptions + $this->displayOptions; } /** * {@inheritdoc} */ public function dumpScalar(Cursor $cursor, string $type, $value) { $this->dumpKey($cursor); $style = 'const'; $attr = $cursor->attr; switch ($type) { case 'default': $style = 'default'; break; case 'integer': $style = 'num'; if (isset($this->styles['integer'])) { $style = 'integer'; } break; case 'double': $style = 'num'; if (isset($this->styles['float'])) { $style = 'float'; } switch (true) { case \INF === $value: $value = 'INF'; break; case -\INF === $value: $value = '-INF'; break; case is_nan($value): $value = 'NAN'; break; default: $value = (string) $value; if (!str_contains($value, $this->decimalPoint)) { $value .= $this->decimalPoint.'0'; } break; } break; case 'NULL': $value = 'null'; break; case 'boolean': $value = $value ? 'true' : 'false'; break; default: $attr += ['value' => $this->utf8Encode($value)]; $value = $this->utf8Encode($type); break; } $this->line .= $this->style($style, $value, $attr); $this->endValue($cursor); } /** * {@inheritdoc} */ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) { $this->dumpKey($cursor); $attr = $cursor->attr; if ($bin) { $str = $this->utf8Encode($str); } if ('' === $str) { $this->line .= '""'; $this->endValue($cursor); } else { $attr += [ 'length' => 0 <= $cut ? mb_strlen($str, 'UTF-8') + $cut : 0, 'binary' => $bin, ]; $str = $bin && false !== strpos($str, "\0") ? [$str] : explode("\n", $str); if (isset($str[1]) && !isset($str[2]) && !isset($str[1][0])) { unset($str[1]); $str[0] .= "\n"; } $m = \count($str) - 1; $i = $lineCut = 0; if (self::DUMP_STRING_LENGTH & $this->flags) { $this->line .= '('.$attr['length'].') '; } if ($bin) { $this->line .= 'b'; } if ($m) { $this->line .= '"""'; $this->dumpLine($cursor->depth); } else { $this->line .= '"'; } foreach ($str as $str) { if ($i < $m) { $str .= "\n"; } if (0 < $this->maxStringWidth && $this->maxStringWidth < $len = mb_strlen($str, 'UTF-8')) { $str = mb_substr($str, 0, $this->maxStringWidth, 'UTF-8'); $lineCut = $len - $this->maxStringWidth; } if ($m && 0 < $cursor->depth) { $this->line .= $this->indentPad; } if ('' !== $str) { $this->line .= $this->style('str', $str, $attr); } if ($i++ == $m) { if ($m) { if ('' !== $str) { $this->dumpLine($cursor->depth); if (0 < $cursor->depth) { $this->line .= $this->indentPad; } } $this->line .= '"""'; } else { $this->line .= '"'; } if ($cut < 0) { $this->line .= '…'; $lineCut = 0; } elseif ($cut) { $lineCut += $cut; } } if ($lineCut) { $this->line .= '…'.$lineCut; $lineCut = 0; } if ($i > $m) { $this->endValue($cursor); } else { $this->dumpLine($cursor->depth); } } } } /** * {@inheritdoc} */ public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) { if (null === $this->colors) { $this->colors = $this->supportsColors(); } $this->dumpKey($cursor); $attr = $cursor->attr; if ($this->collapseNextHash) { $cursor->skipChildren = true; $this->collapseNextHash = $hasChild = false; } $class = $this->utf8Encode($class); if (Cursor::HASH_OBJECT === $type) { $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class, $attr).(empty($attr['cut_hash']) ? ' {' : '') : '{'; } elseif (Cursor::HASH_RESOURCE === $type) { $prefix = $this->style('note', $class.' resource', $attr).($hasChild ? ' {' : ' '); } else { $prefix = $class && !(self::DUMP_LIGHT_ARRAY & $this->flags) ? $this->style('note', 'array:'.$class).' [' : '['; } if (($cursor->softRefCount || 0 < $cursor->softRefHandle) && empty($attr['cut_hash'])) { $prefix .= $this->style('ref', (Cursor::HASH_RESOURCE === $type ? '@' : '#').(0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->softRefTo), ['count' => $cursor->softRefCount]); } elseif ($cursor->hardRefTo && !$cursor->refIndex && $class) { $prefix .= $this->style('ref', '&'.$cursor->hardRefTo, ['count' => $cursor->hardRefCount]); } elseif (!$hasChild && Cursor::HASH_RESOURCE === $type) { $prefix = substr($prefix, 0, -1); } $this->line .= $prefix; if ($hasChild) { $this->dumpLine($cursor->depth); } } /** * {@inheritdoc} */ public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) { if (empty($cursor->attr['cut_hash'])) { $this->dumpEllipsis($cursor, $hasChild, $cut); $this->line .= Cursor::HASH_OBJECT === $type ? '}' : (Cursor::HASH_RESOURCE !== $type ? ']' : ($hasChild ? '}' : '')); } $this->endValue($cursor); } /** * Dumps an ellipsis for cut children. * * @param bool $hasChild When the dump of the hash has child item * @param int $cut The number of items the hash has been cut by */ protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut) { if ($cut) { $this->line .= ' …'; if (0 < $cut) { $this->line .= $cut; } if ($hasChild) { $this->dumpLine($cursor->depth + 1); } } } /** * Dumps a key in a hash structure. */ protected function dumpKey(Cursor $cursor) { if (null !== $key = $cursor->hashKey) { if ($cursor->hashKeyIsBinary) { $key = $this->utf8Encode($key); } $attr = ['binary' => $cursor->hashKeyIsBinary]; $bin = $cursor->hashKeyIsBinary ? 'b' : ''; $style = 'key'; switch ($cursor->hashType) { default: case Cursor::HASH_INDEXED: if (self::DUMP_LIGHT_ARRAY & $this->flags) { break; } $style = 'index'; // no break case Cursor::HASH_ASSOC: if (\is_int($key)) { $this->line .= $this->style($style, $key).' => '; } else { $this->line .= $bin.'"'.$this->style($style, $key).'" => '; } break; case Cursor::HASH_RESOURCE: $key = "\0~\0".$key; // no break case Cursor::HASH_OBJECT: if (!isset($key[0]) || "\0" !== $key[0]) { $this->line .= '+'.$bin.$this->style('public', $key).': '; } elseif (0 < strpos($key, "\0", 1)) { $key = explode("\0", substr($key, 1), 2); switch ($key[0][0]) { case '+': // User inserted keys $attr['dynamic'] = true; $this->line .= '+'.$bin.'"'.$this->style('public', $key[1], $attr).'": '; break 2; case '~': $style = 'meta'; if (isset($key[0][1])) { parse_str(substr($key[0], 1), $attr); $attr += ['binary' => $cursor->hashKeyIsBinary]; } break; case '*': $style = 'protected'; $bin = '#'.$bin; break; default: $attr['class'] = $key[0]; $style = 'private'; $bin = '-'.$bin; break; } if (isset($attr['collapse'])) { if ($attr['collapse']) { $this->collapseNextHash = true; } else { $this->expandNextHash = true; } } $this->line .= $bin.$this->style($style, $key[1], $attr).($attr['separator'] ?? ': '); } else { // This case should not happen $this->line .= '-'.$bin.'"'.$this->style('private', $key, ['class' => '']).'": '; } break; } if ($cursor->hardRefTo) { $this->line .= $this->style('ref', '&'.($cursor->hardRefCount ? $cursor->hardRefTo : ''), ['count' => $cursor->hardRefCount]).' '; } } } /** * Decorates a value with some style. * * @param string $style The type of style being applied * @param string $value The value being styled * @param array $attr Optional context information * * @return string */ protected function style(string $style, string $value, array $attr = []) { if (null === $this->colors) { $this->colors = $this->supportsColors(); } if (null === $this->handlesHrefGracefully) { $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); } if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { $prefix = substr($value, 0, -$attr['ellipsis']); if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) { $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd])); } if (!empty($attr['ellipsis-tail'])) { $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']); $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']); } else { $value = substr($value, -$attr['ellipsis']); } $value = $this->style('default', $prefix).$this->style($style, $value); goto href; } $map = static::$controlCharsMap; $startCchr = $this->colors ? "\033[m\033[{$this->styles['default']}m" : ''; $endCchr = $this->colors ? "\033[m\033[{$this->styles[$style]}m" : ''; $value = preg_replace_callback(static::$controlCharsRx, function ($c) use ($map, $startCchr, $endCchr) { $s = $startCchr; $c = $c[$i = 0]; do { $s .= $map[$c[$i]] ?? sprintf('\x%02X', \ord($c[$i])); } while (isset($c[++$i])); return $s.$endCchr; }, $value, -1, $cchrCount); if ($this->colors) { if ($cchrCount && "\033" === $value[0]) { $value = substr($value, \strlen($startCchr)); } else { $value = "\033[{$this->styles[$style]}m".$value; } if ($cchrCount && str_ends_with($value, $endCchr)) { $value = substr($value, 0, -\strlen($endCchr)); } else { $value .= "\033[{$this->styles['default']}m"; } } href: if ($this->colors && $this->handlesHrefGracefully) { if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { if ('note' === $style) { $value .= "\033]8;;{$href}\033\\^\033]8;;\033\\"; } else { $attr['href'] = $href; } } if (isset($attr['href'])) { $value = "\033]8;;{$attr['href']}\033\\{$value}\033]8;;\033\\"; } } elseif ($attr['if_links'] ?? false) { return ''; } return $value; } /** * @return bool */ protected function supportsColors() { if ($this->outputStream !== static::$defaultOutput) { return $this->hasColorSupport($this->outputStream); } if (null !== static::$defaultColors) { return static::$defaultColors; } if (isset($_SERVER['argv'][1])) { $colors = $_SERVER['argv']; $i = \count($colors); while (--$i > 0) { if (isset($colors[$i][5])) { switch ($colors[$i]) { case '--ansi': case '--color': case '--color=yes': case '--color=force': case '--color=always': case '--colors=always': return static::$defaultColors = true; case '--no-ansi': case '--color=no': case '--color=none': case '--color=never': case '--colors=never': return static::$defaultColors = false; } } } } $h = stream_get_meta_data($this->outputStream) + ['wrapper_type' => null]; $h = 'Output' === $h['stream_type'] && 'PHP' === $h['wrapper_type'] ? fopen('php://stdout', 'w') : $this->outputStream; return static::$defaultColors = $this->hasColorSupport($h); } /** * {@inheritdoc} */ protected function dumpLine(int $depth, bool $endOfValue = false) { if ($this->colors) { $this->line = sprintf("\033[%sm%s\033[m", $this->styles['default'], $this->line); } parent::dumpLine($depth); } protected function endValue(Cursor $cursor) { if (-1 === $cursor->hashType) { return; } if (Stub::ARRAY_INDEXED === $cursor->hashType || Stub::ARRAY_ASSOC === $cursor->hashType) { if (self::DUMP_TRAILING_COMMA & $this->flags && 0 < $cursor->depth) { $this->line .= ','; } elseif (self::DUMP_COMMA_SEPARATOR & $this->flags && 1 < $cursor->hashLength - $cursor->hashIndex) { $this->line .= ','; } } $this->dumpLine($cursor->depth, true); } /** * Returns true if the stream supports colorization. * * Reference: Composer\XdebugHandler\Process::supportsColor * https://github.com/composer/xdebug-handler * * @param mixed $stream A CLI output stream */ private function hasColorSupport($stream): bool { if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { return false; } // Follow https://no-color.org/ if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { return false; } if ('Hyper' === getenv('TERM_PROGRAM')) { return true; } if (\DIRECTORY_SEPARATOR === '\\') { return (\function_exists('sapi_windows_vt100_support') && @sapi_windows_vt100_support($stream)) || false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM'); } return stream_isatty($stream); } /** * Returns true if the Windows terminal supports true color. * * Note that this does not check an output stream, but relies on environment * variables from known implementations, or a PHP and Windows version that * supports true color. */ private function isWindowsTrueColor(): bool { $result = 183 <= getenv('ANSICON_VER') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM') || 'Hyper' === getenv('TERM_PROGRAM'); if (!$result) { $version = sprintf( '%s.%s.%s', PHP_WINDOWS_VERSION_MAJOR, PHP_WINDOWS_VERSION_MINOR, PHP_WINDOWS_VERSION_BUILD ); $result = $version >= '10.0.15063'; } return $result; } private function getSourceLink(string $file, int $line) { if ($fmt = $this->displayOptions['fileLinkFormat']) { return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : ($fmt->format($file, $line) ?: 'file://'.$file.'#L'.$line); } return false; } } var-dumper/Dumper/ContextualizedDumper.php000064400000002226150432043210014746 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; /** * @author Kévin Thérage */ class ContextualizedDumper implements DataDumperInterface { private $wrappedDumper; private $contextProviders; /** * @param ContextProviderInterface[] $contextProviders */ public function __construct(DataDumperInterface $wrappedDumper, array $contextProviders) { $this->wrappedDumper = $wrappedDumper; $this->contextProviders = $contextProviders; } public function dump(Data $data) { $context = []; foreach ($this->contextProviders as $contextProvider) { $context[\get_class($contextProvider)] = $contextProvider->getContext(); } $this->wrappedDumper->dump($data->withContext($context)); } } var-dumper/Dumper/HtmlDumper.php000064400000102521150432043210012647 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper; use Symfony\Component\VarDumper\Cloner\Cursor; use Symfony\Component\VarDumper\Cloner\Data; /** * HtmlDumper dumps variables as HTML. * * @author Nicolas Grekas */ class HtmlDumper extends CliDumper { public static $defaultOutput = 'php://output'; protected static $themes = [ 'dark' => [ 'default' => 'background-color:#18171B; color:#FF8400; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', 'num' => 'font-weight:bold; color:#1299DA', 'const' => 'font-weight:bold', 'str' => 'font-weight:bold; color:#56DB3A', 'note' => 'color:#1299DA', 'ref' => 'color:#A0A0A0', 'public' => 'color:#FFFFFF', 'protected' => 'color:#FFFFFF', 'private' => 'color:#FFFFFF', 'meta' => 'color:#B729D9', 'key' => 'color:#56DB3A', 'index' => 'color:#1299DA', 'ellipsis' => 'color:#FF8400', 'ns' => 'user-select:none;', ], 'light' => [ 'default' => 'background:none; color:#CC7832; line-height:1.2em; font:12px Menlo, Monaco, Consolas, monospace; word-wrap: break-word; white-space: pre-wrap; position:relative; z-index:99999; word-break: break-all', 'num' => 'font-weight:bold; color:#1299DA', 'const' => 'font-weight:bold', 'str' => 'font-weight:bold; color:#629755;', 'note' => 'color:#6897BB', 'ref' => 'color:#6E6E6E', 'public' => 'color:#262626', 'protected' => 'color:#262626', 'private' => 'color:#262626', 'meta' => 'color:#B729D9', 'key' => 'color:#789339', 'index' => 'color:#1299DA', 'ellipsis' => 'color:#CC7832', 'ns' => 'user-select:none;', ], ]; protected $dumpHeader; protected $dumpPrefix = '
    ';
        protected $dumpSuffix = '
    '; protected $dumpId = 'sf-dump'; protected $colors = true; protected $headerIsDumped = false; protected $lastDepth = -1; protected $styles; private $displayOptions = [ 'maxDepth' => 1, 'maxStringLength' => 160, 'fileLinkFormat' => null, ]; private $extraDisplayOptions = []; /** * {@inheritdoc} */ public function __construct($output = null, string $charset = null, int $flags = 0) { AbstractDumper::__construct($output, $charset, $flags); $this->dumpId = 'sf-dump-'.mt_rand(); $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); $this->styles = static::$themes['dark'] ?? self::$themes['dark']; } /** * {@inheritdoc} */ public function setStyles(array $styles) { $this->headerIsDumped = false; $this->styles = $styles + $this->styles; } public function setTheme(string $themeName) { if (!isset(static::$themes[$themeName])) { throw new \InvalidArgumentException(sprintf('Theme "%s" does not exist in class "%s".', $themeName, static::class)); } $this->setStyles(static::$themes[$themeName]); } /** * Configures display options. * * @param array $displayOptions A map of display options to customize the behavior */ public function setDisplayOptions(array $displayOptions) { $this->headerIsDumped = false; $this->displayOptions = $displayOptions + $this->displayOptions; } /** * Sets an HTML header that will be dumped once in the output stream. */ public function setDumpHeader(?string $header) { $this->dumpHeader = $header; } /** * Sets an HTML prefix and suffix that will encapse every single dump. */ public function setDumpBoundaries(string $prefix, string $suffix) { $this->dumpPrefix = $prefix; $this->dumpSuffix = $suffix; } /** * {@inheritdoc} */ public function dump(Data $data, $output = null, array $extraDisplayOptions = []) { $this->extraDisplayOptions = $extraDisplayOptions; $result = parent::dump($data, $output); $this->dumpId = 'sf-dump-'.mt_rand(); return $result; } /** * Dumps the HTML header. */ protected function getDumpHeader() { $this->headerIsDumped = $this->outputStream ?? $this->lineDumper; if (null !== $this->dumpHeader) { return $this->dumpHeader; } $line = str_replace('{$options}', json_encode($this->displayOptions, \JSON_FORCE_OBJECT), <<<'EOHTML' '.$this->dumpHeader; } /** * {@inheritdoc} */ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) { if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) { $this->dumpKey($cursor); $this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []); $this->line .= $cursor->depth >= $this->displayOptions['maxDepth'] ? ' ' : ' '; $this->endValue($cursor); $this->line .= $this->indentPad; $this->line .= sprintf('', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data'])); $this->endValue($cursor); } else { parent::dumpString($cursor, $str, $bin, $cut); } } /** * {@inheritdoc} */ public function enterHash(Cursor $cursor, int $type, $class, bool $hasChild) { if (Cursor::HASH_OBJECT === $type) { $cursor->attr['depth'] = $cursor->depth; } parent::enterHash($cursor, $type, $class, false); if ($cursor->skipChildren || $cursor->depth >= $this->displayOptions['maxDepth']) { $cursor->skipChildren = false; $eol = ' class=sf-dump-compact>'; } else { $this->expandNextHash = false; $eol = ' class=sf-dump-expanded>'; } if ($hasChild) { $this->line .= 'dumpId, $r); } $this->line .= $eol; $this->dumpLine($cursor->depth); } } /** * {@inheritdoc} */ public function leaveHash(Cursor $cursor, int $type, $class, bool $hasChild, int $cut) { $this->dumpEllipsis($cursor, $hasChild, $cut); if ($hasChild) { $this->line .= ''; } parent::leaveHash($cursor, $type, $class, $hasChild, 0); } /** * {@inheritdoc} */ protected function style(string $style, string $value, array $attr = []) { if ('' === $value) { return ''; } $v = esc($value); if ('ref' === $style) { if (empty($attr['count'])) { return sprintf('%s', $v); } $r = ('#' !== $v[0] ? 1 - ('@' !== $v[0]) : 2).substr($value, 1); return sprintf('%s', $this->dumpId, $r, 1 + $attr['count'], $v); } if ('const' === $style && isset($attr['value'])) { $style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); } elseif ('public' === $style) { $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); } elseif ('str' === $style && 1 < $attr['length']) { $style .= sprintf(' title="%d%s characters"', $attr['length'], $attr['binary'] ? ' binary or non-UTF-8' : ''); } elseif ('note' === $style && 0 < ($attr['depth'] ?? 0) && false !== $c = strrpos($value, '\\')) { $style .= ' title=""'; $attr += [ 'ellipsis' => \strlen($value) - $c, 'ellipsis-type' => 'note', 'ellipsis-tail' => 1, ]; } elseif ('protected' === $style) { $style .= ' title="Protected property"'; } elseif ('meta' === $style && isset($attr['title'])) { $style .= sprintf(' title="%s"', esc($this->utf8Encode($attr['title']))); } elseif ('private' === $style) { $style .= sprintf(' title="Private property defined in class: `%s`"', esc($this->utf8Encode($attr['class']))); } $map = static::$controlCharsMap; if (isset($attr['ellipsis'])) { $class = 'sf-dump-ellipsis'; if (isset($attr['ellipsis-type'])) { $class = sprintf('"%s sf-dump-ellipsis-%s"', $class, $attr['ellipsis-type']); } $label = esc(substr($value, -$attr['ellipsis'])); $style = str_replace(' title="', " title=\"$v\n", $style); $v = sprintf('%s', $class, substr($v, 0, -\strlen($label))); if (!empty($attr['ellipsis-tail'])) { $tail = \strlen(esc(substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']))); $v .= sprintf('%s%s', $class, substr($label, 0, $tail), substr($label, $tail)); } else { $v .= $label; } } $v = "".preg_replace_callback(static::$controlCharsRx, function ($c) use ($map) { $s = $b = ''; }, $v).''; if (isset($attr['file']) && $href = $this->getSourceLink($attr['file'], $attr['line'] ?? 0)) { $attr['href'] = $href; } if (isset($attr['href'])) { $target = isset($attr['file']) ? '' : ' target="_blank"'; $v = sprintf('%s', esc($this->utf8Encode($attr['href'])), $target, $v); } if (isset($attr['lang'])) { $v = sprintf('%s', esc($attr['lang']), $v); } return $v; } /** * {@inheritdoc} */ protected function dumpLine(int $depth, bool $endOfValue = false) { if (-1 === $this->lastDepth) { $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line; } if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) { $this->line = $this->getDumpHeader().$this->line; } if (-1 === $depth) { $args = ['"'.$this->dumpId.'"']; if ($this->extraDisplayOptions) { $args[] = json_encode($this->extraDisplayOptions, \JSON_FORCE_OBJECT); } // Replace is for BC $this->line .= sprintf(str_replace('"%s"', '%s', $this->dumpSuffix), implode(', ', $args)); } $this->lastDepth = $depth; $this->line = mb_convert_encoding($this->line, 'HTML-ENTITIES', 'UTF-8'); if (-1 === $depth) { AbstractDumper::dumpLine(0); } AbstractDumper::dumpLine($depth); } private function getSourceLink(string $file, int $line) { $options = $this->extraDisplayOptions + $this->displayOptions; if ($fmt = $options['fileLinkFormat']) { return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); } return false; } } function esc(string $str) { return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8'); } var-dumper/Dumper/AbstractDumper.php000064400000014076150432043210013515 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\DumperInterface; /** * Abstract mechanism for dumping a Data object. * * @author Nicolas Grekas */ abstract class AbstractDumper implements DataDumperInterface, DumperInterface { public const DUMP_LIGHT_ARRAY = 1; public const DUMP_STRING_LENGTH = 2; public const DUMP_COMMA_SEPARATOR = 4; public const DUMP_TRAILING_COMMA = 8; public static $defaultOutput = 'php://output'; protected $line = ''; protected $lineDumper; protected $outputStream; protected $decimalPoint; // This is locale dependent protected $indentPad = ' '; protected $flags; private $charset = ''; /** * @param callable|resource|string|null $output A line dumper callable, an opened stream or an output path, defaults to static::$defaultOutput * @param string|null $charset The default character encoding to use for non-UTF8 strings * @param int $flags A bit field of static::DUMP_* constants to fine tune dumps representation */ public function __construct($output = null, string $charset = null, int $flags = 0) { $this->flags = $flags; $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'); $this->decimalPoint = localeconv(); $this->decimalPoint = $this->decimalPoint['decimal_point']; $this->setOutput($output ?: static::$defaultOutput); if (!$output && \is_string(static::$defaultOutput)) { static::$defaultOutput = $this->outputStream; } } /** * Sets the output destination of the dumps. * * @param callable|resource|string $output A line dumper callable, an opened stream or an output path * * @return callable|resource|string The previous output destination */ public function setOutput($output) { $prev = $this->outputStream ?? $this->lineDumper; if (\is_callable($output)) { $this->outputStream = null; $this->lineDumper = $output; } else { if (\is_string($output)) { $output = fopen($output, 'w'); } $this->outputStream = $output; $this->lineDumper = [$this, 'echoLine']; } return $prev; } /** * Sets the default character encoding to use for non-UTF8 strings. * * @return string The previous charset */ public function setCharset(string $charset) { $prev = $this->charset; $charset = strtoupper($charset); $charset = null === $charset || 'UTF-8' === $charset || 'UTF8' === $charset ? 'CP1252' : $charset; $this->charset = $charset; return $prev; } /** * Sets the indentation pad string. * * @param string $pad A string that will be prepended to dumped lines, repeated by nesting level * * @return string The previous indent pad */ public function setIndentPad(string $pad) { $prev = $this->indentPad; $this->indentPad = $pad; return $prev; } /** * Dumps a Data object. * * @param callable|resource|string|true|null $output A line dumper callable, an opened stream, an output path or true to return the dump * * @return string|null The dump as string when $output is true */ public function dump(Data $data, $output = null) { $this->decimalPoint = localeconv(); $this->decimalPoint = $this->decimalPoint['decimal_point']; if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(\LC_NUMERIC, 0) : null) { setlocale(\LC_NUMERIC, 'C'); } if ($returnDump = true === $output) { $output = fopen('php://memory', 'r+'); } if ($output) { $prevOutput = $this->setOutput($output); } try { $data->dump($this); $this->dumpLine(-1); if ($returnDump) { $result = stream_get_contents($output, -1, 0); fclose($output); return $result; } } finally { if ($output) { $this->setOutput($prevOutput); } if ($locale) { setlocale(\LC_NUMERIC, $locale); } } return null; } /** * Dumps the current line. * * @param int $depth The recursive depth in the dumped structure for the line being dumped, * or -1 to signal the end-of-dump to the line dumper callable */ protected function dumpLine(int $depth) { ($this->lineDumper)($this->line, $depth, $this->indentPad); $this->line = ''; } /** * Generic line dumper callback. */ protected function echoLine(string $line, int $depth, string $indentPad) { if (-1 !== $depth) { fwrite($this->outputStream, str_repeat($indentPad, $depth).$line."\n"); } } /** * Converts a non-UTF-8 string to UTF-8. * * @return string|null */ protected function utf8Encode(?string $s) { if (null === $s || preg_match('//u', $s)) { return $s; } if (!\function_exists('iconv')) { throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.'); } if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) { return $c; } if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) { return $c; } return iconv('CP850', 'UTF-8', $s); } } var-dumper/Dumper/ServerDumper.php000064400000003105150432043210013207 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Dumper; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; use Symfony\Component\VarDumper\Server\Connection; /** * ServerDumper forwards serialized Data clones to a server. * * @author Maxime Steinhausser */ class ServerDumper implements DataDumperInterface { private $connection; private $wrappedDumper; /** * @param string $host The server host * @param DataDumperInterface|null $wrappedDumper A wrapped instance used whenever we failed contacting the server * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name */ public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = []) { $this->connection = new Connection($host, $contextProviders); $this->wrappedDumper = $wrappedDumper; } public function getContextProviders(): array { return $this->connection->getContextProviders(); } /** * {@inheritdoc} */ public function dump(Data $data) { if (!$this->connection->write($data) && $this->wrappedDumper) { $this->wrappedDumper->dump($data); } } } var-dumper/composer.json000064400000003000150432043210011333 0ustar00{ "name": "symfony/var-dumper", "type": "library", "description": "Provides mechanisms for walking through any arbitrary PHP variable", "keywords": ["dump", "debug"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "^1.16" }, "require-dev": { "ext-iconv": "*", "symfony/console": "^4.4|^5.0|^6.0", "symfony/process": "^4.4|^5.0|^6.0", "symfony/uid": "^5.1|^6.0", "twig/twig": "^2.13|^3.0.4" }, "conflict": { "phpunit/phpunit": "<5.4.3", "symfony/console": "<4.4" }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", "ext-intl": "To show region name in time zone dump", "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, "autoload": { "files": [ "Resources/functions/dump.php" ], "psr-4": { "Symfony\\Component\\VarDumper\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "bin": [ "Resources/bin/var-dump-server" ], "minimum-stability": "dev" } var-dumper/Server/Connection.php000064400000005330150432043210012677 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Server; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface; /** * Forwards serialized Data clones to a server. * * @author Maxime Steinhausser */ class Connection { private $host; private $contextProviders; /** * @var resource|null */ private $socket; /** * @param string $host The server host * @param ContextProviderInterface[] $contextProviders Context providers indexed by context name */ public function __construct(string $host, array $contextProviders = []) { if (!str_contains($host, '://')) { $host = 'tcp://'.$host; } $this->host = $host; $this->contextProviders = $contextProviders; } public function getContextProviders(): array { return $this->contextProviders; } public function write(Data $data): bool { $socketIsFresh = !$this->socket; if (!$this->socket = $this->socket ?: $this->createSocket()) { return false; } $context = ['timestamp' => microtime(true)]; foreach ($this->contextProviders as $name => $provider) { $context[$name] = $provider->getContext(); } $context = array_filter($context); $encodedPayload = base64_encode(serialize([$data, $context]))."\n"; set_error_handler([self::class, 'nullErrorHandler']); try { if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { return true; } if (!$socketIsFresh) { stream_socket_shutdown($this->socket, \STREAM_SHUT_RDWR); fclose($this->socket); $this->socket = $this->createSocket(); } if (-1 !== stream_socket_sendto($this->socket, $encodedPayload)) { return true; } } finally { restore_error_handler(); } return false; } private static function nullErrorHandler(int $t, string $m) { // no-op } private function createSocket() { set_error_handler([self::class, 'nullErrorHandler']); try { return stream_socket_client($this->host, $errno, $errstr, 3, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT); } finally { restore_error_handler(); } } } var-dumper/Server/DumpServer.php000064400000006307150432043210012701 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Server; use Psr\Log\LoggerInterface; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\Stub; /** * A server collecting Data clones sent by a ServerDumper. * * @author Maxime Steinhausser * * @final */ class DumpServer { private $host; private $logger; /** * @var resource|null */ private $socket; public function __construct(string $host, LoggerInterface $logger = null) { if (!str_contains($host, '://')) { $host = 'tcp://'.$host; } $this->host = $host; $this->logger = $logger; } public function start(): void { if (!$this->socket = stream_socket_server($this->host, $errno, $errstr)) { throw new \RuntimeException(sprintf('Server start failed on "%s": ', $this->host).$errstr.' '.$errno); } } public function listen(callable $callback): void { if (null === $this->socket) { $this->start(); } foreach ($this->getMessages() as $clientId => $message) { if ($this->logger) { $this->logger->info('Received a payload from client {clientId}', ['clientId' => $clientId]); } $payload = @unserialize(base64_decode($message), ['allowed_classes' => [Data::class, Stub::class]]); // Impossible to decode the message, give up. if (false === $payload) { if ($this->logger) { $this->logger->warning('Unable to decode a message from {clientId} client.', ['clientId' => $clientId]); } continue; } if (!\is_array($payload) || \count($payload) < 2 || !$payload[0] instanceof Data || !\is_array($payload[1])) { if ($this->logger) { $this->logger->warning('Invalid payload from {clientId} client. Expected an array of two elements (Data $data, array $context)', ['clientId' => $clientId]); } continue; } [$data, $context] = $payload; $callback($data, $context, $clientId); } } public function getHost(): string { return $this->host; } private function getMessages(): iterable { $sockets = [(int) $this->socket => $this->socket]; $write = []; while (true) { $read = $sockets; stream_select($read, $write, $write, null); foreach ($read as $stream) { if ($this->socket === $stream) { $stream = stream_socket_accept($this->socket); $sockets[(int) $stream] = $stream; } elseif (feof($stream)) { unset($sockets[(int) $stream]); fclose($stream); } else { yield (int) $stream => fgets($stream); } } } } } var-dumper/LICENSE000064400000002051150432043210007623 0ustar00Copyright (c) 2014-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var-dumper/Exception/ThrowingCasterException.php000064400000001217150432043210016112 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Exception; /** * @author Nicolas Grekas */ class ThrowingCasterException extends \Exception { /** * @param \Throwable $prev The exception thrown from the caster */ public function __construct(\Throwable $prev) { parent::__construct('Unexpected '.\get_class($prev).' thrown from a caster: '.$prev->getMessage(), 0, $prev); } } var-dumper/Test/VarDumperTestTrait.php000064400000005000150432043210014014 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Test; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\CliDumper; /** * @author Nicolas Grekas */ trait VarDumperTestTrait { /** * @internal */ private $varDumperConfig = [ 'casters' => [], 'flags' => null, ]; protected function setUpVarDumper(array $casters, int $flags = null): void { $this->varDumperConfig['casters'] = $casters; $this->varDumperConfig['flags'] = $flags; } /** * @after */ protected function tearDownVarDumper(): void { $this->varDumperConfig['casters'] = []; $this->varDumperConfig['flags'] = null; } public function assertDumpEquals($expected, $data, int $filter = 0, string $message = '') { $this->assertSame($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); } public function assertDumpMatchesFormat($expected, $data, int $filter = 0, string $message = '') { $this->assertStringMatchesFormat($this->prepareExpectation($expected, $filter), $this->getDump($data, null, $filter), $message); } protected function getDump($data, $key = null, int $filter = 0): ?string { if (null === $flags = $this->varDumperConfig['flags']) { $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0; $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0; $flags |= getenv('DUMP_COMMA_SEPARATOR') ? CliDumper::DUMP_COMMA_SEPARATOR : 0; } $cloner = new VarCloner(); $cloner->addCasters($this->varDumperConfig['casters']); $cloner->setMaxItems(-1); $dumper = new CliDumper(null, null, $flags); $dumper->setColors(false); $data = $cloner->cloneVar($data, $filter)->withRefHandles(false); if (null !== $key && null === $data = $data->seek($key)) { return null; } return rtrim($dumper->dump($data, true)); } private function prepareExpectation($expected, int $filter): string { if (!\is_string($expected)) { $expected = $this->getDump($expected, null, $filter); } return rtrim($expected); } } var-dumper/Command/ServerDumpCommand.php000064400000007464150432043210014315 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Completion\CompletionInput; use Symfony\Component\Console\Completion\CompletionSuggestions; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor; use Symfony\Component\VarDumper\Command\Descriptor\DumpDescriptorInterface; use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor; use Symfony\Component\VarDumper\Dumper\CliDumper; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Symfony\Component\VarDumper\Server\DumpServer; /** * Starts a dump server to collect and output dumps on a single place with multiple formats support. * * @author Maxime Steinhausser * * @final */ class ServerDumpCommand extends Command { protected static $defaultName = 'server:dump'; protected static $defaultDescription = 'Start a dump server that collects and displays dumps in a single place'; private $server; /** @var DumpDescriptorInterface[] */ private $descriptors; public function __construct(DumpServer $server, array $descriptors = []) { $this->server = $server; $this->descriptors = $descriptors + [ 'cli' => new CliDescriptor(new CliDumper()), 'html' => new HtmlDescriptor(new HtmlDumper()), ]; parent::__construct(); } protected function configure() { $this ->addOption('format', null, InputOption::VALUE_REQUIRED, sprintf('The output format (%s)', implode(', ', $this->getAvailableFormats())), 'cli') ->setDescription(self::$defaultDescription) ->setHelp(<<<'EOF' %command.name% starts a dump server that collects and displays dumps in a single place for debugging you application: php %command.full_name% You can consult dumped data in HTML format in your browser by providing the --format=html option and redirecting the output to a file: php %command.full_name% --format="html" > dump.html EOF ) ; } protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); $format = $input->getOption('format'); if (!$descriptor = $this->descriptors[$format] ?? null) { throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $format)); } $errorIo = $io->getErrorStyle(); $errorIo->title('Symfony Var Dumper Server'); $this->server->start(); $errorIo->success(sprintf('Server listening on %s', $this->server->getHost())); $errorIo->comment('Quit the server with CONTROL-C.'); $this->server->listen(function (Data $data, array $context, int $clientId) use ($descriptor, $io) { $descriptor->describe($io, $data, $context, $clientId); }); return 0; } public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { if ($input->mustSuggestOptionValuesFor('format')) { $suggestions->suggestValues($this->getAvailableFormats()); } } private function getAvailableFormats(): array { return array_keys($this->descriptors); } } var-dumper/Command/Descriptor/CliDescriptor.php000064400000005115150432043210015575 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Command\Descriptor; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\CliDumper; /** * Describe collected data clones for cli output. * * @author Maxime Steinhausser * * @final */ class CliDescriptor implements DumpDescriptorInterface { private $dumper; private $lastIdentifier; public function __construct(CliDumper $dumper) { $this->dumper = $dumper; } public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void { $io = $output instanceof SymfonyStyle ? $output : new SymfonyStyle(new ArrayInput([]), $output); $this->dumper->setColors($output->isDecorated()); $rows = [['date', date('r', (int) $context['timestamp'])]]; $lastIdentifier = $this->lastIdentifier; $this->lastIdentifier = $clientId; $section = "Received from client #$clientId"; if (isset($context['request'])) { $request = $context['request']; $this->lastIdentifier = $request['identifier']; $section = sprintf('%s %s', $request['method'], $request['uri']); if ($controller = $request['controller']) { $rows[] = ['controller', rtrim($this->dumper->dump($controller, true), "\n")]; } } elseif (isset($context['cli'])) { $this->lastIdentifier = $context['cli']['identifier']; $section = '$ '.$context['cli']['command_line']; } if ($this->lastIdentifier !== $lastIdentifier) { $io->section($section); } if (isset($context['source'])) { $source = $context['source']; $sourceInfo = sprintf('%s on line %d', $source['name'], $source['line']); if ($fileLink = $source['file_link'] ?? null) { $sourceInfo = sprintf('%s', $fileLink, $sourceInfo); } $rows[] = ['source', $sourceInfo]; $file = $source['file_relative'] ?? $source['file']; $rows[] = ['file', $file]; } $io->table([], $rows); $this->dumper->dump($data); $io->newLine(); } } var-dumper/Command/Descriptor/DumpDescriptorInterface.php000064400000001142150432043210017610 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Command\Descriptor; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\VarDumper\Cloner\Data; /** * @author Maxime Steinhausser */ interface DumpDescriptorInterface { public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void; } var-dumper/Command/Descriptor/HtmlDescriptor.php000064400000007154150432043210015777 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Command\Descriptor; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\HtmlDumper; /** * Describe collected data clones for html output. * * @author Maxime Steinhausser * * @final */ class HtmlDescriptor implements DumpDescriptorInterface { private $dumper; private $initialized = false; public function __construct(HtmlDumper $dumper) { $this->dumper = $dumper; } public function describe(OutputInterface $output, Data $data, array $context, int $clientId): void { if (!$this->initialized) { $styles = file_get_contents(__DIR__.'/../../Resources/css/htmlDescriptor.css'); $scripts = file_get_contents(__DIR__.'/../../Resources/js/htmlDescriptor.js'); $output->writeln(""); $this->initialized = true; } $title = '-'; if (isset($context['request'])) { $request = $context['request']; $controller = "{$this->dumper->dump($request['controller'], true, ['maxDepth' => 0])}"; $title = sprintf('%s %s', $request['method'], $uri = $request['uri'], $uri); $dedupIdentifier = $request['identifier']; } elseif (isset($context['cli'])) { $title = '$ '.$context['cli']['command_line']; $dedupIdentifier = $context['cli']['identifier']; } else { $dedupIdentifier = uniqid('', true); } $sourceDescription = ''; if (isset($context['source'])) { $source = $context['source']; $projectDir = $source['project_dir'] ?? null; $sourceDescription = sprintf('%s on line %d', $source['name'], $source['line']); if (isset($source['file_link'])) { $sourceDescription = sprintf('%s', $source['file_link'], $sourceDescription); } } $isoDate = $this->extractDate($context, 'c'); $tags = array_filter([ 'controller' => $controller ?? null, 'project dir' => $projectDir ?? null, ]); $output->writeln(<<

    $title

    {$this->renderTags($tags)}

    $sourceDescription

    {$this->dumper->dump($data, true)}
    HTML ); } private function extractDate(array $context, string $format = 'r'): string { return date($format, (int) $context['timestamp']); } private function renderTags(array $tags): string { if (!$tags) { return ''; } $renderedTags = ''; foreach ($tags as $key => $value) { $renderedTags .= sprintf('
  • %s%s
  • ', $key, $value); } return <<
      $renderedTags
    HTML; } } var-dumper/Caster/PgSqlCaster.php000064400000012554150432043210012751 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts pqsql resources to array representation. * * @author Nicolas Grekas * * @final */ class PgSqlCaster { private const PARAM_CODES = [ 'server_encoding', 'client_encoding', 'is_superuser', 'session_authorization', 'DateStyle', 'TimeZone', 'IntervalStyle', 'integer_datetimes', 'application_name', 'standard_conforming_strings', ]; private const TRANSACTION_STATUS = [ \PGSQL_TRANSACTION_IDLE => 'PGSQL_TRANSACTION_IDLE', \PGSQL_TRANSACTION_ACTIVE => 'PGSQL_TRANSACTION_ACTIVE', \PGSQL_TRANSACTION_INTRANS => 'PGSQL_TRANSACTION_INTRANS', \PGSQL_TRANSACTION_INERROR => 'PGSQL_TRANSACTION_INERROR', \PGSQL_TRANSACTION_UNKNOWN => 'PGSQL_TRANSACTION_UNKNOWN', ]; private const RESULT_STATUS = [ \PGSQL_EMPTY_QUERY => 'PGSQL_EMPTY_QUERY', \PGSQL_COMMAND_OK => 'PGSQL_COMMAND_OK', \PGSQL_TUPLES_OK => 'PGSQL_TUPLES_OK', \PGSQL_COPY_OUT => 'PGSQL_COPY_OUT', \PGSQL_COPY_IN => 'PGSQL_COPY_IN', \PGSQL_BAD_RESPONSE => 'PGSQL_BAD_RESPONSE', \PGSQL_NONFATAL_ERROR => 'PGSQL_NONFATAL_ERROR', \PGSQL_FATAL_ERROR => 'PGSQL_FATAL_ERROR', ]; private const DIAG_CODES = [ 'severity' => \PGSQL_DIAG_SEVERITY, 'sqlstate' => \PGSQL_DIAG_SQLSTATE, 'message' => \PGSQL_DIAG_MESSAGE_PRIMARY, 'detail' => \PGSQL_DIAG_MESSAGE_DETAIL, 'hint' => \PGSQL_DIAG_MESSAGE_HINT, 'statement position' => \PGSQL_DIAG_STATEMENT_POSITION, 'internal position' => \PGSQL_DIAG_INTERNAL_POSITION, 'internal query' => \PGSQL_DIAG_INTERNAL_QUERY, 'context' => \PGSQL_DIAG_CONTEXT, 'file' => \PGSQL_DIAG_SOURCE_FILE, 'line' => \PGSQL_DIAG_SOURCE_LINE, 'function' => \PGSQL_DIAG_SOURCE_FUNCTION, ]; public static function castLargeObject($lo, array $a, Stub $stub, bool $isNested) { $a['seek position'] = pg_lo_tell($lo); return $a; } public static function castLink($link, array $a, Stub $stub, bool $isNested) { $a['status'] = pg_connection_status($link); $a['status'] = new ConstStub(\PGSQL_CONNECTION_OK === $a['status'] ? 'PGSQL_CONNECTION_OK' : 'PGSQL_CONNECTION_BAD', $a['status']); $a['busy'] = pg_connection_busy($link); $a['transaction'] = pg_transaction_status($link); if (isset(self::TRANSACTION_STATUS[$a['transaction']])) { $a['transaction'] = new ConstStub(self::TRANSACTION_STATUS[$a['transaction']], $a['transaction']); } $a['pid'] = pg_get_pid($link); $a['last error'] = pg_last_error($link); $a['last notice'] = pg_last_notice($link); $a['host'] = pg_host($link); $a['port'] = pg_port($link); $a['dbname'] = pg_dbname($link); $a['options'] = pg_options($link); $a['version'] = pg_version($link); foreach (self::PARAM_CODES as $v) { if (false !== $s = pg_parameter_status($link, $v)) { $a['param'][$v] = $s; } } $a['param']['client_encoding'] = pg_client_encoding($link); $a['param'] = new EnumStub($a['param']); return $a; } public static function castResult($result, array $a, Stub $stub, bool $isNested) { $a['num rows'] = pg_num_rows($result); $a['status'] = pg_result_status($result); if (isset(self::RESULT_STATUS[$a['status']])) { $a['status'] = new ConstStub(self::RESULT_STATUS[$a['status']], $a['status']); } $a['command-completion tag'] = pg_result_status($result, \PGSQL_STATUS_STRING); if (-1 === $a['num rows']) { foreach (self::DIAG_CODES as $k => $v) { $a['error'][$k] = pg_result_error_field($result, $v); } } $a['affected rows'] = pg_affected_rows($result); $a['last OID'] = pg_last_oid($result); $fields = pg_num_fields($result); for ($i = 0; $i < $fields; ++$i) { $field = [ 'name' => pg_field_name($result, $i), 'table' => sprintf('%s (OID: %s)', pg_field_table($result, $i), pg_field_table($result, $i, true)), 'type' => sprintf('%s (OID: %s)', pg_field_type($result, $i), pg_field_type_oid($result, $i)), 'nullable' => (bool) pg_field_is_null($result, $i), 'storage' => pg_field_size($result, $i).' bytes', 'display' => pg_field_prtlen($result, $i).' chars', ]; if (' (OID: )' === $field['table']) { $field['table'] = null; } if ('-1 bytes' === $field['storage']) { $field['storage'] = 'variable size'; } elseif ('1 bytes' === $field['storage']) { $field['storage'] = '1 byte'; } if ('1 chars' === $field['display']) { $field['display'] = '1 char'; } $a['fields'][] = new EnumStub($field); } return $a; } } var-dumper/Caster/MysqliCaster.php000066600000001263150432043210013200 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Nicolas Grekas * * @internal */ final class MysqliCaster { public static function castMysqliDriver(\mysqli_driver $c, array $a, Stub $stub, bool $isNested): array { foreach ($a as $k => $v) { if (isset($c->$k)) { $a[$k] = $c->$k; } } return $a; } } var-dumper/Caster/StubCaster.php000064400000004134150432043210012633 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts a caster's Stub. * * @author Nicolas Grekas * * @final */ class StubCaster { public static function castStub(Stub $c, array $a, Stub $stub, bool $isNested) { if ($isNested) { $stub->type = $c->type; $stub->class = $c->class; $stub->value = $c->value; $stub->handle = $c->handle; $stub->cut = $c->cut; $stub->attr = $c->attr; if (Stub::TYPE_REF === $c->type && !$c->class && \is_string($c->value) && !preg_match('//u', $c->value)) { $stub->type = Stub::TYPE_STRING; $stub->class = Stub::STRING_BINARY; } $a = []; } return $a; } public static function castCutArray(CutArrayStub $c, array $a, Stub $stub, bool $isNested) { return $isNested ? $c->preservedSubset : $a; } public static function cutInternals($obj, array $a, Stub $stub, bool $isNested) { if ($isNested) { $stub->cut += \count($a); return []; } return $a; } public static function castEnum(EnumStub $c, array $a, Stub $stub, bool $isNested) { if ($isNested) { $stub->class = $c->dumpKeys ? '' : null; $stub->handle = 0; $stub->value = null; $stub->cut = $c->cut; $stub->attr = $c->attr; $a = []; if ($c->value) { foreach (array_keys($c->value) as $k) { $keys[] = !isset($k[0]) || "\0" !== $k[0] ? Caster::PREFIX_VIRTUAL.$k : $k; } // Preserve references with array_combine() $a = array_combine($keys, $c->value); } } return $a; } } var-dumper/Caster/UuidCaster.php000064400000001234150432043210012622 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Ramsey\Uuid\UuidInterface; use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Grégoire Pineau */ final class UuidCaster { public static function castRamseyUuid(UuidInterface $c, array $a, Stub $stub, bool $isNested): array { $a += [ Caster::PREFIX_VIRTUAL.'uuid' => (string) $c, ]; return $a; } } var-dumper/Caster/ImagineCaster.php000064400000001665150432043210013275 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Imagine\Image\ImageInterface; use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Grégoire Pineau */ final class ImagineCaster { public static function castImage(ImageInterface $c, array $a, Stub $stub, bool $isNested): array { $imgData = $c->get('png'); if (\strlen($imgData) > 1 * 1000 * 1000) { $a += [ Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()), ]; } else { $a += [ Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()), ]; } return $a; } } var-dumper/Caster/TraceStub.php000064400000001703150432043210012447 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Represents a backtrace as returned by debug_backtrace() or Exception->getTrace(). * * @author Nicolas Grekas */ class TraceStub extends Stub { public $keepArgs; public $sliceOffset; public $sliceLength; public $numberingOffset; public function __construct(array $trace, bool $keepArgs = true, int $sliceOffset = 0, int $sliceLength = null, int $numberingOffset = 0) { $this->value = $trace; $this->keepArgs = $keepArgs; $this->sliceOffset = $sliceOffset; $this->sliceLength = $sliceLength; $this->numberingOffset = $numberingOffset; } } var-dumper/Caster/AmqpCaster.php000064400000015046150432043210012620 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts Amqp related classes to array representation. * * @author Grégoire Pineau * * @final */ class AmqpCaster { private const FLAGS = [ \AMQP_DURABLE => 'AMQP_DURABLE', \AMQP_PASSIVE => 'AMQP_PASSIVE', \AMQP_EXCLUSIVE => 'AMQP_EXCLUSIVE', \AMQP_AUTODELETE => 'AMQP_AUTODELETE', \AMQP_INTERNAL => 'AMQP_INTERNAL', \AMQP_NOLOCAL => 'AMQP_NOLOCAL', \AMQP_AUTOACK => 'AMQP_AUTOACK', \AMQP_IFEMPTY => 'AMQP_IFEMPTY', \AMQP_IFUNUSED => 'AMQP_IFUNUSED', \AMQP_MANDATORY => 'AMQP_MANDATORY', \AMQP_IMMEDIATE => 'AMQP_IMMEDIATE', \AMQP_MULTIPLE => 'AMQP_MULTIPLE', \AMQP_NOWAIT => 'AMQP_NOWAIT', \AMQP_REQUEUE => 'AMQP_REQUEUE', ]; private const EXCHANGE_TYPES = [ \AMQP_EX_TYPE_DIRECT => 'AMQP_EX_TYPE_DIRECT', \AMQP_EX_TYPE_FANOUT => 'AMQP_EX_TYPE_FANOUT', \AMQP_EX_TYPE_TOPIC => 'AMQP_EX_TYPE_TOPIC', \AMQP_EX_TYPE_HEADERS => 'AMQP_EX_TYPE_HEADERS', ]; public static function castConnection(\AMQPConnection $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'is_connected' => $c->isConnected(), ]; // Recent version of the extension already expose private properties if (isset($a["\x00AMQPConnection\x00login"])) { return $a; } // BC layer in the amqp lib if (method_exists($c, 'getReadTimeout')) { $timeout = $c->getReadTimeout(); } else { $timeout = $c->getTimeout(); } $a += [ $prefix.'is_connected' => $c->isConnected(), $prefix.'login' => $c->getLogin(), $prefix.'password' => $c->getPassword(), $prefix.'host' => $c->getHost(), $prefix.'vhost' => $c->getVhost(), $prefix.'port' => $c->getPort(), $prefix.'read_timeout' => $timeout, ]; return $a; } public static function castChannel(\AMQPChannel $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'is_connected' => $c->isConnected(), $prefix.'channel_id' => $c->getChannelId(), ]; // Recent version of the extension already expose private properties if (isset($a["\x00AMQPChannel\x00connection"])) { return $a; } $a += [ $prefix.'connection' => $c->getConnection(), $prefix.'prefetch_size' => $c->getPrefetchSize(), $prefix.'prefetch_count' => $c->getPrefetchCount(), ]; return $a; } public static function castQueue(\AMQPQueue $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'flags' => self::extractFlags($c->getFlags()), ]; // Recent version of the extension already expose private properties if (isset($a["\x00AMQPQueue\x00name"])) { return $a; } $a += [ $prefix.'connection' => $c->getConnection(), $prefix.'channel' => $c->getChannel(), $prefix.'name' => $c->getName(), $prefix.'arguments' => $c->getArguments(), ]; return $a; } public static function castExchange(\AMQPExchange $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'flags' => self::extractFlags($c->getFlags()), ]; $type = isset(self::EXCHANGE_TYPES[$c->getType()]) ? new ConstStub(self::EXCHANGE_TYPES[$c->getType()], $c->getType()) : $c->getType(); // Recent version of the extension already expose private properties if (isset($a["\x00AMQPExchange\x00name"])) { $a["\x00AMQPExchange\x00type"] = $type; return $a; } $a += [ $prefix.'connection' => $c->getConnection(), $prefix.'channel' => $c->getChannel(), $prefix.'name' => $c->getName(), $prefix.'type' => $type, $prefix.'arguments' => $c->getArguments(), ]; return $a; } public static function castEnvelope(\AMQPEnvelope $c, array $a, Stub $stub, bool $isNested, int $filter = 0) { $prefix = Caster::PREFIX_VIRTUAL; $deliveryMode = new ConstStub($c->getDeliveryMode().(2 === $c->getDeliveryMode() ? ' (persistent)' : ' (non-persistent)'), $c->getDeliveryMode()); // Recent version of the extension already expose private properties if (isset($a["\x00AMQPEnvelope\x00body"])) { $a["\0AMQPEnvelope\0delivery_mode"] = $deliveryMode; return $a; } if (!($filter & Caster::EXCLUDE_VERBOSE)) { $a += [$prefix.'body' => $c->getBody()]; } $a += [ $prefix.'delivery_tag' => $c->getDeliveryTag(), $prefix.'is_redelivery' => $c->isRedelivery(), $prefix.'exchange_name' => $c->getExchangeName(), $prefix.'routing_key' => $c->getRoutingKey(), $prefix.'content_type' => $c->getContentType(), $prefix.'content_encoding' => $c->getContentEncoding(), $prefix.'headers' => $c->getHeaders(), $prefix.'delivery_mode' => $deliveryMode, $prefix.'priority' => $c->getPriority(), $prefix.'correlation_id' => $c->getCorrelationId(), $prefix.'reply_to' => $c->getReplyTo(), $prefix.'expiration' => $c->getExpiration(), $prefix.'message_id' => $c->getMessageId(), $prefix.'timestamp' => $c->getTimeStamp(), $prefix.'type' => $c->getType(), $prefix.'user_id' => $c->getUserId(), $prefix.'app_id' => $c->getAppId(), ]; return $a; } private static function extractFlags(int $flags): ConstStub { $flagsArray = []; foreach (self::FLAGS as $value => $name) { if ($flags & $value) { $flagsArray[] = $name; } } if (!$flagsArray) { $flagsArray = ['AMQP_NOPARAM']; } return new ConstStub(implode('|', $flagsArray), $flags); } } var-dumper/Caster/PdoCaster.php000064400000006746150432043210012453 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts PDO related classes to array representation. * * @author Nicolas Grekas * * @final */ class PdoCaster { private const PDO_ATTRIBUTES = [ 'CASE' => [ \PDO::CASE_LOWER => 'LOWER', \PDO::CASE_NATURAL => 'NATURAL', \PDO::CASE_UPPER => 'UPPER', ], 'ERRMODE' => [ \PDO::ERRMODE_SILENT => 'SILENT', \PDO::ERRMODE_WARNING => 'WARNING', \PDO::ERRMODE_EXCEPTION => 'EXCEPTION', ], 'TIMEOUT', 'PREFETCH', 'AUTOCOMMIT', 'PERSISTENT', 'DRIVER_NAME', 'SERVER_INFO', 'ORACLE_NULLS' => [ \PDO::NULL_NATURAL => 'NATURAL', \PDO::NULL_EMPTY_STRING => 'EMPTY_STRING', \PDO::NULL_TO_STRING => 'TO_STRING', ], 'CLIENT_VERSION', 'SERVER_VERSION', 'STATEMENT_CLASS', 'EMULATE_PREPARES', 'CONNECTION_STATUS', 'STRINGIFY_FETCHES', 'DEFAULT_FETCH_MODE' => [ \PDO::FETCH_ASSOC => 'ASSOC', \PDO::FETCH_BOTH => 'BOTH', \PDO::FETCH_LAZY => 'LAZY', \PDO::FETCH_NUM => 'NUM', \PDO::FETCH_OBJ => 'OBJ', ], ]; public static function castPdo(\PDO $c, array $a, Stub $stub, bool $isNested) { $attr = []; $errmode = $c->getAttribute(\PDO::ATTR_ERRMODE); $c->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); foreach (self::PDO_ATTRIBUTES as $k => $v) { if (!isset($k[0])) { $k = $v; $v = []; } try { $attr[$k] = 'ERRMODE' === $k ? $errmode : $c->getAttribute(\constant('PDO::ATTR_'.$k)); if ($v && isset($v[$attr[$k]])) { $attr[$k] = new ConstStub($v[$attr[$k]], $attr[$k]); } } catch (\Exception $e) { } } if (isset($attr[$k = 'STATEMENT_CLASS'][1])) { if ($attr[$k][1]) { $attr[$k][1] = new ArgsStub($attr[$k][1], '__construct', $attr[$k][0]); } $attr[$k][0] = new ClassStub($attr[$k][0]); } $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'inTransaction' => method_exists($c, 'inTransaction'), $prefix.'errorInfo' => $c->errorInfo(), $prefix.'attributes' => new EnumStub($attr), ]; if ($a[$prefix.'inTransaction']) { $a[$prefix.'inTransaction'] = $c->inTransaction(); } else { unset($a[$prefix.'inTransaction']); } if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { unset($a[$prefix.'errorInfo']); } $c->setAttribute(\PDO::ATTR_ERRMODE, $errmode); return $a; } public static function castPdoStatement(\PDOStatement $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a[$prefix.'errorInfo'] = $c->errorInfo(); if (!isset($a[$prefix.'errorInfo'][1], $a[$prefix.'errorInfo'][2])) { unset($a[$prefix.'errorInfo']); } return $a; } } var-dumper/Caster/ExceptionCaster.php000064400000037571150432043210013667 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; use Symfony\Component\VarDumper\Cloner\Stub; use Symfony\Component\VarDumper\Exception\ThrowingCasterException; /** * Casts common Exception classes to array representation. * * @author Nicolas Grekas * * @final */ class ExceptionCaster { public static $srcContext = 1; public static $traceArgs = true; public static $errorTypes = [ \E_DEPRECATED => 'E_DEPRECATED', \E_USER_DEPRECATED => 'E_USER_DEPRECATED', \E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR', \E_ERROR => 'E_ERROR', \E_WARNING => 'E_WARNING', \E_PARSE => 'E_PARSE', \E_NOTICE => 'E_NOTICE', \E_CORE_ERROR => 'E_CORE_ERROR', \E_CORE_WARNING => 'E_CORE_WARNING', \E_COMPILE_ERROR => 'E_COMPILE_ERROR', \E_COMPILE_WARNING => 'E_COMPILE_WARNING', \E_USER_ERROR => 'E_USER_ERROR', \E_USER_WARNING => 'E_USER_WARNING', \E_USER_NOTICE => 'E_USER_NOTICE', \E_STRICT => 'E_STRICT', ]; private static $framesCache = []; public static function castError(\Error $e, array $a, Stub $stub, bool $isNested, int $filter = 0) { return self::filterExceptionArray($stub->class, $a, "\0Error\0", $filter); } public static function castException(\Exception $e, array $a, Stub $stub, bool $isNested, int $filter = 0) { return self::filterExceptionArray($stub->class, $a, "\0Exception\0", $filter); } public static function castErrorException(\ErrorException $e, array $a, Stub $stub, bool $isNested) { if (isset($a[$s = Caster::PREFIX_PROTECTED.'severity'], self::$errorTypes[$a[$s]])) { $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); } return $a; } public static function castThrowingCasterException(ThrowingCasterException $e, array $a, Stub $stub, bool $isNested) { $trace = Caster::PREFIX_VIRTUAL.'trace'; $prefix = Caster::PREFIX_PROTECTED; $xPrefix = "\0Exception\0"; if (isset($a[$xPrefix.'previous'], $a[$trace]) && $a[$xPrefix.'previous'] instanceof \Exception) { $b = (array) $a[$xPrefix.'previous']; $class = get_debug_type($a[$xPrefix.'previous']); self::traceUnshift($b[$xPrefix.'trace'], $class, $b[$prefix.'file'], $b[$prefix.'line']); $a[$trace] = new TraceStub($b[$xPrefix.'trace'], false, 0, -\count($a[$trace]->value)); } unset($a[$xPrefix.'previous'], $a[$prefix.'code'], $a[$prefix.'file'], $a[$prefix.'line']); return $a; } public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, bool $isNested) { $sPrefix = "\0".SilencedErrorContext::class."\0"; if (!isset($a[$s = $sPrefix.'severity'])) { return $a; } if (isset(self::$errorTypes[$a[$s]])) { $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); } $trace = [[ 'file' => $a[$sPrefix.'file'], 'line' => $a[$sPrefix.'line'], ]]; if (isset($a[$sPrefix.'trace'])) { $trace = array_merge($trace, $a[$sPrefix.'trace']); } unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); return $a; } public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, bool $isNested) { if (!$isNested) { return $a; } $stub->class = ''; $stub->handle = 0; $frames = $trace->value; $prefix = Caster::PREFIX_VIRTUAL; $a = []; $j = \count($frames); if (0 > $i = $trace->sliceOffset) { $i = max(0, $j + $i); } if (!isset($trace->value[$i])) { return []; } $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : ''; $frames[] = ['function' => '']; $collapse = false; for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { $f = $frames[$i]; $call = isset($f['function']) ? (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'] : '???'; $frame = new FrameStub( [ 'object' => $f['object'] ?? null, 'class' => $f['class'] ?? null, 'type' => $f['type'] ?? null, 'function' => $f['function'] ?? null, ] + $frames[$i - 1], false, true ); $f = self::castFrameStub($frame, [], $frame, true); if (isset($f[$prefix.'src'])) { foreach ($f[$prefix.'src']->value as $label => $frame) { if (str_starts_with($label, "\0~collapse=0")) { if ($collapse) { $label = substr_replace($label, '1', 11, 1); } else { $collapse = true; } } $label = substr_replace($label, "title=Stack level $j.&", 2, 0); } $f = $frames[$i - 1]; if ($trace->keepArgs && !empty($f['args']) && $frame instanceof EnumStub) { $frame->value['arguments'] = new ArgsStub($f['args'], $f['function'] ?? null, $f['class'] ?? null); } } elseif ('???' !== $lastCall) { $label = new ClassStub($lastCall); if (isset($label->attr['ellipsis'])) { $label->attr['ellipsis'] += 2; $label = substr_replace($prefix, "ellipsis-type=class&ellipsis={$label->attr['ellipsis']}&ellipsis-tail=1&title=Stack level $j.", 2, 0).$label->value.'()'; } else { $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$label->value.'()'; } } else { $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall; } $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame; $lastCall = $call; } if (null !== $trace->sliceLength) { $a = \array_slice($a, 0, $trace->sliceLength, true); } return $a; } public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, bool $isNested) { if (!$isNested) { return $a; } $f = $frame->value; $prefix = Caster::PREFIX_VIRTUAL; if (isset($f['file'], $f['line'])) { $cacheKey = $f; unset($cacheKey['object'], $cacheKey['args']); $cacheKey[] = self::$srcContext; $cacheKey = implode('-', $cacheKey); if (isset(self::$framesCache[$cacheKey])) { $a[$prefix.'src'] = self::$framesCache[$cacheKey]; } else { if (preg_match('/\((\d+)\)(?:\([\da-f]{32}\))? : (?:eval\(\)\'d code|runtime-created function)$/', $f['file'], $match)) { $f['file'] = substr($f['file'], 0, -\strlen($match[0])); $f['line'] = (int) $match[1]; } $src = $f['line']; $srcKey = $f['file']; $ellipsis = new LinkStub($srcKey, 0); $srcAttr = 'collapse='.(int) $ellipsis->inVendor; $ellipsisTail = $ellipsis->attr['ellipsis-tail'] ?? 0; $ellipsis = $ellipsis->attr['ellipsis'] ?? 0; if (is_file($f['file']) && 0 <= self::$srcContext) { if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { $template = null; if (isset($f['object'])) { $template = $f['object']; } elseif ((new \ReflectionClass($f['class']))->isInstantiable()) { $template = unserialize(sprintf('O:%d:"%s":0:{}', \strlen($f['class']), $f['class'])); } if (null !== $template) { $ellipsis = 0; $templateSrc = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : ''); $templateInfo = $template->getDebugInfo(); if (isset($templateInfo[$f['line']])) { if (!method_exists($template, 'getSourceContext') || !is_file($templatePath = $template->getSourceContext()->getPath())) { $templatePath = null; } if ($templateSrc) { $src = self::extractSource($templateSrc, $templateInfo[$f['line']], self::$srcContext, 'twig', $templatePath, $f); $srcKey = ($templatePath ?: $template->getTemplateName()).':'.$templateInfo[$f['line']]; } } } } if ($srcKey == $f['file']) { $src = self::extractSource(file_get_contents($f['file']), $f['line'], self::$srcContext, 'php', $f['file'], $f); $srcKey .= ':'.$f['line']; if ($ellipsis) { $ellipsis += 1 + \strlen($f['line']); } } $srcAttr .= sprintf('&separator= &file=%s&line=%d', rawurlencode($f['file']), $f['line']); } else { $srcAttr .= '&separator=:'; } $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(["\0~$srcAttr\0$srcKey" => $src]); } } unset($a[$prefix.'args'], $a[$prefix.'line'], $a[$prefix.'file']); if ($frame->inTraceStub) { unset($a[$prefix.'class'], $a[$prefix.'type'], $a[$prefix.'function']); } foreach ($a as $k => $v) { if (!$v) { unset($a[$k]); } } if ($frame->keepArgs && !empty($f['args'])) { $a[$prefix.'arguments'] = new ArgsStub($f['args'], $f['function'], $f['class']); } return $a; } private static function filterExceptionArray(string $xClass, array $a, string $xPrefix, int $filter): array { if (isset($a[$xPrefix.'trace'])) { $trace = $a[$xPrefix.'trace']; unset($a[$xPrefix.'trace']); // Ensures the trace is always last } else { $trace = []; } if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) { if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); } $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); } if (empty($a[$xPrefix.'previous'])) { unset($a[$xPrefix.'previous']); } unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']); if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) { $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $a[Caster::PREFIX_PROTECTED.'message']); } if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { $a[Caster::PREFIX_PROTECTED.'file'] = new LinkStub($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); } return $a; } private static function traceUnshift(array &$trace, ?string $class, string $file, int $line): void { if (isset($trace[0]['file'], $trace[0]['line']) && $trace[0]['file'] === $file && $trace[0]['line'] === $line) { return; } array_unshift($trace, [ 'function' => $class ? 'new '.$class : null, 'file' => $file, 'line' => $line, ]); } private static function extractSource(string $srcLines, int $line, int $srcContext, string $lang, ?string $file, array $frame): EnumStub { $srcLines = explode("\n", $srcLines); $src = []; for ($i = $line - 1 - $srcContext; $i <= $line - 1 + $srcContext; ++$i) { $src[] = ($srcLines[$i] ?? '')."\n"; } if ($frame['function'] ?? false) { $stub = new CutStub(new \stdClass()); $stub->class = (isset($frame['class']) ? $frame['class'].$frame['type'] : '').$frame['function']; $stub->type = Stub::TYPE_OBJECT; $stub->attr['cut_hash'] = true; $stub->attr['file'] = $frame['file']; $stub->attr['line'] = $frame['line']; try { $caller = isset($frame['class']) ? new \ReflectionMethod($frame['class'], $frame['function']) : new \ReflectionFunction($frame['function']); $stub->class .= ReflectionCaster::getSignature(ReflectionCaster::castFunctionAbstract($caller, [], $stub, true, Caster::EXCLUDE_VERBOSE)); if ($f = $caller->getFileName()) { $stub->attr['file'] = $f; $stub->attr['line'] = $caller->getStartLine(); } } catch (\ReflectionException $e) { // ignore fake class/function } $srcLines = ["\0~separator=\0" => $stub]; } else { $stub = null; $srcLines = []; } $ltrim = 0; do { $pad = null; for ($i = $srcContext << 1; $i >= 0; --$i) { if (isset($src[$i][$ltrim]) && "\r" !== ($c = $src[$i][$ltrim]) && "\n" !== $c) { if (null === $pad) { $pad = $c; } if ((' ' !== $c && "\t" !== $c) || $pad !== $c) { break; } } } ++$ltrim; } while (0 > $i && null !== $pad); --$ltrim; foreach ($src as $i => $c) { if ($ltrim) { $c = isset($c[$ltrim]) && "\r" !== $c[$ltrim] ? substr($c, $ltrim) : ltrim($c, " \t"); } $c = substr($c, 0, -1); if ($i !== $srcContext) { $c = new ConstStub('default', $c); } else { $c = new ConstStub($c, $stub ? 'in '.$stub->class : ''); if (null !== $file) { $c->attr['file'] = $file; $c->attr['line'] = $line; } } $c->attr['lang'] = $lang; $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c; } return new EnumStub($srcLines); } } var-dumper/Caster/GmpCaster.php000064400000001355150432043210012443 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts GMP objects to array representation. * * @author Hamza Amrouche * @author Nicolas Grekas * * @final */ class GmpCaster { public static function castGmp(\GMP $gmp, array $a, Stub $stub, bool $isNested, int $filter): array { $a[Caster::PREFIX_VIRTUAL.'value'] = new ConstStub(gmp_strval($gmp), gmp_strval($gmp)); return $a; } } var-dumper/Caster/DoctrineCaster.php000064400000003210150432043210013457 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Doctrine\Common\Proxy\Proxy as CommonProxy; use Doctrine\ORM\PersistentCollection; use Doctrine\ORM\Proxy\Proxy as OrmProxy; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts Doctrine related classes to array representation. * * @author Nicolas Grekas * * @final */ class DoctrineCaster { public static function castCommonProxy(CommonProxy $proxy, array $a, Stub $stub, bool $isNested) { foreach (['__cloner__', '__initializer__'] as $k) { if (\array_key_exists($k, $a)) { unset($a[$k]); ++$stub->cut; } } return $a; } public static function castOrmProxy(OrmProxy $proxy, array $a, Stub $stub, bool $isNested) { foreach (['_entityPersister', '_identifier'] as $k) { if (\array_key_exists($k = "\0Doctrine\\ORM\\Proxy\\Proxy\0".$k, $a)) { unset($a[$k]); ++$stub->cut; } } return $a; } public static function castPersistentCollection(PersistentCollection $coll, array $a, Stub $stub, bool $isNested) { foreach (['snapshot', 'association', 'typeClass'] as $k) { if (\array_key_exists($k = "\0Doctrine\\ORM\\PersistentCollection\0".$k, $a)) { $a[$k] = new CutStub($a[$k]); } } return $a; } } var-dumper/Caster/ClassStub.php000064400000007371150432043210012465 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Represents a PHP class identifier. * * @author Nicolas Grekas */ class ClassStub extends ConstStub { /** * @param string $identifier A PHP identifier, e.g. a class, method, interface, etc. name * @param callable $callable The callable targeted by the identifier when it is ambiguous or not a real PHP identifier */ public function __construct(string $identifier, $callable = null) { $this->value = $identifier; try { if (null !== $callable) { if ($callable instanceof \Closure) { $r = new \ReflectionFunction($callable); } elseif (\is_object($callable)) { $r = [$callable, '__invoke']; } elseif (\is_array($callable)) { $r = $callable; } elseif (false !== $i = strpos($callable, '::')) { $r = [substr($callable, 0, $i), substr($callable, 2 + $i)]; } else { $r = new \ReflectionFunction($callable); } } elseif (0 < $i = strpos($identifier, '::') ?: strpos($identifier, '->')) { $r = [substr($identifier, 0, $i), substr($identifier, 2 + $i)]; } else { $r = new \ReflectionClass($identifier); } if (\is_array($r)) { try { $r = new \ReflectionMethod($r[0], $r[1]); } catch (\ReflectionException $e) { $r = new \ReflectionClass($r[0]); } } if (str_contains($identifier, "@anonymous\0")) { $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) { return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0]; }, $identifier); } if (null !== $callable && $r instanceof \ReflectionFunctionAbstract) { $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE); $s = ReflectionCaster::getSignature($s); if (str_ends_with($identifier, '()')) { $this->value = substr_replace($identifier, $s, -2); } else { $this->value .= $s; } } } catch (\ReflectionException $e) { return; } finally { if (0 < $i = strrpos($this->value, '\\')) { $this->attr['ellipsis'] = \strlen($this->value) - $i; $this->attr['ellipsis-type'] = 'class'; $this->attr['ellipsis-tail'] = 1; } } if ($f = $r->getFileName()) { $this->attr['file'] = $f; $this->attr['line'] = $r->getStartLine(); } } public static function wrapCallable($callable) { if (\is_object($callable) || !\is_callable($callable)) { return $callable; } if (!\is_array($callable)) { $callable = new static($callable, $callable); } elseif (\is_string($callable[0])) { $callable[0] = new static($callable[0], $callable); } else { $callable[1] = new static($callable[1], $callable); } return $callable; } } var-dumper/Caster/RdKafkaCaster.php000064400000011024150432043210013215 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use RdKafka\Conf; use RdKafka\Exception as RdKafkaException; use RdKafka\KafkaConsumer; use RdKafka\Message; use RdKafka\Metadata\Broker as BrokerMetadata; use RdKafka\Metadata\Collection as CollectionMetadata; use RdKafka\Metadata\Partition as PartitionMetadata; use RdKafka\Metadata\Topic as TopicMetadata; use RdKafka\Topic; use RdKafka\TopicConf; use RdKafka\TopicPartition; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts RdKafka related classes to array representation. * * @author Romain Neutron */ class RdKafkaCaster { public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; try { $assignment = $c->getAssignment(); } catch (RdKafkaException $e) { $assignment = []; } $a += [ $prefix.'subscription' => $c->getSubscription(), $prefix.'assignment' => $assignment, ]; $a += self::extractMetadata($c); return $a; } public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'name' => $c->getName(), ]; return $a; } public static function castTopicPartition(TopicPartition $c, array $a) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'offset' => $c->getOffset(), $prefix.'partition' => $c->getPartition(), $prefix.'topic' => $c->getTopic(), ]; return $a; } public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'errstr' => $c->errstr(), ]; return $a; } public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; foreach ($c->dump() as $key => $value) { $a[$prefix.$key] = $value; } return $a; } public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; foreach ($c->dump() as $key => $value) { $a[$prefix.$key] = $value; } return $a; } public static function castRdKafka(\RdKafka $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'out_q_len' => $c->getOutQLen(), ]; $a += self::extractMetadata($c); return $a; } public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested) { $a += iterator_to_array($c); return $a; } public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'name' => $c->getTopic(), $prefix.'partitions' => $c->getPartitions(), ]; return $a; } public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'id' => $c->getId(), $prefix.'err' => $c->getErr(), $prefix.'leader' => $c->getLeader(), ]; return $a; } public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $a += [ $prefix.'id' => $c->getId(), $prefix.'host' => $c->getHost(), $prefix.'port' => $c->getPort(), ]; return $a; } private static function extractMetadata($c) { $prefix = Caster::PREFIX_VIRTUAL; try { $m = $c->getMetadata(true, null, 500); } catch (RdKafkaException $e) { return []; } return [ $prefix.'orig_broker_id' => $m->getOrigBrokerId(), $prefix.'orig_broker_name' => $m->getOrigBrokerName(), $prefix.'brokers' => $m->getBrokers(), $prefix.'topics' => $m->getTopics(), ]; } } var-dumper/Caster/ResourceCaster.php000064400000006261150432043210013510 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts common resource types to array representation. * * @author Nicolas Grekas * * @final */ class ResourceCaster { /** * @param \CurlHandle|resource $h */ public static function castCurl($h, array $a, Stub $stub, bool $isNested): array { return curl_getinfo($h); } public static function castDba($dba, array $a, Stub $stub, bool $isNested) { $list = dba_list(); $a['file'] = $list[(int) $dba]; return $a; } public static function castProcess($process, array $a, Stub $stub, bool $isNested) { return proc_get_status($process); } public static function castStream($stream, array $a, Stub $stub, bool $isNested) { $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested); if ($a['uri'] ?? false) { $a['uri'] = new LinkStub($a['uri']); } return $a; } public static function castStreamContext($stream, array $a, Stub $stub, bool $isNested) { return @stream_context_get_params($stream) ?: $a; } public static function castGd($gd, array $a, Stub $stub, bool $isNested) { $a['size'] = imagesx($gd).'x'.imagesy($gd); $a['trueColor'] = imageistruecolor($gd); return $a; } public static function castMysqlLink($h, array $a, Stub $stub, bool $isNested) { $a['host'] = mysql_get_host_info($h); $a['protocol'] = mysql_get_proto_info($h); $a['server'] = mysql_get_server_info($h); return $a; } public static function castOpensslX509($h, array $a, Stub $stub, bool $isNested) { $stub->cut = -1; $info = openssl_x509_parse($h, false); $pin = openssl_pkey_get_public($h); $pin = openssl_pkey_get_details($pin)['key']; $pin = \array_slice(explode("\n", $pin), 1, -2); $pin = base64_decode(implode('', $pin)); $pin = base64_encode(hash('sha256', $pin, true)); $a += [ 'subject' => new EnumStub(array_intersect_key($info['subject'], ['organizationName' => true, 'commonName' => true])), 'issuer' => new EnumStub(array_intersect_key($info['issuer'], ['organizationName' => true, 'commonName' => true])), 'expiry' => new ConstStub(date(\DateTime::ISO8601, $info['validTo_time_t']), $info['validTo_time_t']), 'fingerprint' => new EnumStub([ 'md5' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'md5')), 2, ':', true)), 'sha1' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha1')), 2, ':', true)), 'sha256' => new ConstStub(wordwrap(strtoupper(openssl_x509_fingerprint($h, 'sha256')), 2, ':', true)), 'pin-sha256' => new ConstStub($pin), ]), ]; return $a; } } var-dumper/Caster/ArgsStub.php000064400000004366150432043210012315 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Represents a list of function arguments. * * @author Nicolas Grekas */ class ArgsStub extends EnumStub { private static $parameters = []; public function __construct(array $args, string $function, ?string $class) { [$variadic, $params] = self::getParameters($function, $class); $values = []; foreach ($args as $k => $v) { $values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v; } if (null === $params) { parent::__construct($values, false); return; } if (\count($values) < \count($params)) { $params = \array_slice($params, 0, \count($values)); } elseif (\count($values) > \count($params)) { $values[] = new EnumStub(array_splice($values, \count($params)), false); $params[] = $variadic; } if (['...'] === $params) { $this->dumpKeys = false; $this->value = $values[0]->value; } else { $this->value = array_combine($params, $values); } } private static function getParameters(string $function, ?string $class): array { if (isset(self::$parameters[$k = $class.'::'.$function])) { return self::$parameters[$k]; } try { $r = null !== $class ? new \ReflectionMethod($class, $function) : new \ReflectionFunction($function); } catch (\ReflectionException $e) { return [null, null]; } $variadic = '...'; $params = []; foreach ($r->getParameters() as $v) { $k = '$'.$v->name; if ($v->isPassedByReference()) { $k = '&'.$k; } if ($v->isVariadic()) { $variadic .= $k; } else { $params[] = $k; } } return self::$parameters[$k] = [$variadic, $params]; } } var-dumper/Caster/DateCaster.php000064400000011321150432043210012567 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts DateTimeInterface related classes to array representation. * * @author Dany Maillard * * @final */ class DateCaster { private const PERIOD_LIMIT = 3; public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, bool $isNested, int $filter) { $prefix = Caster::PREFIX_VIRTUAL; $location = $d->getTimezone()->getLocation(); $fromNow = (new \DateTime())->diff($d); $title = $d->format('l, F j, Y') ."\n".self::formatInterval($fromNow).' from now' .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') ; unset( $a[Caster::PREFIX_DYNAMIC.'date'], $a[Caster::PREFIX_DYNAMIC.'timezone'], $a[Caster::PREFIX_DYNAMIC.'timezone_type'] ); $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title); $stub->class .= $d->format(' @U'); return $a; } public static function castInterval(\DateInterval $interval, array $a, Stub $stub, bool $isNested, int $filter) { $now = new \DateTimeImmutable('@0', new \DateTimeZone('UTC')); $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp(); $title = number_format($numberOfSeconds, 0, '.', ' ').'s'; $i = [Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)]; return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a; } private static function formatInterval(\DateInterval $i): string { $format = '%R '; if (0 === $i->y && 0 === $i->m && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) { $d = new \DateTimeImmutable('@0', new \DateTimeZone('UTC')); $i = $d->diff($d->add($i)); // recalculate carry over points $format .= 0 < $i->days ? '%ad ' : ''; } else { $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : ''); } $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : ''; $format = '%R ' === $format ? '0s' : $format; return $i->format(rtrim($format)); } public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, bool $isNested, int $filter) { $location = $timeZone->getLocation(); $formatted = (new \DateTime('now', $timeZone))->format($location ? 'e (P)' : 'P'); $title = $location && \extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code']) : ''; $z = [Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)]; return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; } public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, bool $isNested, int $filter) { $dates = []; foreach (clone $p as $i => $d) { if (self::PERIOD_LIMIT === $i) { $now = new \DateTimeImmutable('now', new \DateTimeZone('UTC')); $dates[] = sprintf('%s more', ($end = $p->getEndDate()) ? ceil(($end->format('U.u') - $d->format('U.u')) / ((int) $now->add($p->getDateInterval())->format('U.u') - (int) $now->format('U.u'))) : $p->recurrences - $i ); break; } $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d)); } $period = sprintf( 'every %s, from %s (%s) %s', self::formatInterval($p->getDateInterval()), self::formatDateTime($p->getStartDate()), $p->include_start_date ? 'included' : 'excluded', ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end) : 'recurring '.$p->recurrences.' time/s' ); $p = [Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))]; return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a; } private static function formatDateTime(\DateTimeInterface $d, string $extra = ''): string { return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra); } private static function formatSeconds(string $s, string $us): string { return sprintf('%02d.%s', $s, 0 === ($len = \strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); } } var-dumper/Caster/MemcachedCaster.php000064400000004451150432043210013566 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Jan Schädlich * * @final */ class MemcachedCaster { private static $optionConstants; private static $defaultOptions; public static function castMemcached(\Memcached $c, array $a, Stub $stub, bool $isNested) { $a += [ Caster::PREFIX_VIRTUAL.'servers' => $c->getServerList(), Caster::PREFIX_VIRTUAL.'options' => new EnumStub( self::getNonDefaultOptions($c) ), ]; return $a; } private static function getNonDefaultOptions(\Memcached $c): array { self::$defaultOptions = self::$defaultOptions ?? self::discoverDefaultOptions(); self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); $nonDefaultOptions = []; foreach (self::$optionConstants as $constantKey => $value) { if (self::$defaultOptions[$constantKey] !== $option = $c->getOption($value)) { $nonDefaultOptions[$constantKey] = $option; } } return $nonDefaultOptions; } private static function discoverDefaultOptions(): array { $defaultMemcached = new \Memcached(); $defaultMemcached->addServer('127.0.0.1', 11211); $defaultOptions = []; self::$optionConstants = self::$optionConstants ?? self::getOptionConstants(); foreach (self::$optionConstants as $constantKey => $value) { $defaultOptions[$constantKey] = $defaultMemcached->getOption($value); } return $defaultOptions; } private static function getOptionConstants(): array { $reflectedMemcached = new \ReflectionClass(\Memcached::class); $optionConstants = []; foreach ($reflectedMemcached->getConstants() as $constantKey => $value) { if (str_starts_with($constantKey, 'OPT_')) { $optionConstants[$constantKey] = $value; } } return $optionConstants; } } var-dumper/Caster/SplCaster.php000064400000017217150432043210012462 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts SPL related classes to array representation. * * @author Nicolas Grekas * * @final */ class SplCaster { private const SPL_FILE_OBJECT_FLAGS = [ \SplFileObject::DROP_NEW_LINE => 'DROP_NEW_LINE', \SplFileObject::READ_AHEAD => 'READ_AHEAD', \SplFileObject::SKIP_EMPTY => 'SKIP_EMPTY', \SplFileObject::READ_CSV => 'READ_CSV', ]; public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, bool $isNested) { return self::castSplArray($c, $a, $stub, $isNested); } public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, bool $isNested) { return self::castSplArray($c, $a, $stub, $isNested); } public static function castHeap(\Iterator $c, array $a, Stub $stub, bool $isNested) { $a += [ Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c), ]; return $a; } public static function castDoublyLinkedList(\SplDoublyLinkedList $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $mode = $c->getIteratorMode(); $c->setIteratorMode(\SplDoublyLinkedList::IT_MODE_KEEP | $mode & ~\SplDoublyLinkedList::IT_MODE_DELETE); $a += [ $prefix.'mode' => new ConstStub((($mode & \SplDoublyLinkedList::IT_MODE_LIFO) ? 'IT_MODE_LIFO' : 'IT_MODE_FIFO').' | '.(($mode & \SplDoublyLinkedList::IT_MODE_DELETE) ? 'IT_MODE_DELETE' : 'IT_MODE_KEEP'), $mode), $prefix.'dllist' => iterator_to_array($c), ]; $c->setIteratorMode($mode); return $a; } public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool $isNested) { static $map = [ 'path' => 'getPath', 'filename' => 'getFilename', 'basename' => 'getBasename', 'pathname' => 'getPathname', 'extension' => 'getExtension', 'realPath' => 'getRealPath', 'aTime' => 'getATime', 'mTime' => 'getMTime', 'cTime' => 'getCTime', 'inode' => 'getInode', 'size' => 'getSize', 'perms' => 'getPerms', 'owner' => 'getOwner', 'group' => 'getGroup', 'type' => 'getType', 'writable' => 'isWritable', 'readable' => 'isReadable', 'executable' => 'isExecutable', 'file' => 'isFile', 'dir' => 'isDir', 'link' => 'isLink', 'linkTarget' => 'getLinkTarget', ]; $prefix = Caster::PREFIX_VIRTUAL; unset($a["\0SplFileInfo\0fileName"]); unset($a["\0SplFileInfo\0pathName"]); if (\PHP_VERSION_ID < 80000) { if (false === $c->getPathname()) { $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; return $a; } } else { try { $c->isReadable(); } catch (\RuntimeException $e) { if ('Object not initialized' !== $e->getMessage()) { throw $e; } $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; return $a; } catch (\Error $e) { if ('Object not initialized' !== $e->getMessage()) { throw $e; } $a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state'; return $a; } } foreach ($map as $key => $accessor) { try { $a[$prefix.$key] = $c->$accessor(); } catch (\Exception $e) { } } if ($a[$prefix.'realPath'] ?? false) { $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']); } if (isset($a[$prefix.'perms'])) { $a[$prefix.'perms'] = new ConstStub(sprintf('0%o', $a[$prefix.'perms']), $a[$prefix.'perms']); } static $mapDate = ['aTime', 'mTime', 'cTime']; foreach ($mapDate as $key) { if (isset($a[$prefix.$key])) { $a[$prefix.$key] = new ConstStub(date('Y-m-d H:i:s', $a[$prefix.$key]), $a[$prefix.$key]); } } return $a; } public static function castFileObject(\SplFileObject $c, array $a, Stub $stub, bool $isNested) { static $map = [ 'csvControl' => 'getCsvControl', 'flags' => 'getFlags', 'maxLineLen' => 'getMaxLineLen', 'fstat' => 'fstat', 'eof' => 'eof', 'key' => 'key', ]; $prefix = Caster::PREFIX_VIRTUAL; foreach ($map as $key => $accessor) { try { $a[$prefix.$key] = $c->$accessor(); } catch (\Exception $e) { } } if (isset($a[$prefix.'flags'])) { $flagsArray = []; foreach (self::SPL_FILE_OBJECT_FLAGS as $value => $name) { if ($a[$prefix.'flags'] & $value) { $flagsArray[] = $name; } } $a[$prefix.'flags'] = new ConstStub(implode('|', $flagsArray), $a[$prefix.'flags']); } if (isset($a[$prefix.'fstat'])) { $a[$prefix.'fstat'] = new CutArrayStub($a[$prefix.'fstat'], ['dev', 'ino', 'nlink', 'rdev', 'blksize', 'blocks']); } return $a; } public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $stub, bool $isNested) { $storage = []; unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 unset($a["\0SplObjectStorage\0storage"]); $clone = clone $c; foreach ($clone as $obj) { $storage[] = [ 'object' => $obj, 'info' => $clone->getInfo(), ]; } $a += [ Caster::PREFIX_VIRTUAL.'storage' => $storage, ]; return $a; } public static function castOuterIterator(\OuterIterator $c, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'innerIterator'] = $c->getInnerIterator(); return $a; } public static function castWeakReference(\WeakReference $c, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'object'] = $c->get(); return $a; } private static function castSplArray($c, array $a, Stub $stub, bool $isNested): array { $prefix = Caster::PREFIX_VIRTUAL; $flags = $c->getFlags(); if (!($flags & \ArrayObject::STD_PROP_LIST)) { $c->setFlags(\ArrayObject::STD_PROP_LIST); $a = Caster::castObject($c, \get_class($c), method_exists($c, '__debugInfo'), $stub->class); $c->setFlags($flags); } if (\PHP_VERSION_ID < 70400) { $a[$prefix.'storage'] = $c->getArrayCopy(); } $a += [ $prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST), $prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS), ]; if ($c instanceof \ArrayObject) { $a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass()); } return $a; } } var-dumper/Caster/DsPairStub.php000064400000001145150432043210012573 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Nicolas Grekas */ class DsPairStub extends Stub { public function __construct($key, $value) { $this->value = [ Caster::PREFIX_VIRTUAL.'key' => $key, Caster::PREFIX_VIRTUAL.'value' => $value, ]; } } var-dumper/Caster/Caster.php000064400000013565150432043210012005 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Helper for filtering out properties in casters. * * @author Nicolas Grekas * * @final */ class Caster { public const EXCLUDE_VERBOSE = 1; public const EXCLUDE_VIRTUAL = 2; public const EXCLUDE_DYNAMIC = 4; public const EXCLUDE_PUBLIC = 8; public const EXCLUDE_PROTECTED = 16; public const EXCLUDE_PRIVATE = 32; public const EXCLUDE_NULL = 64; public const EXCLUDE_EMPTY = 128; public const EXCLUDE_NOT_IMPORTANT = 256; public const EXCLUDE_STRICT = 512; public const PREFIX_VIRTUAL = "\0~\0"; public const PREFIX_DYNAMIC = "\0+\0"; public const PREFIX_PROTECTED = "\0*\0"; /** * Casts objects to arrays and adds the dynamic property prefix. * * @param bool $hasDebugInfo Whether the __debugInfo method exists on $obj or not */ public static function castObject(object $obj, string $class, bool $hasDebugInfo = false, string $debugClass = null): array { if ($hasDebugInfo) { try { $debugInfo = $obj->__debugInfo(); } catch (\Exception $e) { // ignore failing __debugInfo() $hasDebugInfo = false; } } $a = $obj instanceof \Closure ? [] : (array) $obj; if ($obj instanceof \__PHP_Incomplete_Class) { return $a; } if ($a) { static $publicProperties = []; $debugClass = $debugClass ?? get_debug_type($obj); $i = 0; $prefixedKeys = []; foreach ($a as $k => $v) { if ("\0" !== ($k[0] ?? '')) { if (!isset($publicProperties[$class])) { foreach ((new \ReflectionClass($class))->getProperties(\ReflectionProperty::IS_PUBLIC) as $prop) { $publicProperties[$class][$prop->name] = true; } } if (!isset($publicProperties[$class][$k])) { $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; } } elseif ($debugClass !== $class && 1 === strpos($k, $class)) { $prefixedKeys[$i] = "\0".$debugClass.strrchr($k, "\0"); } ++$i; } if ($prefixedKeys) { $keys = array_keys($a); foreach ($prefixedKeys as $i => $k) { $keys[$i] = $k; } $a = array_combine($keys, $a); } } if ($hasDebugInfo && \is_array($debugInfo)) { foreach ($debugInfo as $k => $v) { if (!isset($k[0]) || "\0" !== $k[0]) { if (\array_key_exists(self::PREFIX_DYNAMIC.$k, $a)) { continue; } $k = self::PREFIX_VIRTUAL.$k; } unset($a[$k]); $a[$k] = $v; } } return $a; } /** * Filters out the specified properties. * * By default, a single match in the $filter bit field filters properties out, following an "or" logic. * When EXCLUDE_STRICT is set, an "and" logic is applied: all bits must match for a property to be removed. * * @param array $a The array containing the properties to filter * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set * @param int &$count Set to the number of removed properties */ public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array { $count = 0; foreach ($a as $k => $v) { $type = self::EXCLUDE_STRICT & $filter; if (null === $v) { $type |= self::EXCLUDE_NULL & $filter; $type |= self::EXCLUDE_EMPTY & $filter; } elseif (false === $v || '' === $v || '0' === $v || 0 === $v || 0.0 === $v || [] === $v) { $type |= self::EXCLUDE_EMPTY & $filter; } if ((self::EXCLUDE_NOT_IMPORTANT & $filter) && !\in_array($k, $listedProperties, true)) { $type |= self::EXCLUDE_NOT_IMPORTANT; } if ((self::EXCLUDE_VERBOSE & $filter) && \in_array($k, $listedProperties, true)) { $type |= self::EXCLUDE_VERBOSE; } if (!isset($k[1]) || "\0" !== $k[0]) { $type |= self::EXCLUDE_PUBLIC & $filter; } elseif ('~' === $k[1]) { $type |= self::EXCLUDE_VIRTUAL & $filter; } elseif ('+' === $k[1]) { $type |= self::EXCLUDE_DYNAMIC & $filter; } elseif ('*' === $k[1]) { $type |= self::EXCLUDE_PROTECTED & $filter; } else { $type |= self::EXCLUDE_PRIVATE & $filter; } if ((self::EXCLUDE_STRICT & $filter) ? $type === $filter : $type) { unset($a[$k]); ++$count; } } return $a; } public static function castPhpIncompleteClass(\__PHP_Incomplete_Class $c, array $a, Stub $stub, bool $isNested): array { if (isset($a['__PHP_Incomplete_Class_Name'])) { $stub->class .= '('.$a['__PHP_Incomplete_Class_Name'].')'; unset($a['__PHP_Incomplete_Class_Name']); } return $a; } } var-dumper/Caster/ConstStub.php000064400000001354150432043210012501 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Represents a PHP constant and its value. * * @author Nicolas Grekas */ class ConstStub extends Stub { public function __construct(string $name, $value = null) { $this->class = $name; $this->value = 1 < \func_num_args() ? $value : $name; } /** * @return string */ public function __toString() { return (string) $this->value; } } var-dumper/Caster/EnumStub.php000064400000001175150432043210012320 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Represents an enumeration of values. * * @author Nicolas Grekas */ class EnumStub extends Stub { public $dumpKeys = true; public function __construct(array $values, bool $dumpKeys = true) { $this->value = $values; $this->dumpKeys = $dumpKeys; } } var-dumper/Caster/ImgStub.php000064400000001175150432043210012130 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; /** * @author Grégoire Pineau */ class ImgStub extends ConstStub { public function __construct(string $data, string $contentType, string $size = '') { $this->value = ''; $this->attr['img-data'] = $data; $this->attr['img-size'] = $size; $this->attr['content-type'] = $contentType; } } var-dumper/Caster/CutStub.php000064400000003611150432043210012144 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Represents the main properties of a PHP variable, pre-casted by a caster. * * @author Nicolas Grekas */ class CutStub extends Stub { public function __construct($value) { $this->value = $value; switch (\gettype($value)) { case 'object': $this->type = self::TYPE_OBJECT; $this->class = \get_class($value); if ($value instanceof \Closure) { ReflectionCaster::castClosure($value, [], $this, true, Caster::EXCLUDE_VERBOSE); } $this->cut = -1; break; case 'array': $this->type = self::TYPE_ARRAY; $this->class = self::ARRAY_ASSOC; $this->cut = $this->value = \count($value); break; case 'resource': case 'unknown type': case 'resource (closed)': $this->type = self::TYPE_RESOURCE; $this->handle = (int) $value; if ('Unknown' === $this->class = @get_resource_type($value)) { $this->class = 'Closed'; } $this->cut = -1; break; case 'string': $this->type = self::TYPE_STRING; $this->class = preg_match('//u', $value) ? self::STRING_UTF8 : self::STRING_BINARY; $this->cut = self::STRING_BINARY === $this->class ? \strlen($value) : mb_strlen($value, 'UTF-8'); $this->value = ''; break; } } } var-dumper/Caster/XmlResourceCaster.php000064400000004761150432043210014174 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts XML resources to array representation. * * @author Nicolas Grekas * * @final */ class XmlResourceCaster { private const XML_ERRORS = [ \XML_ERROR_NONE => 'XML_ERROR_NONE', \XML_ERROR_NO_MEMORY => 'XML_ERROR_NO_MEMORY', \XML_ERROR_SYNTAX => 'XML_ERROR_SYNTAX', \XML_ERROR_NO_ELEMENTS => 'XML_ERROR_NO_ELEMENTS', \XML_ERROR_INVALID_TOKEN => 'XML_ERROR_INVALID_TOKEN', \XML_ERROR_UNCLOSED_TOKEN => 'XML_ERROR_UNCLOSED_TOKEN', \XML_ERROR_PARTIAL_CHAR => 'XML_ERROR_PARTIAL_CHAR', \XML_ERROR_TAG_MISMATCH => 'XML_ERROR_TAG_MISMATCH', \XML_ERROR_DUPLICATE_ATTRIBUTE => 'XML_ERROR_DUPLICATE_ATTRIBUTE', \XML_ERROR_JUNK_AFTER_DOC_ELEMENT => 'XML_ERROR_JUNK_AFTER_DOC_ELEMENT', \XML_ERROR_PARAM_ENTITY_REF => 'XML_ERROR_PARAM_ENTITY_REF', \XML_ERROR_UNDEFINED_ENTITY => 'XML_ERROR_UNDEFINED_ENTITY', \XML_ERROR_RECURSIVE_ENTITY_REF => 'XML_ERROR_RECURSIVE_ENTITY_REF', \XML_ERROR_ASYNC_ENTITY => 'XML_ERROR_ASYNC_ENTITY', \XML_ERROR_BAD_CHAR_REF => 'XML_ERROR_BAD_CHAR_REF', \XML_ERROR_BINARY_ENTITY_REF => 'XML_ERROR_BINARY_ENTITY_REF', \XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF => 'XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF', \XML_ERROR_MISPLACED_XML_PI => 'XML_ERROR_MISPLACED_XML_PI', \XML_ERROR_UNKNOWN_ENCODING => 'XML_ERROR_UNKNOWN_ENCODING', \XML_ERROR_INCORRECT_ENCODING => 'XML_ERROR_INCORRECT_ENCODING', \XML_ERROR_UNCLOSED_CDATA_SECTION => 'XML_ERROR_UNCLOSED_CDATA_SECTION', \XML_ERROR_EXTERNAL_ENTITY_HANDLING => 'XML_ERROR_EXTERNAL_ENTITY_HANDLING', ]; public static function castXml($h, array $a, Stub $stub, bool $isNested) { $a['current_byte_index'] = xml_get_current_byte_index($h); $a['current_column_number'] = xml_get_current_column_number($h); $a['current_line_number'] = xml_get_current_line_number($h); $a['error_code'] = xml_get_error_code($h); if (isset(self::XML_ERRORS[$a['error_code']])) { $a['error_code'] = new ConstStub(self::XML_ERRORS[$a['error_code']], $a['error_code']); } return $a; } } var-dumper/Caster/IntlCaster.php000064400000021345150432043210012627 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Nicolas Grekas * @author Jan Schädlich * * @final */ class IntlCaster { public static function castMessageFormatter(\MessageFormatter $c, array $a, Stub $stub, bool $isNested) { $a += [ Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), ]; return self::castError($c, $a); } public static function castNumberFormatter(\NumberFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) { $a += [ Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), ]; if ($filter & Caster::EXCLUDE_VERBOSE) { $stub->cut += 3; return self::castError($c, $a); } $a += [ Caster::PREFIX_VIRTUAL.'attributes' => new EnumStub( [ 'PARSE_INT_ONLY' => $c->getAttribute(\NumberFormatter::PARSE_INT_ONLY), 'GROUPING_USED' => $c->getAttribute(\NumberFormatter::GROUPING_USED), 'DECIMAL_ALWAYS_SHOWN' => $c->getAttribute(\NumberFormatter::DECIMAL_ALWAYS_SHOWN), 'MAX_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_INTEGER_DIGITS), 'MIN_INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_INTEGER_DIGITS), 'INTEGER_DIGITS' => $c->getAttribute(\NumberFormatter::INTEGER_DIGITS), 'MAX_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS), 'MIN_FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS), 'FRACTION_DIGITS' => $c->getAttribute(\NumberFormatter::FRACTION_DIGITS), 'MULTIPLIER' => $c->getAttribute(\NumberFormatter::MULTIPLIER), 'GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::GROUPING_SIZE), 'ROUNDING_MODE' => $c->getAttribute(\NumberFormatter::ROUNDING_MODE), 'ROUNDING_INCREMENT' => $c->getAttribute(\NumberFormatter::ROUNDING_INCREMENT), 'FORMAT_WIDTH' => $c->getAttribute(\NumberFormatter::FORMAT_WIDTH), 'PADDING_POSITION' => $c->getAttribute(\NumberFormatter::PADDING_POSITION), 'SECONDARY_GROUPING_SIZE' => $c->getAttribute(\NumberFormatter::SECONDARY_GROUPING_SIZE), 'SIGNIFICANT_DIGITS_USED' => $c->getAttribute(\NumberFormatter::SIGNIFICANT_DIGITS_USED), 'MIN_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS), 'MAX_SIGNIFICANT_DIGITS' => $c->getAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS), 'LENIENT_PARSE' => $c->getAttribute(\NumberFormatter::LENIENT_PARSE), ] ), Caster::PREFIX_VIRTUAL.'text_attributes' => new EnumStub( [ 'POSITIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_PREFIX), 'POSITIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::POSITIVE_SUFFIX), 'NEGATIVE_PREFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_PREFIX), 'NEGATIVE_SUFFIX' => $c->getTextAttribute(\NumberFormatter::NEGATIVE_SUFFIX), 'PADDING_CHARACTER' => $c->getTextAttribute(\NumberFormatter::PADDING_CHARACTER), 'CURRENCY_CODE' => $c->getTextAttribute(\NumberFormatter::CURRENCY_CODE), 'DEFAULT_RULESET' => $c->getTextAttribute(\NumberFormatter::DEFAULT_RULESET), 'PUBLIC_RULESETS' => $c->getTextAttribute(\NumberFormatter::PUBLIC_RULESETS), ] ), Caster::PREFIX_VIRTUAL.'symbols' => new EnumStub( [ 'DECIMAL_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL), 'GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL), 'PATTERN_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::PATTERN_SEPARATOR_SYMBOL), 'PERCENT_SYMBOL' => $c->getSymbol(\NumberFormatter::PERCENT_SYMBOL), 'ZERO_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::ZERO_DIGIT_SYMBOL), 'DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::DIGIT_SYMBOL), 'MINUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL), 'PLUS_SIGN_SYMBOL' => $c->getSymbol(\NumberFormatter::PLUS_SIGN_SYMBOL), 'CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::CURRENCY_SYMBOL), 'INTL_CURRENCY_SYMBOL' => $c->getSymbol(\NumberFormatter::INTL_CURRENCY_SYMBOL), 'MONETARY_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL), 'EXPONENTIAL_SYMBOL' => $c->getSymbol(\NumberFormatter::EXPONENTIAL_SYMBOL), 'PERMILL_SYMBOL' => $c->getSymbol(\NumberFormatter::PERMILL_SYMBOL), 'PAD_ESCAPE_SYMBOL' => $c->getSymbol(\NumberFormatter::PAD_ESCAPE_SYMBOL), 'INFINITY_SYMBOL' => $c->getSymbol(\NumberFormatter::INFINITY_SYMBOL), 'NAN_SYMBOL' => $c->getSymbol(\NumberFormatter::NAN_SYMBOL), 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL), 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL), ] ), ]; return self::castError($c, $a); } public static function castIntlTimeZone(\IntlTimeZone $c, array $a, Stub $stub, bool $isNested) { $a += [ Caster::PREFIX_VIRTUAL.'display_name' => $c->getDisplayName(), Caster::PREFIX_VIRTUAL.'id' => $c->getID(), Caster::PREFIX_VIRTUAL.'raw_offset' => $c->getRawOffset(), ]; if ($c->useDaylightTime()) { $a += [ Caster::PREFIX_VIRTUAL.'dst_savings' => $c->getDSTSavings(), ]; } return self::castError($c, $a); } public static function castIntlCalendar(\IntlCalendar $c, array $a, Stub $stub, bool $isNested, int $filter = 0) { $a += [ Caster::PREFIX_VIRTUAL.'type' => $c->getType(), Caster::PREFIX_VIRTUAL.'first_day_of_week' => $c->getFirstDayOfWeek(), Caster::PREFIX_VIRTUAL.'minimal_days_in_first_week' => $c->getMinimalDaysInFirstWeek(), Caster::PREFIX_VIRTUAL.'repeated_wall_time_option' => $c->getRepeatedWallTimeOption(), Caster::PREFIX_VIRTUAL.'skipped_wall_time_option' => $c->getSkippedWallTimeOption(), Caster::PREFIX_VIRTUAL.'time' => $c->getTime(), Caster::PREFIX_VIRTUAL.'in_daylight_time' => $c->inDaylightTime(), Caster::PREFIX_VIRTUAL.'is_lenient' => $c->isLenient(), Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), ]; return self::castError($c, $a); } public static function castIntlDateFormatter(\IntlDateFormatter $c, array $a, Stub $stub, bool $isNested, int $filter = 0) { $a += [ Caster::PREFIX_VIRTUAL.'locale' => $c->getLocale(), Caster::PREFIX_VIRTUAL.'pattern' => $c->getPattern(), Caster::PREFIX_VIRTUAL.'calendar' => $c->getCalendar(), Caster::PREFIX_VIRTUAL.'time_zone_id' => $c->getTimeZoneId(), Caster::PREFIX_VIRTUAL.'time_type' => $c->getTimeType(), Caster::PREFIX_VIRTUAL.'date_type' => $c->getDateType(), Caster::PREFIX_VIRTUAL.'calendar_object' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getCalendarObject()) : $c->getCalendarObject(), Caster::PREFIX_VIRTUAL.'time_zone' => ($filter & Caster::EXCLUDE_VERBOSE) ? new CutStub($c->getTimeZone()) : $c->getTimeZone(), ]; return self::castError($c, $a); } private static function castError(object $c, array $a): array { if ($errorCode = $c->getErrorCode()) { $a += [ Caster::PREFIX_VIRTUAL.'error_code' => $errorCode, Caster::PREFIX_VIRTUAL.'error_message' => $c->getErrorMessage(), ]; } return $a; } } var-dumper/Caster/SymfonyCaster.php000064400000005312150432043210013361 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Uid\Ulid; use Symfony\Component\Uid\Uuid; use Symfony\Component\VarDumper\Cloner\Stub; /** * @final */ class SymfonyCaster { private const REQUEST_GETTERS = [ 'pathInfo' => 'getPathInfo', 'requestUri' => 'getRequestUri', 'baseUrl' => 'getBaseUrl', 'basePath' => 'getBasePath', 'method' => 'getMethod', 'format' => 'getRequestFormat', ]; public static function castRequest(Request $request, array $a, Stub $stub, bool $isNested) { $clone = null; foreach (self::REQUEST_GETTERS as $prop => $getter) { $key = Caster::PREFIX_PROTECTED.$prop; if (\array_key_exists($key, $a) && null === $a[$key]) { if (null === $clone) { $clone = clone $request; } $a[Caster::PREFIX_VIRTUAL.$prop] = $clone->{$getter}(); } } return $a; } public static function castHttpClient($client, array $a, Stub $stub, bool $isNested) { $multiKey = sprintf("\0%s\0multi", \get_class($client)); if (isset($a[$multiKey])) { $a[$multiKey] = new CutStub($a[$multiKey]); } return $a; } public static function castHttpClientResponse($response, array $a, Stub $stub, bool $isNested) { $stub->cut += \count($a); $a = []; foreach ($response->getInfo() as $k => $v) { $a[Caster::PREFIX_VIRTUAL.$k] = $v; } return $a; } public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $uuid->toBase58(); $a[Caster::PREFIX_VIRTUAL.'toBase32'] = $uuid->toBase32(); // symfony/uid >= 5.3 if (method_exists($uuid, 'getDateTime')) { $a[Caster::PREFIX_VIRTUAL.'time'] = $uuid->getDateTime()->format('Y-m-d H:i:s.u \U\T\C'); } return $a; } public static function castUlid(Ulid $ulid, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'toBase58'] = $ulid->toBase58(); $a[Caster::PREFIX_VIRTUAL.'toRfc4122'] = $ulid->toRfc4122(); // symfony/uid >= 5.3 if (method_exists($ulid, 'getDateTime')) { $a[Caster::PREFIX_VIRTUAL.'time'] = $ulid->getDateTime()->format('Y-m-d H:i:s.v \U\T\C'); } return $a; } } var-dumper/Caster/ProxyManagerCaster.php000064400000001321150432043210014325 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use ProxyManager\Proxy\ProxyInterface; use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Nicolas Grekas * * @final */ class ProxyManagerCaster { public static function castProxy(ProxyInterface $c, array $a, Stub $stub, bool $isNested) { if ($parent = get_parent_class($c)) { $stub->class .= ' - '.$parent; } $stub->class .= '@proxy'; return $a; } } var-dumper/Caster/DOMCaster.php000064400000023606150432043210012342 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts DOM related classes to array representation. * * @author Nicolas Grekas * * @final */ class DOMCaster { private const ERROR_CODES = [ \DOM_PHP_ERR => 'DOM_PHP_ERR', \DOM_INDEX_SIZE_ERR => 'DOM_INDEX_SIZE_ERR', \DOMSTRING_SIZE_ERR => 'DOMSTRING_SIZE_ERR', \DOM_HIERARCHY_REQUEST_ERR => 'DOM_HIERARCHY_REQUEST_ERR', \DOM_WRONG_DOCUMENT_ERR => 'DOM_WRONG_DOCUMENT_ERR', \DOM_INVALID_CHARACTER_ERR => 'DOM_INVALID_CHARACTER_ERR', \DOM_NO_DATA_ALLOWED_ERR => 'DOM_NO_DATA_ALLOWED_ERR', \DOM_NO_MODIFICATION_ALLOWED_ERR => 'DOM_NO_MODIFICATION_ALLOWED_ERR', \DOM_NOT_FOUND_ERR => 'DOM_NOT_FOUND_ERR', \DOM_NOT_SUPPORTED_ERR => 'DOM_NOT_SUPPORTED_ERR', \DOM_INUSE_ATTRIBUTE_ERR => 'DOM_INUSE_ATTRIBUTE_ERR', \DOM_INVALID_STATE_ERR => 'DOM_INVALID_STATE_ERR', \DOM_SYNTAX_ERR => 'DOM_SYNTAX_ERR', \DOM_INVALID_MODIFICATION_ERR => 'DOM_INVALID_MODIFICATION_ERR', \DOM_NAMESPACE_ERR => 'DOM_NAMESPACE_ERR', \DOM_INVALID_ACCESS_ERR => 'DOM_INVALID_ACCESS_ERR', \DOM_VALIDATION_ERR => 'DOM_VALIDATION_ERR', ]; private const NODE_TYPES = [ \XML_ELEMENT_NODE => 'XML_ELEMENT_NODE', \XML_ATTRIBUTE_NODE => 'XML_ATTRIBUTE_NODE', \XML_TEXT_NODE => 'XML_TEXT_NODE', \XML_CDATA_SECTION_NODE => 'XML_CDATA_SECTION_NODE', \XML_ENTITY_REF_NODE => 'XML_ENTITY_REF_NODE', \XML_ENTITY_NODE => 'XML_ENTITY_NODE', \XML_PI_NODE => 'XML_PI_NODE', \XML_COMMENT_NODE => 'XML_COMMENT_NODE', \XML_DOCUMENT_NODE => 'XML_DOCUMENT_NODE', \XML_DOCUMENT_TYPE_NODE => 'XML_DOCUMENT_TYPE_NODE', \XML_DOCUMENT_FRAG_NODE => 'XML_DOCUMENT_FRAG_NODE', \XML_NOTATION_NODE => 'XML_NOTATION_NODE', \XML_HTML_DOCUMENT_NODE => 'XML_HTML_DOCUMENT_NODE', \XML_DTD_NODE => 'XML_DTD_NODE', \XML_ELEMENT_DECL_NODE => 'XML_ELEMENT_DECL_NODE', \XML_ATTRIBUTE_DECL_NODE => 'XML_ATTRIBUTE_DECL_NODE', \XML_ENTITY_DECL_NODE => 'XML_ENTITY_DECL_NODE', \XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE', ]; public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested) { $k = Caster::PREFIX_PROTECTED.'code'; if (isset($a[$k], self::ERROR_CODES[$a[$k]])) { $a[$k] = new ConstStub(self::ERROR_CODES[$a[$k]], $a[$k]); } return $a; } public static function castLength($dom, array $a, Stub $stub, bool $isNested) { $a += [ 'length' => $dom->length, ]; return $a; } public static function castImplementation(\DOMImplementation $dom, array $a, Stub $stub, bool $isNested) { $a += [ Caster::PREFIX_VIRTUAL.'Core' => '1.0', Caster::PREFIX_VIRTUAL.'XML' => '2.0', ]; return $a; } public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'nodeName' => $dom->nodeName, 'nodeValue' => new CutStub($dom->nodeValue), 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), 'parentNode' => new CutStub($dom->parentNode), 'childNodes' => $dom->childNodes, 'firstChild' => new CutStub($dom->firstChild), 'lastChild' => new CutStub($dom->lastChild), 'previousSibling' => new CutStub($dom->previousSibling), 'nextSibling' => new CutStub($dom->nextSibling), 'attributes' => $dom->attributes, 'ownerDocument' => new CutStub($dom->ownerDocument), 'namespaceURI' => $dom->namespaceURI, 'prefix' => $dom->prefix, 'localName' => $dom->localName, 'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI, 'textContent' => new CutStub($dom->textContent), ]; return $a; } public static function castNameSpaceNode(\DOMNameSpaceNode $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'nodeName' => $dom->nodeName, 'nodeValue' => new CutStub($dom->nodeValue), 'nodeType' => new ConstStub(self::NODE_TYPES[$dom->nodeType], $dom->nodeType), 'prefix' => $dom->prefix, 'localName' => $dom->localName, 'namespaceURI' => $dom->namespaceURI, 'ownerDocument' => new CutStub($dom->ownerDocument), 'parentNode' => new CutStub($dom->parentNode), ]; return $a; } public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0) { $a += [ 'doctype' => $dom->doctype, 'implementation' => $dom->implementation, 'documentElement' => new CutStub($dom->documentElement), 'actualEncoding' => $dom->actualEncoding, 'encoding' => $dom->encoding, 'xmlEncoding' => $dom->xmlEncoding, 'standalone' => $dom->standalone, 'xmlStandalone' => $dom->xmlStandalone, 'version' => $dom->version, 'xmlVersion' => $dom->xmlVersion, 'strictErrorChecking' => $dom->strictErrorChecking, 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI, 'config' => $dom->config, 'formatOutput' => $dom->formatOutput, 'validateOnParse' => $dom->validateOnParse, 'resolveExternals' => $dom->resolveExternals, 'preserveWhiteSpace' => $dom->preserveWhiteSpace, 'recover' => $dom->recover, 'substituteEntities' => $dom->substituteEntities, ]; if (!($filter & Caster::EXCLUDE_VERBOSE)) { $formatOutput = $dom->formatOutput; $dom->formatOutput = true; $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()]; $dom->formatOutput = $formatOutput; } return $a; } public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'data' => $dom->data, 'length' => $dom->length, ]; return $a; } public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'name' => $dom->name, 'specified' => $dom->specified, 'value' => $dom->value, 'ownerElement' => $dom->ownerElement, 'schemaTypeInfo' => $dom->schemaTypeInfo, ]; return $a; } public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'tagName' => $dom->tagName, 'schemaTypeInfo' => $dom->schemaTypeInfo, ]; return $a; } public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'wholeText' => $dom->wholeText, ]; return $a; } public static function castTypeinfo(\DOMTypeinfo $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'typeName' => $dom->typeName, 'typeNamespace' => $dom->typeNamespace, ]; return $a; } public static function castDomError(\DOMDomError $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'severity' => $dom->severity, 'message' => $dom->message, 'type' => $dom->type, 'relatedException' => $dom->relatedException, 'related_data' => $dom->related_data, 'location' => $dom->location, ]; return $a; } public static function castLocator(\DOMLocator $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'lineNumber' => $dom->lineNumber, 'columnNumber' => $dom->columnNumber, 'offset' => $dom->offset, 'relatedNode' => $dom->relatedNode, 'uri' => $dom->uri ? new LinkStub($dom->uri, $dom->lineNumber) : $dom->uri, ]; return $a; } public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'name' => $dom->name, 'entities' => $dom->entities, 'notations' => $dom->notations, 'publicId' => $dom->publicId, 'systemId' => $dom->systemId, 'internalSubset' => $dom->internalSubset, ]; return $a; } public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'publicId' => $dom->publicId, 'systemId' => $dom->systemId, ]; return $a; } public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'publicId' => $dom->publicId, 'systemId' => $dom->systemId, 'notationName' => $dom->notationName, 'actualEncoding' => $dom->actualEncoding, 'encoding' => $dom->encoding, 'version' => $dom->version, ]; return $a; } public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'target' => $dom->target, 'data' => $dom->data, ]; return $a; } public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested) { $a += [ 'document' => $dom->document, ]; return $a; } } var-dumper/Caster/FrameStub.php000064400000001344150432043210012444 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; /** * Represents a single backtrace frame as returned by debug_backtrace() or Exception->getTrace(). * * @author Nicolas Grekas */ class FrameStub extends EnumStub { public $keepArgs; public $inTraceStub; public function __construct(array $frame, bool $keepArgs = true, bool $inTraceStub = false) { $this->value = $frame; $this->keepArgs = $keepArgs; $this->inTraceStub = $inTraceStub; } } var-dumper/Caster/LinkStub.php000064400000006500150432043210012306 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; /** * Represents a file or a URL. * * @author Nicolas Grekas */ class LinkStub extends ConstStub { public $inVendor = false; private static $vendorRoots; private static $composerRoots; public function __construct(string $label, int $line = 0, string $href = null) { $this->value = $label; if (null === $href) { $href = $label; } if (!\is_string($href)) { return; } if (str_starts_with($href, 'file://')) { if ($href === $label) { $label = substr($label, 7); } $href = substr($href, 7); } elseif (str_contains($href, '://')) { $this->attr['href'] = $href; return; } if (!is_file($href)) { return; } if ($line) { $this->attr['line'] = $line; } if ($label !== $this->attr['file'] = realpath($href) ?: $href) { return; } if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) { $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1; $this->attr['ellipsis-type'] = 'path'; $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) { $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2))); $this->attr['ellipsis-type'] = 'path'; $this->attr['ellipsis-tail'] = 1; } } private function getComposerRoot(string $file, bool &$inVendor) { if (null === self::$vendorRoots) { self::$vendorRoots = []; foreach (get_declared_classes() as $class) { if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); $v = \dirname($r->getFileName(), 2); if (is_file($v.'/composer/installed.json')) { self::$vendorRoots[] = $v.\DIRECTORY_SEPARATOR; } } } } $inVendor = false; if (isset(self::$composerRoots[$dir = \dirname($file)])) { return self::$composerRoots[$dir]; } foreach (self::$vendorRoots as $root) { if ($inVendor = str_starts_with($file, $root)) { return $root; } } $parent = $dir; while (!@is_file($parent.'/composer.json')) { if (!@file_exists($parent)) { // open_basedir restriction in effect break; } if ($parent === \dirname($parent)) { return self::$composerRoots[$dir] = false; } $parent = \dirname($parent); } return self::$composerRoots[$dir] = $parent.\DIRECTORY_SEPARATOR; } } var-dumper/Caster/XmlReaderCaster.php000064400000006350150432043210013603 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts XmlReader class to array representation. * * @author Baptiste Clavié * * @final */ class XmlReaderCaster { private const NODE_TYPES = [ \XMLReader::NONE => 'NONE', \XMLReader::ELEMENT => 'ELEMENT', \XMLReader::ATTRIBUTE => 'ATTRIBUTE', \XMLReader::TEXT => 'TEXT', \XMLReader::CDATA => 'CDATA', \XMLReader::ENTITY_REF => 'ENTITY_REF', \XMLReader::ENTITY => 'ENTITY', \XMLReader::PI => 'PI (Processing Instruction)', \XMLReader::COMMENT => 'COMMENT', \XMLReader::DOC => 'DOC', \XMLReader::DOC_TYPE => 'DOC_TYPE', \XMLReader::DOC_FRAGMENT => 'DOC_FRAGMENT', \XMLReader::NOTATION => 'NOTATION', \XMLReader::WHITESPACE => 'WHITESPACE', \XMLReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE', \XMLReader::END_ELEMENT => 'END_ELEMENT', \XMLReader::END_ENTITY => 'END_ENTITY', \XMLReader::XML_DECLARATION => 'XML_DECLARATION', ]; public static function castXmlReader(\XMLReader $reader, array $a, Stub $stub, bool $isNested) { try { $properties = [ 'LOADDTD' => @$reader->getParserProperty(\XMLReader::LOADDTD), 'DEFAULTATTRS' => @$reader->getParserProperty(\XMLReader::DEFAULTATTRS), 'VALIDATE' => @$reader->getParserProperty(\XMLReader::VALIDATE), 'SUBST_ENTITIES' => @$reader->getParserProperty(\XMLReader::SUBST_ENTITIES), ]; } catch (\Error $e) { $properties = [ 'LOADDTD' => false, 'DEFAULTATTRS' => false, 'VALIDATE' => false, 'SUBST_ENTITIES' => false, ]; } $props = Caster::PREFIX_VIRTUAL.'parserProperties'; $info = [ 'localName' => $reader->localName, 'prefix' => $reader->prefix, 'nodeType' => new ConstStub(self::NODE_TYPES[$reader->nodeType], $reader->nodeType), 'depth' => $reader->depth, 'isDefault' => $reader->isDefault, 'isEmptyElement' => \XMLReader::NONE === $reader->nodeType ? null : $reader->isEmptyElement, 'xmlLang' => $reader->xmlLang, 'attributeCount' => $reader->attributeCount, 'value' => $reader->value, 'namespaceURI' => $reader->namespaceURI, 'baseURI' => $reader->baseURI ? new LinkStub($reader->baseURI) : $reader->baseURI, $props => $properties, ]; if ($info[$props] = Caster::filter($info[$props], Caster::EXCLUDE_EMPTY, [], $count)) { $info[$props] = new EnumStub($info[$props]); $info[$props]->cut = $count; } $info = Caster::filter($info, Caster::EXCLUDE_EMPTY, [], $count); // +2 because hasValue and hasAttributes are always filtered $stub->cut += $count + 2; return $a + $info; } } var-dumper/Caster/RedisCaster.php000064400000012217150432043210012765 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts Redis class from ext-redis to array representation. * * @author Nicolas Grekas * * @final */ class RedisCaster { private const SERIALIZERS = [ \Redis::SERIALIZER_NONE => 'NONE', \Redis::SERIALIZER_PHP => 'PHP', 2 => 'IGBINARY', // Optional Redis::SERIALIZER_IGBINARY ]; private const MODES = [ \Redis::ATOMIC => 'ATOMIC', \Redis::MULTI => 'MULTI', \Redis::PIPELINE => 'PIPELINE', ]; private const COMPRESSION_MODES = [ 0 => 'NONE', // Redis::COMPRESSION_NONE 1 => 'LZF', // Redis::COMPRESSION_LZF ]; private const FAILOVER_OPTIONS = [ \RedisCluster::FAILOVER_NONE => 'NONE', \RedisCluster::FAILOVER_ERROR => 'ERROR', \RedisCluster::FAILOVER_DISTRIBUTE => 'DISTRIBUTE', \RedisCluster::FAILOVER_DISTRIBUTE_SLAVES => 'DISTRIBUTE_SLAVES', ]; public static function castRedis(\Redis $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; if (!$connected = $c->isConnected()) { return $a + [ $prefix.'isConnected' => $connected, ]; } $mode = $c->getMode(); return $a + [ $prefix.'isConnected' => $connected, $prefix.'host' => $c->getHost(), $prefix.'port' => $c->getPort(), $prefix.'auth' => $c->getAuth(), $prefix.'mode' => isset(self::MODES[$mode]) ? new ConstStub(self::MODES[$mode], $mode) : $mode, $prefix.'dbNum' => $c->getDbNum(), $prefix.'timeout' => $c->getTimeout(), $prefix.'lastError' => $c->getLastError(), $prefix.'persistentId' => $c->getPersistentID(), $prefix.'options' => self::getRedisOptions($c), ]; } public static function castRedisArray(\RedisArray $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; return $a + [ $prefix.'hosts' => $c->_hosts(), $prefix.'function' => ClassStub::wrapCallable($c->_function()), $prefix.'lastError' => $c->getLastError(), $prefix.'options' => self::getRedisOptions($c), ]; } public static function castRedisCluster(\RedisCluster $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; $failover = $c->getOption(\RedisCluster::OPT_SLAVE_FAILOVER); $a += [ $prefix.'_masters' => $c->_masters(), $prefix.'_redir' => $c->_redir(), $prefix.'mode' => new ConstStub($c->getMode() ? 'MULTI' : 'ATOMIC', $c->getMode()), $prefix.'lastError' => $c->getLastError(), $prefix.'options' => self::getRedisOptions($c, [ 'SLAVE_FAILOVER' => isset(self::FAILOVER_OPTIONS[$failover]) ? new ConstStub(self::FAILOVER_OPTIONS[$failover], $failover) : $failover, ]), ]; return $a; } /** * @param \Redis|\RedisArray|\RedisCluster $redis */ private static function getRedisOptions($redis, array $options = []): EnumStub { $serializer = $redis->getOption(\Redis::OPT_SERIALIZER); if (\is_array($serializer)) { foreach ($serializer as &$v) { if (isset(self::SERIALIZERS[$v])) { $v = new ConstStub(self::SERIALIZERS[$v], $v); } } } elseif (isset(self::SERIALIZERS[$serializer])) { $serializer = new ConstStub(self::SERIALIZERS[$serializer], $serializer); } $compression = \defined('Redis::OPT_COMPRESSION') ? $redis->getOption(\Redis::OPT_COMPRESSION) : 0; if (\is_array($compression)) { foreach ($compression as &$v) { if (isset(self::COMPRESSION_MODES[$v])) { $v = new ConstStub(self::COMPRESSION_MODES[$v], $v); } } } elseif (isset(self::COMPRESSION_MODES[$compression])) { $compression = new ConstStub(self::COMPRESSION_MODES[$compression], $compression); } $retry = \defined('Redis::OPT_SCAN') ? $redis->getOption(\Redis::OPT_SCAN) : 0; if (\is_array($retry)) { foreach ($retry as &$v) { $v = new ConstStub($v ? 'RETRY' : 'NORETRY', $v); } } else { $retry = new ConstStub($retry ? 'RETRY' : 'NORETRY', $retry); } $options += [ 'TCP_KEEPALIVE' => \defined('Redis::OPT_TCP_KEEPALIVE') ? $redis->getOption(\Redis::OPT_TCP_KEEPALIVE) : 0, 'READ_TIMEOUT' => $redis->getOption(\Redis::OPT_READ_TIMEOUT), 'COMPRESSION' => $compression, 'SERIALIZER' => $serializer, 'PREFIX' => $redis->getOption(\Redis::OPT_PREFIX), 'SCAN' => $retry, ]; return new EnumStub($options); } } var-dumper/Caster/ReflectionCaster.php000064400000035364150432043210014021 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts Reflector related classes to array representation. * * @author Nicolas Grekas * * @final */ class ReflectionCaster { public const UNSET_CLOSURE_FILE_INFO = ['Closure' => __CLASS__.'::unsetClosureFileInfo']; private const EXTRA_MAP = [ 'docComment' => 'getDocComment', 'extension' => 'getExtensionName', 'isDisabled' => 'isDisabled', 'isDeprecated' => 'isDeprecated', 'isInternal' => 'isInternal', 'isUserDefined' => 'isUserDefined', 'isGenerator' => 'isGenerator', 'isVariadic' => 'isVariadic', ]; public static function castClosure(\Closure $c, array $a, Stub $stub, bool $isNested, int $filter = 0) { $prefix = Caster::PREFIX_VIRTUAL; $c = new \ReflectionFunction($c); $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter); if (!str_contains($c->name, '{closure}')) { $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name; unset($a[$prefix.'class']); } unset($a[$prefix.'extra']); $stub->class .= self::getSignature($a); if ($f = $c->getFileName()) { $stub->attr['file'] = $f; $stub->attr['line'] = $c->getStartLine(); } unset($a[$prefix.'parameters']); if ($filter & Caster::EXCLUDE_VERBOSE) { $stub->cut += ($c->getFileName() ? 2 : 0) + \count($a); return []; } if ($f) { $a[$prefix.'file'] = new LinkStub($f, $c->getStartLine()); $a[$prefix.'line'] = $c->getStartLine().' to '.$c->getEndLine(); } return $a; } public static function unsetClosureFileInfo(\Closure $c, array $a) { unset($a[Caster::PREFIX_VIRTUAL.'file'], $a[Caster::PREFIX_VIRTUAL.'line']); return $a; } public static function castGenerator(\Generator $c, array $a, Stub $stub, bool $isNested) { // Cannot create ReflectionGenerator based on a terminated Generator try { $reflectionGenerator = new \ReflectionGenerator($c); } catch (\Exception $e) { $a[Caster::PREFIX_VIRTUAL.'closed'] = true; return $a; } return self::castReflectionGenerator($reflectionGenerator, $a, $stub, $isNested); } public static function castType(\ReflectionType $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; if ($c instanceof \ReflectionNamedType || \PHP_VERSION_ID < 80000) { $a += [ $prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : (string) $c, $prefix.'allowsNull' => $c->allowsNull(), $prefix.'isBuiltin' => $c->isBuiltin(), ]; } elseif ($c instanceof \ReflectionUnionType || $c instanceof \ReflectionIntersectionType) { $a[$prefix.'allowsNull'] = $c->allowsNull(); self::addMap($a, $c, [ 'types' => 'getTypes', ]); } else { $a[$prefix.'allowsNull'] = $c->allowsNull(); } return $a; } public static function castAttribute(\ReflectionAttribute $c, array $a, Stub $stub, bool $isNested) { self::addMap($a, $c, [ 'name' => 'getName', 'arguments' => 'getArguments', ]); return $a; } public static function castReflectionGenerator(\ReflectionGenerator $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; if ($c->getThis()) { $a[$prefix.'this'] = new CutStub($c->getThis()); } $function = $c->getFunction(); $frame = [ 'class' => $function->class ?? null, 'type' => isset($function->class) ? ($function->isStatic() ? '::' : '->') : null, 'function' => $function->name, 'file' => $c->getExecutingFile(), 'line' => $c->getExecutingLine(), ]; if ($trace = $c->getTrace(\DEBUG_BACKTRACE_IGNORE_ARGS)) { $function = new \ReflectionGenerator($c->getExecutingGenerator()); array_unshift($trace, [ 'function' => 'yield', 'file' => $function->getExecutingFile(), 'line' => $function->getExecutingLine() - (int) (\PHP_VERSION_ID < 80100), ]); $trace[] = $frame; $a[$prefix.'trace'] = new TraceStub($trace, false, 0, -1, -1); } else { $function = new FrameStub($frame, false, true); $function = ExceptionCaster::castFrameStub($function, [], $function, true); $a[$prefix.'executing'] = $function[$prefix.'src']; } $a[Caster::PREFIX_VIRTUAL.'closed'] = false; return $a; } public static function castClass(\ReflectionClass $c, array $a, Stub $stub, bool $isNested, int $filter = 0) { $prefix = Caster::PREFIX_VIRTUAL; if ($n = \Reflection::getModifierNames($c->getModifiers())) { $a[$prefix.'modifiers'] = implode(' ', $n); } self::addMap($a, $c, [ 'extends' => 'getParentClass', 'implements' => 'getInterfaceNames', 'constants' => 'getReflectionConstants', ]); foreach ($c->getProperties() as $n) { $a[$prefix.'properties'][$n->name] = $n; } foreach ($c->getMethods() as $n) { $a[$prefix.'methods'][$n->name] = $n; } self::addAttributes($a, $c, $prefix); if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { self::addExtra($a, $c); } return $a; } public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, array $a, Stub $stub, bool $isNested, int $filter = 0) { $prefix = Caster::PREFIX_VIRTUAL; self::addMap($a, $c, [ 'returnsReference' => 'returnsReference', 'returnType' => 'getReturnType', 'class' => 'getClosureScopeClass', 'this' => 'getClosureThis', ]); if (isset($a[$prefix.'returnType'])) { $v = $a[$prefix.'returnType']; $v = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType'] instanceof \ReflectionNamedType && $a[$prefix.'returnType']->allowsNull() && 'mixed' !== $v ? '?'.$v : $v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); } if (isset($a[$prefix.'class'])) { $a[$prefix.'class'] = new ClassStub($a[$prefix.'class']); } if (isset($a[$prefix.'this'])) { $a[$prefix.'this'] = new CutStub($a[$prefix.'this']); } foreach ($c->getParameters() as $v) { $k = '$'.$v->name; if ($v->isVariadic()) { $k = '...'.$k; } if ($v->isPassedByReference()) { $k = '&'.$k; } $a[$prefix.'parameters'][$k] = $v; } if (isset($a[$prefix.'parameters'])) { $a[$prefix.'parameters'] = new EnumStub($a[$prefix.'parameters']); } self::addAttributes($a, $c, $prefix); if (!($filter & Caster::EXCLUDE_VERBOSE) && $v = $c->getStaticVariables()) { foreach ($v as $k => &$v) { if (\is_object($v)) { $a[$prefix.'use']['$'.$k] = new CutStub($v); } else { $a[$prefix.'use']['$'.$k] = &$v; } } unset($v); $a[$prefix.'use'] = new EnumStub($a[$prefix.'use']); } if (!($filter & Caster::EXCLUDE_VERBOSE) && !$isNested) { self::addExtra($a, $c); } return $a; } public static function castClassConstant(\ReflectionClassConstant $c, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); $a[Caster::PREFIX_VIRTUAL.'value'] = $c->getValue(); self::addAttributes($a, $c); return $a; } public static function castMethod(\ReflectionMethod $c, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); return $a; } public static function castParameter(\ReflectionParameter $c, array $a, Stub $stub, bool $isNested) { $prefix = Caster::PREFIX_VIRTUAL; self::addMap($a, $c, [ 'position' => 'getPosition', 'isVariadic' => 'isVariadic', 'byReference' => 'isPassedByReference', 'allowsNull' => 'allowsNull', ]); self::addAttributes($a, $c, $prefix); if ($v = $c->getType()) { $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : (string) $v; } if (isset($a[$prefix.'typeHint'])) { $v = $a[$prefix.'typeHint']; $a[$prefix.'typeHint'] = new ClassStub($v, [class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '']); } else { unset($a[$prefix.'allowsNull']); } if ($c->isOptional()) { try { $a[$prefix.'default'] = $v = $c->getDefaultValue(); if ($c->isDefaultValueConstant()) { $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); } if (null === $v) { unset($a[$prefix.'allowsNull']); } } catch (\ReflectionException $e) { } } return $a; } public static function castProperty(\ReflectionProperty $c, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'modifiers'] = implode(' ', \Reflection::getModifierNames($c->getModifiers())); self::addAttributes($a, $c); self::addExtra($a, $c); return $a; } public static function castReference(\ReflectionReference $c, array $a, Stub $stub, bool $isNested) { $a[Caster::PREFIX_VIRTUAL.'id'] = $c->getId(); return $a; } public static function castExtension(\ReflectionExtension $c, array $a, Stub $stub, bool $isNested) { self::addMap($a, $c, [ 'version' => 'getVersion', 'dependencies' => 'getDependencies', 'iniEntries' => 'getIniEntries', 'isPersistent' => 'isPersistent', 'isTemporary' => 'isTemporary', 'constants' => 'getConstants', 'functions' => 'getFunctions', 'classes' => 'getClasses', ]); return $a; } public static function castZendExtension(\ReflectionZendExtension $c, array $a, Stub $stub, bool $isNested) { self::addMap($a, $c, [ 'version' => 'getVersion', 'author' => 'getAuthor', 'copyright' => 'getCopyright', 'url' => 'getURL', ]); return $a; } public static function getSignature(array $a) { $prefix = Caster::PREFIX_VIRTUAL; $signature = ''; if (isset($a[$prefix.'parameters'])) { foreach ($a[$prefix.'parameters']->value as $k => $param) { $signature .= ', '; if ($type = $param->getType()) { if (!$type instanceof \ReflectionNamedType) { $signature .= $type.' '; } else { if (!$param->isOptional() && $param->allowsNull() && 'mixed' !== $type->getName()) { $signature .= '?'; } $signature .= substr(strrchr('\\'.$type->getName(), '\\'), 1).' '; } } $signature .= $k; if (!$param->isDefaultValueAvailable()) { continue; } $v = $param->getDefaultValue(); $signature .= ' = '; if ($param->isDefaultValueConstant()) { $signature .= substr(strrchr('\\'.$param->getDefaultValueConstantName(), '\\'), 1); } elseif (null === $v) { $signature .= 'null'; } elseif (\is_array($v)) { $signature .= $v ? '[…'.\count($v).']' : '[]'; } elseif (\is_string($v)) { $signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'"; } elseif (\is_bool($v)) { $signature .= $v ? 'true' : 'false'; } elseif (\is_object($v)) { $signature .= 'new '.substr(strrchr('\\'.get_debug_type($v), '\\'), 1); } else { $signature .= $v; } } } $signature = (empty($a[$prefix.'returnsReference']) ? '' : '&').'('.substr($signature, 2).')'; if (isset($a[$prefix.'returnType'])) { $signature .= ': '.substr(strrchr('\\'.$a[$prefix.'returnType'], '\\'), 1); } return $signature; } private static function addExtra(array &$a, \Reflector $c) { $x = isset($a[Caster::PREFIX_VIRTUAL.'extra']) ? $a[Caster::PREFIX_VIRTUAL.'extra']->value : []; if (method_exists($c, 'getFileName') && $m = $c->getFileName()) { $x['file'] = new LinkStub($m, $c->getStartLine()); $x['line'] = $c->getStartLine().' to '.$c->getEndLine(); } self::addMap($x, $c, self::EXTRA_MAP, ''); if ($x) { $a[Caster::PREFIX_VIRTUAL.'extra'] = new EnumStub($x); } } private static function addMap(array &$a, object $c, array $map, string $prefix = Caster::PREFIX_VIRTUAL) { foreach ($map as $k => $m) { if (\PHP_VERSION_ID >= 80000 && 'isDisabled' === $k) { continue; } if (method_exists($c, $m) && false !== ($m = $c->$m()) && null !== $m) { $a[$prefix.$k] = $m instanceof \Reflector ? $m->name : $m; } } } private static function addAttributes(array &$a, \Reflector $c, string $prefix = Caster::PREFIX_VIRTUAL): void { if (\PHP_VERSION_ID >= 80000) { foreach ($c->getAttributes() as $n) { $a[$prefix.'attributes'][] = $n; } } } } var-dumper/Caster/FiberCaster.php000064400000002046150432043210012745 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts Fiber related classes to array representation. * * @author Grégoire Pineau */ final class FiberCaster { public static function castFiber(\Fiber $fiber, array $a, Stub $stub, bool $isNested, int $filter = 0) { $prefix = Caster::PREFIX_VIRTUAL; if ($fiber->isTerminated()) { $status = 'terminated'; } elseif ($fiber->isRunning()) { $status = 'running'; } elseif ($fiber->isSuspended()) { $status = 'suspended'; } elseif ($fiber->isStarted()) { $status = 'started'; } else { $status = 'not started'; } $a[$prefix.'status'] = $status; return $a; } } var-dumper/Caster/DsCaster.php000064400000003066150432043210012267 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; use Ds\Collection; use Ds\Map; use Ds\Pair; use Symfony\Component\VarDumper\Cloner\Stub; /** * Casts Ds extension classes to array representation. * * @author Jáchym Toušek * * @final */ class DsCaster { public static function castCollection(Collection $c, array $a, Stub $stub, bool $isNested): array { $a[Caster::PREFIX_VIRTUAL.'count'] = $c->count(); $a[Caster::PREFIX_VIRTUAL.'capacity'] = $c->capacity(); if (!$c instanceof Map) { $a += $c->toArray(); } return $a; } public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array { foreach ($c as $k => $v) { $a[] = new DsPairStub($k, $v); } return $a; } public static function castPair(Pair $c, array $a, Stub $stub, bool $isNested): array { foreach ($c->toArray() as $k => $v) { $a[Caster::PREFIX_VIRTUAL.$k] = $v; } return $a; } public static function castPairStub(DsPairStub $c, array $a, Stub $stub, bool $isNested): array { if ($isNested) { $stub->class = Pair::class; $stub->value = null; $stub->handle = 0; $a = $c->value; } return $a; } } var-dumper/Caster/CutArrayStub.php000064400000001270150432043210013142 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper\Caster; /** * Represents a cut array. * * @author Nicolas Grekas */ class CutArrayStub extends CutStub { public $preservedSubset; public function __construct(array $value, array $preservedKeys) { parent::__construct($value); $this->preservedSubset = array_intersect_key($value, array_flip($preservedKeys)); $this->cut -= \count($this->preservedSubset); } } var-dumper/VarDumper.php000064400000007414150432043210011244 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\VarDumper; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; use Symfony\Component\VarDumper\Caster\ReflectionCaster; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\CliDumper; use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider; use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; use Symfony\Component\VarDumper\Dumper\ContextualizedDumper; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Symfony\Component\VarDumper\Dumper\ServerDumper; // Load the global dump() function require_once __DIR__.'/Resources/functions/dump.php'; /** * @author Nicolas Grekas */ class VarDumper { /** * @var callable|null */ private static $handler; public static function dump($var) { if (null === self::$handler) { self::register(); } return (self::$handler)($var); } /** * @return callable|null */ public static function setHandler(callable $callable = null) { $prevHandler = self::$handler; // Prevent replacing the handler with expected format as soon as the env var was set: if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { return $prevHandler; } self::$handler = $callable; return $prevHandler; } private static function register(): void { $cloner = new VarCloner(); $cloner->addCasters(ReflectionCaster::UNSET_CLOSURE_FILE_INFO); $format = $_SERVER['VAR_DUMPER_FORMAT'] ?? null; switch (true) { case 'html' === $format: $dumper = new HtmlDumper(); break; case 'cli' === $format: $dumper = new CliDumper(); break; case 'server' === $format: case $format && 'tcp' === parse_url($format, \PHP_URL_SCHEME): $host = 'server' === $format ? $_SERVER['VAR_DUMPER_SERVER'] ?? '127.0.0.1:9912' : $format; $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper(); $dumper = new ServerDumper($host, $dumper, self::getDefaultContextProviders()); break; default: $dumper = \in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) ? new CliDumper() : new HtmlDumper(); } if (!$dumper instanceof ServerDumper) { $dumper = new ContextualizedDumper($dumper, [new SourceContextProvider()]); } self::$handler = function ($var) use ($cloner, $dumper) { $dumper->dump($cloner->cloneVar($var)); }; } private static function getDefaultContextProviders(): array { $contextProviders = []; if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && (class_exists(Request::class))) { $requestStack = new RequestStack(); $requestStack->push(Request::createFromGlobals()); $contextProviders['request'] = new RequestContextProvider($requestStack); } $fileLinkFormatter = class_exists(FileLinkFormatter::class) ? new FileLinkFormatter(null, $requestStack ?? null) : null; return $contextProviders + [ 'cli' => new CliContextProvider(), 'source' => new SourceContextProvider(null, null, $fileLinkFormatter), ]; } } deprecation-contracts/README.md000064400000002264150432043210012314 0ustar00Symfony Deprecation Contracts ============================= A generic function and convention to trigger deprecation notices. This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices. By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component, the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments. The function requires at least 3 arguments: - the name of the Composer package that is triggering the deprecation - the version of the package that introduced the deprecation - the message of the deprecation - more arguments can be provided: they will be inserted in the message using `printf()` formatting Example: ```php trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin'); ``` This will generate the following message: `Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty `function trigger_deprecation() {}` in your application. deprecation-contracts/function.php000064400000001760150432043210013373 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ if (!function_exists('trigger_deprecation')) { /** * Triggers a silenced deprecation notice. * * @param string $package The name of the Composer package that is triggering the deprecation * @param string $version The version of the package that introduced the deprecation * @param string $message The message of the deprecation * @param mixed ...$args Values to insert in the message using printf() formatting * * @author Nicolas Grekas */ function trigger_deprecation(string $package, string $version, string $message, ...$args): void { @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); } } deprecation-contracts/CHANGELOG.md000064400000000235150432043210012642 0ustar00CHANGELOG ========= The changelog is maintained for all Symfony contracts at the following URL: https://github.com/symfony/contracts/blob/main/CHANGELOG.md deprecation-contracts/.gitignore000064400000000042150432043210013015 0ustar00vendor/ composer.lock phpunit.xml deprecation-contracts/composer.json000064400000001511150432043210013551 0ustar00{ "name": "symfony/deprecation-contracts", "type": "library", "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "files": [ "function.php" ] }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", "url": "https://github.com/symfony/contracts" } } } deprecation-contracts/LICENSE000064400000002051150432043210012034 0ustar00Copyright (c) 2020-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. http-foundation/RequestStack.php000064400000006116150432043210013014 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Request stack that controls the lifecycle of requests. * * @author Benjamin Eberlei */ class RequestStack { /** * @var Request[] */ private $requests = []; /** * Pushes a Request on the stack. * * This method should generally not be called directly as the stack * management should be taken care of by the application itself. */ public function push(Request $request) { $this->requests[] = $request; } /** * Pops the current request from the stack. * * This operation lets the current request go out of scope. * * This method should generally not be called directly as the stack * management should be taken care of by the application itself. * * @return Request|null */ public function pop() { if (!$this->requests) { return null; } return array_pop($this->requests); } /** * @return Request|null */ public function getCurrentRequest() { return end($this->requests) ?: null; } /** * Gets the main request. * * Be warned that making your code aware of the main request * might make it un-compatible with other features of your framework * like ESI support. */ public function getMainRequest(): ?Request { if (!$this->requests) { return null; } return $this->requests[0]; } /** * Gets the master request. * * @return Request|null * * @deprecated since symfony/http-foundation 5.3, use getMainRequest() instead */ public function getMasterRequest() { trigger_deprecation('symfony/http-foundation', '5.3', '"%s()" is deprecated, use "getMainRequest()" instead.', __METHOD__); return $this->getMainRequest(); } /** * Returns the parent request of the current. * * Be warned that making your code aware of the parent request * might make it un-compatible with other features of your framework * like ESI support. * * If current Request is the main request, it returns null. * * @return Request|null */ public function getParentRequest() { $pos = \count($this->requests) - 2; return $this->requests[$pos] ?? null; } /** * Gets the current session. * * @throws SessionNotFoundException */ public function getSession(): SessionInterface { if ((null !== $request = end($this->requests) ?: null) && $request->hasSession()) { return $request->getSession(); } throw new SessionNotFoundException(); } } http-foundation/README.md000064400000001654150432043210011146 0ustar00HttpFoundation Component ======================== The HttpFoundation component defines an object-oriented layer for the HTTP specification. Sponsor ------- The HttpFoundation component for Symfony 5.4/6.0 is [backed][1] by [Laravel][2]. Laravel is a PHP web development framework that is passionate about maximum developer happiness. Laravel is built using a variety of bespoke and Symfony based components. Help Symfony by [sponsoring][3] its development! Resources --------- * [Documentation](https://symfony.com/doc/current/components/http_foundation.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) [1]: https://symfony.com/backers [2]: https://laravel.com/ [3]: https://symfony.com/sponsor http-foundation/BinaryFileResponse.php000064400000030326150432043210014141 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\File; /** * BinaryFileResponse represents an HTTP response delivering a file. * * @author Niklas Fiekas * @author stealth35 * @author Igor Wiedler * @author Jordan Alliot * @author Sergey Linnik */ class BinaryFileResponse extends Response { protected static $trustXSendfileTypeHeader = false; /** * @var File */ protected $file; protected $offset = 0; protected $maxlen = -1; protected $deleteFileAfterSend = false; /** * @param \SplFileInfo|string $file The file to stream * @param int $status The response status code * @param array $headers An array of response headers * @param bool $public Files are public by default * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename * @param bool $autoEtag Whether the ETag header should be automatically set * @param bool $autoLastModified Whether the Last-Modified header should be automatically set */ public function __construct($file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { parent::__construct(null, $status, $headers); $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); if ($public) { $this->setPublic(); } } /** * @param \SplFileInfo|string $file The file to stream * @param int $status The response status code * @param array $headers An array of response headers * @param bool $public Files are public by default * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename * @param bool $autoEtag Whether the ETag header should be automatically set * @param bool $autoLastModified Whether the Last-Modified header should be automatically set * * @return static * * @deprecated since Symfony 5.2, use __construct() instead. */ public static function create($file = null, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { trigger_deprecation('symfony/http-foundation', '5.2', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); } /** * Sets the file to stream. * * @param \SplFileInfo|string $file The file to stream * * @return $this * * @throws FileException */ public function setFile($file, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { if (!$file instanceof File) { if ($file instanceof \SplFileInfo) { $file = new File($file->getPathname()); } else { $file = new File((string) $file); } } if (!$file->isReadable()) { throw new FileException('File must be readable.'); } $this->file = $file; if ($autoEtag) { $this->setAutoEtag(); } if ($autoLastModified) { $this->setAutoLastModified(); } if ($contentDisposition) { $this->setContentDisposition($contentDisposition); } return $this; } /** * Gets the file. * * @return File */ public function getFile() { return $this->file; } /** * Automatically sets the Last-Modified header according the file modification date. * * @return $this */ public function setAutoLastModified() { $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); return $this; } /** * Automatically sets the ETag header according to the checksum of the file. * * @return $this */ public function setAutoEtag() { $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true))); return $this; } /** * Sets the Content-Disposition header with the given filename. * * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename * * @return $this */ public function setContentDisposition(string $disposition, string $filename = '', string $filenameFallback = '') { if ('' === $filename) { $filename = $this->file->getFilename(); } if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || str_contains($filename, '%'))) { $encoding = mb_detect_encoding($filename, null, true) ?: '8bit'; for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { $char = mb_substr($filename, $i, 1, $encoding); if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) { $filenameFallback .= '_'; } else { $filenameFallback .= $char; } } } $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); $this->headers->set('Content-Disposition', $dispositionHeader); return $this; } /** * {@inheritdoc} */ public function prepare(Request $request) { if (!$this->headers->has('Content-Type')) { $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); } if ('HTTP/1.0' !== $request->server->get('SERVER_PROTOCOL')) { $this->setProtocolVersion('1.1'); } $this->ensureIEOverSSLCompatibility($request); $this->offset = 0; $this->maxlen = -1; if (false === $fileSize = $this->file->getSize()) { return $this; } $this->headers->set('Content-Length', $fileSize); if (!$this->headers->has('Accept-Ranges')) { // Only accept ranges on safe HTTP methods $this->headers->set('Accept-Ranges', $request->isMethodSafe() ? 'bytes' : 'none'); } if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { // Use X-Sendfile, do not send any content. $type = $request->headers->get('X-Sendfile-Type'); $path = $this->file->getRealPath(); // Fall back to scheme://path for stream wrapped locations. if (false === $path) { $path = $this->file->getPathname(); } if ('x-accel-redirect' === strtolower($type)) { // Do X-Accel-Mapping substitutions. // @link https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-redirect $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); foreach ($parts as $part) { [$pathPrefix, $location] = $part; if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { $path = $location.substr($path, \strlen($pathPrefix)); // Only set X-Accel-Redirect header if a valid URI can be produced // as nginx does not serve arbitrary file paths. $this->headers->set($type, $path); $this->maxlen = 0; break; } } } else { $this->headers->set($type, $path); $this->maxlen = 0; } } elseif ($request->headers->has('Range') && $request->isMethod('GET')) { // Process the range headers. if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) { $range = $request->headers->get('Range'); if (str_starts_with($range, 'bytes=')) { [$start, $end] = explode('-', substr($range, 6), 2) + [0]; $end = ('' === $end) ? $fileSize - 1 : (int) $end; if ('' === $start) { $start = $fileSize - $end; $end = $fileSize - 1; } else { $start = (int) $start; } if ($start <= $end) { $end = min($end, $fileSize - 1); if ($start < 0 || $start > $end) { $this->setStatusCode(416); $this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize)); } elseif ($end - $start < $fileSize - 1) { $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; $this->offset = $start; $this->setStatusCode(206); $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); $this->headers->set('Content-Length', $end - $start + 1); } } } } } return $this; } private function hasValidIfRangeHeader(?string $header): bool { if ($this->getEtag() === $header) { return true; } if (null === $lastModified = $this->getLastModified()) { return false; } return $lastModified->format('D, d M Y H:i:s').' GMT' === $header; } /** * {@inheritdoc} */ public function sendContent() { if (!$this->isSuccessful()) { return parent::sendContent(); } if (0 === $this->maxlen) { return $this; } $out = fopen('php://output', 'w'); $file = fopen($this->file->getPathname(), 'r'); stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); fclose($out); fclose($file); if ($this->deleteFileAfterSend && is_file($this->file->getPathname())) { unlink($this->file->getPathname()); } return $this; } /** * {@inheritdoc} * * @throws \LogicException when the content is not null */ public function setContent(?string $content) { if (null !== $content) { throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); } return $this; } /** * {@inheritdoc} */ public function getContent() { return false; } /** * Trust X-Sendfile-Type header. */ public static function trustXSendfileTypeHeader() { self::$trustXSendfileTypeHeader = true; } /** * If this is set to true, the file will be unlinked after the request is sent * Note: If the X-Sendfile header is used, the deleteFileAfterSend setting will not be used. * * @return $this */ public function deleteFileAfterSend(bool $shouldDelete = true) { $this->deleteFileAfterSend = $shouldDelete; return $this; } } http-foundation/Response.php000064400000112111150432043210012165 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; // Help opcache.preload discover always-needed symbols class_exists(ResponseHeaderBag::class); /** * Response represents an HTTP response. * * @author Fabien Potencier */ class Response { public const HTTP_CONTINUE = 100; public const HTTP_SWITCHING_PROTOCOLS = 101; public const HTTP_PROCESSING = 102; // RFC2518 public const HTTP_EARLY_HINTS = 103; // RFC8297 public const HTTP_OK = 200; public const HTTP_CREATED = 201; public const HTTP_ACCEPTED = 202; public const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; public const HTTP_NO_CONTENT = 204; public const HTTP_RESET_CONTENT = 205; public const HTTP_PARTIAL_CONTENT = 206; public const HTTP_MULTI_STATUS = 207; // RFC4918 public const HTTP_ALREADY_REPORTED = 208; // RFC5842 public const HTTP_IM_USED = 226; // RFC3229 public const HTTP_MULTIPLE_CHOICES = 300; public const HTTP_MOVED_PERMANENTLY = 301; public const HTTP_FOUND = 302; public const HTTP_SEE_OTHER = 303; public const HTTP_NOT_MODIFIED = 304; public const HTTP_USE_PROXY = 305; public const HTTP_RESERVED = 306; public const HTTP_TEMPORARY_REDIRECT = 307; public const HTTP_PERMANENTLY_REDIRECT = 308; // RFC7238 public const HTTP_BAD_REQUEST = 400; public const HTTP_UNAUTHORIZED = 401; public const HTTP_PAYMENT_REQUIRED = 402; public const HTTP_FORBIDDEN = 403; public const HTTP_NOT_FOUND = 404; public const HTTP_METHOD_NOT_ALLOWED = 405; public const HTTP_NOT_ACCEPTABLE = 406; public const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; public const HTTP_REQUEST_TIMEOUT = 408; public const HTTP_CONFLICT = 409; public const HTTP_GONE = 410; public const HTTP_LENGTH_REQUIRED = 411; public const HTTP_PRECONDITION_FAILED = 412; public const HTTP_REQUEST_ENTITY_TOO_LARGE = 413; public const HTTP_REQUEST_URI_TOO_LONG = 414; public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; public const HTTP_EXPECTATION_FAILED = 417; public const HTTP_I_AM_A_TEAPOT = 418; // RFC2324 public const HTTP_MISDIRECTED_REQUEST = 421; // RFC7540 public const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 public const HTTP_LOCKED = 423; // RFC4918 public const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 public const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 public const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; public const HTTP_INTERNAL_SERVER_ERROR = 500; public const HTTP_NOT_IMPLEMENTED = 501; public const HTTP_BAD_GATEWAY = 502; public const HTTP_SERVICE_UNAVAILABLE = 503; public const HTTP_GATEWAY_TIMEOUT = 504; public const HTTP_VERSION_NOT_SUPPORTED = 505; public const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506; // RFC2295 public const HTTP_INSUFFICIENT_STORAGE = 507; // RFC4918 public const HTTP_LOOP_DETECTED = 508; // RFC5842 public const HTTP_NOT_EXTENDED = 510; // RFC2774 public const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 /** * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control */ private const HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES = [ 'must_revalidate' => false, 'no_cache' => false, 'no_store' => false, 'no_transform' => false, 'public' => false, 'private' => false, 'proxy_revalidate' => false, 'max_age' => true, 's_maxage' => true, 'immutable' => false, 'last_modified' => true, 'etag' => true, ]; /** * @var ResponseHeaderBag */ public $headers; /** * @var string */ protected $content; /** * @var string */ protected $version; /** * @var int */ protected $statusCode; /** * @var string */ protected $statusText; /** * @var string */ protected $charset; /** * Status codes translation table. * * The list of codes is complete according to the * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry} * (last updated 2021-10-01). * * Unless otherwise noted, the status code is defined in RFC2616. * * @var array */ public static $statusTexts = [ 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', // RFC2518 103 => 'Early Hints', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', // RFC4918 208 => 'Already Reported', // RFC5842 226 => 'IM Used', // RFC3229 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', // RFC7238 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Content Too Large', // RFC-ietf-httpbis-semantics 414 => 'URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Range Not Satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', // RFC2324 421 => 'Misdirected Request', // RFC7540 422 => 'Unprocessable Content', // RFC-ietf-httpbis-semantics 423 => 'Locked', // RFC4918 424 => 'Failed Dependency', // RFC4918 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 426 => 'Upgrade Required', // RFC2817 428 => 'Precondition Required', // RFC6585 429 => 'Too Many Requests', // RFC6585 431 => 'Request Header Fields Too Large', // RFC6585 451 => 'Unavailable For Legal Reasons', // RFC7725 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', // RFC2295 507 => 'Insufficient Storage', // RFC4918 508 => 'Loop Detected', // RFC5842 510 => 'Not Extended', // RFC2774 511 => 'Network Authentication Required', // RFC6585 ]; /** * @throws \InvalidArgumentException When the HTTP status code is not valid */ public function __construct(?string $content = '', int $status = 200, array $headers = []) { $this->headers = new ResponseHeaderBag($headers); $this->setContent($content); $this->setStatusCode($status); $this->setProtocolVersion('1.0'); } /** * Factory method for chainability. * * Example: * * return Response::create($body, 200) * ->setSharedMaxAge(300); * * @return static * * @deprecated since Symfony 5.1, use __construct() instead. */ public static function create(?string $content = '', int $status = 200, array $headers = []) { trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); return new static($content, $status, $headers); } /** * Returns the Response as an HTTP string. * * The string representation of the Response is the same as the * one that will be sent to the client only if the prepare() method * has been called before. * * @return string * * @see prepare() */ public function __toString() { return sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)."\r\n". $this->headers."\r\n". $this->getContent(); } /** * Clones the current Response instance. */ public function __clone() { $this->headers = clone $this->headers; } /** * Prepares the Response before it is sent to the client. * * This method tweaks the Response to ensure that it is * compliant with RFC 2616. Most of the changes are based on * the Request that is "associated" with this Response. * * @return $this */ public function prepare(Request $request) { $headers = $this->headers; if ($this->isInformational() || $this->isEmpty()) { $this->setContent(null); $headers->remove('Content-Type'); $headers->remove('Content-Length'); // prevent PHP from sending the Content-Type header based on default_mimetype ini_set('default_mimetype', ''); } else { // Content-type based on the Request if (!$headers->has('Content-Type')) { $format = $request->getRequestFormat(null); if (null !== $format && $mimeType = $request->getMimeType($format)) { $headers->set('Content-Type', $mimeType); } } // Fix Content-Type $charset = $this->charset ?: 'UTF-8'; if (!$headers->has('Content-Type')) { $headers->set('Content-Type', 'text/html; charset='.$charset); } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) { // add the charset $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset); } // Fix Content-Length if ($headers->has('Transfer-Encoding')) { $headers->remove('Content-Length'); } if ($request->isMethod('HEAD')) { // cf. RFC2616 14.13 $length = $headers->get('Content-Length'); $this->setContent(null); if ($length) { $headers->set('Content-Length', $length); } } } // Fix protocol if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { $this->setProtocolVersion('1.1'); } // Check if we need to send extra expire info headers if ('1.0' == $this->getProtocolVersion() && str_contains($headers->get('Cache-Control', ''), 'no-cache')) { $headers->set('pragma', 'no-cache'); $headers->set('expires', -1); } $this->ensureIEOverSSLCompatibility($request); if ($request->isSecure()) { foreach ($headers->getCookies() as $cookie) { $cookie->setSecureDefault(true); } } return $this; } /** * Sends HTTP headers. * * @return $this */ public function sendHeaders() { // headers have already been sent by the developer if (headers_sent()) { return $this; } // headers foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { $replace = 0 === strcasecmp($name, 'Content-Type'); foreach ($values as $value) { header($name.': '.$value, $replace, $this->statusCode); } } // cookies foreach ($this->headers->getCookies() as $cookie) { header('Set-Cookie: '.$cookie, false, $this->statusCode); } // status header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); return $this; } /** * Sends content for the current web response. * * @return $this */ public function sendContent() { echo $this->content; return $this; } /** * Sends HTTP headers and content. * * @return $this */ public function send() { $this->sendHeaders(); $this->sendContent(); if (\function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } elseif (\function_exists('litespeed_finish_request')) { litespeed_finish_request(); } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { static::closeOutputBuffers(0, true); } return $this; } /** * Sets the response content. * * @return $this */ public function setContent(?string $content) { $this->content = $content ?? ''; return $this; } /** * Gets the current response content. * * @return string|false */ public function getContent() { return $this->content; } /** * Sets the HTTP protocol version (1.0 or 1.1). * * @return $this * * @final */ public function setProtocolVersion(string $version): object { $this->version = $version; return $this; } /** * Gets the HTTP protocol version. * * @final */ public function getProtocolVersion(): string { return $this->version; } /** * Sets the response status code. * * If the status text is null it will be automatically populated for the known * status codes and left empty otherwise. * * @return $this * * @throws \InvalidArgumentException When the HTTP status code is not valid * * @final */ public function setStatusCode(int $code, string $text = null): object { $this->statusCode = $code; if ($this->isInvalid()) { throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); } if (null === $text) { $this->statusText = self::$statusTexts[$code] ?? 'unknown status'; return $this; } if (false === $text) { $this->statusText = ''; return $this; } $this->statusText = $text; return $this; } /** * Retrieves the status code for the current web response. * * @final */ public function getStatusCode(): int { return $this->statusCode; } /** * Sets the response charset. * * @return $this * * @final */ public function setCharset(string $charset): object { $this->charset = $charset; return $this; } /** * Retrieves the response charset. * * @final */ public function getCharset(): ?string { return $this->charset; } /** * Returns true if the response may safely be kept in a shared (surrogate) cache. * * Responses marked "private" with an explicit Cache-Control directive are * considered uncacheable. * * Responses with neither a freshness lifetime (Expires, max-age) nor cache * validator (Last-Modified, ETag) are considered uncacheable because there is * no way to tell when or how to remove them from the cache. * * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, * for example "status codes that are defined as cacheable by default [...] * can be reused by a cache with heuristic expiration unless otherwise indicated" * (https://tools.ietf.org/html/rfc7231#section-6.1) * * @final */ public function isCacheable(): bool { if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) { return false; } if ($this->headers->hasCacheControlDirective('no-store') || $this->headers->getCacheControlDirective('private')) { return false; } return $this->isValidateable() || $this->isFresh(); } /** * Returns true if the response is "fresh". * * Fresh responses may be served from cache without any interaction with the * origin. A response is considered fresh when it includes a Cache-Control/max-age * indicator or Expires header and the calculated age is less than the freshness lifetime. * * @final */ public function isFresh(): bool { return $this->getTtl() > 0; } /** * Returns true if the response includes headers that can be used to validate * the response with the origin server using a conditional GET request. * * @final */ public function isValidateable(): bool { return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); } /** * Marks the response as "private". * * It makes the response ineligible for serving other clients. * * @return $this * * @final */ public function setPrivate(): object { $this->headers->removeCacheControlDirective('public'); $this->headers->addCacheControlDirective('private'); return $this; } /** * Marks the response as "public". * * It makes the response eligible for serving other clients. * * @return $this * * @final */ public function setPublic(): object { $this->headers->addCacheControlDirective('public'); $this->headers->removeCacheControlDirective('private'); return $this; } /** * Marks the response as "immutable". * * @return $this * * @final */ public function setImmutable(bool $immutable = true): object { if ($immutable) { $this->headers->addCacheControlDirective('immutable'); } else { $this->headers->removeCacheControlDirective('immutable'); } return $this; } /** * Returns true if the response is marked as "immutable". * * @final */ public function isImmutable(): bool { return $this->headers->hasCacheControlDirective('immutable'); } /** * Returns true if the response must be revalidated by shared caches once it has become stale. * * This method indicates that the response must not be served stale by a * cache in any circumstance without first revalidating with the origin. * When present, the TTL of the response should not be overridden to be * greater than the value provided by the origin. * * @final */ public function mustRevalidate(): bool { return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate'); } /** * Returns the Date header as a DateTime instance. * * @throws \RuntimeException When the header is not parseable * * @final */ public function getDate(): ?\DateTimeInterface { return $this->headers->getDate('Date'); } /** * Sets the Date header. * * @return $this * * @final */ public function setDate(\DateTimeInterface $date): object { if ($date instanceof \DateTime) { $date = \DateTimeImmutable::createFromMutable($date); } $date = $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); return $this; } /** * Returns the age of the response in seconds. * * @final */ public function getAge(): int { if (null !== $age = $this->headers->get('Age')) { return (int) $age; } return max(time() - (int) $this->getDate()->format('U'), 0); } /** * Marks the response stale by setting the Age header to be equal to the maximum age of the response. * * @return $this */ public function expire() { if ($this->isFresh()) { $this->headers->set('Age', $this->getMaxAge()); $this->headers->remove('Expires'); } return $this; } /** * Returns the value of the Expires header as a DateTime instance. * * @final */ public function getExpires(): ?\DateTimeInterface { try { return $this->headers->getDate('Expires'); } catch (\RuntimeException $e) { // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past return \DateTime::createFromFormat('U', time() - 172800); } } /** * Sets the Expires HTTP header with a DateTime instance. * * Passing null as value will remove the header. * * @return $this * * @final */ public function setExpires(\DateTimeInterface $date = null): object { if (null === $date) { $this->headers->remove('Expires'); return $this; } if ($date instanceof \DateTime) { $date = \DateTimeImmutable::createFromMutable($date); } $date = $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); return $this; } /** * Returns the number of seconds after the time specified in the response's Date * header when the response should no longer be considered fresh. * * First, it checks for a s-maxage directive, then a max-age directive, and then it falls * back on an expires header. It returns null when no maximum age can be established. * * @final */ public function getMaxAge(): ?int { if ($this->headers->hasCacheControlDirective('s-maxage')) { return (int) $this->headers->getCacheControlDirective('s-maxage'); } if ($this->headers->hasCacheControlDirective('max-age')) { return (int) $this->headers->getCacheControlDirective('max-age'); } if (null !== $this->getExpires()) { return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U'); } return null; } /** * Sets the number of seconds after which the response should no longer be considered fresh. * * This methods sets the Cache-Control max-age directive. * * @return $this * * @final */ public function setMaxAge(int $value): object { $this->headers->addCacheControlDirective('max-age', $value); return $this; } /** * Sets the number of seconds after which the response should no longer be considered fresh by shared caches. * * This methods sets the Cache-Control s-maxage directive. * * @return $this * * @final */ public function setSharedMaxAge(int $value): object { $this->setPublic(); $this->headers->addCacheControlDirective('s-maxage', $value); return $this; } /** * Returns the response's time-to-live in seconds. * * It returns null when no freshness information is present in the response. * * When the responses TTL is <= 0, the response may not be served from cache without first * revalidating with the origin. * * @final */ public function getTtl(): ?int { $maxAge = $this->getMaxAge(); return null !== $maxAge ? $maxAge - $this->getAge() : null; } /** * Sets the response's time-to-live for shared caches in seconds. * * This method adjusts the Cache-Control/s-maxage directive. * * @return $this * * @final */ public function setTtl(int $seconds): object { $this->setSharedMaxAge($this->getAge() + $seconds); return $this; } /** * Sets the response's time-to-live for private/client caches in seconds. * * This method adjusts the Cache-Control/max-age directive. * * @return $this * * @final */ public function setClientTtl(int $seconds): object { $this->setMaxAge($this->getAge() + $seconds); return $this; } /** * Returns the Last-Modified HTTP header as a DateTime instance. * * @throws \RuntimeException When the HTTP header is not parseable * * @final */ public function getLastModified(): ?\DateTimeInterface { return $this->headers->getDate('Last-Modified'); } /** * Sets the Last-Modified HTTP header with a DateTime instance. * * Passing null as value will remove the header. * * @return $this * * @final */ public function setLastModified(\DateTimeInterface $date = null): object { if (null === $date) { $this->headers->remove('Last-Modified'); return $this; } if ($date instanceof \DateTime) { $date = \DateTimeImmutable::createFromMutable($date); } $date = $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); return $this; } /** * Returns the literal value of the ETag HTTP header. * * @final */ public function getEtag(): ?string { return $this->headers->get('ETag'); } /** * Sets the ETag value. * * @param string|null $etag The ETag unique identifier or null to remove the header * @param bool $weak Whether you want a weak ETag or not * * @return $this * * @final */ public function setEtag(string $etag = null, bool $weak = false): object { if (null === $etag) { $this->headers->remove('Etag'); } else { if (!str_starts_with($etag, '"')) { $etag = '"'.$etag.'"'; } $this->headers->set('ETag', (true === $weak ? 'W/' : '').$etag); } return $this; } /** * Sets the response's cache headers (validation and/or expiration). * * Available options are: must_revalidate, no_cache, no_store, no_transform, public, private, proxy_revalidate, max_age, s_maxage, immutable, last_modified and etag. * * @return $this * * @throws \InvalidArgumentException * * @final */ public function setCache(array $options): object { if ($diff = array_diff(array_keys($options), array_keys(self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES))) { throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', $diff))); } if (isset($options['etag'])) { $this->setEtag($options['etag']); } if (isset($options['last_modified'])) { $this->setLastModified($options['last_modified']); } if (isset($options['max_age'])) { $this->setMaxAge($options['max_age']); } if (isset($options['s_maxage'])) { $this->setSharedMaxAge($options['s_maxage']); } foreach (self::HTTP_RESPONSE_CACHE_CONTROL_DIRECTIVES as $directive => $hasValue) { if (!$hasValue && isset($options[$directive])) { if ($options[$directive]) { $this->headers->addCacheControlDirective(str_replace('_', '-', $directive)); } else { $this->headers->removeCacheControlDirective(str_replace('_', '-', $directive)); } } } if (isset($options['public'])) { if ($options['public']) { $this->setPublic(); } else { $this->setPrivate(); } } if (isset($options['private'])) { if ($options['private']) { $this->setPrivate(); } else { $this->setPublic(); } } return $this; } /** * Modifies the response so that it conforms to the rules defined for a 304 status code. * * This sets the status, removes the body, and discards any headers * that MUST NOT be included in 304 responses. * * @return $this * * @see https://tools.ietf.org/html/rfc2616#section-10.3.5 * * @final */ public function setNotModified(): object { $this->setStatusCode(304); $this->setContent(null); // remove headers that MUST NOT be included with 304 Not Modified responses foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) { $this->headers->remove($header); } return $this; } /** * Returns true if the response includes a Vary header. * * @final */ public function hasVary(): bool { return null !== $this->headers->get('Vary'); } /** * Returns an array of header names given in the Vary header. * * @final */ public function getVary(): array { if (!$vary = $this->headers->all('Vary')) { return []; } $ret = []; foreach ($vary as $item) { $ret[] = preg_split('/[\s,]+/', $item); } return array_merge([], ...$ret); } /** * Sets the Vary header. * * @param string|array $headers * @param bool $replace Whether to replace the actual value or not (true by default) * * @return $this * * @final */ public function setVary($headers, bool $replace = true): object { $this->headers->set('Vary', $headers, $replace); return $this; } /** * Determines if the Response validators (ETag, Last-Modified) match * a conditional value specified in the Request. * * If the Response is not modified, it sets the status code to 304 and * removes the actual content by calling the setNotModified() method. * * @final */ public function isNotModified(Request $request): bool { if (!$request->isMethodCacheable()) { return false; } $notModified = false; $lastModified = $this->headers->get('Last-Modified'); $modifiedSince = $request->headers->get('If-Modified-Since'); if ($ifNoneMatchEtags = $request->getETags()) { $etag = $this->getEtag(); if (0 == strncmp($etag, 'W/', 2)) { $etag = substr($etag, 2); } // Use weak comparison as per https://tools.ietf.org/html/rfc7232#section-3.2. foreach ($ifNoneMatchEtags as $ifNoneMatchEtag) { if (0 == strncmp($ifNoneMatchEtag, 'W/', 2)) { $ifNoneMatchEtag = substr($ifNoneMatchEtag, 2); } if ($ifNoneMatchEtag === $etag || '*' === $ifNoneMatchEtag) { $notModified = true; break; } } } // Only do If-Modified-Since date comparison when If-None-Match is not present as per https://tools.ietf.org/html/rfc7232#section-3.3. elseif ($modifiedSince && $lastModified) { $notModified = strtotime($modifiedSince) >= strtotime($lastModified); } if ($notModified) { $this->setNotModified(); } return $notModified; } /** * Is response invalid? * * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html * * @final */ public function isInvalid(): bool { return $this->statusCode < 100 || $this->statusCode >= 600; } /** * Is response informative? * * @final */ public function isInformational(): bool { return $this->statusCode >= 100 && $this->statusCode < 200; } /** * Is response successful? * * @final */ public function isSuccessful(): bool { return $this->statusCode >= 200 && $this->statusCode < 300; } /** * Is the response a redirect? * * @final */ public function isRedirection(): bool { return $this->statusCode >= 300 && $this->statusCode < 400; } /** * Is there a client error? * * @final */ public function isClientError(): bool { return $this->statusCode >= 400 && $this->statusCode < 500; } /** * Was there a server side error? * * @final */ public function isServerError(): bool { return $this->statusCode >= 500 && $this->statusCode < 600; } /** * Is the response OK? * * @final */ public function isOk(): bool { return 200 === $this->statusCode; } /** * Is the response forbidden? * * @final */ public function isForbidden(): bool { return 403 === $this->statusCode; } /** * Is the response a not found error? * * @final */ public function isNotFound(): bool { return 404 === $this->statusCode; } /** * Is the response a redirect of some form? * * @final */ public function isRedirect(string $location = null): bool { return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); } /** * Is the response empty? * * @final */ public function isEmpty(): bool { return \in_array($this->statusCode, [204, 304]); } /** * Cleans or flushes output buffers up to target level. * * Resulting level can be greater than target level if a non-removable buffer has been encountered. * * @final */ public static function closeOutputBuffers(int $targetLevel, bool $flush): void { $status = ob_get_status(true); $level = \count($status); $flags = \PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? \PHP_OUTPUT_HANDLER_FLUSHABLE : \PHP_OUTPUT_HANDLER_CLEANABLE); while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { if ($flush) { ob_end_flush(); } else { ob_end_clean(); } } } /** * Marks a response as safe according to RFC8674. * * @see https://tools.ietf.org/html/rfc8674 */ public function setContentSafe(bool $safe = true): void { if ($safe) { $this->headers->set('Preference-Applied', 'safe'); } elseif ('safe' === $this->headers->get('Preference-Applied')) { $this->headers->remove('Preference-Applied'); } $this->setVary('Prefer', false); } /** * Checks if we need to remove Cache-Control for SSL encrypted downloads when using IE < 9. * * @see http://support.microsoft.com/kb/323308 * * @final */ protected function ensureIEOverSSLCompatibility(Request $request): void { if (false !== stripos($this->headers->get('Content-Disposition') ?? '', 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT') ?? '', $match) && true === $request->isSecure()) { if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { $this->headers->remove('Cache-Control'); } } } } http-foundation/JsonResponse.php000064400000016645150432043210013036 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Response represents an HTTP response in JSON format. * * Note that this class does not force the returned JSON content to be an * object. It is however recommended that you do return an object as it * protects yourself against XSSI and JSON-JavaScript Hijacking. * * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside * * @author Igor Wiedler */ class JsonResponse extends Response { protected $data; protected $callback; // Encode <, >, ', &, and " characters in the JSON, making it also safe to be embedded into HTML. // 15 === JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT public const DEFAULT_ENCODING_OPTIONS = 15; protected $encodingOptions = self::DEFAULT_ENCODING_OPTIONS; /** * @param mixed $data The response data * @param int $status The response status code * @param array $headers An array of response headers * @param bool $json If the data is already a JSON string */ public function __construct($data = null, int $status = 200, array $headers = [], bool $json = false) { parent::__construct('', $status, $headers); if ($json && !\is_string($data) && !is_numeric($data) && !\is_callable([$data, '__toString'])) { throw new \TypeError(sprintf('"%s": If $json is set to true, argument $data must be a string or object implementing __toString(), "%s" given.', __METHOD__, get_debug_type($data))); } if (null === $data) { $data = new \ArrayObject(); } $json ? $this->setJson($data) : $this->setData($data); } /** * Factory method for chainability. * * Example: * * return JsonResponse::create(['key' => 'value']) * ->setSharedMaxAge(300); * * @param mixed $data The JSON response data * @param int $status The response status code * @param array $headers An array of response headers * * @return static * * @deprecated since Symfony 5.1, use __construct() instead. */ public static function create($data = null, int $status = 200, array $headers = []) { trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); return new static($data, $status, $headers); } /** * Factory method for chainability. * * Example: * * return JsonResponse::fromJsonString('{"key": "value"}') * ->setSharedMaxAge(300); * * @param string $data The JSON response string * @param int $status The response status code * @param array $headers An array of response headers * * @return static */ public static function fromJsonString(string $data, int $status = 200, array $headers = []) { return new static($data, $status, $headers, true); } /** * Sets the JSONP callback. * * @param string|null $callback The JSONP callback or null to use none * * @return $this * * @throws \InvalidArgumentException When the callback name is not valid */ public function setCallback(string $callback = null) { if (null !== $callback) { // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ // partially taken from https://github.com/willdurand/JsonpCallbackValidator // JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details. // (c) William Durand $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u'; $reserved = [ 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false', ]; $parts = explode('.', $callback); foreach ($parts as $part) { if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) { throw new \InvalidArgumentException('The callback name is not valid.'); } } } $this->callback = $callback; return $this->update(); } /** * Sets a raw string containing a JSON document to be sent. * * @return $this */ public function setJson(string $json) { $this->data = $json; return $this->update(); } /** * Sets the data to be sent as JSON. * * @param mixed $data * * @return $this * * @throws \InvalidArgumentException */ public function setData($data = []) { try { $data = json_encode($data, $this->encodingOptions); } catch (\Exception $e) { if ('Exception' === \get_class($e) && str_starts_with($e->getMessage(), 'Failed calling ')) { throw $e->getPrevious() ?: $e; } throw $e; } if (\PHP_VERSION_ID >= 70300 && (\JSON_THROW_ON_ERROR & $this->encodingOptions)) { return $this->setJson($data); } if (\JSON_ERROR_NONE !== json_last_error()) { throw new \InvalidArgumentException(json_last_error_msg()); } return $this->setJson($data); } /** * Returns options used while encoding data to JSON. * * @return int */ public function getEncodingOptions() { return $this->encodingOptions; } /** * Sets options used while encoding data to JSON. * * @return $this */ public function setEncodingOptions(int $encodingOptions) { $this->encodingOptions = $encodingOptions; return $this->setData(json_decode($this->data)); } /** * Updates the content and headers according to the JSON data and callback. * * @return $this */ protected function update() { if (null !== $this->callback) { // Not using application/javascript for compatibility reasons with older browsers. $this->headers->set('Content-Type', 'text/javascript'); return $this->setContent(sprintf('/**/%s(%s);', $this->callback, $this->data)); } // Only set the header when there is none or when it equals 'text/javascript' (from a previous update with callback) // in order to not overwrite a custom definition. if (!$this->headers->has('Content-Type') || 'text/javascript' === $this->headers->get('Content-Type')) { $this->headers->set('Content-Type', 'application/json'); } return $this->setContent($this->data); } } http-foundation/HeaderUtils.php000064400000022232150432043210012604 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * HTTP header utility functions. * * @author Christian Schmidt */ class HeaderUtils { public const DISPOSITION_ATTACHMENT = 'attachment'; public const DISPOSITION_INLINE = 'inline'; /** * This class should not be instantiated. */ private function __construct() { } /** * Splits an HTTP header by one or more separators. * * Example: * * HeaderUtils::split("da, en-gb;q=0.8", ",;") * // => ['da'], ['en-gb', 'q=0.8']] * * @param string $separators List of characters to split on, ordered by * precedence, e.g. ",", ";=", or ",;=" * * @return array Nested array with as many levels as there are characters in * $separators */ public static function split(string $header, string $separators): array { $quotedSeparators = preg_quote($separators, '/'); preg_match_all(' / (?!\s) (?: # quoted-string "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) | # token [^"'.$quotedSeparators.']+ )+ (?['.$quotedSeparators.']) \s* /x', trim($header), $matches, \PREG_SET_ORDER); return self::groupParts($matches, $separators); } /** * Combines an array of arrays into one associative array. * * Each of the nested arrays should have one or two elements. The first * value will be used as the keys in the associative array, and the second * will be used as the values, or true if the nested array only contains one * element. Array keys are lowercased. * * Example: * * HeaderUtils::combine([["foo", "abc"], ["bar"]]) * // => ["foo" => "abc", "bar" => true] */ public static function combine(array $parts): array { $assoc = []; foreach ($parts as $part) { $name = strtolower($part[0]); $value = $part[1] ?? true; $assoc[$name] = $value; } return $assoc; } /** * Joins an associative array into a string for use in an HTTP header. * * The key and value of each entry are joined with "=", and all entries * are joined with the specified separator and an additional space (for * readability). Values are quoted if necessary. * * Example: * * HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",") * // => 'foo=abc, bar, baz="a b c"' */ public static function toString(array $assoc, string $separator): string { $parts = []; foreach ($assoc as $name => $value) { if (true === $value) { $parts[] = $name; } else { $parts[] = $name.'='.self::quote($value); } } return implode($separator.' ', $parts); } /** * Encodes a string as a quoted string, if necessary. * * If a string contains characters not allowed by the "token" construct in * the HTTP specification, it is backslash-escaped and enclosed in quotes * to match the "quoted-string" construct. */ public static function quote(string $s): string { if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { return $s; } return '"'.addcslashes($s, '"\\"').'"'; } /** * Decodes a quoted string. * * If passed an unquoted string that matches the "token" construct (as * defined in the HTTP specification), it is passed through verbatimly. */ public static function unquote(string $s): string { return preg_replace('/\\\\(.)|"/', '$1', $s); } /** * Generates an HTTP Content-Disposition field-value. * * @param string $disposition One of "inline" or "attachment" * @param string $filename A unicode string * @param string $filenameFallback A string containing only ASCII characters that * is semantically equivalent to $filename. If the filename is already ASCII, * it can be omitted, or just copied from $filename * * @return string * * @throws \InvalidArgumentException * * @see RFC 6266 */ public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string { if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) { throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); } if ('' === $filenameFallback) { $filenameFallback = $filename; } // filenameFallback is not ASCII. if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); } // percent characters aren't safe in fallback. if (str_contains($filenameFallback, '%')) { throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); } // path separators aren't allowed in either. if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) { throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); } $params = ['filename' => $filenameFallback]; if ($filename !== $filenameFallback) { $params['filename*'] = "utf-8''".rawurlencode($filename); } return $disposition.'; '.self::toString($params, ';'); } /** * Like parse_str(), but preserves dots in variable names. */ public static function parseQuery(string $query, bool $ignoreBrackets = false, string $separator = '&'): array { $q = []; foreach (explode($separator, $query) as $v) { if (false !== $i = strpos($v, "\0")) { $v = substr($v, 0, $i); } if (false === $i = strpos($v, '=')) { $k = urldecode($v); $v = ''; } else { $k = urldecode(substr($v, 0, $i)); $v = substr($v, $i); } if (false !== $i = strpos($k, "\0")) { $k = substr($k, 0, $i); } $k = ltrim($k, ' '); if ($ignoreBrackets) { $q[$k][] = urldecode(substr($v, 1)); continue; } if (false === $i = strpos($k, '[')) { $q[] = bin2hex($k).$v; } else { $q[] = bin2hex(substr($k, 0, $i)).rawurlencode(substr($k, $i)).$v; } } if ($ignoreBrackets) { return $q; } parse_str(implode('&', $q), $q); $query = []; foreach ($q as $k => $v) { if (false !== $i = strpos($k, '_')) { $query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v; } else { $query[hex2bin($k)] = $v; } } return $query; } private static function groupParts(array $matches, string $separators, bool $first = true): array { $separator = $separators[0]; $partSeparators = substr($separators, 1); $i = 0; $partMatches = []; $previousMatchWasSeparator = false; foreach ($matches as $match) { if (!$first && $previousMatchWasSeparator && isset($match['separator']) && $match['separator'] === $separator) { $previousMatchWasSeparator = true; $partMatches[$i][] = $match; } elseif (isset($match['separator']) && $match['separator'] === $separator) { $previousMatchWasSeparator = true; ++$i; } else { $previousMatchWasSeparator = false; $partMatches[$i][] = $match; } } $parts = []; if ($partSeparators) { foreach ($partMatches as $matches) { $parts[] = self::groupParts($matches, $partSeparators, false); } } else { foreach ($partMatches as $matches) { $parts[] = self::unquote($matches[0][0]); } if (!$first && 2 < \count($parts)) { $parts = [ $parts[0], implode($separator, \array_slice($parts, 1)), ]; } } return $parts; } } http-foundation/ExpressionRequestMatcher.php000064400000002512150432043210015406 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; /** * ExpressionRequestMatcher uses an expression to match a Request. * * @author Fabien Potencier */ class ExpressionRequestMatcher extends RequestMatcher { private $language; private $expression; public function setExpression(ExpressionLanguage $language, $expression) { $this->language = $language; $this->expression = $expression; } public function matches(Request $request) { if (!$this->language) { throw new \LogicException('Unable to match the request as the expression language is not available.'); } return $this->language->evaluate($this->expression, [ 'request' => $request, 'method' => $request->getMethod(), 'path' => rawurldecode($request->getPathInfo()), 'host' => $request->getHost(), 'ip' => $request->getClientIp(), 'attributes' => $request->attributes->all(), ]) && parent::matches($request); } } http-foundation/Cookie.php000064400000026543150432043210011615 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents a cookie. * * @author Johannes M. Schmitt */ class Cookie { public const SAMESITE_NONE = 'none'; public const SAMESITE_LAX = 'lax'; public const SAMESITE_STRICT = 'strict'; protected $name; protected $value; protected $domain; protected $expire; protected $path; protected $secure; protected $httpOnly; private $raw; private $sameSite; private $secureDefault = false; private const RESERVED_CHARS_LIST = "=,; \t\r\n\v\f"; private const RESERVED_CHARS_FROM = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"]; private const RESERVED_CHARS_TO = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C']; /** * Creates cookie from raw header string. * * @return static */ public static function fromString(string $cookie, bool $decode = false) { $data = [ 'expires' => 0, 'path' => '/', 'domain' => null, 'secure' => false, 'httponly' => false, 'raw' => !$decode, 'samesite' => null, ]; $parts = HeaderUtils::split($cookie, ';='); $part = array_shift($parts); $name = $decode ? urldecode($part[0]) : $part[0]; $value = isset($part[1]) ? ($decode ? urldecode($part[1]) : $part[1]) : null; $data = HeaderUtils::combine($parts) + $data; $data['expires'] = self::expiresTimestamp($data['expires']); if (isset($data['max-age']) && ($data['max-age'] > 0 || $data['expires'] > time())) { $data['expires'] = time() + (int) $data['max-age']; } return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); } public static function create(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self { return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite); } /** * @param string $name The name of the cookie * @param string|null $value The value of the cookie * @param int|string|\DateTimeInterface $expire The time the cookie expires * @param string $path The path on the server in which the cookie will be available on * @param string|null $domain The domain that the cookie is available to * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol * @param bool $raw Whether the cookie value should be sent with no url encoding * @param string|null $sameSite Whether the cookie will be available for cross-site requests * * @throws \InvalidArgumentException */ public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = 'lax') { // from PHP source code if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) { throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); } if (empty($name)) { throw new \InvalidArgumentException('The cookie name cannot be empty.'); } $this->name = $name; $this->value = $value; $this->domain = $domain; $this->expire = self::expiresTimestamp($expire); $this->path = empty($path) ? '/' : $path; $this->secure = $secure; $this->httpOnly = $httpOnly; $this->raw = $raw; $this->sameSite = $this->withSameSite($sameSite)->sameSite; } /** * Creates a cookie copy with a new value. * * @return static */ public function withValue(?string $value): self { $cookie = clone $this; $cookie->value = $value; return $cookie; } /** * Creates a cookie copy with a new domain that the cookie is available to. * * @return static */ public function withDomain(?string $domain): self { $cookie = clone $this; $cookie->domain = $domain; return $cookie; } /** * Creates a cookie copy with a new time the cookie expires. * * @param int|string|\DateTimeInterface $expire * * @return static */ public function withExpires($expire = 0): self { $cookie = clone $this; $cookie->expire = self::expiresTimestamp($expire); return $cookie; } /** * Converts expires formats to a unix timestamp. * * @param int|string|\DateTimeInterface $expire */ private static function expiresTimestamp($expire = 0): int { // convert expiration time to a Unix timestamp if ($expire instanceof \DateTimeInterface) { $expire = $expire->format('U'); } elseif (!is_numeric($expire)) { $expire = strtotime($expire); if (false === $expire) { throw new \InvalidArgumentException('The cookie expiration time is not valid.'); } } return 0 < $expire ? (int) $expire : 0; } /** * Creates a cookie copy with a new path on the server in which the cookie will be available on. * * @return static */ public function withPath(string $path): self { $cookie = clone $this; $cookie->path = '' === $path ? '/' : $path; return $cookie; } /** * Creates a cookie copy that only be transmitted over a secure HTTPS connection from the client. * * @return static */ public function withSecure(bool $secure = true): self { $cookie = clone $this; $cookie->secure = $secure; return $cookie; } /** * Creates a cookie copy that be accessible only through the HTTP protocol. * * @return static */ public function withHttpOnly(bool $httpOnly = true): self { $cookie = clone $this; $cookie->httpOnly = $httpOnly; return $cookie; } /** * Creates a cookie copy that uses no url encoding. * * @return static */ public function withRaw(bool $raw = true): self { if ($raw && false !== strpbrk($this->name, self::RESERVED_CHARS_LIST)) { throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $this->name)); } $cookie = clone $this; $cookie->raw = $raw; return $cookie; } /** * Creates a cookie copy with SameSite attribute. * * @return static */ public function withSameSite(?string $sameSite): self { if ('' === $sameSite) { $sameSite = null; } elseif (null !== $sameSite) { $sameSite = strtolower($sameSite); } if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) { throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); } $cookie = clone $this; $cookie->sameSite = $sameSite; return $cookie; } /** * Returns the cookie as a string. * * @return string */ public function __toString() { if ($this->isRaw()) { $str = $this->getName(); } else { $str = str_replace(self::RESERVED_CHARS_FROM, self::RESERVED_CHARS_TO, $this->getName()); } $str .= '='; if ('' === (string) $this->getValue()) { $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; } else { $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); if (0 !== $this->getExpiresTime()) { $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); } } if ($this->getPath()) { $str .= '; path='.$this->getPath(); } if ($this->getDomain()) { $str .= '; domain='.$this->getDomain(); } if (true === $this->isSecure()) { $str .= '; secure'; } if (true === $this->isHttpOnly()) { $str .= '; httponly'; } if (null !== $this->getSameSite()) { $str .= '; samesite='.$this->getSameSite(); } return $str; } /** * Gets the name of the cookie. * * @return string */ public function getName() { return $this->name; } /** * Gets the value of the cookie. * * @return string|null */ public function getValue() { return $this->value; } /** * Gets the domain that the cookie is available to. * * @return string|null */ public function getDomain() { return $this->domain; } /** * Gets the time the cookie expires. * * @return int */ public function getExpiresTime() { return $this->expire; } /** * Gets the max-age attribute. * * @return int */ public function getMaxAge() { $maxAge = $this->expire - time(); return 0 >= $maxAge ? 0 : $maxAge; } /** * Gets the path on the server in which the cookie will be available on. * * @return string */ public function getPath() { return $this->path; } /** * Checks whether the cookie should only be transmitted over a secure HTTPS connection from the client. * * @return bool */ public function isSecure() { return $this->secure ?? $this->secureDefault; } /** * Checks whether the cookie will be made accessible only through the HTTP protocol. * * @return bool */ public function isHttpOnly() { return $this->httpOnly; } /** * Whether this cookie is about to be cleared. * * @return bool */ public function isCleared() { return 0 !== $this->expire && $this->expire < time(); } /** * Checks if the cookie value should be sent with no url encoding. * * @return bool */ public function isRaw() { return $this->raw; } /** * Gets the SameSite attribute. * * @return string|null */ public function getSameSite() { return $this->sameSite; } /** * @param bool $default The default value of the "secure" flag when it is set to null */ public function setSecureDefault(bool $default): void { $this->secureDefault = $default; } } http-foundation/RequestMatcherInterface.php000064400000001202150432043210015142 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RequestMatcherInterface is an interface for strategies to match a Request. * * @author Fabien Potencier */ interface RequestMatcherInterface { /** * Decides whether the rule(s) implemented by the strategy matches the supplied request. * * @return bool */ public function matches(Request $request); } http-foundation/AcceptHeaderItem.php000064400000006520150432043210013524 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Represents an Accept-* header item. * * @author Jean-François Simon */ class AcceptHeaderItem { private $value; private $quality = 1.0; private $index = 0; private $attributes = []; public function __construct(string $value, array $attributes = []) { $this->value = $value; foreach ($attributes as $name => $value) { $this->setAttribute($name, $value); } } /** * Builds an AcceptHeaderInstance instance from a string. * * @return self */ public static function fromString(?string $itemValue) { $parts = HeaderUtils::split($itemValue ?? '', ';='); $part = array_shift($parts); $attributes = HeaderUtils::combine($parts); return new self($part[0], $attributes); } /** * Returns header value's string representation. * * @return string */ public function __toString() { $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); if (\count($this->attributes) > 0) { $string .= '; '.HeaderUtils::toString($this->attributes, ';'); } return $string; } /** * Set the item value. * * @return $this */ public function setValue(string $value) { $this->value = $value; return $this; } /** * Returns the item value. * * @return string */ public function getValue() { return $this->value; } /** * Set the item quality. * * @return $this */ public function setQuality(float $quality) { $this->quality = $quality; return $this; } /** * Returns the item quality. * * @return float */ public function getQuality() { return $this->quality; } /** * Set the item index. * * @return $this */ public function setIndex(int $index) { $this->index = $index; return $this; } /** * Returns the item index. * * @return int */ public function getIndex() { return $this->index; } /** * Tests if an attribute exists. * * @return bool */ public function hasAttribute(string $name) { return isset($this->attributes[$name]); } /** * Returns an attribute by its name. * * @param mixed $default * * @return mixed */ public function getAttribute(string $name, $default = null) { return $this->attributes[$name] ?? $default; } /** * Returns all attributes. * * @return array */ public function getAttributes() { return $this->attributes; } /** * Set an attribute. * * @return $this */ public function setAttribute(string $name, string $value) { if ('q' === $name) { $this->quality = (float) $value; } else { $this->attributes[$name] = $value; } return $this; } } http-foundation/StreamedResponse.php000064400000006101150432043210013653 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * StreamedResponse represents a streamed HTTP response. * * A StreamedResponse uses a callback for its content. * * The callback should use the standard PHP functions like echo * to stream the response back to the client. The flush() function * can also be used if needed. * * @see flush() * * @author Fabien Potencier */ class StreamedResponse extends Response { protected $callback; protected $streamed; private $headersSent; public function __construct(callable $callback = null, int $status = 200, array $headers = []) { parent::__construct(null, $status, $headers); if (null !== $callback) { $this->setCallback($callback); } $this->streamed = false; $this->headersSent = false; } /** * Factory method for chainability. * * @param callable|null $callback A valid PHP callback or null to set it later * * @return static * * @deprecated since Symfony 5.1, use __construct() instead. */ public static function create($callback = null, int $status = 200, array $headers = []) { trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); return new static($callback, $status, $headers); } /** * Sets the PHP callback associated with this Response. * * @return $this */ public function setCallback(callable $callback) { $this->callback = $callback; return $this; } /** * {@inheritdoc} * * This method only sends the headers once. * * @return $this */ public function sendHeaders() { if ($this->headersSent) { return $this; } $this->headersSent = true; return parent::sendHeaders(); } /** * {@inheritdoc} * * This method only sends the content once. * * @return $this */ public function sendContent() { if ($this->streamed) { return $this; } $this->streamed = true; if (null === $this->callback) { throw new \LogicException('The Response callback must not be null.'); } ($this->callback)(); return $this; } /** * {@inheritdoc} * * @throws \LogicException when the content is not null * * @return $this */ public function setContent(?string $content) { if (null !== $content) { throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); } $this->streamed = true; return $this; } /** * {@inheritdoc} */ public function getContent() { return false; } } http-foundation/FileBag.php000064400000007525150432043210011674 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * FileBag is a container for uploaded files. * * @author Fabien Potencier * @author Bulat Shakirzyanov */ class FileBag extends ParameterBag { private const FILE_KEYS = ['error', 'name', 'size', 'tmp_name', 'type']; /** * @param array|UploadedFile[] $parameters An array of HTTP files */ public function __construct(array $parameters = []) { $this->replace($parameters); } /** * {@inheritdoc} */ public function replace(array $files = []) { $this->parameters = []; $this->add($files); } /** * {@inheritdoc} */ public function set(string $key, $value) { if (!\is_array($value) && !$value instanceof UploadedFile) { throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); } parent::set($key, $this->convertFileInformation($value)); } /** * {@inheritdoc} */ public function add(array $files = []) { foreach ($files as $key => $file) { $this->set($key, $file); } } /** * Converts uploaded files to UploadedFile instances. * * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information * * @return UploadedFile[]|UploadedFile|null */ protected function convertFileInformation($file) { if ($file instanceof UploadedFile) { return $file; } $file = $this->fixPhpFilesArray($file); $keys = array_keys($file); sort($keys); if (self::FILE_KEYS == $keys) { if (\UPLOAD_ERR_NO_FILE == $file['error']) { $file = null; } else { $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false); } } else { $file = array_map(function ($v) { return $v instanceof UploadedFile || \is_array($v) ? $this->convertFileInformation($v) : $v; }, $file); if (array_keys($keys) === $keys) { $file = array_filter($file); } } return $file; } /** * Fixes a malformed PHP $_FILES array. * * PHP has a bug that the format of the $_FILES array differs, depending on * whether the uploaded file fields had normal field names or array-like * field names ("normal" vs. "parent[child]"). * * This method fixes the array to look like the "normal" $_FILES array. * * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * * @return array */ protected function fixPhpFilesArray(array $data) { // Remove extra key added by PHP 8.1. unset($data['full_path']); $keys = array_keys($data); sort($keys); if (self::FILE_KEYS != $keys || !isset($data['name']) || !\is_array($data['name'])) { return $data; } $files = $data; foreach (self::FILE_KEYS as $k) { unset($files[$k]); } foreach ($data['name'] as $key => $name) { $files[$key] = $this->fixPhpFilesArray([ 'error' => $data['error'][$key], 'name' => $name, 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key], ]); } return $files; } } http-foundation/CHANGELOG.md000064400000036504150432043210011502 0ustar00CHANGELOG ========= 5.4 --- * Deprecate passing `null` as `$requestIp` to `IpUtils::__checkIp()`, `IpUtils::__checkIp4()` or `IpUtils::__checkIp6()`, pass an empty string instead. * Add the `litespeed_finish_request` method to work with Litespeed * Deprecate `upload_progress.*` and `url_rewriter.tags` session options * Allow setting session options via DSN 5.3 --- * Add the `SessionFactory`, `NativeSessionStorageFactory`, `PhpBridgeSessionStorageFactory` and `MockFileSessionStorageFactory` classes * Calling `Request::getSession()` when there is no available session throws a `SessionNotFoundException` * Add the `RequestStack::getSession` method * Deprecate the `NamespacedAttributeBag` class * Add `ResponseFormatSame` PHPUnit constraint * Deprecate the `RequestStack::getMasterRequest()` method and add `getMainRequest()` as replacement 5.2.0 ----- * added support for `X-Forwarded-Prefix` header * added `HeaderUtils::parseQuery()`: it does the same as `parse_str()` but preserves dots in variable names * added `File::getContent()` * added ability to use comma separated ip addresses for `RequestMatcher::matchIps()` * added `Request::toArray()` to parse a JSON request body to an array * added `RateLimiter\RequestRateLimiterInterface` and `RateLimiter\AbstractRequestRateLimiter` * deprecated not passing a `Closure` together with `FILTER_CALLBACK` to `ParameterBag::filter()`; wrap your filter in a closure instead. * Deprecated the `Request::HEADER_X_FORWARDED_ALL` constant, use either `HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO` or `HEADER_X_FORWARDED_AWS_ELB` or `HEADER_X_FORWARDED_TRAEFIK` constants instead. * Deprecated `BinaryFileResponse::create()`, use `__construct()` instead 5.1.0 ----- * added `Cookie::withValue`, `Cookie::withDomain`, `Cookie::withExpires`, `Cookie::withPath`, `Cookie::withSecure`, `Cookie::withHttpOnly`, `Cookie::withRaw`, `Cookie::withSameSite` * Deprecate `Response::create()`, `JsonResponse::create()`, `RedirectResponse::create()`, and `StreamedResponse::create()` methods (use `__construct()` instead) * added `Request::preferSafeContent()` and `Response::setContentSafe()` to handle "safe" HTTP preference according to [RFC 8674](https://tools.ietf.org/html/rfc8674) * made the Mime component an optional dependency * added `MarshallingSessionHandler`, `IdentityMarshaller` * made `Session` accept a callback to report when the session is being used * Add support for all core cache control directives * Added `Symfony\Component\HttpFoundation\InputBag` * Deprecated retrieving non-string values using `InputBag::get()`, use `InputBag::all()` if you need access to the collection of values 5.0.0 ----- * made `Cookie` auto-secure and lax by default * removed classes in the `MimeType` namespace, use the Symfony Mime component instead * removed method `UploadedFile::getClientSize()` and the related constructor argument * made `Request::getSession()` throw if the session has not been set before * removed `Response::HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL` * passing a null url when instantiating a `RedirectResponse` is not allowed 4.4.0 ----- * passing arguments to `Request::isMethodSafe()` is deprecated. * `ApacheRequest` is deprecated, use the `Request` class instead. * passing a third argument to `HeaderBag::get()` is deprecated, use method `all()` instead * [BC BREAK] `PdoSessionHandler` with MySQL changed the type of the lifetime column, make sure to run `ALTER TABLE sessions MODIFY sess_lifetime INTEGER UNSIGNED NOT NULL` to update your database. * `PdoSessionHandler` now precalculates the expiry timestamp in the lifetime column, make sure to run `CREATE INDEX EXPIRY ON sessions (sess_lifetime)` to update your database to speed up garbage collection of expired sessions. * added `SessionHandlerFactory` to create session handlers with a DSN * added `IpUtils::anonymize()` to help with GDPR compliance. 4.3.0 ----- * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`, `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame` * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`. * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`. * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`. * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`. * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path 4.2.0 ----- * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor will respectively change from "false" to "null" and from "null" to "lax" in Symfony 5.0, you should define their values explicitly or use "Cookie::create()" instead. * added `matchPort()` in RequestMatcher 4.1.3 ----- * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL` HTTP headers has been dropped for security reasons. 4.1.0 ----- * Query string normalization uses `parse_str()` instead of custom parsing logic. * Passing the file size to the constructor of the `UploadedFile` class is deprecated. * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead. * added `RedisSessionHandler` to use Redis as a session storage * The `get()` method of the `AcceptHeader` class now takes into account the `*` and `*/*` default values (if they are present in the Accept HTTP header) when looking for items. * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead. * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`, `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to handle failed `UploadedFile`. * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions * added `HeaderUtils`. 4.0.0 ----- * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods have been removed * the `Request::HEADER_CLIENT_IP` constant has been removed, use `Request::HEADER_X_FORWARDED_FOR` instead * the `Request::HEADER_CLIENT_HOST` constant has been removed, use `Request::HEADER_X_FORWARDED_HOST` instead * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use `Request::HEADER_X_FORWARDED_PROTO` instead * the `Request::HEADER_CLIENT_PORT` constant has been removed, use `Request::HEADER_X_FORWARDED_PORT` instead * checking for cacheable HTTP methods using the `Request::isMethodSafe()` method (by not passing `false` as its argument) is not supported anymore and throws a `\BadMethodCallException` * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed * setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a `\TypeError` 3.4.0 ----- * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead 3.3.0 ----- * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, see https://symfony.com/doc/current/deployment/proxies.html for more info, * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, disabling `Range` and `Content-Length` handling, switching to chunked encoding instead * added the `Cookie::fromString()` method that allows to create a cookie from a raw header string 3.1.0 ----- * Added support for creating `JsonResponse` with a string of JSON data 3.0.0 ----- * The precedence of parameters returned from `Request::get()` changed from "GET, PATH, BODY" to "PATH, GET, BODY" 2.8.0 ----- * Finding deep items in `ParameterBag::get()` is deprecated since version 2.8 and will be removed in 3.0. 2.6.0 ----- * PdoSessionHandler changes - implemented different session locking strategies to prevent loss of data by concurrent access to the same session - [BC BREAK] save session data in a binary column without base64_encode - [BC BREAK] added lifetime column to the session table which allows to have different lifetimes for each session - implemented lazy connections that are only opened when a session is used by either passing a dsn string explicitly or falling back to session.save_path ini setting - added a createTable method that initializes a correctly defined table depending on the database vendor 2.5.0 ----- * added `JsonResponse::setEncodingOptions()` & `JsonResponse::getEncodingOptions()` for easier manipulation of the options used while encoding data to JSON format. 2.4.0 ----- * added RequestStack * added Request::getEncodings() * added accessors methods to session handlers 2.3.0 ----- * added support for ranges of IPs in trusted proxies * `UploadedFile::isValid` now returns false if the file was not uploaded via HTTP (in a non-test mode) * Improved error-handling of `\Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` to ensure the supplied PDO handler throws Exceptions on error (as the class expects). Added related test cases to verify that Exceptions are properly thrown when the PDO queries fail. 2.2.0 ----- * fixed the Request::create() precedence (URI information always take precedence now) * added Request::getTrustedProxies() * deprecated Request::isProxyTrusted() * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects * added a IpUtils class to check if an IP belongs to a CIDR * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method) * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to enable it, and Request::getHttpMethodParameterOverride() to check if it is supported) * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3 * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3 2.1.0 ----- * added Request::getSchemeAndHttpHost() and Request::getUserInfo() * added a fluent interface to the Response class * added Request::isProxyTrusted() * added JsonResponse * added a getTargetUrl method to RedirectResponse * added support for streamed responses * made Response::prepare() method the place to enforce HTTP specification * [BC BREAK] moved management of the locale from the Session class to the Request class * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter() * made FileBinaryMimeTypeGuesser command configurable * added Request::getUser() and Request::getPassword() * added support for the PATCH method in Request * removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3 * added ResponseHeaderBag::makeDisposition() (implements RFC 6266) * made mimetype to extension conversion configurable * [BC BREAK] Moved all session related classes and interfaces into own namespace, as `Symfony\Component\HttpFoundation\Session` and renamed classes accordingly. Session handlers are located in the subnamespace `Symfony\Component\HttpFoundation\Session\Handler`. * SessionHandlers must implement `\SessionHandlerInterface` or extend from the `Symfony\Component\HttpFoundation\Storage\Handler\NativeSessionHandler` base class. * Added internal storage driver proxy mechanism for forward compatibility with PHP 5.4 `\SessionHandler` class. * Added session handlers for custom Memcache, Memcached and Null session save handlers. * [BC BREAK] Removed `NativeSessionStorage` and replaced with `NativeFileSessionHandler`. * [BC BREAK] `SessionStorageInterface` methods removed: `write()`, `read()` and `remove()`. Added `getBag()`, `registerBag()`. The `NativeSessionStorage` class is a mediator for the session storage internals including the session handlers which do the real work of participating in the internal PHP session workflow. * [BC BREAK] Introduced mock implementations of `SessionStorage` to enable unit and functional testing without starting real PHP sessions. Removed `ArraySessionStorage`, and replaced with `MockArraySessionStorage` for unit tests; removed `FilesystemSessionStorage`, and replaced with`MockFileSessionStorage` for functional tests. These do not interact with global session ini configuration values, session functions or `$_SESSION` superglobal. This means they can be configured directly allowing multiple instances to work without conflicting in the same PHP process. * [BC BREAK] Removed the `close()` method from the `Session` class, as this is now redundant. * Deprecated the following methods from the Session class: `setFlash()`, `setFlashes()` `getFlash()`, `hasFlash()`, and `removeFlash()`. Use `getFlashBag()` instead which returns a `FlashBagInterface`. * `Session->clear()` now only clears session attributes as before it cleared flash messages and attributes. `Session->getFlashBag()->all()` clears flashes now. * Session data is now managed by `SessionBagInterface` to better encapsulate session data. * Refactored session attribute and flash messages system to their own `SessionBagInterface` implementations. * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This implementation is ESI compatible. * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire behavior of messages auto expiring after one page page load. Messages must be retrieved by `get()` or `all()`. * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate attributes storage behavior from 2.0.x (default). * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for namespace session attributes. * Flash API can stores messages in an array so there may be multiple messages per flash type. The old `Session` class API remains without BC break as it will allow single messages as before. * Added basic session meta-data to the session to record session create time, last updated time, and the lifetime of the session cookie that was provided to the client. * Request::getClientIp() method doesn't take a parameter anymore but bases itself on the trustProxy parameter. * Added isMethod() to Request object. * [BC BREAK] The methods `getPathInfo()`, `getBaseUrl()` and `getBasePath()` of a `Request` now all return a raw value (vs a urldecoded value before). Any call to one of these methods must be checked and wrapped in a `rawurldecode()` if needed. http-foundation/File/Stream.php000064400000001066150432043210012507 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File; /** * A PHP stream of unknown size. * * @author Nicolas Grekas */ class Stream extends File { /** * {@inheritdoc} * * @return int|false */ #[\ReturnTypeWillChange] public function getSize() { return false; } } http-foundation/File/UploadedFile.php000064400000023576150432043210013623 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; use Symfony\Component\HttpFoundation\File\Exception\NoFileException; use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; use Symfony\Component\Mime\MimeTypes; /** * A file uploaded through a form. * * @author Bernhard Schussek * @author Florian Eckerstorfer * @author Fabien Potencier */ class UploadedFile extends File { private $test; private $originalName; private $mimeType; private $error; /** * Accepts the information of the uploaded file as provided by the PHP global $_FILES. * * The file object is only created when the uploaded file is valid (i.e. when the * isValid() method returns true). Otherwise the only methods that could be called * on an UploadedFile instance are: * * * getClientOriginalName, * * getClientMimeType, * * isValid, * * getError. * * Calling any other method on an non-valid instance will cause an unpredictable result. * * @param string $path The full temporary path to the file * @param string $originalName The original file name of the uploaded file * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK * @param bool $test Whether the test mode is active * Local files are used in test mode hence the code should not enforce HTTP uploads * * @throws FileException If file_uploads is disabled * @throws FileNotFoundException If the file does not exist */ public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false) { $this->originalName = $this->getName($originalName); $this->mimeType = $mimeType ?: 'application/octet-stream'; $this->error = $error ?: \UPLOAD_ERR_OK; $this->test = $test; parent::__construct($path, \UPLOAD_ERR_OK === $this->error); } /** * Returns the original file name. * * It is extracted from the request from which the file has been uploaded. * Then it should not be considered as a safe value. * * @return string */ public function getClientOriginalName() { return $this->originalName; } /** * Returns the original file extension. * * It is extracted from the original file name that was uploaded. * Then it should not be considered as a safe value. * * @return string */ public function getClientOriginalExtension() { return pathinfo($this->originalName, \PATHINFO_EXTENSION); } /** * Returns the file mime type. * * The client mime type is extracted from the request from which the file * was uploaded, so it should not be considered as a safe value. * * For a trusted mime type, use getMimeType() instead (which guesses the mime * type based on the file content). * * @return string * * @see getMimeType() */ public function getClientMimeType() { return $this->mimeType; } /** * Returns the extension based on the client mime type. * * If the mime type is unknown, returns null. * * This method uses the mime type as guessed by getClientMimeType() * to guess the file extension. As such, the extension returned * by this method cannot be trusted. * * For a trusted extension, use guessExtension() instead (which guesses * the extension based on the guessed mime type for the file). * * @return string|null * * @see guessExtension() * @see getClientMimeType() */ public function guessClientExtension() { if (!class_exists(MimeTypes::class)) { throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); } return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null; } /** * Returns the upload error. * * If the upload was successful, the constant UPLOAD_ERR_OK is returned. * Otherwise one of the other UPLOAD_ERR_XXX constants is returned. * * @return int */ public function getError() { return $this->error; } /** * Returns whether the file has been uploaded with HTTP and no error occurred. * * @return bool */ public function isValid() { $isOk = \UPLOAD_ERR_OK === $this->error; return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); } /** * Moves the file to a new location. * * @return File * * @throws FileException if, for any reason, the file could not have been moved */ public function move(string $directory, string $name = null) { if ($this->isValid()) { if ($this->test) { return parent::move($directory, $name); } $target = $this->getTargetFile($directory, $name); set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); try { $moved = move_uploaded_file($this->getPathname(), $target); } finally { restore_error_handler(); } if (!$moved) { throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); return $target; } switch ($this->error) { case \UPLOAD_ERR_INI_SIZE: throw new IniSizeFileException($this->getErrorMessage()); case \UPLOAD_ERR_FORM_SIZE: throw new FormSizeFileException($this->getErrorMessage()); case \UPLOAD_ERR_PARTIAL: throw new PartialFileException($this->getErrorMessage()); case \UPLOAD_ERR_NO_FILE: throw new NoFileException($this->getErrorMessage()); case \UPLOAD_ERR_CANT_WRITE: throw new CannotWriteFileException($this->getErrorMessage()); case \UPLOAD_ERR_NO_TMP_DIR: throw new NoTmpDirFileException($this->getErrorMessage()); case \UPLOAD_ERR_EXTENSION: throw new ExtensionFileException($this->getErrorMessage()); } throw new FileException($this->getErrorMessage()); } /** * Returns the maximum size of an uploaded file as configured in php.ini. * * @return int|float The maximum size of an uploaded file in bytes (returns float if size > PHP_INT_MAX) */ public static function getMaxFilesize() { $sizePostMax = self::parseFilesize(ini_get('post_max_size')); $sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize')); return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX); } /** * Returns the given size from an ini value in bytes. * * @return int|float Returns float if size > PHP_INT_MAX */ private static function parseFilesize(string $size) { if ('' === $size) { return 0; } $size = strtolower($size); $max = ltrim($size, '+'); if (str_starts_with($max, '0x')) { $max = \intval($max, 16); } elseif (str_starts_with($max, '0')) { $max = \intval($max, 8); } else { $max = (int) $max; } switch (substr($size, -1)) { case 't': $max *= 1024; // no break case 'g': $max *= 1024; // no break case 'm': $max *= 1024; // no break case 'k': $max *= 1024; } return $max; } /** * Returns an informative upload error message. * * @return string */ public function getErrorMessage() { static $errors = [ \UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', \UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', \UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', \UPLOAD_ERR_NO_FILE => 'No file was uploaded.', \UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', \UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', \UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', ]; $errorCode = $this->error; $maxFilesize = \UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; $message = $errors[$errorCode] ?? 'The file "%s" was not uploaded due to an unknown error.'; return sprintf($message, $this->getClientOriginalName(), $maxFilesize); } } http-foundation/File/File.php000064400000010730150432043210012131 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\Mime\MimeTypes; /** * A file in the file system. * * @author Bernhard Schussek */ class File extends \SplFileInfo { /** * Constructs a new file from the given path. * * @param string $path The path to the file * @param bool $checkPath Whether to check the path or not * * @throws FileNotFoundException If the given path is not a file */ public function __construct(string $path, bool $checkPath = true) { if ($checkPath && !is_file($path)) { throw new FileNotFoundException($path); } parent::__construct($path); } /** * Returns the extension based on the mime type. * * If the mime type is unknown, returns null. * * This method uses the mime type as guessed by getMimeType() * to guess the file extension. * * @return string|null * * @see MimeTypes * @see getMimeType() */ public function guessExtension() { if (!class_exists(MimeTypes::class)) { throw new \LogicException('You cannot guess the extension as the Mime component is not installed. Try running "composer require symfony/mime".'); } return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null; } /** * Returns the mime type of the file. * * The mime type is guessed using a MimeTypeGuesserInterface instance, * which uses finfo_file() then the "file" system binary, * depending on which of those are available. * * @return string|null * * @see MimeTypes */ public function getMimeType() { if (!class_exists(MimeTypes::class)) { throw new \LogicException('You cannot guess the mime type as the Mime component is not installed. Try running "composer require symfony/mime".'); } return MimeTypes::getDefault()->guessMimeType($this->getPathname()); } /** * Moves the file to a new location. * * @return self * * @throws FileException if the target file could not be created */ public function move(string $directory, string $name = null) { $target = $this->getTargetFile($directory, $name); set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); try { $renamed = rename($this->getPathname(), $target); } finally { restore_error_handler(); } if (!$renamed) { throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s).', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); return $target; } public function getContent(): string { $content = file_get_contents($this->getPathname()); if (false === $content) { throw new FileException(sprintf('Could not get the content of the file "%s".', $this->getPathname())); } return $content; } /** * @return self */ protected function getTargetFile(string $directory, string $name = null) { if (!is_dir($directory)) { if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { throw new FileException(sprintf('Unable to create the "%s" directory.', $directory)); } } elseif (!is_writable($directory)) { throw new FileException(sprintf('Unable to write in the "%s" directory.', $directory)); } $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); return new self($target, false); } /** * Returns locale independent base name of the given path. * * @return string */ protected function getName(string $name) { $originalName = str_replace('\\', '/', $name); $pos = strrpos($originalName, '/'); $originalName = false === $pos ? $originalName : substr($originalName, $pos + 1); return $originalName; } } http-foundation/File/Exception/IniSizeFileException.php000064400000000742150432043210017243 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile. * * @author Florent Mata */ class IniSizeFileException extends FileException { } http-foundation/File/Exception/CannotWriteFileException.php000064400000000750150432043210020125 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile. * * @author Florent Mata */ class CannotWriteFileException extends FileException { } http-foundation/File/Exception/FileException.php000064400000000722150432043210015746 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an error occurred in the component File. * * @author Bernhard Schussek */ class FileException extends \RuntimeException { } http-foundation/File/Exception/PartialFileException.php000064400000000741150432043210017264 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile. * * @author Florent Mata */ class PartialFileException extends FileException { } http-foundation/File/Exception/AccessDeniedException.php000064400000001132150432043210017375 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when the access on a file was denied. * * @author Bernhard Schussek */ class AccessDeniedException extends FileException { public function __construct(string $path) { parent::__construct(sprintf('The file %s could not be accessed', $path)); } } http-foundation/File/Exception/UploadException.php000064400000000715150432043210016315 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an error occurred during file upload. * * @author Bernhard Schussek */ class UploadException extends FileException { } http-foundation/File/Exception/NoFileException.php000064400000000734150432043210016246 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile. * * @author Florent Mata */ class NoFileException extends FileException { } http-foundation/File/Exception/NoTmpDirFileException.php000064400000000745150432043210017370 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile. * * @author Florent Mata */ class NoTmpDirFileException extends FileException { } http-foundation/File/Exception/FileNotFoundException.php000064400000001112150432043210017415 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when a file was not found. * * @author Bernhard Schussek */ class FileNotFoundException extends FileException { public function __construct(string $path) { parent::__construct(sprintf('The file "%s" does not exist', $path)); } } http-foundation/File/Exception/ExtensionFileException.php000064400000000745150432043210017650 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile. * * @author Florent Mata */ class ExtensionFileException extends FileException { } http-foundation/File/Exception/FormSizeFileException.php000064400000000744150432043210017431 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; /** * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile. * * @author Florent Mata */ class FormSizeFileException extends FileException { } http-foundation/File/Exception/UnexpectedTypeException.php000064400000001043150432043210020032 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\File\Exception; class UnexpectedTypeException extends FileException { public function __construct($value, string $expectedType) { parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, get_debug_type($value))); } } http-foundation/RateLimiter/RequestRateLimiterInterface.php000064400000001336150432043210020231 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\RateLimiter; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\RateLimiter\RateLimit; /** * A special type of limiter that deals with requests. * * This allows to limit on different types of information * from the requests. * * @author Wouter de Jong */ interface RequestRateLimiterInterface { public function consume(Request $request): RateLimit; public function reset(Request $request): void; } http-foundation/RateLimiter/AbstractRequestRateLimiter.php000064400000003127150432043210020074 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\RateLimiter; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\RateLimiter\LimiterInterface; use Symfony\Component\RateLimiter\Policy\NoLimiter; use Symfony\Component\RateLimiter\RateLimit; /** * An implementation of RequestRateLimiterInterface that * fits most use-cases. * * @author Wouter de Jong */ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface { public function consume(Request $request): RateLimit { $limiters = $this->getLimiters($request); if (0 === \count($limiters)) { $limiters = [new NoLimiter()]; } $minimalRateLimit = null; foreach ($limiters as $limiter) { $rateLimit = $limiter->consume(1); if (null === $minimalRateLimit || $rateLimit->getRemainingTokens() < $minimalRateLimit->getRemainingTokens()) { $minimalRateLimit = $rateLimit; } } return $minimalRateLimit; } public function reset(Request $request): void { foreach ($this->getLimiters($request) as $limiter) { $limiter->reset(); } } /** * @return LimiterInterface[] a set of limiters using keys extracted from the request */ abstract protected function getLimiters(Request $request): array; } http-foundation/RequestMatcher.php000064400000011445150432043210013333 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RequestMatcher compares a pre-defined set of checks against a Request instance. * * @author Fabien Potencier */ class RequestMatcher implements RequestMatcherInterface { /** * @var string|null */ private $path; /** * @var string|null */ private $host; /** * @var int|null */ private $port; /** * @var string[] */ private $methods = []; /** * @var string[] */ private $ips = []; /** * @var array */ private $attributes = []; /** * @var string[] */ private $schemes = []; /** * @param string|string[]|null $methods * @param string|string[]|null $ips * @param string|string[]|null $schemes */ public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, int $port = null) { $this->matchPath($path); $this->matchHost($host); $this->matchMethod($methods); $this->matchIps($ips); $this->matchScheme($schemes); $this->matchPort($port); foreach ($attributes as $k => $v) { $this->matchAttribute($k, $v); } } /** * Adds a check for the HTTP scheme. * * @param string|string[]|null $scheme An HTTP scheme or an array of HTTP schemes */ public function matchScheme($scheme) { $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : []; } /** * Adds a check for the URL host name. */ public function matchHost(?string $regexp) { $this->host = $regexp; } /** * Adds a check for the the URL port. * * @param int|null $port The port number to connect to */ public function matchPort(?int $port) { $this->port = $port; } /** * Adds a check for the URL path info. */ public function matchPath(?string $regexp) { $this->path = $regexp; } /** * Adds a check for the client IP. * * @param string $ip A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 */ public function matchIp(string $ip) { $this->matchIps($ip); } /** * Adds a check for the client IP. * * @param string|string[]|null $ips A specific IP address or a range specified using IP/netmask like 192.168.1.0/24 */ public function matchIps($ips) { $ips = null !== $ips ? (array) $ips : []; $this->ips = array_reduce($ips, static function (array $ips, string $ip) { return array_merge($ips, preg_split('/\s*,\s*/', $ip)); }, []); } /** * Adds a check for the HTTP method. * * @param string|string[]|null $method An HTTP method or an array of HTTP methods */ public function matchMethod($method) { $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : []; } /** * Adds a check for request attribute. */ public function matchAttribute(string $key, string $regexp) { $this->attributes[$key] = $regexp; } /** * {@inheritdoc} */ public function matches(Request $request) { if ($this->schemes && !\in_array($request->getScheme(), $this->schemes, true)) { return false; } if ($this->methods && !\in_array($request->getMethod(), $this->methods, true)) { return false; } foreach ($this->attributes as $key => $pattern) { $requestAttribute = $request->attributes->get($key); if (!\is_string($requestAttribute)) { return false; } if (!preg_match('{'.$pattern.'}', $requestAttribute)) { return false; } } if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) { return false; } if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) { return false; } if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) { return false; } if (IpUtils::checkIp($request->getClientIp() ?? '', $this->ips)) { return true; } // Note to future implementors: add additional checks above the // foreach above or else your check might not be run! return 0 === \count($this->ips); } } http-foundation/HeaderBag.php000064400000016050150432043210012176 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * HeaderBag is a container for HTTP headers. * * @author Fabien Potencier * * @implements \IteratorAggregate> */ class HeaderBag implements \IteratorAggregate, \Countable { protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ'; protected const LOWER = '-abcdefghijklmnopqrstuvwxyz'; /** * @var array> */ protected $headers = []; protected $cacheControl = []; public function __construct(array $headers = []) { foreach ($headers as $key => $values) { $this->set($key, $values); } } /** * Returns the headers as a string. * * @return string */ public function __toString() { if (!$headers = $this->all()) { return ''; } ksort($headers); $max = max(array_map('strlen', array_keys($headers))) + 1; $content = ''; foreach ($headers as $name => $values) { $name = ucwords($name, '-'); foreach ($values as $value) { $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); } } return $content; } /** * Returns the headers. * * @param string|null $key The name of the headers to return or null to get them all * * @return array>|array */ public function all(string $key = null) { if (null !== $key) { return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; } return $this->headers; } /** * Returns the parameter keys. * * @return string[] */ public function keys() { return array_keys($this->all()); } /** * Replaces the current HTTP headers by a new set. */ public function replace(array $headers = []) { $this->headers = []; $this->add($headers); } /** * Adds new headers the current HTTP headers set. */ public function add(array $headers) { foreach ($headers as $key => $values) { $this->set($key, $values); } } /** * Returns the first header by name or the default one. * * @return string|null */ public function get(string $key, string $default = null) { $headers = $this->all($key); if (!$headers) { return $default; } if (null === $headers[0]) { return null; } return (string) $headers[0]; } /** * Sets a header by name. * * @param string|string[]|null $values The value or an array of values * @param bool $replace Whether to replace the actual value or not (true by default) */ public function set(string $key, $values, bool $replace = true) { $key = strtr($key, self::UPPER, self::LOWER); if (\is_array($values)) { $values = array_values($values); if (true === $replace || !isset($this->headers[$key])) { $this->headers[$key] = $values; } else { $this->headers[$key] = array_merge($this->headers[$key], $values); } } else { if (true === $replace || !isset($this->headers[$key])) { $this->headers[$key] = [$values]; } else { $this->headers[$key][] = $values; } } if ('cache-control' === $key) { $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); } } /** * Returns true if the HTTP header is defined. * * @return bool */ public function has(string $key) { return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all()); } /** * Returns true if the given HTTP header contains the given value. * * @return bool */ public function contains(string $key, string $value) { return \in_array($value, $this->all($key)); } /** * Removes a header. */ public function remove(string $key) { $key = strtr($key, self::UPPER, self::LOWER); unset($this->headers[$key]); if ('cache-control' === $key) { $this->cacheControl = []; } } /** * Returns the HTTP header value converted to a date. * * @return \DateTimeInterface|null * * @throws \RuntimeException When the HTTP header is not parseable */ public function getDate(string $key, \DateTime $default = null) { if (null === $value = $this->get($key)) { return $default; } if (false === $date = \DateTime::createFromFormat(\DATE_RFC2822, $value)) { throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value)); } return $date; } /** * Adds a custom Cache-Control directive. * * @param bool|string $value The Cache-Control directive value */ public function addCacheControlDirective(string $key, $value = true) { $this->cacheControl[$key] = $value; $this->set('Cache-Control', $this->getCacheControlHeader()); } /** * Returns true if the Cache-Control directive is defined. * * @return bool */ public function hasCacheControlDirective(string $key) { return \array_key_exists($key, $this->cacheControl); } /** * Returns a Cache-Control directive value by name. * * @return bool|string|null */ public function getCacheControlDirective(string $key) { return $this->cacheControl[$key] ?? null; } /** * Removes a Cache-Control directive. */ public function removeCacheControlDirective(string $key) { unset($this->cacheControl[$key]); $this->set('Cache-Control', $this->getCacheControlHeader()); } /** * Returns an iterator for headers. * * @return \ArrayIterator> */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->headers); } /** * Returns the number of headers. * * @return int */ #[\ReturnTypeWillChange] public function count() { return \count($this->headers); } protected function getCacheControlHeader() { ksort($this->cacheControl); return HeaderUtils::toString($this->cacheControl, ','); } /** * Parses a Cache-Control HTTP header. * * @return array */ protected function parseCacheControl(string $header) { $parts = HeaderUtils::split($header, ',='); return HeaderUtils::combine($parts); } } http-foundation/ServerBag.php000064400000007644150432043210012265 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ServerBag is a container for HTTP headers from the $_SERVER variable. * * @author Fabien Potencier * @author Bulat Shakirzyanov * @author Robert Kiss */ class ServerBag extends ParameterBag { /** * Gets the HTTP headers. * * @return array */ public function getHeaders() { $headers = []; foreach ($this->parameters as $key => $value) { if (str_starts_with($key, 'HTTP_')) { $headers[substr($key, 5)] = $value; } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { $headers[$key] = $value; } } if (isset($this->parameters['PHP_AUTH_USER'])) { $headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER']; $headers['PHP_AUTH_PW'] = $this->parameters['PHP_AUTH_PW'] ?? ''; } else { /* * php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default * For this workaround to work, add these lines to your .htaccess file: * RewriteCond %{HTTP:Authorization} .+ * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] * * A sample .htaccess file: * RewriteEngine On * RewriteCond %{HTTP:Authorization} .+ * RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] * RewriteCond %{REQUEST_FILENAME} !-f * RewriteRule ^(.*)$ app.php [QSA,L] */ $authorizationHeader = null; if (isset($this->parameters['HTTP_AUTHORIZATION'])) { $authorizationHeader = $this->parameters['HTTP_AUTHORIZATION']; } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; } if (null !== $authorizationHeader) { if (0 === stripos($authorizationHeader, 'basic ')) { // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); if (2 == \count($exploded)) { [$headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']] = $exploded; } } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { // In some circumstances PHP_AUTH_DIGEST needs to be set $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; } elseif (0 === stripos($authorizationHeader, 'bearer ')) { /* * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables, * I'll just set $headers['AUTHORIZATION'] here. * https://php.net/reserved.variables.server */ $headers['AUTHORIZATION'] = $authorizationHeader; } } } if (isset($headers['AUTHORIZATION'])) { return $headers; } // PHP_AUTH_USER/PHP_AUTH_PW if (isset($headers['PHP_AUTH_USER'])) { $headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']); } elseif (isset($headers['PHP_AUTH_DIGEST'])) { $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; } return $headers; } } http-foundation/composer.json000064400000002164150432043210012406 0ustar00{ "name": "symfony/http-foundation", "type": "library", "description": "Defines an object-oriented layer for the HTTP specification", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php80": "^1.16" }, "require-dev": { "predis/predis": "~1.0", "symfony/cache": "^4.4|^5.0|^6.0", "symfony/mime": "^4.4|^5.0|^6.0", "symfony/expression-language": "^4.4|^5.0|^6.0" }, "suggest" : { "symfony/mime": "To use the file extension guesser" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } http-foundation/UrlHelper.php000064400000006026150432043210012300 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\Routing\RequestContext; /** * A helper service for manipulating URLs within and outside the request scope. * * @author Valentin Udaltsov */ final class UrlHelper { private $requestStack; private $requestContext; public function __construct(RequestStack $requestStack, RequestContext $requestContext = null) { $this->requestStack = $requestStack; $this->requestContext = $requestContext; } public function getAbsoluteUrl(string $path): string { if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { return $path; } if (null === $request = $this->requestStack->getMainRequest()) { return $this->getAbsoluteUrlFromContext($path); } if ('#' === $path[0]) { $path = $request->getRequestUri().$path; } elseif ('?' === $path[0]) { $path = $request->getPathInfo().$path; } if (!$path || '/' !== $path[0]) { $prefix = $request->getPathInfo(); $last = \strlen($prefix) - 1; if ($last !== $pos = strrpos($prefix, '/')) { $prefix = substr($prefix, 0, $pos).'/'; } return $request->getUriForPath($prefix.$path); } return $request->getSchemeAndHttpHost().$path; } public function getRelativePath(string $path): string { if (str_contains($path, '://') || '//' === substr($path, 0, 2)) { return $path; } if (null === $request = $this->requestStack->getMainRequest()) { return $path; } return $request->getRelativeUriForPath($path); } private function getAbsoluteUrlFromContext(string $path): string { if (null === $this->requestContext || '' === $host = $this->requestContext->getHost()) { return $path; } $scheme = $this->requestContext->getScheme(); $port = ''; if ('http' === $scheme && 80 !== $this->requestContext->getHttpPort()) { $port = ':'.$this->requestContext->getHttpPort(); } elseif ('https' === $scheme && 443 !== $this->requestContext->getHttpsPort()) { $port = ':'.$this->requestContext->getHttpsPort(); } if ('#' === $path[0]) { $queryString = $this->requestContext->getQueryString(); $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path; } elseif ('?' === $path[0]) { $path = $this->requestContext->getPathInfo().$path; } if ('/' !== $path[0]) { $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path; } return $scheme.'://'.$host.$port.$path; } } http-foundation/ParameterBag.php000064400000013427150432043210012733 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Exception\BadRequestException; /** * ParameterBag is a container for key/value pairs. * * @author Fabien Potencier * * @implements \IteratorAggregate */ class ParameterBag implements \IteratorAggregate, \Countable { /** * Parameter storage. */ protected $parameters; public function __construct(array $parameters = []) { $this->parameters = $parameters; } /** * Returns the parameters. * * @param string|null $key The name of the parameter to return or null to get them all * * @return array */ public function all(/*string $key = null*/) { $key = \func_num_args() > 0 ? func_get_arg(0) : null; if (null === $key) { return $this->parameters; } if (!\is_array($value = $this->parameters[$key] ?? [])) { throw new BadRequestException(sprintf('Unexpected value for parameter "%s": expecting "array", got "%s".', $key, get_debug_type($value))); } return $value; } /** * Returns the parameter keys. * * @return array */ public function keys() { return array_keys($this->parameters); } /** * Replaces the current parameters by a new set. */ public function replace(array $parameters = []) { $this->parameters = $parameters; } /** * Adds parameters. */ public function add(array $parameters = []) { $this->parameters = array_replace($this->parameters, $parameters); } /** * Returns a parameter by name. * * @param mixed $default The default value if the parameter key does not exist * * @return mixed */ public function get(string $key, $default = null) { return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; } /** * Sets a parameter by name. * * @param mixed $value The value */ public function set(string $key, $value) { $this->parameters[$key] = $value; } /** * Returns true if the parameter is defined. * * @return bool */ public function has(string $key) { return \array_key_exists($key, $this->parameters); } /** * Removes a parameter. */ public function remove(string $key) { unset($this->parameters[$key]); } /** * Returns the alphabetic characters of the parameter value. * * @return string */ public function getAlpha(string $key, string $default = '') { return preg_replace('/[^[:alpha:]]/', '', $this->get($key, $default)); } /** * Returns the alphabetic characters and digits of the parameter value. * * @return string */ public function getAlnum(string $key, string $default = '') { return preg_replace('/[^[:alnum:]]/', '', $this->get($key, $default)); } /** * Returns the digits of the parameter value. * * @return string */ public function getDigits(string $key, string $default = '') { // we need to remove - and + because they're allowed in the filter return str_replace(['-', '+'], '', $this->filter($key, $default, \FILTER_SANITIZE_NUMBER_INT)); } /** * Returns the parameter value converted to integer. * * @return int */ public function getInt(string $key, int $default = 0) { return (int) $this->get($key, $default); } /** * Returns the parameter value converted to boolean. * * @return bool */ public function getBoolean(string $key, bool $default = false) { return $this->filter($key, $default, \FILTER_VALIDATE_BOOLEAN); } /** * Filter key. * * @param mixed $default Default = null * @param int $filter FILTER_* constant * @param mixed $options Filter options * * @see https://php.net/filter-var * * @return mixed */ public function filter(string $key, $default = null, int $filter = \FILTER_DEFAULT, $options = []) { $value = $this->get($key, $default); // Always turn $options into an array - this allows filter_var option shortcuts. if (!\is_array($options) && $options) { $options = ['flags' => $options]; } // Add a convenience check for arrays. if (\is_array($value) && !isset($options['flags'])) { $options['flags'] = \FILTER_REQUIRE_ARRAY; } if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); } return filter_var($value, $filter, $options); } /** * Returns an iterator for parameters. * * @return \ArrayIterator */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->parameters); } /** * Returns the number of parameters. * * @return int */ #[\ReturnTypeWillChange] public function count() { return \count($this->parameters); } } http-foundation/RedirectResponse.php000064400000005765150432043210013667 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * RedirectResponse represents an HTTP response doing a redirect. * * @author Fabien Potencier */ class RedirectResponse extends Response { protected $targetUrl; /** * Creates a redirect response so that it conforms to the rules defined for a redirect status code. * * @param string $url The URL to redirect to. The URL should be a full URL, with schema etc., * but practically every browser redirects on paths only as well * @param int $status The status code (302 by default) * @param array $headers The headers (Location is always set to the given URL) * * @throws \InvalidArgumentException * * @see https://tools.ietf.org/html/rfc2616#section-10.3 */ public function __construct(string $url, int $status = 302, array $headers = []) { parent::__construct('', $status, $headers); $this->setTargetUrl($url); if (!$this->isRedirect()) { throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); } if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { $this->headers->remove('cache-control'); } } /** * Factory method for chainability. * * @param string $url The URL to redirect to * * @return static * * @deprecated since Symfony 5.1, use __construct() instead. */ public static function create($url = '', int $status = 302, array $headers = []) { trigger_deprecation('symfony/http-foundation', '5.1', 'The "%s()" method is deprecated, use "new %s()" instead.', __METHOD__, static::class); return new static($url, $status, $headers); } /** * Returns the target URL. * * @return string */ public function getTargetUrl() { return $this->targetUrl; } /** * Sets the redirect target of this response. * * @return $this * * @throws \InvalidArgumentException */ public function setTargetUrl(string $url) { if ('' === $url) { throw new \InvalidArgumentException('Cannot redirect to an empty URL.'); } $this->targetUrl = $url; $this->setContent( sprintf(' Redirecting to %1$s Redirecting to %1$s. ', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8'))); $this->headers->set('Location', $url); return $this; } } http-foundation/ResponseHeaderBag.php000064400000017425150432043210013724 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * ResponseHeaderBag is a container for Response HTTP headers. * * @author Fabien Potencier */ class ResponseHeaderBag extends HeaderBag { public const COOKIES_FLAT = 'flat'; public const COOKIES_ARRAY = 'array'; public const DISPOSITION_ATTACHMENT = 'attachment'; public const DISPOSITION_INLINE = 'inline'; protected $computedCacheControl = []; protected $cookies = []; protected $headerNames = []; public function __construct(array $headers = []) { parent::__construct($headers); if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } /* RFC2616 - 14.18 says all Responses need to have a Date */ if (!isset($this->headers['date'])) { $this->initDate(); } } /** * Returns the headers, with original capitalizations. * * @return array */ public function allPreserveCase() { $headers = []; foreach ($this->all() as $name => $value) { $headers[$this->headerNames[$name] ?? $name] = $value; } return $headers; } public function allPreserveCaseWithoutCookies() { $headers = $this->allPreserveCase(); if (isset($this->headerNames['set-cookie'])) { unset($headers[$this->headerNames['set-cookie']]); } return $headers; } /** * {@inheritdoc} */ public function replace(array $headers = []) { $this->headerNames = []; parent::replace($headers); if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } if (!isset($this->headers['date'])) { $this->initDate(); } } /** * {@inheritdoc} */ public function all(string $key = null) { $headers = parent::all(); if (null !== $key) { $key = strtr($key, self::UPPER, self::LOWER); return 'set-cookie' !== $key ? $headers[$key] ?? [] : array_map('strval', $this->getCookies()); } foreach ($this->getCookies() as $cookie) { $headers['set-cookie'][] = (string) $cookie; } return $headers; } /** * {@inheritdoc} */ public function set(string $key, $values, bool $replace = true) { $uniqueKey = strtr($key, self::UPPER, self::LOWER); if ('set-cookie' === $uniqueKey) { if ($replace) { $this->cookies = []; } foreach ((array) $values as $cookie) { $this->setCookie(Cookie::fromString($cookie)); } $this->headerNames[$uniqueKey] = $key; return; } $this->headerNames[$uniqueKey] = $key; parent::set($key, $values, $replace); // ensure the cache-control header has sensible defaults if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) { $this->headers['cache-control'] = [$computed]; $this->headerNames['cache-control'] = 'Cache-Control'; $this->computedCacheControl = $this->parseCacheControl($computed); } } /** * {@inheritdoc} */ public function remove(string $key) { $uniqueKey = strtr($key, self::UPPER, self::LOWER); unset($this->headerNames[$uniqueKey]); if ('set-cookie' === $uniqueKey) { $this->cookies = []; return; } parent::remove($key); if ('cache-control' === $uniqueKey) { $this->computedCacheControl = []; } if ('date' === $uniqueKey) { $this->initDate(); } } /** * {@inheritdoc} */ public function hasCacheControlDirective(string $key) { return \array_key_exists($key, $this->computedCacheControl); } /** * {@inheritdoc} */ public function getCacheControlDirective(string $key) { return $this->computedCacheControl[$key] ?? null; } public function setCookie(Cookie $cookie) { $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie; $this->headerNames['set-cookie'] = 'Set-Cookie'; } /** * Removes a cookie from the array, but does not unset it in the browser. */ public function removeCookie(string $name, ?string $path = '/', string $domain = null) { if (null === $path) { $path = '/'; } unset($this->cookies[$domain][$path][$name]); if (empty($this->cookies[$domain][$path])) { unset($this->cookies[$domain][$path]); if (empty($this->cookies[$domain])) { unset($this->cookies[$domain]); } } if (empty($this->cookies)) { unset($this->headerNames['set-cookie']); } } /** * Returns an array with all cookies. * * @return Cookie[] * * @throws \InvalidArgumentException When the $format is invalid */ public function getCookies(string $format = self::COOKIES_FLAT) { if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) { throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY]))); } if (self::COOKIES_ARRAY === $format) { return $this->cookies; } $flattenedCookies = []; foreach ($this->cookies as $path) { foreach ($path as $cookies) { foreach ($cookies as $cookie) { $flattenedCookies[] = $cookie; } } } return $flattenedCookies; } /** * Clears a cookie in the browser. */ public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true, string $sameSite = null) { $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite)); } /** * @see HeaderUtils::makeDisposition() */ public function makeDisposition(string $disposition, string $filename, string $filenameFallback = '') { return HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback); } /** * Returns the calculated value of the cache-control header. * * This considers several other headers and calculates or modifies the * cache-control header to a sensible, conservative value. * * @return string */ protected function computeCacheControlValue() { if (!$this->cacheControl) { if ($this->has('Last-Modified') || $this->has('Expires')) { return 'private, must-revalidate'; // allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified" } // conservative by default return 'no-cache, private'; } $header = $this->getCacheControlHeader(); if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) { return $header; } // public if s-maxage is defined, private otherwise if (!isset($this->cacheControl['s-maxage'])) { return $header.', private'; } return $header; } private function initDate(): void { $this->set('Date', gmdate('D, d M Y H:i:s').' GMT'); } } http-foundation/LICENSE000064400000002051150432043210010664 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. http-foundation/Exception/SessionNotFoundException.php000064400000001513150432043210017307 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Exception; /** * Raised when a session does not exists. This happens in the following cases: * - the session is not enabled * - attempt to read a session outside a request context (ie. cli script). * * @author Jérémy Derussé */ class SessionNotFoundException extends \LogicException implements RequestExceptionInterface { public function __construct(string $message = 'There is currently no session available.', int $code = 0, \Throwable $previous = null) { parent::__construct($message, $code, $previous); } } http-foundation/Exception/RequestExceptionInterface.php000064400000000744150432043210017465 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Exception; /** * Interface for Request exceptions. * * Exceptions implementing this interface should trigger an HTTP 400 response in the application code. */ interface RequestExceptionInterface { } http-foundation/Exception/SuspiciousOperationException.php000064400000001021150432043210020230 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Exception; /** * Raised when a user has performed an operation that should be considered * suspicious from a security perspective. */ class SuspiciousOperationException extends \UnexpectedValueException implements RequestExceptionInterface { } http-foundation/Exception/JsonException.php000064400000001021150432043210015112 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Exception; /** * Thrown by Request::toArray() when the content cannot be JSON-decoded. * * @author Tobias Nyholm */ final class JsonException extends \UnexpectedValueException implements RequestExceptionInterface { } http-foundation/Exception/BadRequestException.php000064400000000703150432043210016246 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Exception; /** * Raised when a user sends a malformed request. */ class BadRequestException extends \UnexpectedValueException implements RequestExceptionInterface { } http-foundation/Exception/ConflictingHeadersException.php000064400000001017150432043210017741 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Exception; /** * The HTTP request contains headers with conflicting information. * * @author Magnus Nordlander */ class ConflictingHeadersException extends \UnexpectedValueException implements RequestExceptionInterface { } http-foundation/AcceptHeader.php000064400000007067150432043210012714 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; // Help opcache.preload discover always-needed symbols class_exists(AcceptHeaderItem::class); /** * Represents an Accept-* header. * * An accept header is compound with a list of items, * sorted by descending quality. * * @author Jean-François Simon */ class AcceptHeader { /** * @var AcceptHeaderItem[] */ private $items = []; /** * @var bool */ private $sorted = true; /** * @param AcceptHeaderItem[] $items */ public function __construct(array $items) { foreach ($items as $item) { $this->add($item); } } /** * Builds an AcceptHeader instance from a string. * * @return self */ public static function fromString(?string $headerValue) { $index = 0; $parts = HeaderUtils::split($headerValue ?? '', ',;='); return new self(array_map(function ($subParts) use (&$index) { $part = array_shift($subParts); $attributes = HeaderUtils::combine($subParts); $item = new AcceptHeaderItem($part[0], $attributes); $item->setIndex($index++); return $item; }, $parts)); } /** * Returns header value's string representation. * * @return string */ public function __toString() { return implode(',', $this->items); } /** * Tests if header has given value. * * @return bool */ public function has(string $value) { return isset($this->items[$value]); } /** * Returns given value's item, if exists. * * @return AcceptHeaderItem|null */ public function get(string $value) { return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null; } /** * Adds an item. * * @return $this */ public function add(AcceptHeaderItem $item) { $this->items[$item->getValue()] = $item; $this->sorted = false; return $this; } /** * Returns all items. * * @return AcceptHeaderItem[] */ public function all() { $this->sort(); return $this->items; } /** * Filters items on their value using given regex. * * @return self */ public function filter(string $pattern) { return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { return preg_match($pattern, $item->getValue()); })); } /** * Returns first item. * * @return AcceptHeaderItem|null */ public function first() { $this->sort(); return !empty($this->items) ? reset($this->items) : null; } /** * Sorts items by descending quality. */ private function sort(): void { if (!$this->sorted) { uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) { $qA = $a->getQuality(); $qB = $b->getQuality(); if ($qA === $qB) { return $a->getIndex() > $b->getIndex() ? 1 : -1; } return $qA > $qB ? -1 : 1; }); $this->sorted = true; } } } http-foundation/Test/Constraint/ResponseIsUnprocessable.php000064400000002220150432043210020251 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Response; final class ResponseIsUnprocessable extends Constraint { /** * {@inheritdoc} */ public function toString(): string { return 'is unprocessable'; } /** * @param Response $other * * {@inheritdoc} */ protected function matches($other): bool { return Response::HTTP_UNPROCESSABLE_ENTITY === $other->getStatusCode(); } /** * @param Response $other * * {@inheritdoc} */ protected function failureDescription($other): string { return 'the Response '.$this->toString(); } /** * @param Response $other * * {@inheritdoc} */ protected function additionalFailureDescription($other): string { return (string) $other; } } http-foundation/Test/Constraint/ResponseHasHeader.php000064400000002145150432043210017002 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Response; final class ResponseHasHeader extends Constraint { private $headerName; public function __construct(string $headerName) { $this->headerName = $headerName; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('has header "%s"', $this->headerName); } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { return $response->headers->has($this->headerName); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } } http-foundation/Test/Constraint/RequestAttributeValueSame.php000064400000002267150432043210020563 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Request; final class RequestAttributeValueSame extends Constraint { private $name; private $value; public function __construct(string $name, string $value) { $this->name = $name; $this->value = $value; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('has attribute "%s" with value "%s"', $this->name, $this->value); } /** * @param Request $request * * {@inheritdoc} */ protected function matches($request): bool { return $this->value === $request->attributes->get($this->name); } /** * @param Request $request * * {@inheritdoc} */ protected function failureDescription($request): string { return 'the Request '.$this->toString(); } } http-foundation/Test/Constraint/ResponseFormatSame.php000064400000003045150432043210017214 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Asserts that the response is in the given format. * * @author Kévin Dunglas */ final class ResponseFormatSame extends Constraint { private $request; private $format; public function __construct(Request $request, ?string $format) { $this->request = $request; $this->format = $format; } /** * {@inheritdoc} */ public function toString(): string { return 'format is '.($this->format ?? 'null'); } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { return $this->format === $this->request->getFormat($response->headers->get('Content-Type')); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } /** * @param Response $response * * {@inheritdoc} */ protected function additionalFailureDescription($response): string { return (string) $response; } } http-foundation/Test/Constraint/ResponseHasCookie.php000064400000003567150432043210017034 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Response; final class ResponseHasCookie extends Constraint { private $name; private $path; private $domain; public function __construct(string $name, string $path = '/', string $domain = null) { $this->name = $name; $this->path = $path; $this->domain = $domain; } /** * {@inheritdoc} */ public function toString(): string { $str = sprintf('has cookie "%s"', $this->name); if ('/' !== $this->path) { $str .= sprintf(' with path "%s"', $this->path); } if ($this->domain) { $str .= sprintf(' for domain "%s"', $this->domain); } return $str; } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { return null !== $this->getCookie($response); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } private function getCookie(Response $response): ?Cookie { $cookies = $response->headers->getCookies(); $filteredCookies = array_filter($cookies, function (Cookie $cookie) { return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; }); return reset($filteredCookies) ?: null; } } http-foundation/Test/Constraint/ResponseIsRedirected.php000064400000002167150432043210017530 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Response; final class ResponseIsRedirected extends Constraint { /** * {@inheritdoc} */ public function toString(): string { return 'is redirected'; } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { return $response->isRedirect(); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } /** * @param Response $response * * {@inheritdoc} */ protected function additionalFailureDescription($response): string { return (string) $response; } } http-foundation/Test/Constraint/ResponseCookieValueSame.php000064400000004150150432043210020170 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Response; final class ResponseCookieValueSame extends Constraint { private $name; private $value; private $path; private $domain; public function __construct(string $name, string $value, string $path = '/', string $domain = null) { $this->name = $name; $this->value = $value; $this->path = $path; $this->domain = $domain; } /** * {@inheritdoc} */ public function toString(): string { $str = sprintf('has cookie "%s"', $this->name); if ('/' !== $this->path) { $str .= sprintf(' with path "%s"', $this->path); } if ($this->domain) { $str .= sprintf(' for domain "%s"', $this->domain); } $str .= sprintf(' with value "%s"', $this->value); return $str; } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { $cookie = $this->getCookie($response); if (!$cookie) { return false; } return $this->value === $cookie->getValue(); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } protected function getCookie(Response $response): ?Cookie { $cookies = $response->headers->getCookies(); $filteredCookies = array_filter($cookies, function (Cookie $cookie) { return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; }); return reset($filteredCookies) ?: null; } } http-foundation/Test/Constraint/ResponseHeaderSame.php000064400000002415150432043210017154 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Response; final class ResponseHeaderSame extends Constraint { private $headerName; private $expectedValue; public function __construct(string $headerName, string $expectedValue) { $this->headerName = $headerName; $this->expectedValue = $expectedValue; } /** * {@inheritdoc} */ public function toString(): string { return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { return $this->expectedValue === $response->headers->get($this->headerName, null); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } } http-foundation/Test/Constraint/ResponseStatusCodeSame.php000064400000002447150432043210020047 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Response; final class ResponseStatusCodeSame extends Constraint { private $statusCode; public function __construct(int $statusCode) { $this->statusCode = $statusCode; } /** * {@inheritdoc} */ public function toString(): string { return 'status code is '.$this->statusCode; } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { return $this->statusCode === $response->getStatusCode(); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } /** * @param Response $response * * {@inheritdoc} */ protected function additionalFailureDescription($response): string { return (string) $response; } } http-foundation/Test/Constraint/ResponseIsSuccessful.php000064400000002171150432043210017570 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Test\Constraint; use PHPUnit\Framework\Constraint\Constraint; use Symfony\Component\HttpFoundation\Response; final class ResponseIsSuccessful extends Constraint { /** * {@inheritdoc} */ public function toString(): string { return 'is successful'; } /** * @param Response $response * * {@inheritdoc} */ protected function matches($response): bool { return $response->isSuccessful(); } /** * @param Response $response * * {@inheritdoc} */ protected function failureDescription($response): string { return 'the Response '.$this->toString(); } /** * @param Response $response * * {@inheritdoc} */ protected function additionalFailureDescription($response): string { return (string) $response; } } http-foundation/InputBag.php000064400000010050150432043210012077 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Exception\BadRequestException; /** * InputBag is a container for user input values such as $_GET, $_POST, $_REQUEST, and $_COOKIE. * * @author Saif Eddin Gmati */ final class InputBag extends ParameterBag { /** * Returns a scalar input value by name. * * @param string|int|float|bool|null $default The default value if the input key does not exist * * @return string|int|float|bool|null */ public function get(string $key, $default = null) { if (null !== $default && !is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) { trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__); } $value = parent::get($key, $this); if (null !== $value && $this !== $value && !is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) { trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-string value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__); } return $this === $value ? $default : $value; } /** * {@inheritdoc} */ public function all(string $key = null): array { return parent::all($key); } /** * Replaces the current input values by a new set. */ public function replace(array $inputs = []) { $this->parameters = []; $this->add($inputs); } /** * Adds input values. */ public function add(array $inputs = []) { foreach ($inputs as $input => $value) { $this->set($input, $value); } } /** * Sets an input by name. * * @param string|int|float|bool|array|null $value */ public function set(string $key, $value) { if (null !== $value && !is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) { trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__); } $this->parameters[$key] = $value; } /** * {@inheritdoc} */ public function filter(string $key, $default = null, int $filter = \FILTER_DEFAULT, $options = []) { $value = $this->has($key) ? $this->all()[$key] : $default; // Always turn $options into an array - this allows filter_var option shortcuts. if (!\is_array($options) && $options) { $options = ['flags' => $options]; } if (\is_array($value) && !(($options['flags'] ?? 0) & (\FILTER_REQUIRE_ARRAY | \FILTER_FORCE_ARRAY))) { trigger_deprecation('symfony/http-foundation', '5.1', 'Filtering an array value with "%s()" without passing the FILTER_REQUIRE_ARRAY or FILTER_FORCE_ARRAY flag is deprecated', __METHOD__); if (!isset($options['flags'])) { $options['flags'] = \FILTER_REQUIRE_ARRAY; } } if ((\FILTER_CALLBACK & $filter) && !(($options['options'] ?? null) instanceof \Closure)) { trigger_deprecation('symfony/http-foundation', '5.2', 'Not passing a Closure together with FILTER_CALLBACK to "%s()" is deprecated. Wrap your filter in a closure instead.', __METHOD__); // throw new \InvalidArgumentException(sprintf('A Closure must be passed to "%s()" when FILTER_CALLBACK is used, "%s" given.', __METHOD__, get_debug_type($options['options'] ?? null))); } return filter_var($value, $filter, $options); } } http-foundation/IpUtils.php000064400000014121150432043210011762 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; /** * Http utility functions. * * @author Fabien Potencier */ class IpUtils { private static $checkedIps = []; /** * This class should not be instantiated. */ private function __construct() { } /** * Checks if an IPv4 or IPv6 address is contained in the list of given IPs or subnets. * * @param string|array $ips List of IPs or subnets (can be a string if only a single one) * * @return bool */ public static function checkIp(?string $requestIp, $ips) { if (null === $requestIp) { trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); return false; } if (!\is_array($ips)) { $ips = [$ips]; } $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4'; foreach ($ips as $ip) { if (self::$method($requestIp, $ip)) { return true; } } return false; } /** * Compares two IPv4 addresses. * In case a subnet is given, it checks if it contains the request IP. * * @param string $ip IPv4 address or subnet in CIDR notation * * @return bool Whether the request IP matches the IP, or whether the request IP is within the CIDR subnet */ public static function checkIp4(?string $requestIp, string $ip) { if (null === $requestIp) { trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); return false; } $cacheKey = $requestIp.'-'.$ip; if (isset(self::$checkedIps[$cacheKey])) { return self::$checkedIps[$cacheKey]; } if (!filter_var($requestIp, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)) { return self::$checkedIps[$cacheKey] = false; } if (str_contains($ip, '/')) { [$address, $netmask] = explode('/', $ip, 2); if ('0' === $netmask) { return self::$checkedIps[$cacheKey] = filter_var($address, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4); } if ($netmask < 0 || $netmask > 32) { return self::$checkedIps[$cacheKey] = false; } } else { $address = $ip; $netmask = 32; } if (false === ip2long($address)) { return self::$checkedIps[$cacheKey] = false; } return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); } /** * Compares two IPv6 addresses. * In case a subnet is given, it checks if it contains the request IP. * * @author David Soria Parra * * @see https://github.com/dsp/v6tools * * @param string $ip IPv6 address or subnet in CIDR notation * * @return bool * * @throws \RuntimeException When IPV6 support is not enabled */ public static function checkIp6(?string $requestIp, string $ip) { if (null === $requestIp) { trigger_deprecation('symfony/http-foundation', '5.4', 'Passing null as $requestIp to "%s()" is deprecated, pass an empty string instead.', __METHOD__); return false; } $cacheKey = $requestIp.'-'.$ip; if (isset(self::$checkedIps[$cacheKey])) { return self::$checkedIps[$cacheKey]; } if (!((\extension_loaded('sockets') && \defined('AF_INET6')) || @inet_pton('::1'))) { throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } if (str_contains($ip, '/')) { [$address, $netmask] = explode('/', $ip, 2); if ('0' === $netmask) { return (bool) unpack('n*', @inet_pton($address)); } if ($netmask < 1 || $netmask > 128) { return self::$checkedIps[$cacheKey] = false; } } else { $address = $ip; $netmask = 128; } $bytesAddr = unpack('n*', @inet_pton($address)); $bytesTest = unpack('n*', @inet_pton($requestIp)); if (!$bytesAddr || !$bytesTest) { return self::$checkedIps[$cacheKey] = false; } for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { $left = $netmask - 16 * ($i - 1); $left = ($left <= 16) ? $left : 16; $mask = ~(0xFFFF >> $left) & 0xFFFF; if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { return self::$checkedIps[$cacheKey] = false; } } return self::$checkedIps[$cacheKey] = true; } /** * Anonymizes an IP/IPv6. * * Removes the last byte for v4 and the last 8 bytes for v6 IPs */ public static function anonymize(string $ip): string { $wrappedIPv6 = false; if ('[' === substr($ip, 0, 1) && ']' === substr($ip, -1, 1)) { $wrappedIPv6 = true; $ip = substr($ip, 1, -1); } $packedAddress = inet_pton($ip); if (4 === \strlen($packedAddress)) { $mask = '255.255.255.0'; } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff:ffff'))) { $mask = '::ffff:ffff:ff00'; } elseif ($ip === inet_ntop($packedAddress & inet_pton('::ffff:ffff'))) { $mask = '::ffff:ff00'; } else { $mask = 'ffff:ffff:ffff:ffff:0000:0000:0000:0000'; } $ip = inet_ntop($packedAddress & inet_pton($mask)); if ($wrappedIPv6) { $ip = '['.$ip.']'; } return $ip; } } http-foundation/Request.php000064400000204374150432043210012034 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation; use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; use Symfony\Component\HttpFoundation\Exception\JsonException; use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\Session\SessionInterface; // Help opcache.preload discover always-needed symbols class_exists(AcceptHeader::class); class_exists(FileBag::class); class_exists(HeaderBag::class); class_exists(HeaderUtils::class); class_exists(InputBag::class); class_exists(ParameterBag::class); class_exists(ServerBag::class); /** * Request represents an HTTP request. * * The methods dealing with URL accept / return a raw path (% encoded): * * getBasePath * * getBaseUrl * * getPathInfo * * getRequestUri * * getUri * * getUriForPath * * @author Fabien Potencier */ class Request { public const HEADER_FORWARDED = 0b000001; // When using RFC 7239 public const HEADER_X_FORWARDED_FOR = 0b000010; public const HEADER_X_FORWARDED_HOST = 0b000100; public const HEADER_X_FORWARDED_PROTO = 0b001000; public const HEADER_X_FORWARDED_PORT = 0b010000; public const HEADER_X_FORWARDED_PREFIX = 0b100000; /** @deprecated since Symfony 5.2, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead. */ public const HEADER_X_FORWARDED_ALL = 0b1011110; // All "X-Forwarded-*" headers sent by "usual" reverse proxy public const HEADER_X_FORWARDED_AWS_ELB = 0b0011010; // AWS ELB doesn't send X-Forwarded-Host public const HEADER_X_FORWARDED_TRAEFIK = 0b0111110; // All "X-Forwarded-*" headers sent by Traefik reverse proxy public const METHOD_HEAD = 'HEAD'; public const METHOD_GET = 'GET'; public const METHOD_POST = 'POST'; public const METHOD_PUT = 'PUT'; public const METHOD_PATCH = 'PATCH'; public const METHOD_DELETE = 'DELETE'; public const METHOD_PURGE = 'PURGE'; public const METHOD_OPTIONS = 'OPTIONS'; public const METHOD_TRACE = 'TRACE'; public const METHOD_CONNECT = 'CONNECT'; /** * @var string[] */ protected static $trustedProxies = []; /** * @var string[] */ protected static $trustedHostPatterns = []; /** * @var string[] */ protected static $trustedHosts = []; protected static $httpMethodParameterOverride = false; /** * Custom parameters. * * @var ParameterBag */ public $attributes; /** * Request body parameters ($_POST). * * @var InputBag */ public $request; /** * Query string parameters ($_GET). * * @var InputBag */ public $query; /** * Server and execution environment parameters ($_SERVER). * * @var ServerBag */ public $server; /** * Uploaded files ($_FILES). * * @var FileBag */ public $files; /** * Cookies ($_COOKIE). * * @var InputBag */ public $cookies; /** * Headers (taken from the $_SERVER). * * @var HeaderBag */ public $headers; /** * @var string|resource|false|null */ protected $content; /** * @var array */ protected $languages; /** * @var array */ protected $charsets; /** * @var array */ protected $encodings; /** * @var array */ protected $acceptableContentTypes; /** * @var string */ protected $pathInfo; /** * @var string */ protected $requestUri; /** * @var string */ protected $baseUrl; /** * @var string */ protected $basePath; /** * @var string */ protected $method; /** * @var string */ protected $format; /** * @var SessionInterface|callable(): SessionInterface */ protected $session; /** * @var string */ protected $locale; /** * @var string */ protected $defaultLocale = 'en'; /** * @var array */ protected static $formats; protected static $requestFactory; /** * @var string|null */ private $preferredFormat; private $isHostValid = true; private $isForwardedValid = true; /** * @var bool|null */ private $isSafeContentPreferred; private static $trustedHeaderSet = -1; private const FORWARDED_PARAMS = [ self::HEADER_X_FORWARDED_FOR => 'for', self::HEADER_X_FORWARDED_HOST => 'host', self::HEADER_X_FORWARDED_PROTO => 'proto', self::HEADER_X_FORWARDED_PORT => 'host', ]; /** * Names for headers that can be trusted when * using trusted proxies. * * The FORWARDED header is the standard as of rfc7239. * * The other headers are non-standard, but widely used * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). */ private const TRUSTED_HEADERS = [ self::HEADER_FORWARDED => 'FORWARDED', self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', self::HEADER_X_FORWARDED_PREFIX => 'X_FORWARDED_PREFIX', ]; /** * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string|resource|null $content The raw body data */ public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) { $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); } /** * Sets the parameters for this request. * * This method also re-initializes all properties. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * @param string|resource|null $content The raw body data */ public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) { $this->request = new InputBag($request); $this->query = new InputBag($query); $this->attributes = new ParameterBag($attributes); $this->cookies = new InputBag($cookies); $this->files = new FileBag($files); $this->server = new ServerBag($server); $this->headers = new HeaderBag($this->server->getHeaders()); $this->content = $content; $this->languages = null; $this->charsets = null; $this->encodings = null; $this->acceptableContentTypes = null; $this->pathInfo = null; $this->requestUri = null; $this->baseUrl = null; $this->basePath = null; $this->method = null; $this->format = null; } /** * Creates a new request with values from PHP's super globals. * * @return static */ public static function createFromGlobals() { $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER); if (str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded') && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH']) ) { parse_str($request->getContent(), $data); $request->request = new InputBag($data); } return $request; } /** * Creates a Request based on a given URI and configuration. * * The information contained in the URI always take precedence * over the other information (server and parameters). * * @param string $uri The URI * @param string $method The HTTP method * @param array $parameters The query (GET) or request (POST) parameters * @param array $cookies The request cookies ($_COOKIE) * @param array $files The request files ($_FILES) * @param array $server The server parameters ($_SERVER) * @param string|resource|null $content The raw body data * * @return static */ public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null) { $server = array_replace([ 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', 'HTTP_USER_AGENT' => 'Symfony', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', 'REMOTE_ADDR' => '127.0.0.1', 'SCRIPT_NAME' => '', 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time(), 'REQUEST_TIME_FLOAT' => microtime(true), ], $server); $server['PATH_INFO'] = ''; $server['REQUEST_METHOD'] = strtoupper($method); $components = parse_url($uri); if (isset($components['host'])) { $server['SERVER_NAME'] = $components['host']; $server['HTTP_HOST'] = $components['host']; } if (isset($components['scheme'])) { if ('https' === $components['scheme']) { $server['HTTPS'] = 'on'; $server['SERVER_PORT'] = 443; } else { unset($server['HTTPS']); $server['SERVER_PORT'] = 80; } } if (isset($components['port'])) { $server['SERVER_PORT'] = $components['port']; $server['HTTP_HOST'] .= ':'.$components['port']; } if (isset($components['user'])) { $server['PHP_AUTH_USER'] = $components['user']; } if (isset($components['pass'])) { $server['PHP_AUTH_PW'] = $components['pass']; } if (!isset($components['path'])) { $components['path'] = '/'; } switch (strtoupper($method)) { case 'POST': case 'PUT': case 'DELETE': if (!isset($server['CONTENT_TYPE'])) { $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; } // no break case 'PATCH': $request = $parameters; $query = []; break; default: $request = []; $query = $parameters; break; } $queryString = ''; if (isset($components['query'])) { parse_str(html_entity_decode($components['query']), $qs); if ($query) { $query = array_replace($qs, $query); $queryString = http_build_query($query, '', '&'); } else { $query = $qs; $queryString = $components['query']; } } elseif ($query) { $queryString = http_build_query($query, '', '&'); } $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); $server['QUERY_STRING'] = $queryString; return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content); } /** * Sets a callable able to create a Request instance. * * This is mainly useful when you need to override the Request class * to keep BC with an existing system. It should not be used for any * other purpose. */ public static function setFactory(?callable $callable) { self::$requestFactory = $callable; } /** * Clones a request and overrides some of its parameters. * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) * @param array $cookies The COOKIE parameters * @param array $files The FILES parameters * @param array $server The SERVER parameters * * @return static */ public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { $dup = clone $this; if (null !== $query) { $dup->query = new InputBag($query); } if (null !== $request) { $dup->request = new InputBag($request); } if (null !== $attributes) { $dup->attributes = new ParameterBag($attributes); } if (null !== $cookies) { $dup->cookies = new InputBag($cookies); } if (null !== $files) { $dup->files = new FileBag($files); } if (null !== $server) { $dup->server = new ServerBag($server); $dup->headers = new HeaderBag($dup->server->getHeaders()); } $dup->languages = null; $dup->charsets = null; $dup->encodings = null; $dup->acceptableContentTypes = null; $dup->pathInfo = null; $dup->requestUri = null; $dup->baseUrl = null; $dup->basePath = null; $dup->method = null; $dup->format = null; if (!$dup->get('_format') && $this->get('_format')) { $dup->attributes->set('_format', $this->get('_format')); } if (!$dup->getRequestFormat(null)) { $dup->setRequestFormat($this->getRequestFormat(null)); } return $dup; } /** * Clones the current request. * * Note that the session is not cloned as duplicated requests * are most of the time sub-requests of the main one. */ public function __clone() { $this->query = clone $this->query; $this->request = clone $this->request; $this->attributes = clone $this->attributes; $this->cookies = clone $this->cookies; $this->files = clone $this->files; $this->server = clone $this->server; $this->headers = clone $this->headers; } /** * Returns the request as a string. * * @return string */ public function __toString() { $content = $this->getContent(); $cookieHeader = ''; $cookies = []; foreach ($this->cookies as $k => $v) { $cookies[] = $k.'='.$v; } if (!empty($cookies)) { $cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n"; } return sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n". $this->headers. $cookieHeader."\r\n". $content; } /** * Overrides the PHP global variables according to this request instance. * * It overrides $_GET, $_POST, $_REQUEST, $_SERVER, $_COOKIE. * $_FILES is never overridden, see rfc1867 */ public function overrideGlobals() { $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); $_GET = $this->query->all(); $_POST = $this->request->all(); $_SERVER = $this->server->all(); $_COOKIE = $this->cookies->all(); foreach ($this->headers->all() as $key => $value) { $key = strtoupper(str_replace('-', '_', $key)); if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { $_SERVER[$key] = implode(', ', $value); } else { $_SERVER['HTTP_'.$key] = implode(', ', $value); } } $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; $_REQUEST = [[]]; foreach (str_split($requestOrder) as $order) { $_REQUEST[] = $request[$order]; } $_REQUEST = array_merge(...$_REQUEST); } /** * Sets a list of trusted proxies. * * You should only list the reverse proxies that you manage directly. * * @param array $proxies A list of trusted proxies, the string 'REMOTE_ADDR' will be replaced with $_SERVER['REMOTE_ADDR'] * @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies */ public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) { if (self::HEADER_X_FORWARDED_ALL === $trustedHeaderSet) { trigger_deprecation('symfony/http-foundation', '5.2', 'The "HEADER_X_FORWARDED_ALL" constant is deprecated, use either "HEADER_X_FORWARDED_FOR | HEADER_X_FORWARDED_HOST | HEADER_X_FORWARDED_PORT | HEADER_X_FORWARDED_PROTO" or "HEADER_X_FORWARDED_AWS_ELB" or "HEADER_X_FORWARDED_TRAEFIK" constants instead.'); } self::$trustedProxies = array_reduce($proxies, function ($proxies, $proxy) { if ('REMOTE_ADDR' !== $proxy) { $proxies[] = $proxy; } elseif (isset($_SERVER['REMOTE_ADDR'])) { $proxies[] = $_SERVER['REMOTE_ADDR']; } return $proxies; }, []); self::$trustedHeaderSet = $trustedHeaderSet; } /** * Gets the list of trusted proxies. * * @return array */ public static function getTrustedProxies() { return self::$trustedProxies; } /** * Gets the set of trusted headers from trusted proxies. * * @return int A bit field of Request::HEADER_* that defines which headers are trusted from your proxies */ public static function getTrustedHeaderSet() { return self::$trustedHeaderSet; } /** * Sets a list of trusted host patterns. * * You should only list the hosts you manage using regexs. * * @param array $hostPatterns A list of trusted host patterns */ public static function setTrustedHosts(array $hostPatterns) { self::$trustedHostPatterns = array_map(function ($hostPattern) { return sprintf('{%s}i', $hostPattern); }, $hostPatterns); // we need to reset trusted hosts on trusted host patterns change self::$trustedHosts = []; } /** * Gets the list of trusted host patterns. * * @return array */ public static function getTrustedHosts() { return self::$trustedHostPatterns; } /** * Normalizes a query string. * * It builds a normalized query string, where keys/value pairs are alphabetized, * have consistent escaping and unneeded delimiters are removed. * * @return string */ public static function normalizeQueryString(?string $qs) { if ('' === ($qs ?? '')) { return ''; } $qs = HeaderUtils::parseQuery($qs); ksort($qs); return http_build_query($qs, '', '&', \PHP_QUERY_RFC3986); } /** * Enables support for the _method request parameter to determine the intended HTTP method. * * Be warned that enabling this feature might lead to CSRF issues in your code. * Check that you are using CSRF tokens when required. * If the HTTP method parameter override is enabled, an html-form with method "POST" can be altered * and used to send a "PUT" or "DELETE" request via the _method request parameter. * If these methods are not protected against CSRF, this presents a possible vulnerability. * * The HTTP method can only be overridden when the real HTTP method is POST. */ public static function enableHttpMethodParameterOverride() { self::$httpMethodParameterOverride = true; } /** * Checks whether support for the _method request parameter is enabled. * * @return bool */ public static function getHttpMethodParameterOverride() { return self::$httpMethodParameterOverride; } /** * Gets a "parameter" value from any bag. * * This method is mainly useful for libraries that want to provide some flexibility. If you don't need the * flexibility in controllers, it is better to explicitly get request parameters from the appropriate * public property instead (attributes, query, request). * * Order of precedence: PATH (routing placeholders or custom attributes), GET, POST * * @param mixed $default The default value if the parameter key does not exist * * @return mixed * * @internal since Symfony 5.4, use explicit input sources instead */ public function get(string $key, $default = null) { if ($this !== $result = $this->attributes->get($key, $this)) { return $result; } if ($this->query->has($key)) { return $this->query->all()[$key]; } if ($this->request->has($key)) { return $this->request->all()[$key]; } return $default; } /** * Gets the Session. * * @return SessionInterface */ public function getSession() { $session = $this->session; if (!$session instanceof SessionInterface && null !== $session) { $this->setSession($session = $session()); } if (null === $session) { throw new SessionNotFoundException('Session has not been set.'); } return $session; } /** * Whether the request contains a Session which was started in one of the * previous requests. * * @return bool */ public function hasPreviousSession() { // the check for $this->session avoids malicious users trying to fake a session cookie with proper name return $this->hasSession() && $this->cookies->has($this->getSession()->getName()); } /** * Whether the request contains a Session object. * * This method does not give any information about the state of the session object, * like whether the session is started or not. It is just a way to check if this Request * is associated with a Session instance. * * @param bool $skipIfUninitialized When true, ignores factories injected by `setSessionFactory` * * @return bool */ public function hasSession(/* bool $skipIfUninitialized = false */) { $skipIfUninitialized = \func_num_args() > 0 ? func_get_arg(0) : false; return null !== $this->session && (!$skipIfUninitialized || $this->session instanceof SessionInterface); } public function setSession(SessionInterface $session) { $this->session = $session; } /** * @internal * * @param callable(): SessionInterface $factory */ public function setSessionFactory(callable $factory) { $this->session = $factory; } /** * Returns the client IP addresses. * * In the returned array the most trusted IP address is first, and the * least trusted one last. The "real" client IP address is the last one, * but this is also the least trusted one. Trusted proxies are stripped. * * Use this method carefully; you should use getClientIp() instead. * * @return array * * @see getClientIp() */ public function getClientIps() { $ip = $this->server->get('REMOTE_ADDR'); if (!$this->isFromTrustedProxy()) { return [$ip]; } return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip]; } /** * Returns the client IP address. * * This method can read the client IP address from the "X-Forwarded-For" header * when trusted proxies were set via "setTrustedProxies()". The "X-Forwarded-For" * header value is a comma+space separated list of IP addresses, the left-most * being the original client, and each successive proxy that passed the request * adding the IP address where it received the request from. * * If your reverse proxy uses a different header name than "X-Forwarded-For", * ("Client-Ip" for instance), configure it via the $trustedHeaderSet * argument of the Request::setTrustedProxies() method instead. * * @return string|null * * @see getClientIps() * @see https://wikipedia.org/wiki/X-Forwarded-For */ public function getClientIp() { $ipAddresses = $this->getClientIps(); return $ipAddresses[0]; } /** * Returns current script name. * * @return string */ public function getScriptName() { return $this->server->get('SCRIPT_NAME', $this->server->get('ORIG_SCRIPT_NAME', '')); } /** * Returns the path being requested relative to the executed script. * * The path info always starts with a /. * * Suppose this request is instantiated from /mysite on localhost: * * * http://localhost/mysite returns an empty string * * http://localhost/mysite/about returns '/about' * * http://localhost/mysite/enco%20ded returns '/enco%20ded' * * http://localhost/mysite/about?var=1 returns '/about' * * @return string The raw path (i.e. not urldecoded) */ public function getPathInfo() { if (null === $this->pathInfo) { $this->pathInfo = $this->preparePathInfo(); } return $this->pathInfo; } /** * Returns the root path from which this request is executed. * * Suppose that an index.php file instantiates this request object: * * * http://localhost/index.php returns an empty string * * http://localhost/index.php/page returns an empty string * * http://localhost/web/index.php returns '/web' * * http://localhost/we%20b/index.php returns '/we%20b' * * @return string The raw path (i.e. not urldecoded) */ public function getBasePath() { if (null === $this->basePath) { $this->basePath = $this->prepareBasePath(); } return $this->basePath; } /** * Returns the root URL from which this request is executed. * * The base URL never ends with a /. * * This is similar to getBasePath(), except that it also includes the * script filename (e.g. index.php) if one exists. * * @return string The raw URL (i.e. not urldecoded) */ public function getBaseUrl() { $trustedPrefix = ''; // the proxy prefix must be prepended to any prefix being needed at the webserver level if ($this->isFromTrustedProxy() && $trustedPrefixValues = $this->getTrustedValues(self::HEADER_X_FORWARDED_PREFIX)) { $trustedPrefix = rtrim($trustedPrefixValues[0], '/'); } return $trustedPrefix.$this->getBaseUrlReal(); } /** * Returns the real base URL received by the webserver from which this request is executed. * The URL does not include trusted reverse proxy prefix. * * @return string The raw URL (i.e. not urldecoded) */ private function getBaseUrlReal(): string { if (null === $this->baseUrl) { $this->baseUrl = $this->prepareBaseUrl(); } return $this->baseUrl; } /** * Gets the request's scheme. * * @return string */ public function getScheme() { return $this->isSecure() ? 'https' : 'http'; } /** * Returns the port on which the request is made. * * This method can read the client port from the "X-Forwarded-Port" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Port" header must contain the client port. * * @return int|string|null Can be a string if fetched from the server bag */ public function getPort() { if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { $host = $host[0]; } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { $host = $host[0]; } elseif (!$host = $this->headers->get('HOST')) { return $this->server->get('SERVER_PORT'); } if ('[' === $host[0]) { $pos = strpos($host, ':', strrpos($host, ']')); } else { $pos = strrpos($host, ':'); } if (false !== $pos && $port = substr($host, $pos + 1)) { return (int) $port; } return 'https' === $this->getScheme() ? 443 : 80; } /** * Returns the user. * * @return string|null */ public function getUser() { return $this->headers->get('PHP_AUTH_USER'); } /** * Returns the password. * * @return string|null */ public function getPassword() { return $this->headers->get('PHP_AUTH_PW'); } /** * Gets the user info. * * @return string|null A user name if any and, optionally, scheme-specific information about how to gain authorization to access the server */ public function getUserInfo() { $userinfo = $this->getUser(); $pass = $this->getPassword(); if ('' != $pass) { $userinfo .= ":$pass"; } return $userinfo; } /** * Returns the HTTP host being requested. * * The port name will be appended to the host if it's non-standard. * * @return string */ public function getHttpHost() { $scheme = $this->getScheme(); $port = $this->getPort(); if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) { return $this->getHost(); } return $this->getHost().':'.$port; } /** * Returns the requested URI (path and query string). * * @return string The raw URI (i.e. not URI decoded) */ public function getRequestUri() { if (null === $this->requestUri) { $this->requestUri = $this->prepareRequestUri(); } return $this->requestUri; } /** * Gets the scheme and HTTP host. * * If the URL was called with basic authentication, the user * and the password are not added to the generated string. * * @return string */ public function getSchemeAndHttpHost() { return $this->getScheme().'://'.$this->getHttpHost(); } /** * Generates a normalized URI (URL) for the Request. * * @return string * * @see getQueryString() */ public function getUri() { if (null !== $qs = $this->getQueryString()) { $qs = '?'.$qs; } return $this->getSchemeAndHttpHost().$this->getBaseUrl().$this->getPathInfo().$qs; } /** * Generates a normalized URI for the given path. * * @param string $path A path to use instead of the current one * * @return string */ public function getUriForPath(string $path) { return $this->getSchemeAndHttpHost().$this->getBaseUrl().$path; } /** * Returns the path as relative reference from the current Request path. * * Only the URIs path component (no schema, host etc.) is relevant and must be given. * Both paths must be absolute and not contain relative parts. * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. * Furthermore, they can be used to reduce the link size in documents. * * Example target paths, given a base path of "/a/b/c/d": * - "/a/b/c/d" -> "" * - "/a/b/c/" -> "./" * - "/a/b/" -> "../" * - "/a/b/c/other" -> "other" * - "/a/x/y" -> "../../x/y" * * @return string */ public function getRelativeUriForPath(string $path) { // be sure that we are dealing with an absolute path if (!isset($path[0]) || '/' !== $path[0]) { return $path; } if ($path === $basePath = $this->getPathInfo()) { return ''; } $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); $targetDirs = explode('/', substr($path, 1)); array_pop($sourceDirs); $targetFile = array_pop($targetDirs); foreach ($sourceDirs as $i => $dir) { if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { unset($sourceDirs[$i], $targetDirs[$i]); } else { break; } } $targetDirs[] = $targetFile; $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); // A reference to the same base directory or an empty subdirectory must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used // as the first segment of a relative-path reference, as it would be mistaken for a scheme name // (see https://tools.ietf.org/html/rfc3986#section-4.2). return !isset($path[0]) || '/' === $path[0] || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) ? "./$path" : $path; } /** * Generates the normalized query string for the Request. * * It builds a normalized query string, where keys/value pairs are alphabetized * and have consistent escaping. * * @return string|null */ public function getQueryString() { $qs = static::normalizeQueryString($this->server->get('QUERY_STRING')); return '' === $qs ? null : $qs; } /** * Checks whether the request is secure or not. * * This method can read the client protocol from the "X-Forwarded-Proto" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". * * @return bool */ public function isSecure() { if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true); } $https = $this->server->get('HTTPS'); return !empty($https) && 'off' !== strtolower($https); } /** * Returns the host name. * * This method can read the client host name from the "X-Forwarded-Host" header * when trusted proxies were set via "setTrustedProxies()". * * The "X-Forwarded-Host" header must contain the client host name. * * @return string * * @throws SuspiciousOperationException when the host name is invalid or not trusted */ public function getHost() { if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { $host = $host[0]; } elseif (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { $host = $this->server->get('SERVER_ADDR', ''); } } // trim and remove port number from host // host is lowercase as per RFC 952/2181 $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); // as the host can come from the user (HTTP_HOST and depending on the configuration, SERVER_NAME too can come from the user) // check that it does not contain forbidden characters (see RFC 952 and RFC 2181) // use preg_replace() instead of preg_match() to prevent DoS attacks with long host names if ($host && '' !== preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host)) { if (!$this->isHostValid) { return ''; } $this->isHostValid = false; throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host)); } if (\count(self::$trustedHostPatterns) > 0) { // to avoid host header injection attacks, you should provide a list of trusted host patterns if (\in_array($host, self::$trustedHosts)) { return $host; } foreach (self::$trustedHostPatterns as $pattern) { if (preg_match($pattern, $host)) { self::$trustedHosts[] = $host; return $host; } } if (!$this->isHostValid) { return ''; } $this->isHostValid = false; throw new SuspiciousOperationException(sprintf('Untrusted Host "%s".', $host)); } return $host; } /** * Sets the request method. */ public function setMethod(string $method) { $this->method = null; $this->server->set('REQUEST_METHOD', $method); } /** * Gets the request "intended" method. * * If the X-HTTP-Method-Override header is set, and if the method is a POST, * then it is used to determine the "real" intended HTTP method. * * The _method request parameter can also be used to determine the HTTP method, * but only if enableHttpMethodParameterOverride() has been called. * * The method is always an uppercased string. * * @return string * * @see getRealMethod() */ public function getMethod() { if (null !== $this->method) { return $this->method; } $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); if ('POST' !== $this->method) { return $this->method; } $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE'); if (!$method && self::$httpMethodParameterOverride) { $method = $this->request->get('_method', $this->query->get('_method', 'POST')); } if (!\is_string($method)) { return $this->method; } $method = strtoupper($method); if (\in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) { return $this->method = $method; } if (!preg_match('/^[A-Z]++$/D', $method)) { throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); } return $this->method = $method; } /** * Gets the "real" request method. * * @return string * * @see getMethod() */ public function getRealMethod() { return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); } /** * Gets the mime type associated with the format. * * @return string|null */ public function getMimeType(string $format) { if (null === static::$formats) { static::initializeFormats(); } return isset(static::$formats[$format]) ? static::$formats[$format][0] : null; } /** * Gets the mime types associated with the format. * * @return array */ public static function getMimeTypes(string $format) { if (null === static::$formats) { static::initializeFormats(); } return static::$formats[$format] ?? []; } /** * Gets the format associated with the mime type. * * @return string|null */ public function getFormat(?string $mimeType) { $canonicalMimeType = null; if ($mimeType && false !== $pos = strpos($mimeType, ';')) { $canonicalMimeType = trim(substr($mimeType, 0, $pos)); } if (null === static::$formats) { static::initializeFormats(); } foreach (static::$formats as $format => $mimeTypes) { if (\in_array($mimeType, (array) $mimeTypes)) { return $format; } if (null !== $canonicalMimeType && \in_array($canonicalMimeType, (array) $mimeTypes)) { return $format; } } return null; } /** * Associates a format with mime types. * * @param string|array $mimeTypes The associated mime types (the preferred one must be the first as it will be used as the content type) */ public function setFormat(?string $format, $mimeTypes) { if (null === static::$formats) { static::initializeFormats(); } static::$formats[$format] = \is_array($mimeTypes) ? $mimeTypes : [$mimeTypes]; } /** * Gets the request format. * * Here is the process to determine the format: * * * format defined by the user (with setRequestFormat()) * * _format request attribute * * $default * * @see getPreferredFormat * * @return string|null */ public function getRequestFormat(?string $default = 'html') { if (null === $this->format) { $this->format = $this->attributes->get('_format'); } return $this->format ?? $default; } /** * Sets the request format. */ public function setRequestFormat(?string $format) { $this->format = $format; } /** * Gets the format associated with the request. * * @return string|null */ public function getContentType() { return $this->getFormat($this->headers->get('CONTENT_TYPE', '')); } /** * Sets the default locale. */ public function setDefaultLocale(string $locale) { $this->defaultLocale = $locale; if (null === $this->locale) { $this->setPhpDefaultLocale($locale); } } /** * Get the default locale. * * @return string */ public function getDefaultLocale() { return $this->defaultLocale; } /** * Sets the locale. */ public function setLocale(string $locale) { $this->setPhpDefaultLocale($this->locale = $locale); } /** * Get the locale. * * @return string */ public function getLocale() { return null === $this->locale ? $this->defaultLocale : $this->locale; } /** * Checks if the request method is of specified type. * * @param string $method Uppercase request method (GET, POST etc) * * @return bool */ public function isMethod(string $method) { return $this->getMethod() === strtoupper($method); } /** * Checks whether or not the method is safe. * * @see https://tools.ietf.org/html/rfc7231#section-4.2.1 * * @return bool */ public function isMethodSafe() { return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']); } /** * Checks whether or not the method is idempotent. * * @return bool */ public function isMethodIdempotent() { return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']); } /** * Checks whether the method is cacheable or not. * * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 * * @return bool */ public function isMethodCacheable() { return \in_array($this->getMethod(), ['GET', 'HEAD']); } /** * Returns the protocol version. * * If the application is behind a proxy, the protocol version used in the * requests between the client and the proxy and between the proxy and the * server might be different. This returns the former (from the "Via" header) * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns * the latter (from the "SERVER_PROTOCOL" server parameter). * * @return string|null */ public function getProtocolVersion() { if ($this->isFromTrustedProxy()) { preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via') ?? '', $matches); if ($matches) { return 'HTTP/'.$matches[2]; } } return $this->server->get('SERVER_PROTOCOL'); } /** * Returns the request body content. * * @param bool $asResource If true, a resource will be returned * * @return string|resource */ public function getContent(bool $asResource = false) { $currentContentIsResource = \is_resource($this->content); if (true === $asResource) { if ($currentContentIsResource) { rewind($this->content); return $this->content; } // Content passed in parameter (test) if (\is_string($this->content)) { $resource = fopen('php://temp', 'r+'); fwrite($resource, $this->content); rewind($resource); return $resource; } $this->content = false; return fopen('php://input', 'r'); } if ($currentContentIsResource) { rewind($this->content); return stream_get_contents($this->content); } if (null === $this->content || false === $this->content) { $this->content = file_get_contents('php://input'); } return $this->content; } /** * Gets the request body decoded as array, typically from a JSON payload. * * @throws JsonException When the body cannot be decoded to an array * * @return array */ public function toArray() { if ('' === $content = $this->getContent()) { throw new JsonException('Request body is empty.'); } try { $content = json_decode($content, true, 512, \JSON_BIGINT_AS_STRING | (\PHP_VERSION_ID >= 70300 ? \JSON_THROW_ON_ERROR : 0)); } catch (\JsonException $e) { throw new JsonException('Could not decode request body.', $e->getCode(), $e); } if (\PHP_VERSION_ID < 70300 && \JSON_ERROR_NONE !== json_last_error()) { throw new JsonException('Could not decode request body: '.json_last_error_msg(), json_last_error()); } if (!\is_array($content)) { throw new JsonException(sprintf('JSON content was expected to decode to an array, "%s" returned.', get_debug_type($content))); } return $content; } /** * Gets the Etags. * * @return array */ public function getETags() { return preg_split('/\s*,\s*/', $this->headers->get('If-None-Match', ''), -1, \PREG_SPLIT_NO_EMPTY); } /** * @return bool */ public function isNoCache() { return $this->headers->hasCacheControlDirective('no-cache') || 'no-cache' == $this->headers->get('Pragma'); } /** * Gets the preferred format for the response by inspecting, in the following order: * * the request format set using setRequestFormat; * * the values of the Accept HTTP header. * * Note that if you use this method, you should send the "Vary: Accept" header * in the response to prevent any issues with intermediary HTTP caches. */ public function getPreferredFormat(?string $default = 'html'): ?string { if (null !== $this->preferredFormat || null !== $this->preferredFormat = $this->getRequestFormat(null)) { return $this->preferredFormat; } foreach ($this->getAcceptableContentTypes() as $mimeType) { if ($this->preferredFormat = $this->getFormat($mimeType)) { return $this->preferredFormat; } } return $default; } /** * Returns the preferred language. * * @param string[] $locales An array of ordered available locales * * @return string|null */ public function getPreferredLanguage(array $locales = null) { $preferredLanguages = $this->getLanguages(); if (empty($locales)) { return $preferredLanguages[0] ?? null; } if (!$preferredLanguages) { return $locales[0]; } $extendedPreferredLanguages = []; foreach ($preferredLanguages as $language) { $extendedPreferredLanguages[] = $language; if (false !== $position = strpos($language, '_')) { $superLanguage = substr($language, 0, $position); if (!\in_array($superLanguage, $preferredLanguages)) { $extendedPreferredLanguages[] = $superLanguage; } } } $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); return $preferredLanguages[0] ?? $locales[0]; } /** * Gets a list of languages acceptable by the client browser ordered in the user browser preferences. * * @return array */ public function getLanguages() { if (null !== $this->languages) { return $this->languages; } $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); $this->languages = []; foreach ($languages as $lang => $acceptHeaderItem) { if (str_contains($lang, '-')) { $codes = explode('-', $lang); if ('i' === $codes[0]) { // Language not listed in ISO 639 that are not variants // of any listed language, which can be registered with the // i-prefix, such as i-cherokee if (\count($codes) > 1) { $lang = $codes[1]; } } else { for ($i = 0, $max = \count($codes); $i < $max; ++$i) { if (0 === $i) { $lang = strtolower($codes[0]); } else { $lang .= '_'.strtoupper($codes[$i]); } } } } $this->languages[] = $lang; } return $this->languages; } /** * Gets a list of charsets acceptable by the client browser in preferable order. * * @return array */ public function getCharsets() { if (null !== $this->charsets) { return $this->charsets; } return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()); } /** * Gets a list of encodings acceptable by the client browser in preferable order. * * @return array */ public function getEncodings() { if (null !== $this->encodings) { return $this->encodings; } return $this->encodings = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Encoding'))->all()); } /** * Gets a list of content types acceptable by the client browser in preferable order. * * @return array */ public function getAcceptableContentTypes() { if (null !== $this->acceptableContentTypes) { return $this->acceptableContentTypes; } return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()); } /** * Returns true if the request is an XMLHttpRequest. * * It works if your JavaScript library sets an X-Requested-With HTTP header. * It is known to work with common JavaScript frameworks: * * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript * * @return bool */ public function isXmlHttpRequest() { return 'XMLHttpRequest' == $this->headers->get('X-Requested-With'); } /** * Checks whether the client browser prefers safe content or not according to RFC8674. * * @see https://tools.ietf.org/html/rfc8674 */ public function preferSafeContent(): bool { if (null !== $this->isSafeContentPreferred) { return $this->isSafeContentPreferred; } if (!$this->isSecure()) { // see https://tools.ietf.org/html/rfc8674#section-3 return $this->isSafeContentPreferred = false; } return $this->isSafeContentPreferred = AcceptHeader::fromString($this->headers->get('Prefer'))->has('safe'); } /* * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) * * Code subject to the new BSD license (https://framework.zend.com/license). * * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/) */ protected function prepareRequestUri() { $requestUri = ''; if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); $this->server->remove('UNENCODED_URL'); $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->server->has('REQUEST_URI')) { $requestUri = $this->server->get('REQUEST_URI'); if ('' !== $requestUri && '/' === $requestUri[0]) { // To only use path and query remove the fragment. if (false !== $pos = strpos($requestUri, '#')) { $requestUri = substr($requestUri, 0, $pos); } } else { // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, // only use URL path. $uriComponents = parse_url($requestUri); if (isset($uriComponents['path'])) { $requestUri = $uriComponents['path']; } if (isset($uriComponents['query'])) { $requestUri .= '?'.$uriComponents['query']; } } } elseif ($this->server->has('ORIG_PATH_INFO')) { // IIS 5.0, PHP as CGI $requestUri = $this->server->get('ORIG_PATH_INFO'); if ('' != $this->server->get('QUERY_STRING')) { $requestUri .= '?'.$this->server->get('QUERY_STRING'); } $this->server->remove('ORIG_PATH_INFO'); } // normalize the request URI to ease creating sub-requests from this request $this->server->set('REQUEST_URI', $requestUri); return $requestUri; } /** * Prepares the base URL. * * @return string */ protected function prepareBaseUrl() { $filename = basename($this->server->get('SCRIPT_FILENAME', '')); if (basename($this->server->get('SCRIPT_NAME', '')) === $filename) { $baseUrl = $this->server->get('SCRIPT_NAME'); } elseif (basename($this->server->get('PHP_SELF', '')) === $filename) { $baseUrl = $this->server->get('PHP_SELF'); } elseif (basename($this->server->get('ORIG_SCRIPT_NAME', '')) === $filename) { $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility } else { // Backtrack up the script_filename to find the portion matching // php_self $path = $this->server->get('PHP_SELF', ''); $file = $this->server->get('SCRIPT_FILENAME', ''); $segs = explode('/', trim($file, '/')); $segs = array_reverse($segs); $index = 0; $last = \count($segs); $baseUrl = ''; do { $seg = $segs[$index]; $baseUrl = '/'.$seg.$baseUrl; ++$index; } while ($last > $index && (false !== $pos = strpos($path, $baseUrl)) && 0 != $pos); } // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); if ('' !== $requestUri && '/' !== $requestUri[0]) { $requestUri = '/'.$requestUri; } if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) { // full $baseUrl matches return $prefix; } if ($baseUrl && null !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) { // directory portion of $baseUrl matches return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR); } $truncatedRequestUri = $requestUri; if (false !== $pos = strpos($requestUri, '?')) { $truncatedRequestUri = substr($requestUri, 0, $pos); } $basename = basename($baseUrl ?? ''); if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { // no match whatsoever; set it blank return ''; } // If using mod_rewrite or ISAPI_Rewrite strip the script filename // out of baseUrl. $pos !== 0 makes sure it is not matching a value // from PATH_INFO or QUERY_STRING if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl)); } return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR); } /** * Prepares the base path. * * @return string */ protected function prepareBasePath() { $baseUrl = $this->getBaseUrl(); if (empty($baseUrl)) { return ''; } $filename = basename($this->server->get('SCRIPT_FILENAME')); if (basename($baseUrl) === $filename) { $basePath = \dirname($baseUrl); } else { $basePath = $baseUrl; } if ('\\' === \DIRECTORY_SEPARATOR) { $basePath = str_replace('\\', '/', $basePath); } return rtrim($basePath, '/'); } /** * Prepares the path info. * * @return string */ protected function preparePathInfo() { if (null === ($requestUri = $this->getRequestUri())) { return '/'; } // Remove the query string from REQUEST_URI if (false !== $pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } if ('' !== $requestUri && '/' !== $requestUri[0]) { $requestUri = '/'.$requestUri; } if (null === ($baseUrl = $this->getBaseUrlReal())) { return $requestUri; } $pathInfo = substr($requestUri, \strlen($baseUrl)); if (false === $pathInfo || '' === $pathInfo) { // If substr() returns false then PATH_INFO is set to an empty string return '/'; } return $pathInfo; } /** * Initializes HTTP request formats. */ protected static function initializeFormats() { static::$formats = [ 'html' => ['text/html', 'application/xhtml+xml'], 'txt' => ['text/plain'], 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], 'css' => ['text/css'], 'json' => ['application/json', 'application/x-json'], 'jsonld' => ['application/ld+json'], 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], 'rdf' => ['application/rdf+xml'], 'atom' => ['application/atom+xml'], 'rss' => ['application/rss+xml'], 'form' => ['application/x-www-form-urlencoded', 'multipart/form-data'], ]; } private function setPhpDefaultLocale(string $locale): void { // if either the class Locale doesn't exist, or an exception is thrown when // setting the default locale, the intl module is not installed, and // the call can be ignored: try { if (class_exists(\Locale::class, false)) { \Locale::setDefault($locale); } } catch (\Exception $e) { } } /** * Returns the prefix as encoded in the string when the string starts with * the given prefix, null otherwise. */ private function getUrlencodedPrefix(string $string, string $prefix): ?string { if (!str_starts_with(rawurldecode($string), $prefix)) { return null; } $len = \strlen($prefix); if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { return $match[0]; } return null; } private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): self { if (self::$requestFactory) { $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content); if (!$request instanceof self) { throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); } return $request; } return new static($query, $request, $attributes, $cookies, $files, $server, $content); } /** * Indicates whether this request originated from a trusted proxy. * * This can be useful to determine whether or not to trust the * contents of a proxy-specific header. * * @return bool */ public function isFromTrustedProxy() { return self::$trustedProxies && IpUtils::checkIp($this->server->get('REMOTE_ADDR', ''), self::$trustedProxies); } private function getTrustedValues(int $type, string $ip = null): array { $clientValues = []; $forwardedValues = []; if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::TRUSTED_HEADERS[$type])) { foreach (explode(',', $this->headers->get(self::TRUSTED_HEADERS[$type])) as $v) { $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); } } if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && (isset(self::FORWARDED_PARAMS[$type])) && $this->headers->has(self::TRUSTED_HEADERS[self::HEADER_FORWARDED])) { $forwarded = $this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]); $parts = HeaderUtils::split($forwarded, ',;='); $forwardedValues = []; $param = self::FORWARDED_PARAMS[$type]; foreach ($parts as $subParts) { if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) { continue; } if (self::HEADER_X_FORWARDED_PORT === $type) { if (str_ends_with($v, ']') || false === $v = strrchr($v, ':')) { $v = $this->isSecure() ? ':443' : ':80'; } $v = '0.0.0.0'.$v; } $forwardedValues[] = $v; } } if (null !== $ip) { $clientValues = $this->normalizeAndFilterClientIps($clientValues, $ip); $forwardedValues = $this->normalizeAndFilterClientIps($forwardedValues, $ip); } if ($forwardedValues === $clientValues || !$clientValues) { return $forwardedValues; } if (!$forwardedValues) { return $clientValues; } if (!$this->isForwardedValid) { return null !== $ip ? ['0.0.0.0', $ip] : []; } $this->isForwardedValid = false; throw new ConflictingHeadersException(sprintf('The request has both a trusted "%s" header and a trusted "%s" header, conflicting with each other. You should either configure your proxy to remove one of them, or configure your project to distrust the offending one.', self::TRUSTED_HEADERS[self::HEADER_FORWARDED], self::TRUSTED_HEADERS[$type])); } private function normalizeAndFilterClientIps(array $clientIps, string $ip): array { if (!$clientIps) { return []; } $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from $firstTrustedIp = null; foreach ($clientIps as $key => $clientIp) { if (strpos($clientIp, '.')) { // Strip :port from IPv4 addresses. This is allowed in Forwarded // and may occur in X-Forwarded-For. $i = strpos($clientIp, ':'); if ($i) { $clientIps[$key] = $clientIp = substr($clientIp, 0, $i); } } elseif (str_starts_with($clientIp, '[')) { // Strip brackets and :port from IPv6 addresses. $i = strpos($clientIp, ']', 1); $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1); } if (!filter_var($clientIp, \FILTER_VALIDATE_IP)) { unset($clientIps[$key]); continue; } if (IpUtils::checkIp($clientIp, self::$trustedProxies)) { unset($clientIps[$key]); // Fallback to this when the client IP falls into the range of trusted proxies if (null === $firstTrustedIp) { $firstTrustedIp = $clientIp; } } } // Now the IP chain contains only untrusted proxies and the client IP return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; } } http-foundation/Session/SessionInterface.php000064400000007474150432043210015275 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; /** * Interface for the session. * * @author Drak */ interface SessionInterface { /** * Starts the session storage. * * @return bool * * @throws \RuntimeException if session fails to start */ public function start(); /** * Returns the session ID. * * @return string */ public function getId(); /** * Sets the session ID. */ public function setId(string $id); /** * Returns the session name. * * @return string */ public function getName(); /** * Sets the session name. */ public function setName(string $name); /** * Invalidates the current session. * * Clears all session attributes and flashes and regenerates the * session and deletes the old session from persistence. * * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return bool */ public function invalidate(int $lifetime = null); /** * Migrates the current session to a new session id while maintaining all * session attributes. * * @param bool $destroy Whether to delete the old session or leave it to garbage collection * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return bool */ public function migrate(bool $destroy = false, int $lifetime = null); /** * Force the session to be saved and closed. * * This method is generally not required for real sessions as * the session will be automatically saved at the end of * code execution. */ public function save(); /** * Checks if an attribute is defined. * * @return bool */ public function has(string $name); /** * Returns an attribute. * * @param mixed $default The default value if not found * * @return mixed */ public function get(string $name, $default = null); /** * Sets an attribute. * * @param mixed $value */ public function set(string $name, $value); /** * Returns attributes. * * @return array */ public function all(); /** * Sets attributes. */ public function replace(array $attributes); /** * Removes an attribute. * * @return mixed The removed value or null when it does not exist */ public function remove(string $name); /** * Clears all attributes. */ public function clear(); /** * Checks if the session was started. * * @return bool */ public function isStarted(); /** * Registers a SessionBagInterface with the session. */ public function registerBag(SessionBagInterface $bag); /** * Gets a bag instance by name. * * @return SessionBagInterface */ public function getBag(string $name); /** * Gets session meta. * * @return MetadataBag */ public function getMetadataBag(); } http-foundation/Session/Attribute/NamespacedAttributeBag.php000064400000010247150432043210020322 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; trigger_deprecation('symfony/http-foundation', '5.3', 'The "%s" class is deprecated.', NamespacedAttributeBag::class); /** * This class provides structured storage of session attributes using * a name spacing character in the key. * * @author Drak * * @deprecated since Symfony 5.3 */ class NamespacedAttributeBag extends AttributeBag { private $namespaceCharacter; /** * @param string $storageKey Session storage key * @param string $namespaceCharacter Namespace character to use in keys */ public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/') { $this->namespaceCharacter = $namespaceCharacter; parent::__construct($storageKey); } /** * {@inheritdoc} */ public function has(string $name) { // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null === $attributes) { return false; } return \array_key_exists($name, $attributes); } /** * {@inheritdoc} */ public function get(string $name, $default = null) { // reference mismatch: if fixed, re-introduced in array_key_exists; keep as it is $attributes = $this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null === $attributes) { return $default; } return \array_key_exists($name, $attributes) ? $attributes[$name] : $default; } /** * {@inheritdoc} */ public function set(string $name, $value) { $attributes = &$this->resolveAttributePath($name, true); $name = $this->resolveKey($name); $attributes[$name] = $value; } /** * {@inheritdoc} */ public function remove(string $name) { $retval = null; $attributes = &$this->resolveAttributePath($name); $name = $this->resolveKey($name); if (null !== $attributes && \array_key_exists($name, $attributes)) { $retval = $attributes[$name]; unset($attributes[$name]); } return $retval; } /** * Resolves a path in attributes property and returns it as a reference. * * This method allows structured namespacing of session attributes. * * @param string $name Key name * @param bool $writeContext Write context, default false * * @return array|null */ protected function &resolveAttributePath(string $name, bool $writeContext = false) { $array = &$this->attributes; $name = (str_starts_with($name, $this->namespaceCharacter)) ? substr($name, 1) : $name; // Check if there is anything to do, else return if (!$name) { return $array; } $parts = explode($this->namespaceCharacter, $name); if (\count($parts) < 2) { if (!$writeContext) { return $array; } $array[$parts[0]] = []; return $array; } unset($parts[\count($parts) - 1]); foreach ($parts as $part) { if (null !== $array && !\array_key_exists($part, $array)) { if (!$writeContext) { $null = null; return $null; } $array[$part] = []; } $array = &$array[$part]; } return $array; } /** * Resolves the key from the name. * * This is the last part in a dot separated string. * * @return string */ protected function resolveKey(string $name) { if (false !== $pos = strrpos($name, $this->namespaceCharacter)) { $name = substr($name, $pos + 1); } return $name; } } http-foundation/Session/Attribute/AttributeBagInterface.php000064400000002367150432043210020166 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * Attributes store. * * @author Drak */ interface AttributeBagInterface extends SessionBagInterface { /** * Checks if an attribute is defined. * * @return bool */ public function has(string $name); /** * Returns an attribute. * * @param mixed $default The default value if not found * * @return mixed */ public function get(string $name, $default = null); /** * Sets an attribute. * * @param mixed $value */ public function set(string $name, $value); /** * Returns attributes. * * @return array */ public function all(); public function replace(array $attributes); /** * Removes an attribute. * * @return mixed The removed value or null when it does not exist */ public function remove(string $name); } http-foundation/Session/Attribute/AttributeBag.php000064400000005700150432043210016337 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Attribute; /** * This class relates to session attribute storage. * * @implements \IteratorAggregate */ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Countable { private $name = 'attributes'; private $storageKey; protected $attributes = []; /** * @param string $storageKey The key used to store attributes in the session */ public function __construct(string $storageKey = '_sf2_attributes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName(string $name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$attributes) { $this->attributes = &$attributes; } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function has(string $name) { return \array_key_exists($name, $this->attributes); } /** * {@inheritdoc} */ public function get(string $name, $default = null) { return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** * {@inheritdoc} */ public function set(string $name, $value) { $this->attributes[$name] = $value; } /** * {@inheritdoc} */ public function all() { return $this->attributes; } /** * {@inheritdoc} */ public function replace(array $attributes) { $this->attributes = []; foreach ($attributes as $key => $value) { $this->set($key, $value); } } /** * {@inheritdoc} */ public function remove(string $name) { $retval = null; if (\array_key_exists($name, $this->attributes)) { $retval = $this->attributes[$name]; unset($this->attributes[$name]); } return $retval; } /** * {@inheritdoc} */ public function clear() { $return = $this->attributes; $this->attributes = []; return $return; } /** * Returns an iterator for attributes. * * @return \ArrayIterator */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->attributes); } /** * Returns the number of attributes. * * @return int */ #[\ReturnTypeWillChange] public function count() { return \count($this->attributes); } } http-foundation/Session/Session.php000064400000014217150432043210013445 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; // Help opcache.preload discover always-needed symbols class_exists(AttributeBag::class); class_exists(FlashBag::class); class_exists(SessionBagProxy::class); /** * @author Fabien Potencier * @author Drak * * @implements \IteratorAggregate */ class Session implements SessionInterface, \IteratorAggregate, \Countable { protected $storage; private $flashName; private $attributeName; private $data = []; private $usageIndex = 0; private $usageReporter; public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, callable $usageReporter = null) { $this->storage = $storage ?? new NativeSessionStorage(); $this->usageReporter = $usageReporter; $attributes = $attributes ?? new AttributeBag(); $this->attributeName = $attributes->getName(); $this->registerBag($attributes); $flashes = $flashes ?? new FlashBag(); $this->flashName = $flashes->getName(); $this->registerBag($flashes); } /** * {@inheritdoc} */ public function start() { return $this->storage->start(); } /** * {@inheritdoc} */ public function has(string $name) { return $this->getAttributeBag()->has($name); } /** * {@inheritdoc} */ public function get(string $name, $default = null) { return $this->getAttributeBag()->get($name, $default); } /** * {@inheritdoc} */ public function set(string $name, $value) { $this->getAttributeBag()->set($name, $value); } /** * {@inheritdoc} */ public function all() { return $this->getAttributeBag()->all(); } /** * {@inheritdoc} */ public function replace(array $attributes) { $this->getAttributeBag()->replace($attributes); } /** * {@inheritdoc} */ public function remove(string $name) { return $this->getAttributeBag()->remove($name); } /** * {@inheritdoc} */ public function clear() { $this->getAttributeBag()->clear(); } /** * {@inheritdoc} */ public function isStarted() { return $this->storage->isStarted(); } /** * Returns an iterator for attributes. * * @return \ArrayIterator */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->getAttributeBag()->all()); } /** * Returns the number of attributes. * * @return int */ #[\ReturnTypeWillChange] public function count() { return \count($this->getAttributeBag()->all()); } public function &getUsageIndex(): int { return $this->usageIndex; } /** * @internal */ public function isEmpty(): bool { if ($this->isStarted()) { ++$this->usageIndex; if ($this->usageReporter && 0 <= $this->usageIndex) { ($this->usageReporter)(); } } foreach ($this->data as &$data) { if (!empty($data)) { return false; } } return true; } /** * {@inheritdoc} */ public function invalidate(int $lifetime = null) { $this->storage->clear(); return $this->migrate(true, $lifetime); } /** * {@inheritdoc} */ public function migrate(bool $destroy = false, int $lifetime = null) { return $this->storage->regenerate($destroy, $lifetime); } /** * {@inheritdoc} */ public function save() { $this->storage->save(); } /** * {@inheritdoc} */ public function getId() { return $this->storage->getId(); } /** * {@inheritdoc} */ public function setId(string $id) { if ($this->storage->getId() !== $id) { $this->storage->setId($id); } } /** * {@inheritdoc} */ public function getName() { return $this->storage->getName(); } /** * {@inheritdoc} */ public function setName(string $name) { $this->storage->setName($name); } /** * {@inheritdoc} */ public function getMetadataBag() { ++$this->usageIndex; if ($this->usageReporter && 0 <= $this->usageIndex) { ($this->usageReporter)(); } return $this->storage->getMetadataBag(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex, $this->usageReporter)); } /** * {@inheritdoc} */ public function getBag(string $name) { $bag = $this->storage->getBag($name); return method_exists($bag, 'getBag') ? $bag->getBag() : $bag; } /** * Gets the flashbag interface. * * @return FlashBagInterface */ public function getFlashBag() { return $this->getBag($this->flashName); } /** * Gets the attributebag interface. * * Note that this method was added to help with IDE autocompletion. */ private function getAttributeBag(): AttributeBagInterface { return $this->getBag($this->attributeName); } } http-foundation/Session/Storage/NativeSessionStorage.php000064400000034173150432043210017550 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\SessionUtils; use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; // Help opcache.preload discover always-needed symbols class_exists(MetadataBag::class); class_exists(StrictSessionHandler::class); class_exists(SessionHandlerProxy::class); /** * This provides a base class for session attribute storage. * * @author Drak */ class NativeSessionStorage implements SessionStorageInterface { /** * @var SessionBagInterface[] */ protected $bags = []; /** * @var bool */ protected $started = false; /** * @var bool */ protected $closed = false; /** * @var AbstractProxy|\SessionHandlerInterface */ protected $saveHandler; /** * @var MetadataBag */ protected $metadataBag; /** * @var string|null */ private $emulateSameSite; /** * Depending on how you want the storage driver to behave you probably * want to override this constructor entirely. * * List of options for $options array with their defaults. * * @see https://php.net/session.configuration for options * but we omit 'session.' from the beginning of the keys for convenience. * * ("auto_start", is not supported as it tells PHP to start a session before * PHP starts to execute user-land code. Setting during runtime has no effect). * * cache_limiter, "" (use "0" to prevent headers from being sent entirely). * cache_expire, "0" * cookie_domain, "" * cookie_httponly, "" * cookie_lifetime, "0" * cookie_path, "/" * cookie_secure, "" * cookie_samesite, null * gc_divisor, "100" * gc_maxlifetime, "1440" * gc_probability, "1" * lazy_write, "1" * name, "PHPSESSID" * referer_check, "" * serialize_handler, "php" * use_strict_mode, "1" * use_cookies, "1" * use_only_cookies, "1" * use_trans_sid, "0" * sid_length, "32" * sid_bits_per_character, "5" * trans_sid_hosts, $_SERVER['HTTP_HOST'] * trans_sid_tags, "a=href,area=href,frame=src,form=" * * @param AbstractProxy|\SessionHandlerInterface|null $handler */ public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null) { if (!\extension_loaded('session')) { throw new \LogicException('PHP extension "session" is required.'); } $options += [ 'cache_limiter' => '', 'cache_expire' => 0, 'use_cookies' => 1, 'lazy_write' => 1, 'use_strict_mode' => 1, ]; session_register_shutdown(); $this->setMetadataBag($metaBag); $this->setOptions($options); $this->setSaveHandler($handler); } /** * Gets the save handler instance. * * @return AbstractProxy|\SessionHandlerInterface */ public function getSaveHandler() { return $this->saveHandler; } /** * {@inheritdoc} */ public function start() { if ($this->started) { return true; } if (\PHP_SESSION_ACTIVE === session_status()) { throw new \RuntimeException('Failed to start the session: already started by PHP.'); } if (filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); } // ok to try and start the session if (!session_start()) { throw new \RuntimeException('Failed to start the session.'); } if (null !== $this->emulateSameSite) { $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); if (null !== $originalCookie) { header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); } } $this->loadSession(); return true; } /** * {@inheritdoc} */ public function getId() { return $this->saveHandler->getId(); } /** * {@inheritdoc} */ public function setId(string $id) { $this->saveHandler->setId($id); } /** * {@inheritdoc} */ public function getName() { return $this->saveHandler->getName(); } /** * {@inheritdoc} */ public function setName(string $name) { $this->saveHandler->setName($name); } /** * {@inheritdoc} */ public function regenerate(bool $destroy = false, int $lifetime = null) { // Cannot regenerate the session ID for non-active sessions. if (\PHP_SESSION_ACTIVE !== session_status()) { return false; } if (headers_sent()) { return false; } if (null !== $lifetime && $lifetime != ini_get('session.cookie_lifetime')) { $this->save(); ini_set('session.cookie_lifetime', $lifetime); $this->start(); } if ($destroy) { $this->metadataBag->stampNew(); } $isRegenerated = session_regenerate_id($destroy); if (null !== $this->emulateSameSite) { $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); if (null !== $originalCookie) { header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); } } return $isRegenerated; } /** * {@inheritdoc} */ public function save() { // Store a copy so we can restore the bags in case the session was not left empty $session = $_SESSION; foreach ($this->bags as $bag) { if (empty($_SESSION[$key = $bag->getStorageKey()])) { unset($_SESSION[$key]); } } if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { unset($_SESSION[$key]); } // Register error handler to add information about the current save handler $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) { if (\E_WARNING === $type && str_starts_with($msg, 'session_write_close():')) { $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler; $msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler)); } return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false; }); try { session_write_close(); } finally { restore_error_handler(); // Restore only if not empty if ($_SESSION) { $_SESSION = $session; } } $this->closed = true; $this->started = false; } /** * {@inheritdoc} */ public function clear() { // clear out the bags foreach ($this->bags as $bag) { $bag->clear(); } // clear out the session $_SESSION = []; // reconnect the bags to the session $this->loadSession(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { if ($this->started) { throw new \LogicException('Cannot register a bag when the session is already started.'); } $this->bags[$bag->getName()] = $bag; } /** * {@inheritdoc} */ public function getBag(string $name) { if (!isset($this->bags[$name])) { throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); } if (!$this->started && $this->saveHandler->isActive()) { $this->loadSession(); } elseif (!$this->started) { $this->start(); } return $this->bags[$name]; } public function setMetadataBag(MetadataBag $metaBag = null) { if (null === $metaBag) { $metaBag = new MetadataBag(); } $this->metadataBag = $metaBag; } /** * Gets the MetadataBag. * * @return MetadataBag */ public function getMetadataBag() { return $this->metadataBag; } /** * {@inheritdoc} */ public function isStarted() { return $this->started; } /** * Sets session.* ini variables. * * For convenience we omit 'session.' from the beginning of the keys. * Explicitly ignores other ini keys. * * @param array $options Session ini directives [key => value] * * @see https://php.net/session.configuration */ public function setOptions(array $options) { if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { return; } $validOptions = array_flip([ 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'lazy_write', 'name', 'referer_check', 'serialize_handler', 'use_strict_mode', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', ]); foreach ($options as $key => $value) { if (isset($validOptions[$key])) { if (str_starts_with($key, 'upload_progress.')) { trigger_deprecation('symfony/http-foundation', '5.4', 'Support for the "%s" session option is deprecated. The settings prefixed with "session.upload_progress." can not be changed at runtime.', $key); continue; } if ('url_rewriter.tags' === $key) { trigger_deprecation('symfony/http-foundation', '5.4', 'Support for the "%s" session option is deprecated. Use "trans_sid_tags" instead.', $key); } if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) { // PHP < 7.3 does not support same_site cookies. We will emulate it in // the start() method instead. $this->emulateSameSite = $value; continue; } if ('cookie_secure' === $key && 'auto' === $value) { continue; } ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); } } } /** * Registers session save handler as a PHP session handler. * * To use internal PHP session save handlers, override this method using ini_set with * session.save_handler and session.save_path e.g. * * ini_set('session.save_handler', 'files'); * ini_set('session.save_path', '/tmp'); * * or pass in a \SessionHandler instance which configures session.save_handler in the * constructor, for a template see NativeFileSessionHandler. * * @see https://php.net/session-set-save-handler * @see https://php.net/sessionhandlerinterface * @see https://php.net/sessionhandler * * @param AbstractProxy|\SessionHandlerInterface|null $saveHandler * * @throws \InvalidArgumentException */ public function setSaveHandler($saveHandler = null) { if (!$saveHandler instanceof AbstractProxy && !$saveHandler instanceof \SessionHandlerInterface && null !== $saveHandler) { throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); } // Wrap $saveHandler in proxy and prevent double wrapping of proxy if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); } elseif (!$saveHandler instanceof AbstractProxy) { $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); } $this->saveHandler = $saveHandler; if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) { return; } if ($this->saveHandler instanceof SessionHandlerProxy) { session_set_save_handler($this->saveHandler, false); } } /** * Load the session with attributes. * * After starting the session, PHP retrieves the session from whatever handlers * are set to (either PHP's internal, or a custom save handler set with session_set_save_handler()). * PHP takes the return value from the read() handler, unserializes it * and populates $_SESSION with the result automatically. */ protected function loadSession(array &$session = null) { if (null === $session) { $session = &$_SESSION; } $bags = array_merge($this->bags, [$this->metadataBag]); foreach ($bags as $bag) { $key = $bag->getStorageKey(); $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : []; $bag->initialize($session[$key]); } $this->started = true; $this->closed = false; } } http-foundation/Session/Storage/MetadataBag.php000064400000007133150432043210015557 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * Metadata container. * * Adds metadata to the session. * * @author Drak */ class MetadataBag implements SessionBagInterface { public const CREATED = 'c'; public const UPDATED = 'u'; public const LIFETIME = 'l'; /** * @var string */ private $name = '__metadata'; /** * @var string */ private $storageKey; /** * @var array */ protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0]; /** * Unix timestamp. * * @var int */ private $lastUsed; /** * @var int */ private $updateThreshold; /** * @param string $storageKey The key used to store bag in the session * @param int $updateThreshold The time to wait between two UPDATED updates */ public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0) { $this->storageKey = $storageKey; $this->updateThreshold = $updateThreshold; } /** * {@inheritdoc} */ public function initialize(array &$array) { $this->meta = &$array; if (isset($array[self::CREATED])) { $this->lastUsed = $this->meta[self::UPDATED]; $timeStamp = time(); if ($timeStamp - $array[self::UPDATED] >= $this->updateThreshold) { $this->meta[self::UPDATED] = $timeStamp; } } else { $this->stampCreated(); } } /** * Gets the lifetime that the session cookie was set with. * * @return int */ public function getLifetime() { return $this->meta[self::LIFETIME]; } /** * Stamps a new session's metadata. * * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. */ public function stampNew(int $lifetime = null) { $this->stampCreated($lifetime); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * Gets the created timestamp metadata. * * @return int Unix timestamp */ public function getCreated() { return $this->meta[self::CREATED]; } /** * Gets the last used metadata. * * @return int Unix timestamp */ public function getLastUsed() { return $this->lastUsed; } /** * {@inheritdoc} */ public function clear() { // nothing to do return null; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * Sets name. */ public function setName(string $name) { $this->name = $name; } private function stampCreated(int $lifetime = null): void { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; $this->meta[self::LIFETIME] = $lifetime ?? (int) ini_get('session.cookie_lifetime'); } } http-foundation/Session/Storage/MockFileSessionStorageFactory.php000064400000002144150432043210021334 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Request; // Help opcache.preload discover always-needed symbols class_exists(MockFileSessionStorage::class); /** * @author Jérémy Derussé */ class MockFileSessionStorageFactory implements SessionStorageFactoryInterface { private $savePath; private $name; private $metaBag; /** * @see MockFileSessionStorage constructor. */ public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->savePath = $savePath; $this->name = $name; $this->metaBag = $metaBag; } public function createStorage(?Request $request): SessionStorageInterface { return new MockFileSessionStorage($this->savePath, $this->name, $this->metaBag); } } http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php000064400000002364150432043210021513 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Request; // Help opcache.preload discover always-needed symbols class_exists(PhpBridgeSessionStorage::class); /** * @author Jérémy Derussé */ class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface { private $handler; private $metaBag; private $secure; /** * @see PhpBridgeSessionStorage constructor. */ public function __construct($handler = null, MetadataBag $metaBag = null, bool $secure = false) { $this->handler = $handler; $this->metaBag = $metaBag; $this->secure = $secure; } public function createStorage(?Request $request): SessionStorageInterface { $storage = new PhpBridgeSessionStorage($this->handler, $this->metaBag); if ($this->secure && $request && $request->isSecure()) { $storage->setOptions(['cookie_secure' => true]); } return $storage; } } http-foundation/Session/Storage/NativeSessionStorageFactory.php000064400000002506150432043210021073 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Request; // Help opcache.preload discover always-needed symbols class_exists(NativeSessionStorage::class); /** * @author Jérémy Derussé */ class NativeSessionStorageFactory implements SessionStorageFactoryInterface { private $options; private $handler; private $metaBag; private $secure; /** * @see NativeSessionStorage constructor. */ public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null, bool $secure = false) { $this->options = $options; $this->handler = $handler; $this->metaBag = $metaBag; $this->secure = $secure; } public function createStorage(?Request $request): SessionStorageInterface { $storage = new NativeSessionStorage($this->options, $this->handler, $this->metaBag); if ($this->secure && $request && $request->isSecure()) { $storage->setOptions(['cookie_secure' => true]); } return $storage; } } http-foundation/Session/Storage/SessionStorageInterface.php000064400000007426150432043210020223 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * StorageInterface. * * @author Fabien Potencier * @author Drak */ interface SessionStorageInterface { /** * Starts the session. * * @return bool * * @throws \RuntimeException if something goes wrong starting the session */ public function start(); /** * Checks if the session is started. * * @return bool */ public function isStarted(); /** * Returns the session ID. * * @return string */ public function getId(); /** * Sets the session ID. */ public function setId(string $id); /** * Returns the session name. * * @return string */ public function getName(); /** * Sets the session name. */ public function setName(string $name); /** * Regenerates id that represents this storage. * * This method must invoke session_regenerate_id($destroy) unless * this interface is used for a storage object designed for unit * or functional testing where a real PHP session would interfere * with testing. * * Note regenerate+destroy should not clear the session data in memory * only delete the session data from persistent storage. * * Care: When regenerating the session ID no locking is involved in PHP's * session design. See https://bugs.php.net/61470 for a discussion. * So you must make sure the regenerated session is saved BEFORE sending the * headers with the new ID. Symfony's HttpKernel offers a listener for this. * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. * Otherwise session data could get lost again for concurrent requests with the * new ID. One result could be that you get logged out after just logging in. * * @param bool $destroy Destroy session when regenerating? * @param int $lifetime Sets the cookie lifetime for the session cookie. A null value * will leave the system settings unchanged, 0 sets the cookie * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. * * @return bool * * @throws \RuntimeException If an error occurs while regenerating this storage */ public function regenerate(bool $destroy = false, int $lifetime = null); /** * Force the session to be saved and closed. * * This method must invoke session_write_close() unless this interface is * used for a storage object design for unit or functional testing where * a real PHP session would interfere with testing, in which case * it should actually persist the session data if required. * * @throws \RuntimeException if the session is saved without being started, or if the session * is already closed */ public function save(); /** * Clear all session data in memory. */ public function clear(); /** * Gets a SessionBagInterface by name. * * @return SessionBagInterface * * @throws \InvalidArgumentException If the bag does not exist */ public function getBag(string $name); /** * Registers a SessionBagInterface for use. */ public function registerBag(SessionBagInterface $bag); /** * @return MetadataBag */ public function getMetadataBag(); } http-foundation/Session/Storage/MockArraySessionStorage.php000064400000011751150432043210020207 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * MockArraySessionStorage mocks the session for unit tests. * * No PHP session is actually started since a session can be initialized * and shutdown only once per PHP execution cycle. * * When doing functional testing, you should use MockFileSessionStorage instead. * * @author Fabien Potencier * @author Bulat Shakirzyanov * @author Drak */ class MockArraySessionStorage implements SessionStorageInterface { /** * @var string */ protected $id = ''; /** * @var string */ protected $name; /** * @var bool */ protected $started = false; /** * @var bool */ protected $closed = false; /** * @var array */ protected $data = []; /** * @var MetadataBag */ protected $metadataBag; /** * @var array|SessionBagInterface[] */ protected $bags = []; public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->name = $name; $this->setMetadataBag($metaBag); } public function setSessionData(array $array) { $this->data = $array; } /** * {@inheritdoc} */ public function start() { if ($this->started) { return true; } if (empty($this->id)) { $this->id = $this->generateId(); } $this->loadSession(); return true; } /** * {@inheritdoc} */ public function regenerate(bool $destroy = false, int $lifetime = null) { if (!$this->started) { $this->start(); } $this->metadataBag->stampNew($lifetime); $this->id = $this->generateId(); return true; } /** * {@inheritdoc} */ public function getId() { return $this->id; } /** * {@inheritdoc} */ public function setId(string $id) { if ($this->started) { throw new \LogicException('Cannot set session ID after the session has started.'); } $this->id = $id; } /** * {@inheritdoc} */ public function getName() { return $this->name; } /** * {@inheritdoc} */ public function setName(string $name) { $this->name = $name; } /** * {@inheritdoc} */ public function save() { if (!$this->started || $this->closed) { throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); } // nothing to do since we don't persist the session data $this->closed = false; $this->started = false; } /** * {@inheritdoc} */ public function clear() { // clear out the bags foreach ($this->bags as $bag) { $bag->clear(); } // clear out the session $this->data = []; // reconnect the bags to the session $this->loadSession(); } /** * {@inheritdoc} */ public function registerBag(SessionBagInterface $bag) { $this->bags[$bag->getName()] = $bag; } /** * {@inheritdoc} */ public function getBag(string $name) { if (!isset($this->bags[$name])) { throw new \InvalidArgumentException(sprintf('The SessionBagInterface "%s" is not registered.', $name)); } if (!$this->started) { $this->start(); } return $this->bags[$name]; } /** * {@inheritdoc} */ public function isStarted() { return $this->started; } public function setMetadataBag(MetadataBag $bag = null) { if (null === $bag) { $bag = new MetadataBag(); } $this->metadataBag = $bag; } /** * Gets the MetadataBag. * * @return MetadataBag */ public function getMetadataBag() { return $this->metadataBag; } /** * Generates a session ID. * * This doesn't need to be particularly cryptographically secure since this is just * a mock. * * @return string */ protected function generateId() { return hash('sha256', uniqid('ss_mock_', true)); } protected function loadSession() { $bags = array_merge($this->bags, [$this->metadataBag]); foreach ($bags as $bag) { $key = $bag->getStorageKey(); $this->data[$key] = $this->data[$key] ?? []; $bag->initialize($this->data[$key]); } $this->started = true; $this->closed = false; } } http-foundation/Session/Storage/SessionStorageFactoryInterface.php000064400000001132150432043210021537 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Request; /** * @author Jérémy Derussé */ interface SessionStorageFactoryInterface { /** * Creates a new instance of SessionStorageInterface. */ public function createStorage(?Request $request): SessionStorageInterface; } http-foundation/Session/Storage/ServiceSessionFactory.php000064400000001701150432043210017714 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Request; /** * @author Jérémy Derussé * * @internal to be removed in Symfony 6 */ final class ServiceSessionFactory implements SessionStorageFactoryInterface { private $storage; public function __construct(SessionStorageInterface $storage) { $this->storage = $storage; } public function createStorage(?Request $request): SessionStorageInterface { if ($this->storage instanceof NativeSessionStorage && $request && $request->isSecure()) { $this->storage->setOptions(['cookie_secure' => true]); } return $this->storage; } } http-foundation/Session/Storage/MockFileSessionStorage.php000064400000007652150432043210020015 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; /** * MockFileSessionStorage is used to mock sessions for * functional testing when done in a single PHP process. * * No PHP session is actually started since a session can be initialized * and shutdown only once per PHP execution cycle and this class does * not pollute any session related globals, including session_*() functions * or session.* PHP ini directives. * * @author Drak */ class MockFileSessionStorage extends MockArraySessionStorage { private $savePath; /** * @param string|null $savePath Path of directory to save session files */ public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { if (null === $savePath) { $savePath = sys_get_temp_dir(); } if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) { throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $savePath)); } $this->savePath = $savePath; parent::__construct($name, $metaBag); } /** * {@inheritdoc} */ public function start() { if ($this->started) { return true; } if (!$this->id) { $this->id = $this->generateId(); } $this->read(); $this->started = true; return true; } /** * {@inheritdoc} */ public function regenerate(bool $destroy = false, int $lifetime = null) { if (!$this->started) { $this->start(); } if ($destroy) { $this->destroy(); } return parent::regenerate($destroy, $lifetime); } /** * {@inheritdoc} */ public function save() { if (!$this->started) { throw new \RuntimeException('Trying to save a session that was not started yet or was already closed.'); } $data = $this->data; foreach ($this->bags as $bag) { if (empty($data[$key = $bag->getStorageKey()])) { unset($data[$key]); } } if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { unset($data[$key]); } try { if ($data) { $path = $this->getFilePath(); $tmp = $path.bin2hex(random_bytes(6)); file_put_contents($tmp, serialize($data)); rename($tmp, $path); } else { $this->destroy(); } } finally { $this->data = $data; } // this is needed when the session object is re-used across multiple requests // in functional tests. $this->started = false; } /** * Deletes a session from persistent storage. * Deliberately leaves session data in memory intact. */ private function destroy(): void { set_error_handler(static function () {}); try { unlink($this->getFilePath()); } finally { restore_error_handler(); } } /** * Calculate path to file. */ private function getFilePath(): string { return $this->savePath.'/'.$this->id.'.mocksess'; } /** * Reads session from storage and loads session. */ private function read(): void { set_error_handler(static function () {}); try { $data = file_get_contents($this->getFilePath()); } finally { restore_error_handler(); } $this->data = $data ? unserialize($data) : []; $this->loadSession(); } } http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php000064400000004716150432043210020535 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * @author Drak */ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface { protected $handler; public function __construct(\SessionHandlerInterface $handler) { $this->handler = $handler; $this->wrapper = $handler instanceof \SessionHandler; $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; } /** * @return \SessionHandlerInterface */ public function getHandler() { return $this->handler; } // \SessionHandlerInterface /** * @return bool */ #[\ReturnTypeWillChange] public function open($savePath, $sessionName) { return $this->handler->open($savePath, $sessionName); } /** * @return bool */ #[\ReturnTypeWillChange] public function close() { return $this->handler->close(); } /** * @return string|false */ #[\ReturnTypeWillChange] public function read($sessionId) { return $this->handler->read($sessionId); } /** * @return bool */ #[\ReturnTypeWillChange] public function write($sessionId, $data) { return $this->handler->write($sessionId, $data); } /** * @return bool */ #[\ReturnTypeWillChange] public function destroy($sessionId) { return $this->handler->destroy($sessionId); } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { return $this->handler->gc($maxlifetime); } /** * @return bool */ #[\ReturnTypeWillChange] public function validateId($sessionId) { return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId); } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data); } } http-foundation/Session/Storage/Proxy/AbstractProxy.php000064400000004372150432043210017355 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * @author Drak */ abstract class AbstractProxy { /** * Flag if handler wraps an internal PHP session handler (using \SessionHandler). * * @var bool */ protected $wrapper = false; /** * @var string */ protected $saveHandlerName; /** * Gets the session.save_handler name. * * @return string|null */ public function getSaveHandlerName() { return $this->saveHandlerName; } /** * Is this proxy handler and instance of \SessionHandlerInterface. * * @return bool */ public function isSessionHandlerInterface() { return $this instanceof \SessionHandlerInterface; } /** * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. * * @return bool */ public function isWrapper() { return $this->wrapper; } /** * Has a session started? * * @return bool */ public function isActive() { return \PHP_SESSION_ACTIVE === session_status(); } /** * Gets the session ID. * * @return string */ public function getId() { return session_id(); } /** * Sets the session ID. * * @throws \LogicException */ public function setId(string $id) { if ($this->isActive()) { throw new \LogicException('Cannot change the ID of an active session.'); } session_id($id); } /** * Gets the session name. * * @return string */ public function getName() { return session_name(); } /** * Sets the session name. * * @throws \LogicException */ public function setName(string $name) { if ($this->isActive()) { throw new \LogicException('Cannot change the name of an active session.'); } session_name($name); } } http-foundation/Session/Storage/PhpBridgeSessionStorage.php000064400000002723150432043210020162 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; /** * Allows session to be started by PHP and managed by Symfony. * * @author Drak */ class PhpBridgeSessionStorage extends NativeSessionStorage { /** * @param AbstractProxy|\SessionHandlerInterface|null $handler */ public function __construct($handler = null, MetadataBag $metaBag = null) { if (!\extension_loaded('session')) { throw new \LogicException('PHP extension "session" is required.'); } $this->setMetadataBag($metaBag); $this->setSaveHandler($handler); } /** * {@inheritdoc} */ public function start() { if ($this->started) { return true; } $this->loadSession(); return true; } /** * {@inheritdoc} */ public function clear() { // clear out the bags and nothing else that may be set // since the purpose of this driver is to share a handler foreach ($this->bags as $bag) { $bag->clear(); } // reconnect the bags to the session $this->loadSession(); } } http-foundation/Session/Storage/Handler/StrictSessionHandler.php000064400000004666150432043210021124 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`. * * @author Nicolas Grekas */ class StrictSessionHandler extends AbstractSessionHandler { private $handler; private $doDestroy; public function __construct(\SessionHandlerInterface $handler) { if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', get_debug_type($handler), self::class)); } $this->handler = $handler; } /** * @return bool */ #[\ReturnTypeWillChange] public function open($savePath, $sessionName) { parent::open($savePath, $sessionName); return $this->handler->open($savePath, $sessionName); } /** * {@inheritdoc} */ protected function doRead(string $sessionId) { return $this->handler->read($sessionId); } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { return $this->write($sessionId, $data); } /** * {@inheritdoc} */ protected function doWrite(string $sessionId, string $data) { return $this->handler->write($sessionId, $data); } /** * @return bool */ #[\ReturnTypeWillChange] public function destroy($sessionId) { $this->doDestroy = true; $destroyed = parent::destroy($sessionId); return $this->doDestroy ? $this->doDestroy($sessionId) : $destroyed; } /** * {@inheritdoc} */ protected function doDestroy(string $sessionId) { $this->doDestroy = false; return $this->handler->destroy($sessionId); } /** * @return bool */ #[\ReturnTypeWillChange] public function close() { return $this->handler->close(); } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { return $this->handler->gc($maxlifetime); } } http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php000064400000005735150432043210021520 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Memcached based session storage handler based on the Memcached class * provided by the PHP memcached extension. * * @see https://php.net/memcached * * @author Drak */ class MemcachedSessionHandler extends AbstractSessionHandler { private $memcached; /** * @var int Time to live in seconds */ private $ttl; /** * @var string Key prefix for shared environments */ private $prefix; /** * Constructor. * * List of available options: * * prefix: The prefix to use for the memcached keys in order to avoid collision * * ttl: The time to live in seconds. * * @throws \InvalidArgumentException When unsupported options are passed */ public function __construct(\Memcached $memcached, array $options = []) { $this->memcached = $memcached; if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime', 'ttl'])) { throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); } $this->ttl = $options['expiretime'] ?? $options['ttl'] ?? null; $this->prefix = $options['prefix'] ?? 'sf2s'; } /** * @return bool */ #[\ReturnTypeWillChange] public function close() { return $this->memcached->quit(); } /** * {@inheritdoc} */ protected function doRead(string $sessionId) { return $this->memcached->get($this->prefix.$sessionId) ?: ''; } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { $this->memcached->touch($this->prefix.$sessionId, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); return true; } /** * {@inheritdoc} */ protected function doWrite(string $sessionId, string $data) { return $this->memcached->set($this->prefix.$sessionId, $data, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); } /** * {@inheritdoc} */ protected function doDestroy(string $sessionId) { $result = $this->memcached->delete($this->prefix.$sessionId); return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode(); } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { // not required here because memcached will auto expire the records anyhow. return 0; } /** * Return a Memcached instance. * * @return \Memcached */ protected function getMemcached() { return $this->memcached; } } http-foundation/Session/Storage/Handler/MarshallingSessionHandler.php000064400000004533150432043210022106 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; use Symfony\Component\Cache\Marshaller\MarshallerInterface; /** * @author Ahmed TAILOULOUTE */ class MarshallingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface { private $handler; private $marshaller; public function __construct(AbstractSessionHandler $handler, MarshallerInterface $marshaller) { $this->handler = $handler; $this->marshaller = $marshaller; } /** * @return bool */ #[\ReturnTypeWillChange] public function open($savePath, $name) { return $this->handler->open($savePath, $name); } /** * @return bool */ #[\ReturnTypeWillChange] public function close() { return $this->handler->close(); } /** * @return bool */ #[\ReturnTypeWillChange] public function destroy($sessionId) { return $this->handler->destroy($sessionId); } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { return $this->handler->gc($maxlifetime); } /** * @return string */ #[\ReturnTypeWillChange] public function read($sessionId) { return $this->marshaller->unmarshall($this->handler->read($sessionId)); } /** * @return bool */ #[\ReturnTypeWillChange] public function write($sessionId, $data) { $failed = []; $marshalledData = $this->marshaller->marshall(['data' => $data], $failed); if (isset($failed['data'])) { return false; } return $this->handler->write($sessionId, $marshalledData['data']); } /** * @return bool */ #[\ReturnTypeWillChange] public function validateId($sessionId) { return $this->handler->validateId($sessionId); } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { return $this->handler->updateTimestamp($sessionId, $data); } } http-foundation/Session/Storage/Handler/PdoSessionHandler.php000064400000111351150432043210020364 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Session handler using a PDO connection to read and write data. * * It works with MySQL, PostgreSQL, Oracle, SQL Server and SQLite and implements * different locking strategies to handle concurrent access to the same session. * Locking is necessary to prevent loss of data due to race conditions and to keep * the session data consistent between read() and write(). With locking, requests * for the same session will wait until the other one finished writing. For this * reason it's best practice to close a session as early as possible to improve * concurrency. PHPs internal files session handler also implements locking. * * Attention: Since SQLite does not support row level locks but locks the whole database, * it means only one session can be accessed at a time. Even different sessions would wait * for another to finish. So saving session in SQLite should only be considered for * development or prototypes. * * Session data is a binary string that can contain non-printable characters like the null byte. * For this reason it must be saved in a binary column in the database like BLOB in MySQL. * Saving it in a character column could corrupt the data. You can use createTable() * to initialize a correctly defined table. * * @see https://php.net/sessionhandlerinterface * * @author Fabien Potencier * @author Michael Williams * @author Tobias Schultze */ class PdoSessionHandler extends AbstractSessionHandler { /** * No locking is done. This means sessions are prone to loss of data due to * race conditions of concurrent requests to the same session. The last session * write will win in this case. It might be useful when you implement your own * logic to deal with this like an optimistic approach. */ public const LOCK_NONE = 0; /** * Creates an application-level lock on a session. The disadvantage is that the * lock is not enforced by the database and thus other, unaware parts of the * application could still concurrently modify the session. The advantage is it * does not require a transaction. * This mode is not available for SQLite and not yet implemented for oci and sqlsrv. */ public const LOCK_ADVISORY = 1; /** * Issues a real row lock. Since it uses a transaction between opening and * closing a session, you have to be careful when you use same database connection * that you also use for your application logic. This mode is the default because * it's the only reliable solution across DBMSs. */ public const LOCK_TRANSACTIONAL = 2; private const MAX_LIFETIME = 315576000; /** * @var \PDO|null PDO instance or null when not connected yet */ private $pdo; /** * DSN string or null for session.save_path or false when lazy connection disabled. * * @var string|false|null */ private $dsn = false; /** * @var string|null */ private $driver; /** * @var string */ private $table = 'sessions'; /** * @var string */ private $idCol = 'sess_id'; /** * @var string */ private $dataCol = 'sess_data'; /** * @var string */ private $lifetimeCol = 'sess_lifetime'; /** * @var string */ private $timeCol = 'sess_time'; /** * Username when lazy-connect. * * @var string */ private $username = ''; /** * Password when lazy-connect. * * @var string */ private $password = ''; /** * Connection options when lazy-connect. * * @var array */ private $connectionOptions = []; /** * The strategy for locking, see constants. * * @var int */ private $lockMode = self::LOCK_TRANSACTIONAL; /** * It's an array to support multiple reads before closing which is manual, non-standard usage. * * @var \PDOStatement[] An array of statements to release advisory locks */ private $unlockStatements = []; /** * True when the current session exists but expired according to session.gc_maxlifetime. * * @var bool */ private $sessionExpired = false; /** * Whether a transaction is active. * * @var bool */ private $inTransaction = false; /** * Whether gc() has been called. * * @var bool */ private $gcCalled = false; /** * You can either pass an existing database connection as PDO instance or * pass a DSN string that will be used to lazy-connect to the database * when the session is actually used. Furthermore it's possible to pass null * which will then use the session.save_path ini setting as PDO DSN parameter. * * List of available options: * * db_table: The name of the table [default: sessions] * * db_id_col: The column where to store the session id [default: sess_id] * * db_data_col: The column where to store the session data [default: sess_data] * * db_lifetime_col: The column where to store the lifetime [default: sess_lifetime] * * db_time_col: The column where to store the timestamp [default: sess_time] * * db_username: The username when lazy-connect [default: ''] * * db_password: The password when lazy-connect [default: ''] * * db_connection_options: An array of driver-specific connection options [default: []] * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] * * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null * * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION */ public function __construct($pdoOrDsn = null, array $options = []) { if ($pdoOrDsn instanceof \PDO) { if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { throw new \InvalidArgumentException(sprintf('"%s" requires PDO error mode attribute be set to throw Exceptions (i.e. $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)).', __CLASS__)); } $this->pdo = $pdoOrDsn; $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); } elseif (\is_string($pdoOrDsn) && str_contains($pdoOrDsn, '://')) { $this->dsn = $this->buildDsnFromUrl($pdoOrDsn); } else { $this->dsn = $pdoOrDsn; } $this->table = $options['db_table'] ?? $this->table; $this->idCol = $options['db_id_col'] ?? $this->idCol; $this->dataCol = $options['db_data_col'] ?? $this->dataCol; $this->lifetimeCol = $options['db_lifetime_col'] ?? $this->lifetimeCol; $this->timeCol = $options['db_time_col'] ?? $this->timeCol; $this->username = $options['db_username'] ?? $this->username; $this->password = $options['db_password'] ?? $this->password; $this->connectionOptions = $options['db_connection_options'] ?? $this->connectionOptions; $this->lockMode = $options['lock_mode'] ?? $this->lockMode; } /** * Creates the table to store sessions which can be called once for setup. * * Session ID is saved in a column of maximum length 128 because that is enough even * for a 512 bit configured session.hash_function like Whirlpool. Session data is * saved in a BLOB. One could also use a shorter inlined varbinary column * if one was sure the data fits into it. * * @throws \PDOException When the table already exists * @throws \DomainException When an unsupported PDO driver is used */ public function createTable() { // connect if we are not yet $this->getConnection(); switch ($this->driver) { case 'mysql': // We use varbinary for the ID column because it prevents unwanted conversions: // - character set conversions between server and client // - trailing space removal // - case-insensitivity // - language processing like é == e $sql = "CREATE TABLE $this->table ($this->idCol VARBINARY(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER UNSIGNED NOT NULL, $this->timeCol INTEGER UNSIGNED NOT NULL) COLLATE utf8mb4_bin, ENGINE = InnoDB"; break; case 'sqlite': $sql = "CREATE TABLE $this->table ($this->idCol TEXT NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; break; case 'pgsql': $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol BYTEA NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; break; case 'oci': $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR2(128) NOT NULL PRIMARY KEY, $this->dataCol BLOB NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; break; case 'sqlsrv': $sql = "CREATE TABLE $this->table ($this->idCol VARCHAR(128) NOT NULL PRIMARY KEY, $this->dataCol VARBINARY(MAX) NOT NULL, $this->lifetimeCol INTEGER NOT NULL, $this->timeCol INTEGER NOT NULL)"; break; default: throw new \DomainException(sprintf('Creating the session table is currently not implemented for PDO driver "%s".', $this->driver)); } try { $this->pdo->exec($sql); $this->pdo->exec("CREATE INDEX EXPIRY ON $this->table ($this->lifetimeCol)"); } catch (\PDOException $e) { $this->rollback(); throw $e; } } /** * Returns true when the current session exists but expired according to session.gc_maxlifetime. * * Can be used to distinguish between a new session and one that expired due to inactivity. * * @return bool */ public function isSessionExpired() { return $this->sessionExpired; } /** * @return bool */ #[\ReturnTypeWillChange] public function open($savePath, $sessionName) { $this->sessionExpired = false; if (null === $this->pdo) { $this->connect($this->dsn ?: $savePath); } return parent::open($savePath, $sessionName); } /** * @return string */ #[\ReturnTypeWillChange] public function read($sessionId) { try { return parent::read($sessionId); } catch (\PDOException $e) { $this->rollback(); throw $e; } } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { // We delay gc() to close() so that it is executed outside the transactional and blocking read-write process. // This way, pruning expired sessions does not block them from being started while the current session is used. $this->gcCalled = true; return 0; } /** * {@inheritdoc} */ protected function doDestroy(string $sessionId) { // delete the record associated with this id $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; try { $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $stmt->execute(); } catch (\PDOException $e) { $this->rollback(); throw $e; } return true; } /** * {@inheritdoc} */ protected function doWrite(string $sessionId, string $data) { $maxlifetime = (int) ini_get('session.gc_maxlifetime'); try { // We use a single MERGE SQL query when supported by the database. $mergeStmt = $this->getMergeStatement($sessionId, $data, $maxlifetime); if (null !== $mergeStmt) { $mergeStmt->execute(); return true; } $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime); $updateStmt->execute(); // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in // duplicate key errors when the same session is written simultaneously (given the LOCK_NONE behavior). // We can just catch such an error and re-execute the update. This is similar to a serializable // transaction with retry logic on serialization failures but without the overhead and without possible // false positives due to longer gap locking. if (!$updateStmt->rowCount()) { try { $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime); $insertStmt->execute(); } catch (\PDOException $e) { // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys if (str_starts_with($e->getCode(), '23')) { $updateStmt->execute(); } else { throw $e; } } } } catch (\PDOException $e) { $this->rollback(); throw $e; } return true; } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { $expiry = time() + (int) ini_get('session.gc_maxlifetime'); try { $updateStmt = $this->pdo->prepare( "UPDATE $this->table SET $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id" ); $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $updateStmt->bindParam(':expiry', $expiry, \PDO::PARAM_INT); $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); $updateStmt->execute(); } catch (\PDOException $e) { $this->rollback(); throw $e; } return true; } /** * @return bool */ #[\ReturnTypeWillChange] public function close() { $this->commit(); while ($unlockStmt = array_shift($this->unlockStatements)) { $unlockStmt->execute(); } if ($this->gcCalled) { $this->gcCalled = false; // delete the session records that have expired $sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time AND $this->lifetimeCol > :min"; $stmt = $this->pdo->prepare($sql); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); $stmt->execute(); // to be removed in 6.0 if ('mysql' === $this->driver) { $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol + $this->timeCol < :time"; } else { $legacySql = "DELETE FROM $this->table WHERE $this->lifetimeCol <= :min AND $this->lifetimeCol < :time - $this->timeCol"; } $stmt = $this->pdo->prepare($legacySql); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); $stmt->bindValue(':min', self::MAX_LIFETIME, \PDO::PARAM_INT); $stmt->execute(); } if (false !== $this->dsn) { $this->pdo = null; // only close lazy-connection $this->driver = null; } return true; } /** * Lazy-connects to the database. */ private function connect(string $dsn): void { $this->pdo = new \PDO($dsn, $this->username, $this->password, $this->connectionOptions); $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); } /** * Builds a PDO DSN from a URL-like connection string. * * @todo implement missing support for oci DSN (which look totally different from other PDO ones) */ private function buildDsnFromUrl(string $dsnOrUrl): string { // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl); $params = parse_url($url); if (false === $params) { return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already. } $params = array_map('rawurldecode', $params); // Override the default username and password. Values passed through options will still win over these in the constructor. if (isset($params['user'])) { $this->username = $params['user']; } if (isset($params['pass'])) { $this->password = $params['pass']; } if (!isset($params['scheme'])) { throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler.'); } $driverAliasMap = [ 'mssql' => 'sqlsrv', 'mysql2' => 'mysql', // Amazon RDS, for some weird reason 'postgres' => 'pgsql', 'postgresql' => 'pgsql', 'sqlite3' => 'sqlite', ]; $driver = $driverAliasMap[$params['scheme']] ?? $params['scheme']; // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here. if (str_starts_with($driver, 'pdo_') || str_starts_with($driver, 'pdo-')) { $driver = substr($driver, 4); } $dsn = null; switch ($driver) { case 'mysql': $dsn = 'mysql:'; if ('' !== ($params['query'] ?? '')) { $queryParams = []; parse_str($params['query'], $queryParams); if ('' !== ($queryParams['charset'] ?? '')) { $dsn .= 'charset='.$queryParams['charset'].';'; } if ('' !== ($queryParams['unix_socket'] ?? '')) { $dsn .= 'unix_socket='.$queryParams['unix_socket'].';'; if (isset($params['path'])) { $dbName = substr($params['path'], 1); // Remove the leading slash $dsn .= 'dbname='.$dbName.';'; } return $dsn; } } // If "unix_socket" is not in the query, we continue with the same process as pgsql // no break case 'pgsql': $dsn ?? $dsn = 'pgsql:'; if (isset($params['host']) && '' !== $params['host']) { $dsn .= 'host='.$params['host'].';'; } if (isset($params['port']) && '' !== $params['port']) { $dsn .= 'port='.$params['port'].';'; } if (isset($params['path'])) { $dbName = substr($params['path'], 1); // Remove the leading slash $dsn .= 'dbname='.$dbName.';'; } return $dsn; case 'sqlite': return 'sqlite:'.substr($params['path'], 1); case 'sqlsrv': $dsn = 'sqlsrv:server='; if (isset($params['host'])) { $dsn .= $params['host']; } if (isset($params['port']) && '' !== $params['port']) { $dsn .= ','.$params['port']; } if (isset($params['path'])) { $dbName = substr($params['path'], 1); // Remove the leading slash $dsn .= ';Database='.$dbName; } return $dsn; default: throw new \InvalidArgumentException(sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme'])); } } /** * Helper method to begin a transaction. * * Since SQLite does not support row level locks, we have to acquire a reserved lock * on the database immediately. Because of https://bugs.php.net/42766 we have to create * such a transaction manually which also means we cannot use PDO::commit or * PDO::rollback or PDO::inTransaction for SQLite. * * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . * So we change it to READ COMMITTED. */ private function beginTransaction(): void { if (!$this->inTransaction) { if ('sqlite' === $this->driver) { $this->pdo->exec('BEGIN IMMEDIATE TRANSACTION'); } else { if ('mysql' === $this->driver) { $this->pdo->exec('SET TRANSACTION ISOLATION LEVEL READ COMMITTED'); } $this->pdo->beginTransaction(); } $this->inTransaction = true; } } /** * Helper method to commit a transaction. */ private function commit(): void { if ($this->inTransaction) { try { // commit read-write transaction which also releases the lock if ('sqlite' === $this->driver) { $this->pdo->exec('COMMIT'); } else { $this->pdo->commit(); } $this->inTransaction = false; } catch (\PDOException $e) { $this->rollback(); throw $e; } } } /** * Helper method to rollback a transaction. */ private function rollback(): void { // We only need to rollback if we are in a transaction. Otherwise the resulting // error would hide the real problem why rollback was called. We might not be // in a transaction when not using the transactional locking behavior or when // two callbacks (e.g. destroy and write) are invoked that both fail. if ($this->inTransaction) { if ('sqlite' === $this->driver) { $this->pdo->exec('ROLLBACK'); } else { $this->pdo->rollBack(); } $this->inTransaction = false; } } /** * Reads the session data in respect to the different locking strategies. * * We need to make sure we do not return session data that is already considered garbage according * to the session.gc_maxlifetime setting because gc() is called after read() and only sometimes. * * @return string */ protected function doRead(string $sessionId) { if (self::LOCK_ADVISORY === $this->lockMode) { $this->unlockStatements[] = $this->doAdvisoryLock($sessionId); } $selectSql = $this->getSelectSql(); $selectStmt = $this->pdo->prepare($selectSql); $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $insertStmt = null; do { $selectStmt->execute(); $sessionRows = $selectStmt->fetchAll(\PDO::FETCH_NUM); if ($sessionRows) { $expiry = (int) $sessionRows[0][1]; if ($expiry <= self::MAX_LIFETIME) { $expiry += $sessionRows[0][2]; } if ($expiry < time()) { $this->sessionExpired = true; return ''; } return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; } if (null !== $insertStmt) { $this->rollback(); throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); } if (!filter_var(ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { // In strict mode, session fixation is not possible: new sessions always start with a unique // random id, so that concurrency is not possible and this code path can be skipped. // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block // until other connections to the session are committed. try { $insertStmt = $this->getInsertStatement($sessionId, '', 0); $insertStmt->execute(); } catch (\PDOException $e) { // Catch duplicate key error because other connection created the session already. // It would only not be the case when the other connection destroyed the session. if (str_starts_with($e->getCode(), '23')) { // Retrieve finished session data written by concurrent connection by restarting the loop. // We have to start a new transaction as a failed query will mark the current transaction as // aborted in PostgreSQL and disallow further queries within it. $this->rollback(); $this->beginTransaction(); continue; } throw $e; } } return ''; } while (true); } /** * Executes an application-level lock on the database. * * @return \PDOStatement The statement that needs to be executed later to release the lock * * @throws \DomainException When an unsupported PDO driver is used * * @todo implement missing advisory locks * - for oci using DBMS_LOCK.REQUEST * - for sqlsrv using sp_getapplock with LockOwner = Session */ private function doAdvisoryLock(string $sessionId): \PDOStatement { switch ($this->driver) { case 'mysql': // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. $lockId = substr($sessionId, 0, 64); // should we handle the return value? 0 on timeout, null on error // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); $stmt->execute(); $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); return $releaseStmt; case 'pgsql': // Obtaining an exclusive session level advisory lock requires an integer key. // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters. // So we cannot just use hexdec(). if (4 === \PHP_INT_SIZE) { $sessionInt1 = $this->convertStringToInt($sessionId); $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4)); $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)'); $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); $stmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); $stmt->execute(); $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key1, :key2)'); $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); } else { $sessionBigInt = $this->convertStringToInt($sessionId); $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)'); $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); $stmt->execute(); $releaseStmt = $this->pdo->prepare('SELECT pg_advisory_unlock(:key)'); $releaseStmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); } return $releaseStmt; case 'sqlite': throw new \DomainException('SQLite does not support advisory locks.'); default: throw new \DomainException(sprintf('Advisory locks are currently not implemented for PDO driver "%s".', $this->driver)); } } /** * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. * * Keep in mind, PHP integers are signed. */ private function convertStringToInt(string $string): int { if (4 === \PHP_INT_SIZE) { return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); } $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]); $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); return $int2 + ($int1 << 32); } /** * Return a locking or nonlocking SQL query to read session information. * * @throws \DomainException When an unsupported PDO driver is used */ private function getSelectSql(): string { if (self::LOCK_TRANSACTIONAL === $this->lockMode) { $this->beginTransaction(); // selecting the time column should be removed in 6.0 switch ($this->driver) { case 'mysql': case 'oci': case 'pgsql': return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id FOR UPDATE"; case 'sqlsrv': return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WITH (UPDLOCK, ROWLOCK) WHERE $this->idCol = :id"; case 'sqlite': // we already locked when starting transaction break; default: throw new \DomainException(sprintf('Transactional locks are currently not implemented for PDO driver "%s".', $this->driver)); } } return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id"; } /** * Returns an insert statement supported by the database for writing session data. */ private function getInsertStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement { switch ($this->driver) { case 'oci': $data = fopen('php://memory', 'r+'); fwrite($data, $sessionData); rewind($data); $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :expiry, :time) RETURNING $this->dataCol into :data"; break; default: $data = $sessionData; $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; break; } $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); return $stmt; } /** * Returns an update statement supported by the database for writing session data. */ private function getUpdateStatement(string $sessionId, string $sessionData, int $maxlifetime): \PDOStatement { switch ($this->driver) { case 'oci': $data = fopen('php://memory', 'r+'); fwrite($data, $sessionData); rewind($data); $sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data"; break; default: $data = $sessionData; $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :expiry, $this->timeCol = :time WHERE $this->idCol = :id"; break; } $stmt = $this->pdo->prepare($sql); $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); $stmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); $stmt->bindValue(':time', time(), \PDO::PARAM_INT); return $stmt; } /** * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. */ private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement { switch (true) { case 'mysql' === $this->driver: $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; break; case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): // MERGE is only available since SQL Server 2008 and must be terminated by semicolon // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ $mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; break; case 'sqlite' === $this->driver: $mergeSql = "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time)"; break; case 'pgsql' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '9.5', '>='): $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :expiry, :time) ". "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; break; default: // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html return null; } $mergeStmt = $this->pdo->prepare($mergeSql); if ('sqlsrv' === $this->driver) { $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB); $mergeStmt->bindValue(4, time() + $maxlifetime, \PDO::PARAM_INT); $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB); $mergeStmt->bindValue(7, time() + $maxlifetime, \PDO::PARAM_INT); $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); } else { $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); $mergeStmt->bindValue(':expiry', time() + $maxlifetime, \PDO::PARAM_INT); $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); } return $mergeStmt; } /** * Return a PDO instance. * * @return \PDO */ protected function getConnection() { if (null === $this->pdo) { $this->connect($this->dsn ?: ini_get('session.save_path')); } return $this->pdo; } } http-foundation/Session/Storage/Handler/NullSessionHandler.php000064400000002640150432043210020554 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Can be used in unit testing or in a situations where persisted sessions are not desired. * * @author Drak */ class NullSessionHandler extends AbstractSessionHandler { /** * @return bool */ #[\ReturnTypeWillChange] public function close() { return true; } /** * @return bool */ #[\ReturnTypeWillChange] public function validateId($sessionId) { return true; } /** * {@inheritdoc} */ protected function doRead(string $sessionId) { return ''; } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { return true; } /** * {@inheritdoc} */ protected function doWrite(string $sessionId, string $data) { return true; } /** * {@inheritdoc} */ protected function doDestroy(string $sessionId) { return true; } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { return 0; } } http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php000064400000012365150432043210021174 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; use MongoDB\BSON\Binary; use MongoDB\BSON\UTCDateTime; use MongoDB\Client; use MongoDB\Collection; /** * Session handler using the mongodb/mongodb package and MongoDB driver extension. * * @author Markus Bachmann * * @see https://packagist.org/packages/mongodb/mongodb * @see https://php.net/mongodb */ class MongoDbSessionHandler extends AbstractSessionHandler { private $mongo; /** * @var Collection */ private $collection; /** * @var array */ private $options; /** * Constructor. * * List of available options: * * database: The name of the database [required] * * collection: The name of the collection [required] * * id_field: The field name for storing the session id [default: _id] * * data_field: The field name for storing the session data [default: data] * * time_field: The field name for storing the timestamp [default: time] * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]. * * It is strongly recommended to put an index on the `expiry_field` for * garbage-collection. Alternatively it's possible to automatically expire * the sessions in the database as described below: * * A TTL collections can be used on MongoDB 2.2+ to cleanup expired sessions * automatically. Such an index can for example look like this: * * db..createIndex( * { "": 1 }, * { "expireAfterSeconds": 0 } * ) * * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/ * * If you use such an index, you can drop `gc_probability` to 0 since * no garbage-collection is required. * * @throws \InvalidArgumentException When "database" or "collection" not provided */ public function __construct(Client $mongo, array $options) { if (!isset($options['database']) || !isset($options['collection'])) { throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler.'); } $this->mongo = $mongo; $this->options = array_merge([ 'id_field' => '_id', 'data_field' => 'data', 'time_field' => 'time', 'expiry_field' => 'expires_at', ], $options); } /** * @return bool */ #[\ReturnTypeWillChange] public function close() { return true; } /** * {@inheritdoc} */ protected function doDestroy(string $sessionId) { $this->getCollection()->deleteOne([ $this->options['id_field'] => $sessionId, ]); return true; } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { return $this->getCollection()->deleteMany([ $this->options['expiry_field'] => ['$lt' => new UTCDateTime()], ])->getDeletedCount(); } /** * {@inheritdoc} */ protected function doWrite(string $sessionId, string $data) { $expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); $fields = [ $this->options['time_field'] => new UTCDateTime(), $this->options['expiry_field'] => $expiry, $this->options['data_field'] => new Binary($data, Binary::TYPE_OLD_BINARY), ]; $this->getCollection()->updateOne( [$this->options['id_field'] => $sessionId], ['$set' => $fields], ['upsert' => true] ); return true; } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { $expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); $this->getCollection()->updateOne( [$this->options['id_field'] => $sessionId], ['$set' => [ $this->options['time_field'] => new UTCDateTime(), $this->options['expiry_field'] => $expiry, ]] ); return true; } /** * {@inheritdoc} */ protected function doRead(string $sessionId) { $dbData = $this->getCollection()->findOne([ $this->options['id_field'] => $sessionId, $this->options['expiry_field'] => ['$gte' => new UTCDateTime()], ]); if (null === $dbData) { return ''; } return $dbData[$this->options['data_field']]->getData(); } private function getCollection(): Collection { if (null === $this->collection) { $this->collection = $this->mongo->selectCollection($this->options['database'], $this->options['collection']); } return $this->collection; } /** * @return Client */ protected function getMongo() { return $this->mongo; } } http-foundation/Session/Storage/Handler/RedisSessionHandler.php000064400000007155150432043210020716 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; use Predis\Response\ErrorInterface; use Symfony\Component\Cache\Traits\RedisClusterProxy; use Symfony\Component\Cache\Traits\RedisProxy; /** * Redis based session storage handler based on the Redis class * provided by the PHP redis extension. * * @author Dalibor Karlović */ class RedisSessionHandler extends AbstractSessionHandler { private $redis; /** * @var string Key prefix for shared environments */ private $prefix; /** * @var int Time to live in seconds */ private $ttl; /** * List of available options: * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server * * ttl: The time to live in seconds. * * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis * * @throws \InvalidArgumentException When unsupported client or options are passed */ public function __construct($redis, array $options = []) { if ( !$redis instanceof \Redis && !$redis instanceof \RedisArray && !$redis instanceof \RedisCluster && !$redis instanceof \Predis\ClientInterface && !$redis instanceof RedisProxy && !$redis instanceof RedisClusterProxy ) { throw new \InvalidArgumentException(sprintf('"%s()" expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, "%s" given.', __METHOD__, get_debug_type($redis))); } if ($diff = array_diff(array_keys($options), ['prefix', 'ttl'])) { throw new \InvalidArgumentException(sprintf('The following options are not supported "%s".', implode(', ', $diff))); } $this->redis = $redis; $this->prefix = $options['prefix'] ?? 'sf_s'; $this->ttl = $options['ttl'] ?? null; } /** * {@inheritdoc} */ protected function doRead(string $sessionId): string { return $this->redis->get($this->prefix.$sessionId) ?: ''; } /** * {@inheritdoc} */ protected function doWrite(string $sessionId, string $data): bool { $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')), $data); return $result && !$result instanceof ErrorInterface; } /** * {@inheritdoc} */ protected function doDestroy(string $sessionId): bool { static $unlink = true; if ($unlink) { try { $unlink = false !== $this->redis->unlink($this->prefix.$sessionId); } catch (\Throwable $e) { $unlink = false; } } if (!$unlink) { $this->redis->del($this->prefix.$sessionId); } return true; } /** * {@inheritdoc} */ public function close(): bool { return true; } /** * {@inheritdoc} * * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { return 0; } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); } } http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php000064400000003443150432043210021672 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Native session handler using PHP's built in file storage. * * @author Drak */ class NativeFileSessionHandler extends \SessionHandler { /** * @param string $savePath Path of directory to save session files * Default null will leave setting as defined by PHP. * '/path', 'N;/path', or 'N;octal-mode;/path * * @see https://php.net/session.configuration#ini.session.save-path for further details. * * @throws \InvalidArgumentException On invalid $savePath * @throws \RuntimeException When failing to create the save directory */ public function __construct(string $savePath = null) { if (null === $savePath) { $savePath = ini_get('session.save_path'); } $baseDir = $savePath; if ($count = substr_count($savePath, ';')) { if ($count > 2) { throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'.', $savePath)); } // characters after last ';' are the path $baseDir = ltrim(strrchr($savePath, ';'), ';'); } if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) { throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s".', $baseDir)); } ini_set('session.save_path', $savePath); ini_set('session.save_handler', 'files'); } } http-foundation/Session/Storage/Handler/IdentityMarshaller.php000064400000001714150432043210020605 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; use Symfony\Component\Cache\Marshaller\MarshallerInterface; /** * @author Ahmed TAILOULOUTE */ class IdentityMarshaller implements MarshallerInterface { /** * {@inheritdoc} */ public function marshall(array $values, ?array &$failed): array { foreach ($values as $key => $value) { if (!\is_string($value)) { throw new \LogicException(sprintf('%s accepts only string as data.', __METHOD__)); } } return $values; } /** * {@inheritdoc} */ public function unmarshall(string $value): string { return $value; } } http-foundation/Session/Storage/Handler/SessionHandlerFactory.php000064400000010136150432043210021250 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; use Doctrine\DBAL\DriverManager; use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\Traits\RedisClusterProxy; use Symfony\Component\Cache\Traits\RedisProxy; /** * @author Nicolas Grekas */ class SessionHandlerFactory { /** * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy|\Memcached|\PDO|string $connection Connection or DSN */ public static function createHandler($connection): AbstractSessionHandler { if (!\is_string($connection) && !\is_object($connection)) { throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a string or a connection object, "%s" given.', __METHOD__, get_debug_type($connection))); } if ($options = \is_string($connection) ? parse_url($connection) : false) { parse_str($options['query'] ?? '', $options); } switch (true) { case $connection instanceof \Redis: case $connection instanceof \RedisArray: case $connection instanceof \RedisCluster: case $connection instanceof \Predis\ClientInterface: case $connection instanceof RedisProxy: case $connection instanceof RedisClusterProxy: return new RedisSessionHandler($connection); case $connection instanceof \Memcached: return new MemcachedSessionHandler($connection); case $connection instanceof \PDO: return new PdoSessionHandler($connection); case !\is_string($connection): throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', get_debug_type($connection))); case str_starts_with($connection, 'file://'): $savePath = substr($connection, 7); return new StrictSessionHandler(new NativeFileSessionHandler('' === $savePath ? null : $savePath)); case str_starts_with($connection, 'redis:'): case str_starts_with($connection, 'rediss:'): case str_starts_with($connection, 'memcached:'): if (!class_exists(AbstractAdapter::class)) { throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require symfony/cache".', $connection)); } $handlerClass = str_starts_with($connection, 'memcached:') ? MemcachedSessionHandler::class : RedisSessionHandler::class; $connection = AbstractAdapter::createConnection($connection, ['lazy' => true]); return new $handlerClass($connection, array_intersect_key($options ?: [], ['prefix' => 1, 'ttl' => 1])); case str_starts_with($connection, 'pdo_oci://'): if (!class_exists(DriverManager::class)) { throw new \InvalidArgumentException(sprintf('Unsupported DSN "%s". Try running "composer require doctrine/dbal".', $connection)); } $connection = DriverManager::getConnection(['url' => $connection])->getWrappedConnection(); // no break; case str_starts_with($connection, 'mssql://'): case str_starts_with($connection, 'mysql://'): case str_starts_with($connection, 'mysql2://'): case str_starts_with($connection, 'pgsql://'): case str_starts_with($connection, 'postgres://'): case str_starts_with($connection, 'postgresql://'): case str_starts_with($connection, 'sqlsrv://'): case str_starts_with($connection, 'sqlite://'): case str_starts_with($connection, 'sqlite3://'): return new PdoSessionHandler($connection, $options ?: []); } throw new \InvalidArgumentException(sprintf('Unsupported Connection: "%s".', $connection)); } } http-foundation/Session/Storage/Handler/AbstractSessionHandler.php000064400000012036150432043210021405 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; use Symfony\Component\HttpFoundation\Session\SessionUtils; /** * This abstract session handler provides a generic implementation * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, * enabling strict and lazy session handling. * * @author Nicolas Grekas */ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface { private $sessionName; private $prefetchId; private $prefetchData; private $newSessionId; private $igbinaryEmptyData; /** * @return bool */ #[\ReturnTypeWillChange] public function open($savePath, $sessionName) { $this->sessionName = $sessionName; if (!headers_sent() && !ini_get('session.cache_limiter') && '0' !== ini_get('session.cache_limiter')) { header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) ini_get('session.cache_expire'))); } return true; } /** * @return string */ abstract protected function doRead(string $sessionId); /** * @return bool */ abstract protected function doWrite(string $sessionId, string $data); /** * @return bool */ abstract protected function doDestroy(string $sessionId); /** * @return bool */ #[\ReturnTypeWillChange] public function validateId($sessionId) { $this->prefetchData = $this->read($sessionId); $this->prefetchId = $sessionId; if (\PHP_VERSION_ID < 70317 || (70400 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70405)) { // work around https://bugs.php.net/79413 foreach (debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { if (!isset($frame['class']) && isset($frame['function']) && \in_array($frame['function'], ['session_regenerate_id', 'session_create_id'], true)) { return '' === $this->prefetchData; } } } return '' !== $this->prefetchData; } /** * @return string */ #[\ReturnTypeWillChange] public function read($sessionId) { if (null !== $this->prefetchId) { $prefetchId = $this->prefetchId; $prefetchData = $this->prefetchData; $this->prefetchId = $this->prefetchData = null; if ($prefetchId === $sessionId || '' === $prefetchData) { $this->newSessionId = '' === $prefetchData ? $sessionId : null; return $prefetchData; } } $data = $this->doRead($sessionId); $this->newSessionId = '' === $data ? $sessionId : null; return $data; } /** * @return bool */ #[\ReturnTypeWillChange] public function write($sessionId, $data) { if (null === $this->igbinaryEmptyData) { // see https://github.com/igbinary/igbinary/issues/146 $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize([]) : ''; } if ('' === $data || $this->igbinaryEmptyData === $data) { return $this->destroy($sessionId); } $this->newSessionId = null; return $this->doWrite($sessionId, $data); } /** * @return bool */ #[\ReturnTypeWillChange] public function destroy($sessionId) { if (!headers_sent() && filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) { if (!$this->sessionName) { throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); } $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); /* * We send an invalidation Set-Cookie header (zero lifetime) * when either the session was started or a cookie with * the session name was sent by the client (in which case * we know it's invalid as a valid session cookie would've * started the session). */ if (null === $cookie || isset($_COOKIE[$this->sessionName])) { if (\PHP_VERSION_ID < 70300) { setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN)); } else { $params = session_get_cookie_params(); unset($params['lifetime']); setcookie($this->sessionName, '', $params); } } } return $this->newSessionId === $sessionId || $this->doDestroy($sessionId); } } http-foundation/Session/Storage/Handler/MigratingSessionHandler.php000064400000007115150432043210021565 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** * Migrating session handler for migrating from one handler to another. It reads * from the current handler and writes both the current and new ones. * * It ignores errors from the new handler. * * @author Ross Motley * @author Oliver Radwell */ class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface { /** * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface */ private $currentHandler; /** * @var \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface */ private $writeOnlyHandler; public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler) { if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) { $currentHandler = new StrictSessionHandler($currentHandler); } if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) { $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler); } $this->currentHandler = $currentHandler; $this->writeOnlyHandler = $writeOnlyHandler; } /** * @return bool */ #[\ReturnTypeWillChange] public function close() { $result = $this->currentHandler->close(); $this->writeOnlyHandler->close(); return $result; } /** * @return bool */ #[\ReturnTypeWillChange] public function destroy($sessionId) { $result = $this->currentHandler->destroy($sessionId); $this->writeOnlyHandler->destroy($sessionId); return $result; } /** * @return int|false */ #[\ReturnTypeWillChange] public function gc($maxlifetime) { $result = $this->currentHandler->gc($maxlifetime); $this->writeOnlyHandler->gc($maxlifetime); return $result; } /** * @return bool */ #[\ReturnTypeWillChange] public function open($savePath, $sessionName) { $result = $this->currentHandler->open($savePath, $sessionName); $this->writeOnlyHandler->open($savePath, $sessionName); return $result; } /** * @return string */ #[\ReturnTypeWillChange] public function read($sessionId) { // No reading from new handler until switch-over return $this->currentHandler->read($sessionId); } /** * @return bool */ #[\ReturnTypeWillChange] public function write($sessionId, $sessionData) { $result = $this->currentHandler->write($sessionId, $sessionData); $this->writeOnlyHandler->write($sessionId, $sessionData); return $result; } /** * @return bool */ #[\ReturnTypeWillChange] public function validateId($sessionId) { // No reading from new handler until switch-over return $this->currentHandler->validateId($sessionId); } /** * @return bool */ #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $sessionData) { $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData); $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData); return $result; } } http-foundation/Session/SessionBagProxy.php000064400000004051150432043210015114 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; /** * @author Nicolas Grekas * * @internal */ final class SessionBagProxy implements SessionBagInterface { private $bag; private $data; private $usageIndex; private $usageReporter; public function __construct(SessionBagInterface $bag, array &$data, ?int &$usageIndex, ?callable $usageReporter) { $this->bag = $bag; $this->data = &$data; $this->usageIndex = &$usageIndex; $this->usageReporter = $usageReporter; } public function getBag(): SessionBagInterface { ++$this->usageIndex; if ($this->usageReporter && 0 <= $this->usageIndex) { ($this->usageReporter)(); } return $this->bag; } public function isEmpty(): bool { if (!isset($this->data[$this->bag->getStorageKey()])) { return true; } ++$this->usageIndex; if ($this->usageReporter && 0 <= $this->usageIndex) { ($this->usageReporter)(); } return empty($this->data[$this->bag->getStorageKey()]); } /** * {@inheritdoc} */ public function getName(): string { return $this->bag->getName(); } /** * {@inheritdoc} */ public function initialize(array &$array): void { ++$this->usageIndex; if ($this->usageReporter && 0 <= $this->usageIndex) { ($this->usageReporter)(); } $this->data[$this->bag->getStorageKey()] = &$array; $this->bag->initialize($array); } /** * {@inheritdoc} */ public function getStorageKey(): string { return $this->bag->getStorageKey(); } /** * {@inheritdoc} */ public function clear() { return $this->bag->clear(); } } http-foundation/Session/SessionFactoryInterface.php000064400000000664150432043210016617 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; /** * @author Kevin Bond */ interface SessionFactoryInterface { public function createSession(): SessionInterface; } http-foundation/Session/Flash/AutoExpireFlashBag.php000064400000006605150432043210016536 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; /** * AutoExpireFlashBag flash message container. * * @author Drak */ class AutoExpireFlashBag implements FlashBagInterface { private $name = 'flashes'; private $flashes = ['display' => [], 'new' => []]; private $storageKey; /** * @param string $storageKey The key used to store flashes in the session */ public function __construct(string $storageKey = '_symfony_flashes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName(string $name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$flashes) { $this->flashes = &$flashes; // The logic: messages from the last request will be stored in new, so we move them to previous // This request we will show what is in 'display'. What is placed into 'new' this time round will // be moved to display next time round. $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; $this->flashes['new'] = []; } /** * {@inheritdoc} */ public function add(string $type, $message) { $this->flashes['new'][$type][] = $message; } /** * {@inheritdoc} */ public function peek(string $type, array $default = []) { return $this->has($type) ? $this->flashes['display'][$type] : $default; } /** * {@inheritdoc} */ public function peekAll() { return \array_key_exists('display', $this->flashes) ? $this->flashes['display'] : []; } /** * {@inheritdoc} */ public function get(string $type, array $default = []) { $return = $default; if (!$this->has($type)) { return $return; } if (isset($this->flashes['display'][$type])) { $return = $this->flashes['display'][$type]; unset($this->flashes['display'][$type]); } return $return; } /** * {@inheritdoc} */ public function all() { $return = $this->flashes['display']; $this->flashes['display'] = []; return $return; } /** * {@inheritdoc} */ public function setAll(array $messages) { $this->flashes['new'] = $messages; } /** * {@inheritdoc} */ public function set(string $type, $messages) { $this->flashes['new'][$type] = (array) $messages; } /** * {@inheritdoc} */ public function has(string $type) { return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; } /** * {@inheritdoc} */ public function keys() { return array_keys($this->flashes['display']); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function clear() { return $this->all(); } } http-foundation/Session/Flash/FlashBagInterface.php000064400000003522150432043210016344 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; /** * FlashBagInterface. * * @author Drak */ interface FlashBagInterface extends SessionBagInterface { /** * Adds a flash message for the given type. * * @param mixed $message */ public function add(string $type, $message); /** * Registers one or more messages for a given type. * * @param string|array $messages */ public function set(string $type, $messages); /** * Gets flash messages for a given type. * * @param string $type Message category type * @param array $default Default value if $type does not exist * * @return array */ public function peek(string $type, array $default = []); /** * Gets all flash messages. * * @return array */ public function peekAll(); /** * Gets and clears flash from the stack. * * @param array $default Default value if $type does not exist * * @return array */ public function get(string $type, array $default = []); /** * Gets and clears flashes from the stack. * * @return array */ public function all(); /** * Sets all flash messages. */ public function setAll(array $messages); /** * Has flash messages for a given type? * * @return bool */ public function has(string $type); /** * Returns a list of all defined types. * * @return array */ public function keys(); } http-foundation/Session/Flash/FlashBag.php000064400000005264150432043210014530 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session\Flash; /** * FlashBag flash message container. * * @author Drak */ class FlashBag implements FlashBagInterface { private $name = 'flashes'; private $flashes = []; private $storageKey; /** * @param string $storageKey The key used to store flashes in the session */ public function __construct(string $storageKey = '_symfony_flashes') { $this->storageKey = $storageKey; } /** * {@inheritdoc} */ public function getName() { return $this->name; } public function setName(string $name) { $this->name = $name; } /** * {@inheritdoc} */ public function initialize(array &$flashes) { $this->flashes = &$flashes; } /** * {@inheritdoc} */ public function add(string $type, $message) { $this->flashes[$type][] = $message; } /** * {@inheritdoc} */ public function peek(string $type, array $default = []) { return $this->has($type) ? $this->flashes[$type] : $default; } /** * {@inheritdoc} */ public function peekAll() { return $this->flashes; } /** * {@inheritdoc} */ public function get(string $type, array $default = []) { if (!$this->has($type)) { return $default; } $return = $this->flashes[$type]; unset($this->flashes[$type]); return $return; } /** * {@inheritdoc} */ public function all() { $return = $this->peekAll(); $this->flashes = []; return $return; } /** * {@inheritdoc} */ public function set(string $type, $messages) { $this->flashes[$type] = (array) $messages; } /** * {@inheritdoc} */ public function setAll(array $messages) { $this->flashes = $messages; } /** * {@inheritdoc} */ public function has(string $type) { return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; } /** * {@inheritdoc} */ public function keys() { return array_keys($this->flashes); } /** * {@inheritdoc} */ public function getStorageKey() { return $this->storageKey; } /** * {@inheritdoc} */ public function clear() { return $this->all(); } } http-foundation/Session/SessionUtils.php000064400000003135150432043210014463 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; /** * Session utility functions. * * @author Nicolas Grekas * @author Rémon van de Kamp * * @internal */ final class SessionUtils { /** * Finds the session header amongst the headers that are to be sent, removes it, and returns * it so the caller can process it further. */ public static function popSessionCookie(string $sessionName, string $sessionId): ?string { $sessionCookie = null; $sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName)); $sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); $otherCookies = []; foreach (headers_list() as $h) { if (0 !== stripos($h, 'Set-Cookie:')) { continue; } if (11 === strpos($h, $sessionCookiePrefix, 11)) { $sessionCookie = $h; if (11 !== strpos($h, $sessionCookieWithId, 11)) { $otherCookies[] = $h; } } else { $otherCookies[] = $h; } } if (null === $sessionCookie) { return null; } header_remove('Set-Cookie'); foreach ($otherCookies as $h) { header($h, false); } return $sessionCookie; } } http-foundation/Session/SessionFactory.php000064400000002300150432043210014763 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageFactoryInterface; // Help opcache.preload discover always-needed symbols class_exists(Session::class); /** * @author Jérémy Derussé */ class SessionFactory implements SessionFactoryInterface { private $requestStack; private $storageFactory; private $usageReporter; public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, callable $usageReporter = null) { $this->requestStack = $requestStack; $this->storageFactory = $storageFactory; $this->usageReporter = $usageReporter; } public function createSession(): SessionInterface { return new Session($this->storageFactory->createStorage($this->requestStack->getMainRequest()), null, null, $this->usageReporter); } } http-foundation/Session/SessionBagInterface.php000064400000001521150432043210015672 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpFoundation\Session; /** * Session Bag store. * * @author Drak */ interface SessionBagInterface { /** * Gets this bag's name. * * @return string */ public function getName(); /** * Initializes the Bag. */ public function initialize(array &$array); /** * Gets the storage key for this bag. * * @return string */ public function getStorageKey(); /** * Clears out data from bag. * * @return mixed Whatever data was contained */ public function clear(); } psr-http-message-bridge/Factory/UploadedFile.php000066600000004072150432043210015657 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\PsrHttpMessage\Factory; use Psr\Http\Message\UploadedFileInterface; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\UploadedFile as BaseUploadedFile; /** * @author Nicolas Grekas */ class UploadedFile extends BaseUploadedFile { private $psrUploadedFile; private $test = false; public function __construct(UploadedFileInterface $psrUploadedFile, callable $getTemporaryPath) { $error = $psrUploadedFile->getError(); $path = ''; if (\UPLOAD_ERR_NO_FILE !== $error) { $path = $psrUploadedFile->getStream()->getMetadata('uri') ?? ''; if ($this->test = !\is_string($path) || !is_uploaded_file($path)) { $path = $getTemporaryPath(); $psrUploadedFile->moveTo($path); } } parent::__construct( $path, (string) $psrUploadedFile->getClientFilename(), $psrUploadedFile->getClientMediaType(), $psrUploadedFile->getError(), $this->test ); $this->psrUploadedFile = $psrUploadedFile; } /** * {@inheritdoc} */ public function move(string $directory, string $name = null): File { if (!$this->isValid() || $this->test) { return parent::move($directory, $name); } $target = $this->getTargetFile($directory, $name); try { $this->psrUploadedFile->moveTo((string) $target); } catch (\RuntimeException $e) { throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, $e->getMessage()), 0, $e); } @chmod($target, 0666 & ~umask()); return $target; } } psr-http-message-bridge/Factory/HttpFoundationFactory.php000066600000016045150432043210017623 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\PsrHttpMessage\Factory; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UriInterface; use Symfony\Bridge\PsrHttpMessage\HttpFoundationFactoryInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; /** * {@inheritdoc} * * @author Kévin Dunglas */ class HttpFoundationFactory implements HttpFoundationFactoryInterface { /** * @var int The maximum output buffering size for each iteration when sending the response */ private $responseBufferMaxLength; public function __construct(int $responseBufferMaxLength = 16372) { $this->responseBufferMaxLength = $responseBufferMaxLength; } /** * {@inheritdoc} * * @return Request */ public function createRequest(ServerRequestInterface $psrRequest, bool $streamed = false) { $server = []; $uri = $psrRequest->getUri(); if ($uri instanceof UriInterface) { $server['SERVER_NAME'] = $uri->getHost(); $server['SERVER_PORT'] = $uri->getPort() ?: ('https' === $uri->getScheme() ? 443 : 80); $server['REQUEST_URI'] = $uri->getPath(); $server['QUERY_STRING'] = $uri->getQuery(); if ('' !== $server['QUERY_STRING']) { $server['REQUEST_URI'] .= '?'.$server['QUERY_STRING']; } if ('https' === $uri->getScheme()) { $server['HTTPS'] = 'on'; } } $server['REQUEST_METHOD'] = $psrRequest->getMethod(); $server = array_replace($psrRequest->getServerParams(), $server); $parsedBody = $psrRequest->getParsedBody(); $parsedBody = \is_array($parsedBody) ? $parsedBody : []; $request = new Request( $psrRequest->getQueryParams(), $parsedBody, $psrRequest->getAttributes(), $psrRequest->getCookieParams(), $this->getFiles($psrRequest->getUploadedFiles()), $server, $streamed ? $psrRequest->getBody()->detach() : $psrRequest->getBody()->__toString() ); $request->headers->add($psrRequest->getHeaders()); return $request; } /** * Converts to the input array to $_FILES structure. */ private function getFiles(array $uploadedFiles): array { $files = []; foreach ($uploadedFiles as $key => $value) { if ($value instanceof UploadedFileInterface) { $files[$key] = $this->createUploadedFile($value); } else { $files[$key] = $this->getFiles($value); } } return $files; } /** * Creates Symfony UploadedFile instance from PSR-7 ones. */ private function createUploadedFile(UploadedFileInterface $psrUploadedFile): UploadedFile { return new UploadedFile($psrUploadedFile, function () { return $this->getTemporaryPath(); }); } /** * Gets a temporary file path. * * @return string */ protected function getTemporaryPath() { return tempnam(sys_get_temp_dir(), uniqid('symfony', true)); } /** * {@inheritdoc} * * @return Response */ public function createResponse(ResponseInterface $psrResponse, bool $streamed = false) { $cookies = $psrResponse->getHeader('Set-Cookie'); $psrResponse = $psrResponse->withoutHeader('Set-Cookie'); if ($streamed) { $response = new StreamedResponse( $this->createStreamedResponseCallback($psrResponse->getBody()), $psrResponse->getStatusCode(), $psrResponse->getHeaders() ); } else { $response = new Response( $psrResponse->getBody()->__toString(), $psrResponse->getStatusCode(), $psrResponse->getHeaders() ); } $response->setProtocolVersion($psrResponse->getProtocolVersion()); foreach ($cookies as $cookie) { $response->headers->setCookie($this->createCookie($cookie)); } return $response; } /** * Creates a Cookie instance from a cookie string. * * Some snippets have been taken from the Guzzle project: https://github.com/guzzle/guzzle/blob/5.3/src/Cookie/SetCookie.php#L34 * * @throws \InvalidArgumentException */ private function createCookie(string $cookie): Cookie { foreach (explode(';', $cookie) as $part) { $part = trim($part); $data = explode('=', $part, 2); $name = $data[0]; $value = isset($data[1]) ? trim($data[1], " \n\r\t\0\x0B\"") : null; if (!isset($cookieName)) { $cookieName = $name; $cookieValue = $value; continue; } if ('expires' === strtolower($name) && null !== $value) { $cookieExpire = new \DateTime($value); continue; } if ('path' === strtolower($name) && null !== $value) { $cookiePath = $value; continue; } if ('domain' === strtolower($name) && null !== $value) { $cookieDomain = $value; continue; } if ('secure' === strtolower($name)) { $cookieSecure = true; continue; } if ('httponly' === strtolower($name)) { $cookieHttpOnly = true; continue; } if ('samesite' === strtolower($name) && null !== $value) { $samesite = $value; continue; } } if (!isset($cookieName)) { throw new \InvalidArgumentException('The value of the Set-Cookie header is malformed.'); } return new Cookie( $cookieName, $cookieValue, $cookieExpire ?? 0, $cookiePath ?? '/', $cookieDomain ?? null, isset($cookieSecure), isset($cookieHttpOnly), true, $samesite ?? null ); } private function createStreamedResponseCallback(StreamInterface $body): callable { return function () use ($body) { if ($body->isSeekable()) { $body->rewind(); } if (!$body->isReadable()) { echo $body; return; } while (!$body->eof()) { echo $body->read($this->responseBufferMaxLength); } }; } } psr-http-message-bridge/Factory/PsrHttpFactory.php000066600000015417150432043210016263 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\PsrHttpMessage\Factory; use Psr\Http\Message\ResponseFactoryInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestFactoryInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamFactoryInterface; use Psr\Http\Message\UploadedFileFactoryInterface; use Psr\Http\Message\UploadedFileInterface; use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; use Symfony\Component\HttpFoundation\BinaryFileResponse; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; /** * Builds Psr\HttpMessage instances using a PSR-17 implementation. * * @author Antonio J. García Lagar * @author Aurélien Pillevesse */ class PsrHttpFactory implements HttpMessageFactoryInterface { private $serverRequestFactory; private $streamFactory; private $uploadedFileFactory; private $responseFactory; public function __construct(ServerRequestFactoryInterface $serverRequestFactory, StreamFactoryInterface $streamFactory, UploadedFileFactoryInterface $uploadedFileFactory, ResponseFactoryInterface $responseFactory) { $this->serverRequestFactory = $serverRequestFactory; $this->streamFactory = $streamFactory; $this->uploadedFileFactory = $uploadedFileFactory; $this->responseFactory = $responseFactory; } /** * {@inheritdoc} * * @return ServerRequestInterface */ public function createRequest(Request $symfonyRequest) { $uri = $symfonyRequest->server->get('QUERY_STRING', ''); $uri = $symfonyRequest->getSchemeAndHttpHost().$symfonyRequest->getBaseUrl().$symfonyRequest->getPathInfo().('' !== $uri ? '?'.$uri : ''); $request = $this->serverRequestFactory->createServerRequest( $symfonyRequest->getMethod(), $uri, $symfonyRequest->server->all() ); foreach ($symfonyRequest->headers->all() as $name => $value) { try { $request = $request->withHeader($name, $value); } catch (\InvalidArgumentException $e) { // ignore invalid header } } $body = $this->streamFactory->createStreamFromResource($symfonyRequest->getContent(true)); if (method_exists(Request::class, 'getContentTypeFormat')) { $format = $symfonyRequest->getContentTypeFormat(); } else { $format = $symfonyRequest->getContentType(); } if ('json' === $format) { $parsedBody = json_decode($symfonyRequest->getContent(), true, 512, \JSON_BIGINT_AS_STRING); if (!\is_array($parsedBody)) { $parsedBody = null; } } else { $parsedBody = $symfonyRequest->request->all(); } $request = $request ->withBody($body) ->withUploadedFiles($this->getFiles($symfonyRequest->files->all())) ->withCookieParams($symfonyRequest->cookies->all()) ->withQueryParams($symfonyRequest->query->all()) ->withParsedBody($parsedBody) ; foreach ($symfonyRequest->attributes->all() as $key => $value) { $request = $request->withAttribute($key, $value); } return $request; } /** * Converts Symfony uploaded files array to the PSR one. */ private function getFiles(array $uploadedFiles): array { $files = []; foreach ($uploadedFiles as $key => $value) { if (null === $value) { $files[$key] = $this->uploadedFileFactory->createUploadedFile($this->streamFactory->createStream(), 0, \UPLOAD_ERR_NO_FILE); continue; } if ($value instanceof UploadedFile) { $files[$key] = $this->createUploadedFile($value); } else { $files[$key] = $this->getFiles($value); } } return $files; } /** * Creates a PSR-7 UploadedFile instance from a Symfony one. */ private function createUploadedFile(UploadedFile $symfonyUploadedFile): UploadedFileInterface { return $this->uploadedFileFactory->createUploadedFile( $this->streamFactory->createStreamFromFile( $symfonyUploadedFile->getRealPath() ), (int) $symfonyUploadedFile->getSize(), $symfonyUploadedFile->getError(), $symfonyUploadedFile->getClientOriginalName(), $symfonyUploadedFile->getClientMimeType() ); } /** * {@inheritdoc} * * @return ResponseInterface */ public function createResponse(Response $symfonyResponse) { $response = $this->responseFactory->createResponse($symfonyResponse->getStatusCode(), Response::$statusTexts[$symfonyResponse->getStatusCode()] ?? ''); if ($symfonyResponse instanceof BinaryFileResponse && !$symfonyResponse->headers->has('Content-Range')) { $stream = $this->streamFactory->createStreamFromFile( $symfonyResponse->getFile()->getPathname() ); } else { $stream = $this->streamFactory->createStreamFromFile('php://temp', 'wb+'); if ($symfonyResponse instanceof StreamedResponse || $symfonyResponse instanceof BinaryFileResponse) { ob_start(function ($buffer) use ($stream) { $stream->write($buffer); return ''; }, 1); $symfonyResponse->sendContent(); ob_end_clean(); } else { $stream->write($symfonyResponse->getContent()); } } $response = $response->withBody($stream); $headers = $symfonyResponse->headers->all(); $cookies = $symfonyResponse->headers->getCookies(); if (!empty($cookies)) { $headers['Set-Cookie'] = []; foreach ($cookies as $cookie) { $headers['Set-Cookie'][] = $cookie->__toString(); } } foreach ($headers as $name => $value) { try { $response = $response->withHeader($name, $value); } catch (\InvalidArgumentException $e) { // ignore invalid header } } $protocolVersion = $symfonyResponse->getProtocolVersion(); $response = $response->withProtocolVersion($protocolVersion); return $response; } } psr-http-message-bridge/README.md000066600000000557150432043210012465 0ustar00PSR-7 Bridge ============ Provides integration for PSR7. Resources --------- * [Documentation](https://symfony.com/doc/current/components/psr7.html) Running the tests ----------------- If you want to run the unit tests, install dev dependencies before running PHPUnit: $ cd path/to/Symfony/Bridge/PsrHttpMessage/ $ composer.phar install $ phpunit psr-http-message-bridge/HttpMessageFactoryInterface.php000066600000001736150432043210017314 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\PsrHttpMessage; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Creates PSR HTTP Request and Response instances from Symfony ones. * * @author Kévin Dunglas */ interface HttpMessageFactoryInterface { /** * Creates a PSR-7 Request instance from a Symfony one. * * @return ServerRequestInterface */ public function createRequest(Request $symfonyRequest); /** * Creates a PSR-7 Response instance from a Symfony one. * * @return ResponseInterface */ public function createResponse(Response $symfonyResponse); } psr-http-message-bridge/HttpFoundationFactoryInterface.php000066600000002006150432043210020025 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\PsrHttpMessage; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Creates Symfony Request and Response instances from PSR-7 ones. * * @author Kévin Dunglas */ interface HttpFoundationFactoryInterface { /** * Creates a Symfony Request instance from a PSR-7 one. * * @return Request */ public function createRequest(ServerRequestInterface $psrRequest, bool $streamed = false); /** * Creates a Symfony Response instance from a PSR-7 one. * * @return Response */ public function createResponse(ResponseInterface $psrResponse, bool $streamed = false); } psr-http-message-bridge/.php-cs-fixer.dist.php000066600000002155150432043210015240 0ustar00setRules([ '@Symfony' => true, '@Symfony:risky' => true, '@PHPUnit48Migration:risky' => true, 'php_unit_no_expectation_annotation' => false, // part of `PHPUnitXYMigration:risky` ruleset, to be enabled when PHPUnit 4.x support will be dropped, as we don't want to rewrite exceptions handling twice 'array_syntax' => ['syntax' => 'short'], 'fopen_flags' => false, 'ordered_imports' => true, 'protected_to_private' => false, // Part of @Symfony:risky in PHP-CS-Fixer 2.13.0. To be removed from the config file once upgrading 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced'], // Part of future @Symfony ruleset in PHP-CS-Fixer To be removed from the config file once upgrading 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], ]) ->setRiskyAllowed(true) ->setFinder( (new PhpCsFixer\Finder()) ->in(__DIR__) ->exclude('vendor') ->name('*.php') ) ; psr-http-message-bridge/CHANGELOG.md000066600000003727150432043210013021 0ustar00CHANGELOG ========= # 2.3.1 (2023-07-26) * Don't rely on `Request::getPayload()` to populate the parsed body # 2.3.0 (2023-07-25) * Leverage `Request::getPayload()` to populate the parsed body of PSR-7 requests * Implement `ValueResolverInterface` introduced with Symfony 6.2 # 2.2.0 (2023-04-21) * Drop support for Symfony 4 * Bump minimum version of PHP to 7.2 * Support version 2 of the psr/http-message contracts # 2.1.3 (2022-09-05) * Ignore invalid HTTP headers when creating PSR7 objects * Fix for wrong type passed to `moveTo()` # 2.1.2 (2021-11-05) * Allow Symfony 6 # 2.1.0 (2021-02-17) * Added a `PsrResponseListener` to automatically convert PSR-7 responses returned by controllers * Added a `PsrServerRequestResolver` that allows injecting PSR-7 request objects into controllers # 2.0.2 (2020-09-29) * Fix populating server params from URI in HttpFoundationFactory * Create cookies as raw in HttpFoundationFactory * Fix BinaryFileResponse with Content-Range PsrHttpFactory # 2.0.1 (2020-06-25) * Don't normalize query string in PsrHttpFactory * Fix conversion for HTTPS requests * Fix populating default port and headers in HttpFoundationFactory # 2.0.0 (2020-01-02) * Remove DiactorosFactory # 1.3.0 (2019-11-25) * Added support for streamed requests * Added support for Symfony 5.0+ * Fixed bridging UploadedFile objects * Bumped minimum version of Symfony to 4.4 # 1.2.0 (2019-03-11) * Added new documentation links * Bumped minimum version of PHP to 7.1 * Added support for streamed responses # 1.1.2 (2019-04-03) * Fixed createResponse # 1.1.1 (2019-03-11) * Deprecated DiactorosFactory, use PsrHttpFactory instead * Removed triggering of deprecation # 1.1.0 (2018-08-30) * Added support for creating PSR-7 messages using PSR-17 factories # 1.0.2 (2017-12-19) * Fixed request target in PSR7 Request (mtibben) # 1.0.1 (2017-12-04) * Added support for Symfony 4 (dunglas) # 1.0.0 (2016-09-14) * Initial release psr-http-message-bridge/EventListener/PsrResponseListener.php000066600000002704150432043210020473 0ustar00 * @author Alexander M. Turek */ final class PsrResponseListener implements EventSubscriberInterface { private $httpFoundationFactory; public function __construct(HttpFoundationFactoryInterface $httpFoundationFactory = null) { $this->httpFoundationFactory = $httpFoundationFactory ?? new HttpFoundationFactory(); } /** * Do the conversion if applicable and update the response of the event. */ public function onKernelView(ViewEvent $event): void { $controllerResult = $event->getControllerResult(); if (!$controllerResult instanceof ResponseInterface) { return; } $event->setResponse($this->httpFoundationFactory->createResponse($controllerResult)); } /** * {@inheritdoc} */ public static function getSubscribedEvents(): array { return [ KernelEvents::VIEW => 'onKernelView', ]; } } psr-http-message-bridge/ArgumentValueResolver/ValueResolverInterface.php000066600000001206150432043210022627 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\PsrHttpMessage\ArgumentValueResolver; use Symfony\Component\HttpKernel\Controller\ValueResolverInterface as BaseValueResolverInterface; if (interface_exists(BaseValueResolverInterface::class)) { /** @internal */ interface ValueResolverInterface extends BaseValueResolverInterface { } } else { /** @internal */ interface ValueResolverInterface { } } psr-http-message-bridge/ArgumentValueResolver/PsrServerRequestResolver.php000066600000004212150432043210023236 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Bridge\PsrHttpMessage\ArgumentValueResolver; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ServerRequestInterface; use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\Controller\ValueResolverInterface as BaseValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Injects the RequestInterface, MessageInterface or ServerRequestInterface when requested. * * @author Iltar van der Berg * @author Alexander M. Turek */ final class PsrServerRequestResolver implements ArgumentValueResolverInterface, ValueResolverInterface { private const SUPPORTED_TYPES = [ ServerRequestInterface::class => true, RequestInterface::class => true, MessageInterface::class => true, ]; private $httpMessageFactory; public function __construct(HttpMessageFactoryInterface $httpMessageFactory) { $this->httpMessageFactory = $httpMessageFactory; } /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { if ($this instanceof BaseValueResolverInterface) { trigger_deprecation('symfony/psr-http-message-bridge', '2.3', 'Method "%s" is deprecated, call "resolve()" without calling "supports()" first.', __METHOD__); } return self::SUPPORTED_TYPES[$argument->getType()] ?? false; } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): \Traversable { if (!isset(self::SUPPORTED_TYPES[$argument->getType()])) { return; } yield $this->httpMessageFactory->createRequest($request); } } psr-http-message-bridge/composer.json000066600000002610150432043210013720 0ustar00{ "name": "symfony/psr-http-message-bridge", "type": "symfony-bridge", "description": "PSR HTTP message bridge", "keywords": ["http", "psr-7", "psr-17", "http-message"], "homepage": "http://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "psr/http-message": "^1.0 || ^2.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", "symfony/http-foundation": "^5.4 || ^6.0" }, "require-dev": { "symfony/browser-kit": "^5.4 || ^6.0", "symfony/config": "^5.4 || ^6.0", "symfony/event-dispatcher": "^5.4 || ^6.0", "symfony/framework-bundle": "^5.4 || ^6.0", "symfony/http-kernel": "^5.4 || ^6.0", "symfony/phpunit-bridge": "^6.2", "nyholm/psr7": "^1.1", "psr/log": "^1.1 || ^2 || ^3" }, "suggest": { "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" }, "autoload": { "psr-4": { "Symfony\\Bridge\\PsrHttpMessage\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "extra": { "branch-alias": { "dev-main": "2.3-dev" } } } psr-http-message-bridge/LICENSE000066600000002051150432043210012202 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. finder/Glob.php000064400000007044150432043210007406 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Glob matches globbing patterns against text. * * if match_glob("foo.*", "foo.bar") echo "matched\n"; * * // prints foo.bar and foo.baz * $regex = glob_to_regex("foo.*"); * for (['foo.bar', 'foo.baz', 'foo', 'bar'] as $t) * { * if (/$regex/) echo "matched: $car\n"; * } * * Glob implements glob(3) style matching that can be used to match * against text, rather than fetching names from a filesystem. * * Based on the Perl Text::Glob module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp */ class Glob { /** * Returns a regexp which is the equivalent of the glob pattern. * * @return string */ public static function toRegex(string $glob, bool $strictLeadingDot = true, bool $strictWildcardSlash = true, string $delimiter = '#') { $firstByte = true; $escaping = false; $inCurlies = 0; $regex = ''; $sizeGlob = \strlen($glob); for ($i = 0; $i < $sizeGlob; ++$i) { $car = $glob[$i]; if ($firstByte && $strictLeadingDot && '.' !== $car) { $regex .= '(?=[^\.])'; } $firstByte = '/' === $car; if ($firstByte && $strictWildcardSlash && isset($glob[$i + 2]) && '**' === $glob[$i + 1].$glob[$i + 2] && (!isset($glob[$i + 3]) || '/' === $glob[$i + 3])) { $car = '[^/]++/'; if (!isset($glob[$i + 3])) { $car .= '?'; } if ($strictLeadingDot) { $car = '(?=[^\.])'.$car; } $car = '/(?:'.$car.')*'; $i += 2 + isset($glob[$i + 3]); if ('/' === $delimiter) { $car = str_replace('/', '\\/', $car); } } if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) { $regex .= "\\$car"; } elseif ('*' === $car) { $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*'); } elseif ('?' === $car) { $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.'); } elseif ('{' === $car) { $regex .= $escaping ? '\\{' : '('; if (!$escaping) { ++$inCurlies; } } elseif ('}' === $car && $inCurlies) { $regex .= $escaping ? '}' : ')'; if (!$escaping) { --$inCurlies; } } elseif (',' === $car && $inCurlies) { $regex .= $escaping ? ',' : '|'; } elseif ('\\' === $car) { if ($escaping) { $regex .= '\\\\'; $escaping = false; } else { $escaping = true; } continue; } else { $regex .= $car; } $escaping = false; } return $delimiter.'^'.$regex.'$'.$delimiter; } } finder/README.md000064400000000757150432043210007275 0ustar00Finder Component ================ The Finder component finds files and directories via an intuitive fluent interface. Resources --------- * [Documentation](https://symfony.com/doc/current/components/finder.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) finder/Comparator/Comparator.php000064400000005765150432043210012751 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * @author Fabien Potencier */ class Comparator { private $target; private $operator = '=='; public function __construct(string $target = null, string $operator = '==') { if (null === $target) { trigger_deprecation('symfony/finder', '5.4', 'Constructing a "%s" without setting "$target" is deprecated.', __CLASS__); } $this->target = $target; $this->doSetOperator($operator); } /** * Gets the target value. * * @return string */ public function getTarget() { if (null === $this->target) { trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__); } return $this->target; } /** * @deprecated set the target via the constructor instead */ public function setTarget(string $target) { trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the target via the constructor instead.', __METHOD__); $this->target = $target; } /** * Gets the comparison operator. * * @return string */ public function getOperator() { return $this->operator; } /** * Sets the comparison operator. * * @throws \InvalidArgumentException * * @deprecated set the operator via the constructor instead */ public function setOperator(string $operator) { trigger_deprecation('symfony/finder', '5.4', '"%s" is deprecated. Set the operator via the constructor instead.', __METHOD__); $this->doSetOperator('' === $operator ? '==' : $operator); } /** * Tests against the target. * * @param mixed $test A test value * * @return bool */ public function test($test) { if (null === $this->target) { trigger_deprecation('symfony/finder', '5.4', 'Calling "%s" without initializing the target is deprecated.', __METHOD__); } switch ($this->operator) { case '>': return $test > $this->target; case '>=': return $test >= $this->target; case '<': return $test < $this->target; case '<=': return $test <= $this->target; case '!=': return $test != $this->target; } return $test == $this->target; } private function doSetOperator(string $operator): void { if (!\in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) { throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator)); } $this->operator = $operator; } } finder/Comparator/DateComparator.php000064400000002570150432043210013536 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * DateCompare compiles date comparisons. * * @author Fabien Potencier */ class DateComparator extends Comparator { /** * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood */ public function __construct(string $test) { if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test)); } try { $date = new \DateTime($matches[2]); $target = $date->format('U'); } catch (\Exception $e) { throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } $operator = $matches[1] ?? '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } if ('until' === $operator || 'before' === $operator) { $operator = '<'; } parent::__construct($target, $operator); } } finder/Comparator/NumberComparator.php000064400000005012150432043210014103 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Comparator; /** * NumberComparator compiles a simple comparison to an anonymous * subroutine, which you can call with a value to be tested again. * * Now this would be very pointless, if NumberCompare didn't understand * magnitudes. * * The target value may use magnitudes of kilobytes (k, ki), * megabytes (m, mi), or gigabytes (g, gi). Those suffixed * with an i use the appropriate 2**n version in accordance with the * IEC standard: http://physics.nist.gov/cuu/Units/binary.html * * Based on the Perl Number::Compare module. * * @author Fabien Potencier PHP port * @author Richard Clamp Perl version * @copyright 2004-2005 Fabien Potencier * @copyright 2002 Richard Clamp * * @see http://physics.nist.gov/cuu/Units/binary.html */ class NumberComparator extends Comparator { /** * @param string|int $test A comparison string or an integer * * @throws \InvalidArgumentException If the test is not understood */ public function __construct(?string $test) { if (null === $test || !preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) { throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test ?? 'null')); } $target = $matches[2]; if (!is_numeric($target)) { throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target)); } if (isset($matches[3])) { // magnitude switch (strtolower($matches[3])) { case 'k': $target *= 1000; break; case 'ki': $target *= 1024; break; case 'm': $target *= 1000000; break; case 'mi': $target *= 1024 * 1024; break; case 'g': $target *= 1000000000; break; case 'gi': $target *= 1024 * 1024 * 1024; break; } } parent::__construct($target, $matches[1] ?: '=='); } } finder/CHANGELOG.md000064400000004316150432043210007622 0ustar00CHANGELOG ========= 5.4.0 ----- * Deprecate `Comparator::setTarget()` and `Comparator::setOperator()` * Add a constructor to `Comparator` that allows setting target and operator * Finder's iterator has now `Symfony\Component\Finder\SplFileInfo` inner type specified * Add recursive .gitignore files support 5.0.0 ----- * added `$useNaturalSort` argument to `Finder::sortByName()` 4.3.0 ----- * added Finder::ignoreVCSIgnored() to ignore files based on rules listed in .gitignore 4.2.0 ----- * added $useNaturalSort option to Finder::sortByName() method * the `Finder::sortByName()` method will have a new `$useNaturalSort` argument in version 5.0, not defining it is deprecated * added `Finder::reverseSorting()` to reverse the sorting 4.0.0 ----- * removed `ExceptionInterface` * removed `Symfony\Component\Finder\Iterator\FilterIterator` 3.4.0 ----- * deprecated `Symfony\Component\Finder\Iterator\FilterIterator` * added Finder::hasResults() method to check if any results were found 3.3.0 ----- * added double-star matching to Glob::toRegex() 3.0.0 ----- * removed deprecated classes 2.8.0 ----- * deprecated adapters and related classes 2.5.0 ----- * added support for GLOB_BRACE in the paths passed to Finder::in() 2.3.0 ----- * added a way to ignore unreadable directories (via Finder::ignoreUnreadableDirs()) * unified the way subfolders that are not executable are handled by always throwing an AccessDeniedException exception 2.2.0 ----- * added Finder::path() and Finder::notPath() methods * added finder adapters to improve performance on specific platforms * added support for wildcard characters (glob patterns) in the paths passed to Finder::in() 2.1.0 ----- * added Finder::sortByAccessedTime(), Finder::sortByChangedTime(), and Finder::sortByModifiedTime() * added Countable to Finder * added support for an array of directories as an argument to Finder::exclude() * added searching based on the file content via Finder::contains() and Finder::notContains() * added support for the != operator in the Comparator * [BC BREAK] filter expressions (used for file name and content) are no more considered as regexps but glob patterns when they are enclosed in '*' or '?' finder/SplFileInfo.php000064400000004010150432043210010663 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Extends \SplFileInfo to support relative paths. * * @author Fabien Potencier */ class SplFileInfo extends \SplFileInfo { private $relativePath; private $relativePathname; /** * @param string $file The file name * @param string $relativePath The relative path * @param string $relativePathname The relative path name */ public function __construct(string $file, string $relativePath, string $relativePathname) { parent::__construct($file); $this->relativePath = $relativePath; $this->relativePathname = $relativePathname; } /** * Returns the relative path. * * This path does not contain the file name. * * @return string */ public function getRelativePath() { return $this->relativePath; } /** * Returns the relative path name. * * This path contains the file name. * * @return string */ public function getRelativePathname() { return $this->relativePathname; } public function getFilenameWithoutExtension(): string { $filename = $this->getFilename(); return pathinfo($filename, \PATHINFO_FILENAME); } /** * Returns the contents of the file. * * @return string * * @throws \RuntimeException */ public function getContents() { set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); try { $content = file_get_contents($this->getPathname()); } finally { restore_error_handler(); } if (false === $content) { throw new \RuntimeException($error); } return $content; } } finder/Iterator/FileTypeFilterIterator.php000064400000002561150432043210014714 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FileTypeFilterIterator only keeps files, directories, or both. * * @author Fabien Potencier * * @extends \FilterIterator */ class FileTypeFilterIterator extends \FilterIterator { public const ONLY_FILES = 1; public const ONLY_DIRECTORIES = 2; private $mode; /** * @param \Iterator $iterator The Iterator to filter * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ public function __construct(\Iterator $iterator, int $mode) { $this->mode = $mode; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) { return false; } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) { return false; } return true; } } finder/Iterator/VcsIgnoredFilterIterator.php000064400000007712150432043210015241 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Gitignore; final class VcsIgnoredFilterIterator extends \FilterIterator { /** * @var string */ private $baseDir; /** * @var array */ private $gitignoreFilesCache = []; /** * @var array */ private $ignoredPathsCache = []; public function __construct(\Iterator $iterator, string $baseDir) { $this->baseDir = $this->normalizePath($baseDir); parent::__construct($iterator); } public function accept(): bool { $file = $this->current(); $fileRealPath = $this->normalizePath($file->getRealPath()); return !$this->isIgnored($fileRealPath); } private function isIgnored(string $fileRealPath): bool { if (is_dir($fileRealPath) && !str_ends_with($fileRealPath, '/')) { $fileRealPath .= '/'; } if (isset($this->ignoredPathsCache[$fileRealPath])) { return $this->ignoredPathsCache[$fileRealPath]; } $ignored = false; foreach ($this->parentsDirectoryDownward($fileRealPath) as $parentDirectory) { if ($this->isIgnored($parentDirectory)) { $ignored = true; // rules in ignored directories are ignored, no need to check further. break; } $fileRelativePath = substr($fileRealPath, \strlen($parentDirectory) + 1); if (null === $regexps = $this->readGitignoreFile("{$parentDirectory}/.gitignore")) { continue; } [$exclusionRegex, $inclusionRegex] = $regexps; if (preg_match($exclusionRegex, $fileRelativePath)) { $ignored = true; continue; } if (preg_match($inclusionRegex, $fileRelativePath)) { $ignored = false; } } return $this->ignoredPathsCache[$fileRealPath] = $ignored; } /** * @return list */ private function parentsDirectoryDownward(string $fileRealPath): array { $parentDirectories = []; $parentDirectory = $fileRealPath; while (true) { $newParentDirectory = \dirname($parentDirectory); // dirname('/') = '/' if ($newParentDirectory === $parentDirectory) { break; } $parentDirectory = $newParentDirectory; if (0 !== strpos($parentDirectory, $this->baseDir)) { break; } $parentDirectories[] = $parentDirectory; } return array_reverse($parentDirectories); } /** * @return array{0: string, 1: string}|null */ private function readGitignoreFile(string $path): ?array { if (\array_key_exists($path, $this->gitignoreFilesCache)) { return $this->gitignoreFilesCache[$path]; } if (!file_exists($path)) { return $this->gitignoreFilesCache[$path] = null; } if (!is_file($path) || !is_readable($path)) { throw new \RuntimeException("The \"ignoreVCSIgnored\" option cannot be used by the Finder as the \"{$path}\" file is not readable."); } $gitignoreFileContent = file_get_contents($path); return $this->gitignoreFilesCache[$path] = [ Gitignore::toRegex($gitignoreFileContent), Gitignore::toRegexMatchingNegatedPatterns($gitignoreFileContent), ]; } private function normalizePath(string $path): string { if ('\\' === \DIRECTORY_SEPARATOR) { return str_replace('\\', '/', $path); } return $path; } } finder/Iterator/PathFilterIterator.php000064400000002654150432043210014072 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * PathFilterIterator filters files by path patterns (e.g. some/special/dir). * * @author Fabien Potencier * @author Włodzimierz Gajda * * @extends MultiplePcreFilterIterator */ class PathFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { $filename = $this->current()->getRelativePathname(); if ('\\' === \DIRECTORY_SEPARATOR) { $filename = str_replace('\\', '/', $filename); } return $this->isAccepted($filename); } /** * Converts strings to regexp. * * PCRE patterns are left unchanged. * * Default conversion: * 'lorem/ipsum/dolor' ==> 'lorem\/ipsum\/dolor/' * * Use only / as directory separator (on Windows also). * * @param string $str Pattern: regexp or dirname * * @return string */ protected function toRegex(string $str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } finder/Iterator/FilenameFilterIterator.php000064400000002230150432043210014704 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Glob; /** * FilenameFilterIterator filters files by patterns (a regexp, a glob, or a string). * * @author Fabien Potencier * * @extends MultiplePcreFilterIterator */ class FilenameFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { return $this->isAccepted($this->current()->getFilename()); } /** * Converts glob to regexp. * * PCRE patterns are left unchanged. * Glob strings are transformed with Glob::toRegex(). * * @param string $str Pattern: glob or regexp * * @return string */ protected function toRegex(string $str) { return $this->isRegex($str) ? $str : Glob::toRegex($str); } } finder/Iterator/SortableIterator.php000064400000007503150432043210013601 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * SortableIterator applies a sort on a given Iterator. * * @author Fabien Potencier * * @implements \IteratorAggregate */ class SortableIterator implements \IteratorAggregate { public const SORT_BY_NONE = 0; public const SORT_BY_NAME = 1; public const SORT_BY_TYPE = 2; public const SORT_BY_ACCESSED_TIME = 3; public const SORT_BY_CHANGED_TIME = 4; public const SORT_BY_MODIFIED_TIME = 5; public const SORT_BY_NAME_NATURAL = 6; private $iterator; private $sort; /** * @param \Traversable $iterator * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) * * @throws \InvalidArgumentException */ public function __construct(\Traversable $iterator, $sort, bool $reverseOrder = false) { $this->iterator = $iterator; $order = $reverseOrder ? -1 : 1; if (self::SORT_BY_NAME === $sort) { $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_NAME_NATURAL === $sort) { $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { return $order * strnatcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_TYPE === $sort) { $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { if ($a->isDir() && $b->isFile()) { return -$order; } elseif ($a->isFile() && $b->isDir()) { return $order; } return $order * strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { return $order * ($a->getATime() - $b->getATime()); }; } elseif (self::SORT_BY_CHANGED_TIME === $sort) { $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { return $order * ($a->getCTime() - $b->getCTime()); }; } elseif (self::SORT_BY_MODIFIED_TIME === $sort) { $this->sort = static function (\SplFileInfo $a, \SplFileInfo $b) use ($order) { return $order * ($a->getMTime() - $b->getMTime()); }; } elseif (self::SORT_BY_NONE === $sort) { $this->sort = $order; } elseif (\is_callable($sort)) { $this->sort = $reverseOrder ? static function (\SplFileInfo $a, \SplFileInfo $b) use ($sort) { return -$sort($a, $b); } : $sort; } else { throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.'); } } /** * @return \Traversable */ #[\ReturnTypeWillChange] public function getIterator() { if (1 === $this->sort) { return $this->iterator; } $array = iterator_to_array($this->iterator, true); if (-1 === $this->sort) { $array = array_reverse($array); } else { uasort($array, $this->sort); } return new \ArrayIterator($array); } } finder/Iterator/RecursiveDirectoryIterator.php000064400000010704150432043210015657 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Exception\AccessDeniedException; use Symfony\Component\Finder\SplFileInfo; /** * Extends the \RecursiveDirectoryIterator to support relative paths. * * @author Victor Berchet */ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator { /** * @var bool */ private $ignoreUnreadableDirs; /** * @var bool */ private $rewindable; // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations private $rootPath; private $subPath; private $directorySeparator = '/'; /** * @throws \RuntimeException */ public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false) { if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) { throw new \RuntimeException('This iterator only support returning current as fileinfo.'); } parent::__construct($path, $flags); $this->ignoreUnreadableDirs = $ignoreUnreadableDirs; $this->rootPath = $path; if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) { $this->directorySeparator = \DIRECTORY_SEPARATOR; } } /** * Return an instance of SplFileInfo with support for relative paths. * * @return SplFileInfo */ #[\ReturnTypeWillChange] public function current() { // the logic here avoids redoing the same work in all iterations if (null === $subPathname = $this->subPath) { $subPathname = $this->subPath = $this->getSubPath(); } if ('' !== $subPathname) { $subPathname .= $this->directorySeparator; } $subPathname .= $this->getFilename(); if ('/' !== $basePath = $this->rootPath) { $basePath .= $this->directorySeparator; } return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname); } /** * @param bool $allowLinks * * @return bool */ #[\ReturnTypeWillChange] public function hasChildren($allowLinks = false) { $hasChildren = parent::hasChildren($allowLinks); if (!$hasChildren || !$this->ignoreUnreadableDirs) { return $hasChildren; } try { parent::getChildren(); return true; } catch (\UnexpectedValueException $e) { // If directory is unreadable and finder is set to ignore it, skip children return false; } } /** * @return \RecursiveDirectoryIterator * * @throws AccessDeniedException */ #[\ReturnTypeWillChange] public function getChildren() { try { $children = parent::getChildren(); if ($children instanceof self) { // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs; // performance optimization to avoid redoing the same work in all children $children->rewindable = &$this->rewindable; $children->rootPath = $this->rootPath; } return $children; } catch (\UnexpectedValueException $e) { throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e); } } /** * Do nothing for non rewindable stream. * * @return void */ #[\ReturnTypeWillChange] public function rewind() { if (false === $this->isRewindable()) { return; } parent::rewind(); } /** * Checks if the stream is rewindable. * * @return bool */ public function isRewindable() { if (null !== $this->rewindable) { return $this->rewindable; } if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); if ($infos['seekable']) { return $this->rewindable = true; } } return $this->rewindable = false; } } finder/Iterator/CustomFilterIterator.php000064400000003043150432043210014441 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * CustomFilterIterator filters files by applying anonymous functions. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @author Fabien Potencier * * @extends \FilterIterator */ class CustomFilterIterator extends \FilterIterator { private $filters = []; /** * @param \Iterator $iterator The Iterator to filter * @param callable[] $filters An array of PHP callbacks * * @throws \InvalidArgumentException */ public function __construct(\Iterator $iterator, array $filters) { foreach ($filters as $filter) { if (!\is_callable($filter)) { throw new \InvalidArgumentException('Invalid PHP callback.'); } } $this->filters = $filters; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); foreach ($this->filters as $filter) { if (false === $filter($fileinfo)) { return false; } } return true; } } finder/Iterator/ExcludeDirectoryFilterIterator.php000064400000005155150432043210016453 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * ExcludeDirectoryFilterIterator filters out directories. * * @author Fabien Potencier * * @extends \FilterIterator * @implements \RecursiveIterator */ class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator { private $iterator; private $isRecursive; private $excludedDirs = []; private $excludedPattern; /** * @param \Iterator $iterator The Iterator to filter * @param string[] $directories An array of directories to exclude */ public function __construct(\Iterator $iterator, array $directories) { $this->iterator = $iterator; $this->isRecursive = $iterator instanceof \RecursiveIterator; $patterns = []; foreach ($directories as $directory) { $directory = rtrim($directory, '/'); if (!$this->isRecursive || str_contains($directory, '/')) { $patterns[] = preg_quote($directory, '#'); } else { $this->excludedDirs[$directory] = true; } } if ($patterns) { $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#'; } parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) { return false; } if ($this->excludedPattern) { $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath(); $path = str_replace('\\', '/', $path); return !preg_match($this->excludedPattern, $path); } return true; } /** * @return bool */ #[\ReturnTypeWillChange] public function hasChildren() { return $this->isRecursive && $this->iterator->hasChildren(); } /** * @return self */ #[\ReturnTypeWillChange] public function getChildren() { $children = new self($this->iterator->getChildren(), []); $children->excludedDirs = $this->excludedDirs; $children->excludedPattern = $this->excludedPattern; return $children; } } finder/Iterator/LazyIterator.php000064400000001240150432043210012735 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * @author Jérémy Derussé * * @internal */ class LazyIterator implements \IteratorAggregate { private $iteratorFactory; public function __construct(callable $iteratorFactory) { $this->iteratorFactory = $iteratorFactory; } public function getIterator(): \Traversable { yield from ($this->iteratorFactory)(); } } finder/Iterator/DateRangeFilterIterator.php000064400000002645150432043210015030 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\DateComparator; /** * DateRangeFilterIterator filters out files that are not in the given date range (last modified dates). * * @author Fabien Potencier * * @extends \FilterIterator */ class DateRangeFilterIterator extends \FilterIterator { private $comparators = []; /** * @param \Iterator $iterator * @param DateComparator[] $comparators */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); if (!file_exists($fileinfo->getPathname())) { return false; } $filedate = $fileinfo->getMTime(); foreach ($this->comparators as $compare) { if (!$compare->test($filedate)) { return false; } } return true; } } finder/Iterator/FilecontentFilterIterator.php000064400000002647150432043210015452 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * FilecontentFilterIterator filters files by their contents using patterns (regexps or strings). * * @author Fabien Potencier * @author Włodzimierz Gajda * * @extends MultiplePcreFilterIterator */ class FilecontentFilterIterator extends MultiplePcreFilterIterator { /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { if (!$this->matchRegexps && !$this->noMatchRegexps) { return true; } $fileinfo = $this->current(); if ($fileinfo->isDir() || !$fileinfo->isReadable()) { return false; } $content = $fileinfo->getContents(); if (!$content) { return false; } return $this->isAccepted($content); } /** * Converts string to regexp if necessary. * * @param string $str Pattern: string or regexp * * @return string */ protected function toRegex(string $str) { return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/'; } } finder/Iterator/DepthRangeFilterIterator.php000064400000002620150432043210015210 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * DepthRangeFilterIterator limits the directory depth. * * @author Fabien Potencier * * @template-covariant TKey * @template-covariant TValue * * @extends \FilterIterator */ class DepthRangeFilterIterator extends \FilterIterator { private $minDepth = 0; /** * @param \RecursiveIteratorIterator<\RecursiveIterator> $iterator The Iterator to filter * @param int $minDepth The min depth * @param int $maxDepth The max depth */ public function __construct(\RecursiveIteratorIterator $iterator, int $minDepth = 0, int $maxDepth = \PHP_INT_MAX) { $this->minDepth = $minDepth; $iterator->setMaxDepth(\PHP_INT_MAX === $maxDepth ? -1 : $maxDepth); parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { return $this->getInnerIterator()->getDepth() >= $this->minDepth; } } finder/Iterator/MultiplePcreFilterIterator.php000064400000006030150432043210015573 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; /** * MultiplePcreFilterIterator filters files using patterns (regexps, globs or strings). * * @author Fabien Potencier * * @template-covariant TKey * @template-covariant TValue * * @extends \FilterIterator */ abstract class MultiplePcreFilterIterator extends \FilterIterator { protected $matchRegexps = []; protected $noMatchRegexps = []; /** * @param \Iterator $iterator The Iterator to filter * @param string[] $matchPatterns An array of patterns that need to match * @param string[] $noMatchPatterns An array of patterns that need to not match */ public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns) { foreach ($matchPatterns as $pattern) { $this->matchRegexps[] = $this->toRegex($pattern); } foreach ($noMatchPatterns as $pattern) { $this->noMatchRegexps[] = $this->toRegex($pattern); } parent::__construct($iterator); } /** * Checks whether the string is accepted by the regex filters. * * If there is no regexps defined in the class, this method will accept the string. * Such case can be handled by child classes before calling the method if they want to * apply a different behavior. * * @return bool */ protected function isAccepted(string $string) { // should at least not match one rule to exclude foreach ($this->noMatchRegexps as $regex) { if (preg_match($regex, $string)) { return false; } } // should at least match one rule if ($this->matchRegexps) { foreach ($this->matchRegexps as $regex) { if (preg_match($regex, $string)) { return true; } } return false; } // If there is no match rules, the file is accepted return true; } /** * Checks whether the string is a regex. * * @return bool */ protected function isRegex(string $str) { if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) { $start = substr($m[1], 0, 1); $end = substr($m[1], -1); if ($start === $end) { return !preg_match('/[*?[:alnum:] \\\\]/', $start); } foreach ([['{', '}'], ['(', ')'], ['[', ']'], ['<', '>']] as $delimiters) { if ($start === $delimiters[0] && $end === $delimiters[1]) { return true; } } } return false; } /** * Converts string into regexp. * * @return string */ abstract protected function toRegex(string $str); } finder/Iterator/SizeRangeFilterIterator.php000064400000002574150432043210015066 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Iterator; use Symfony\Component\Finder\Comparator\NumberComparator; /** * SizeRangeFilterIterator filters out files that are not in the given size range. * * @author Fabien Potencier * * @extends \FilterIterator */ class SizeRangeFilterIterator extends \FilterIterator { private $comparators = []; /** * @param \Iterator $iterator * @param NumberComparator[] $comparators */ public function __construct(\Iterator $iterator, array $comparators) { $this->comparators = $comparators; parent::__construct($iterator); } /** * Filters the iterator values. * * @return bool */ #[\ReturnTypeWillChange] public function accept() { $fileinfo = $this->current(); if (!$fileinfo->isFile()) { return true; } $filesize = $fileinfo->getSize(); foreach ($this->comparators as $compare) { if (!$compare->test($filesize)) { return false; } } return true; } } finder/Gitignore.php000064400000005747150432043210010462 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; /** * Gitignore matches against text. * * @author Michael Voříšek * @author Ahmed Abdou */ class Gitignore { /** * Returns a regexp which is the equivalent of the gitignore pattern. * * Format specification: https://git-scm.com/docs/gitignore#_pattern_format */ public static function toRegex(string $gitignoreFileContent): string { return self::buildRegex($gitignoreFileContent, false); } public static function toRegexMatchingNegatedPatterns(string $gitignoreFileContent): string { return self::buildRegex($gitignoreFileContent, true); } private static function buildRegex(string $gitignoreFileContent, bool $inverted): string { $gitignoreFileContent = preg_replace('~(?=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-php80": "^1.16" }, "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } finder/LICENSE000064400000002051150432043210007010 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. finder/Finder.php000064400000053774150432043210007745 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder; use Symfony\Component\Finder\Comparator\DateComparator; use Symfony\Component\Finder\Comparator\NumberComparator; use Symfony\Component\Finder\Exception\DirectoryNotFoundException; use Symfony\Component\Finder\Iterator\CustomFilterIterator; use Symfony\Component\Finder\Iterator\DateRangeFilterIterator; use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator; use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator; use Symfony\Component\Finder\Iterator\FilecontentFilterIterator; use Symfony\Component\Finder\Iterator\FilenameFilterIterator; use Symfony\Component\Finder\Iterator\LazyIterator; use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator; use Symfony\Component\Finder\Iterator\SortableIterator; /** * Finder allows to build rules to find files and directories. * * It is a thin wrapper around several specialized iterator classes. * * All rules may be invoked several times. * * All methods return the current Finder object to allow chaining: * * $finder = Finder::create()->files()->name('*.php')->in(__DIR__); * * @author Fabien Potencier * * @implements \IteratorAggregate */ class Finder implements \IteratorAggregate, \Countable { public const IGNORE_VCS_FILES = 1; public const IGNORE_DOT_FILES = 2; public const IGNORE_VCS_IGNORED_FILES = 4; private $mode = 0; private $names = []; private $notNames = []; private $exclude = []; private $filters = []; private $depths = []; private $sizes = []; private $followLinks = false; private $reverseSorting = false; private $sort = false; private $ignore = 0; private $dirs = []; private $dates = []; private $iterators = []; private $contains = []; private $notContains = []; private $paths = []; private $notPaths = []; private $ignoreUnreadableDirs = false; private static $vcsPatterns = ['.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg']; public function __construct() { $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; } /** * Creates a new Finder. * * @return static */ public static function create() { return new static(); } /** * Restricts the matching to directories only. * * @return $this */ public function directories() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES; return $this; } /** * Restricts the matching to files only. * * @return $this */ public function files() { $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES; return $this; } /** * Adds tests for the directory depth. * * Usage: * * $finder->depth('> 1') // the Finder will start matching at level 1. * $finder->depth('< 3') // the Finder will descend at most 3 levels of directories below the starting point. * $finder->depth(['>= 1', '< 3']) * * @param string|int|string[]|int[] $levels The depth level expression or an array of depth levels * * @return $this * * @see DepthRangeFilterIterator * @see NumberComparator */ public function depth($levels) { foreach ((array) $levels as $level) { $this->depths[] = new Comparator\NumberComparator($level); } return $this; } /** * Adds tests for file dates (last modified). * * The date must be something that strtotime() is able to parse: * * $finder->date('since yesterday'); * $finder->date('until 2 days ago'); * $finder->date('> now - 2 hours'); * $finder->date('>= 2005-10-15'); * $finder->date(['>= 2005-10-15', '<= 2006-05-27']); * * @param string|string[] $dates A date range string or an array of date ranges * * @return $this * * @see strtotime * @see DateRangeFilterIterator * @see DateComparator */ public function date($dates) { foreach ((array) $dates as $date) { $this->dates[] = new Comparator\DateComparator($date); } return $this; } /** * Adds rules that files must match. * * You can use patterns (delimited with / sign), globs or simple strings. * * $finder->name('*.php') * $finder->name('/\.php$/') // same as above * $finder->name('test.php') * $finder->name(['test.py', 'test.php']) * * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ public function name($patterns) { $this->names = array_merge($this->names, (array) $patterns); return $this; } /** * Adds rules that files must not match. * * @param string|string[] $patterns A pattern (a regexp, a glob, or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ public function notName($patterns) { $this->notNames = array_merge($this->notNames, (array) $patterns); return $this; } /** * Adds tests that file contents must match. * * Strings or PCRE patterns can be used: * * $finder->contains('Lorem ipsum') * $finder->contains('/Lorem ipsum/i') * $finder->contains(['dolor', '/ipsum/i']) * * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns * * @return $this * * @see FilecontentFilterIterator */ public function contains($patterns) { $this->contains = array_merge($this->contains, (array) $patterns); return $this; } /** * Adds tests that file contents must not match. * * Strings or PCRE patterns can be used: * * $finder->notContains('Lorem ipsum') * $finder->notContains('/Lorem ipsum/i') * $finder->notContains(['lorem', '/dolor/i']) * * @param string|string[] $patterns A pattern (string or regexp) or an array of patterns * * @return $this * * @see FilecontentFilterIterator */ public function notContains($patterns) { $this->notContains = array_merge($this->notContains, (array) $patterns); return $this; } /** * Adds rules that filenames must match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->path('some/special/dir') * $finder->path('/some\/special\/dir/') // same as above * $finder->path(['some dir', 'another/dir']) * * Use only / as dirname separator. * * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ public function path($patterns) { $this->paths = array_merge($this->paths, (array) $patterns); return $this; } /** * Adds rules that filenames must not match. * * You can use patterns (delimited with / sign) or simple strings. * * $finder->notPath('some/special/dir') * $finder->notPath('/some\/special\/dir/') // same as above * $finder->notPath(['some/file.txt', 'another/file.log']) * * Use only / as dirname separator. * * @param string|string[] $patterns A pattern (a regexp or a string) or an array of patterns * * @return $this * * @see FilenameFilterIterator */ public function notPath($patterns) { $this->notPaths = array_merge($this->notPaths, (array) $patterns); return $this; } /** * Adds tests for file sizes. * * $finder->size('> 10K'); * $finder->size('<= 1Ki'); * $finder->size(4); * $finder->size(['> 10K', '< 20K']) * * @param string|int|string[]|int[] $sizes A size range string or an integer or an array of size ranges * * @return $this * * @see SizeRangeFilterIterator * @see NumberComparator */ public function size($sizes) { foreach ((array) $sizes as $size) { $this->sizes[] = new Comparator\NumberComparator($size); } return $this; } /** * Excludes directories. * * Directories passed as argument must be relative to the ones defined with the `in()` method. For example: * * $finder->in(__DIR__)->exclude('ruby'); * * @param string|array $dirs A directory path or an array of directories * * @return $this * * @see ExcludeDirectoryFilterIterator */ public function exclude($dirs) { $this->exclude = array_merge($this->exclude, (array) $dirs); return $this; } /** * Excludes "hidden" directories and files (starting with a dot). * * This option is enabled by default. * * @return $this * * @see ExcludeDirectoryFilterIterator */ public function ignoreDotFiles(bool $ignoreDotFiles) { if ($ignoreDotFiles) { $this->ignore |= static::IGNORE_DOT_FILES; } else { $this->ignore &= ~static::IGNORE_DOT_FILES; } return $this; } /** * Forces the finder to ignore version control directories. * * This option is enabled by default. * * @return $this * * @see ExcludeDirectoryFilterIterator */ public function ignoreVCS(bool $ignoreVCS) { if ($ignoreVCS) { $this->ignore |= static::IGNORE_VCS_FILES; } else { $this->ignore &= ~static::IGNORE_VCS_FILES; } return $this; } /** * Forces Finder to obey .gitignore and ignore files based on rules listed there. * * This option is disabled by default. * * @return $this */ public function ignoreVCSIgnored(bool $ignoreVCSIgnored) { if ($ignoreVCSIgnored) { $this->ignore |= static::IGNORE_VCS_IGNORED_FILES; } else { $this->ignore &= ~static::IGNORE_VCS_IGNORED_FILES; } return $this; } /** * Adds VCS patterns. * * @see ignoreVCS() * * @param string|string[] $pattern VCS patterns to ignore */ public static function addVCSPattern($pattern) { foreach ((array) $pattern as $p) { self::$vcsPatterns[] = $p; } self::$vcsPatterns = array_unique(self::$vcsPatterns); } /** * Sorts files and directories by an anonymous function. * * The anonymous function receives two \SplFileInfo instances to compare. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return $this * * @see SortableIterator */ public function sort(\Closure $closure) { $this->sort = $closure; return $this; } /** * Sorts files and directories by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return $this * * @see SortableIterator */ public function sortByName(bool $useNaturalSort = false) { $this->sort = $useNaturalSort ? Iterator\SortableIterator::SORT_BY_NAME_NATURAL : Iterator\SortableIterator::SORT_BY_NAME; return $this; } /** * Sorts files and directories by type (directories before files), then by name. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return $this * * @see SortableIterator */ public function sortByType() { $this->sort = Iterator\SortableIterator::SORT_BY_TYPE; return $this; } /** * Sorts files and directories by the last accessed time. * * This is the time that the file was last accessed, read or written to. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return $this * * @see SortableIterator */ public function sortByAccessedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME; return $this; } /** * Reverses the sorting. * * @return $this */ public function reverseSorting() { $this->reverseSorting = true; return $this; } /** * Sorts files and directories by the last inode changed time. * * This is the time that the inode information was last modified (permissions, owner, group or other metadata). * * On Windows, since inode is not available, changed time is actually the file creation time. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return $this * * @see SortableIterator */ public function sortByChangedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME; return $this; } /** * Sorts files and directories by the last modified time. * * This is the last time the actual contents of the file were last modified. * * This can be slow as all the matching files and directories must be retrieved for comparison. * * @return $this * * @see SortableIterator */ public function sortByModifiedTime() { $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME; return $this; } /** * Filters the iterator with an anonymous function. * * The anonymous function receives a \SplFileInfo and must return false * to remove files. * * @return $this * * @see CustomFilterIterator */ public function filter(\Closure $closure) { $this->filters[] = $closure; return $this; } /** * Forces the following of symlinks. * * @return $this */ public function followLinks() { $this->followLinks = true; return $this; } /** * Tells finder to ignore unreadable directories. * * By default, scanning unreadable directories content throws an AccessDeniedException. * * @return $this */ public function ignoreUnreadableDirs(bool $ignore = true) { $this->ignoreUnreadableDirs = $ignore; return $this; } /** * Searches files and directories which match defined rules. * * @param string|string[] $dirs A directory path or an array of directories * * @return $this * * @throws DirectoryNotFoundException if one of the directories does not exist */ public function in($dirs) { $resolvedDirs = []; foreach ((array) $dirs as $dir) { if (is_dir($dir)) { $resolvedDirs[] = [$this->normalizeDir($dir)]; } elseif ($glob = glob($dir, (\defined('GLOB_BRACE') ? \GLOB_BRACE : 0) | \GLOB_ONLYDIR | \GLOB_NOSORT)) { sort($glob); $resolvedDirs[] = array_map([$this, 'normalizeDir'], $glob); } else { throw new DirectoryNotFoundException(sprintf('The "%s" directory does not exist.', $dir)); } } $this->dirs = array_merge($this->dirs, ...$resolvedDirs); return $this; } /** * Returns an Iterator for the current Finder configuration. * * This method implements the IteratorAggregate interface. * * @return \Iterator * * @throws \LogicException if the in() method has not been called */ #[\ReturnTypeWillChange] public function getIterator() { if (0 === \count($this->dirs) && 0 === \count($this->iterators)) { throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.'); } if (1 === \count($this->dirs) && 0 === \count($this->iterators)) { $iterator = $this->searchInDirectory($this->dirs[0]); if ($this->sort || $this->reverseSorting) { $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); } return $iterator; } $iterator = new \AppendIterator(); foreach ($this->dirs as $dir) { $iterator->append(new \IteratorIterator(new LazyIterator(function () use ($dir) { return $this->searchInDirectory($dir); }))); } foreach ($this->iterators as $it) { $iterator->append($it); } if ($this->sort || $this->reverseSorting) { $iterator = (new Iterator\SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator(); } return $iterator; } /** * Appends an existing set of files/directories to the finder. * * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array. * * @return $this * * @throws \InvalidArgumentException when the given argument is not iterable */ public function append(iterable $iterator) { if ($iterator instanceof \IteratorAggregate) { $this->iterators[] = $iterator->getIterator(); } elseif ($iterator instanceof \Iterator) { $this->iterators[] = $iterator; } elseif (is_iterable($iterator)) { $it = new \ArrayIterator(); foreach ($iterator as $file) { $file = $file instanceof \SplFileInfo ? $file : new \SplFileInfo($file); $it[$file->getPathname()] = $file; } $this->iterators[] = $it; } else { throw new \InvalidArgumentException('Finder::append() method wrong argument type.'); } return $this; } /** * Check if any results were found. * * @return bool */ public function hasResults() { foreach ($this->getIterator() as $_) { return true; } return false; } /** * Counts all the results collected by the iterators. * * @return int */ #[\ReturnTypeWillChange] public function count() { return iterator_count($this->getIterator()); } private function searchInDirectory(string $dir): \Iterator { $exclude = $this->exclude; $notPaths = $this->notPaths; if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) { $exclude = array_merge($exclude, self::$vcsPatterns); } if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) { $notPaths[] = '#(^|/)\..+(/|$)#'; } $minDepth = 0; $maxDepth = \PHP_INT_MAX; foreach ($this->depths as $comparator) { switch ($comparator->getOperator()) { case '>': $minDepth = $comparator->getTarget() + 1; break; case '>=': $minDepth = $comparator->getTarget(); break; case '<': $maxDepth = $comparator->getTarget() - 1; break; case '<=': $maxDepth = $comparator->getTarget(); break; default: $minDepth = $maxDepth = $comparator->getTarget(); } } $flags = \RecursiveDirectoryIterator::SKIP_DOTS; if ($this->followLinks) { $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS; } $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs); if ($exclude) { $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $exclude); } $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST); if ($minDepth > 0 || $maxDepth < \PHP_INT_MAX) { $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth); } if ($this->mode) { $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode); } if ($this->names || $this->notNames) { $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames); } if ($this->contains || $this->notContains) { $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); } if ($this->sizes) { $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes); } if ($this->dates) { $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates); } if ($this->filters) { $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); } if ($this->paths || $notPaths) { $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $notPaths); } if (static::IGNORE_VCS_IGNORED_FILES === (static::IGNORE_VCS_IGNORED_FILES & $this->ignore)) { $iterator = new Iterator\VcsIgnoredFilterIterator($iterator, $dir); } return $iterator; } /** * Normalizes given directory names by removing trailing slashes. * * Excluding: (s)ftp:// or ssh2.(s)ftp:// wrapper */ private function normalizeDir(string $dir): string { if ('/' === $dir) { return $dir; } $dir = rtrim($dir, '/'.\DIRECTORY_SEPARATOR); if (preg_match('#^(ssh2\.)?s?ftp://#', $dir)) { $dir .= '/'; } return $dir; } } finder/Exception/AccessDeniedException.php000064400000000653150432043210014651 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Jean-François Simon */ class AccessDeniedException extends \UnexpectedValueException { } finder/Exception/DirectoryNotFoundException.php000064400000000643150432043210015757 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Finder\Exception; /** * @author Andreas Erhard */ class DirectoryNotFoundException extends \InvalidArgumentException { } translation-contracts/README.md000064400000000524150432043210012352 0ustar00Symfony Translation Contracts ============================= A set of abstractions extracted out of the Symfony components. Can be used to build on semantics that the Symfony components proved useful - and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. translation-contracts/LocaleAwareInterface.php000064400000001225150432043210015603 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Translation; interface LocaleAwareInterface { /** * Sets the current locale. * * @param string $locale The locale * * @throws \InvalidArgumentException If the locale contains invalid characters */ public function setLocale(string $locale); /** * Returns the current locale. * * @return string */ public function getLocale(); } translation-contracts/TranslatableInterface.php000064400000000711150432043210016037 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Translation; /** * @author Nicolas Grekas */ interface TranslatableInterface { public function trans(TranslatorInterface $translator, string $locale = null): string; } translation-contracts/TranslatorTrait.php000064400000020405150432043210014741 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Translation; use Symfony\Component\Translation\Exception\InvalidArgumentException; /** * A trait to help implement TranslatorInterface and LocaleAwareInterface. * * @author Fabien Potencier */ trait TranslatorTrait { private $locale; /** * {@inheritdoc} */ public function setLocale(string $locale) { $this->locale = $locale; } /** * {@inheritdoc} * * @return string */ public function getLocale() { return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en'); } /** * {@inheritdoc} */ public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null): string { if (null === $id || '' === $id) { return ''; } if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) { return strtr($id, $parameters); } $number = (float) $parameters['%count%']; $locale = $locale ?: $this->getLocale(); $parts = []; if (preg_match('/^\|++$/', $id)) { $parts = explode('|', $id); } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) { $parts = $matches[0]; } $intervalRegexp = <<<'EOF' /^(?P ({\s* (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*) \s*}) | (?P[\[\]]) \s* (?P-Inf|\-?\d+(\.\d+)?) \s*,\s* (?P\+?Inf|\-?\d+(\.\d+)?) \s* (?P[\[\]]) )\s*(?P.*?)$/xs EOF; $standardRules = []; foreach ($parts as $part) { $part = trim(str_replace('||', '|', $part)); // try to match an explicit rule, then fallback to the standard ones if (preg_match($intervalRegexp, $part, $matches)) { if ($matches[2]) { foreach (explode(',', $matches[3]) as $n) { if ($number == $n) { return strtr($matches['message'], $parameters); } } } else { $leftNumber = '-Inf' === $matches['left'] ? -\INF : (float) $matches['left']; $rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : \INF; if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber) && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber) ) { return strtr($matches['message'], $parameters); } } } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) { $standardRules[] = $matches[1]; } else { $standardRules[] = $part; } } $position = $this->getPluralizationRule($number, $locale); if (!isset($standardRules[$position])) { // when there's exactly one rule given, and that rule is a standard // rule, use this rule if (1 === \count($parts) && isset($standardRules[0])) { return strtr($standardRules[0], $parameters); } $message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number); if (class_exists(InvalidArgumentException::class)) { throw new InvalidArgumentException($message); } throw new \InvalidArgumentException($message); } return strtr($standardRules[$position], $parameters); } /** * Returns the plural position to use for the given locale and number. * * The plural rules are derived from code of the Zend Framework (2010-09-25), * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd). * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) */ private function getPluralizationRule(float $number, string $locale): int { $number = abs($number); switch ('pt_BR' !== $locale && 'en_US_POSIX' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) { case 'af': case 'bn': case 'bg': case 'ca': case 'da': case 'de': case 'el': case 'en': case 'en_US_POSIX': case 'eo': case 'es': case 'et': case 'eu': case 'fa': case 'fi': case 'fo': case 'fur': case 'fy': case 'gl': case 'gu': case 'ha': case 'he': case 'hu': case 'is': case 'it': case 'ku': case 'lb': case 'ml': case 'mn': case 'mr': case 'nah': case 'nb': case 'ne': case 'nl': case 'nn': case 'no': case 'oc': case 'om': case 'or': case 'pa': case 'pap': case 'ps': case 'pt': case 'so': case 'sq': case 'sv': case 'sw': case 'ta': case 'te': case 'tk': case 'ur': case 'zu': return (1 == $number) ? 0 : 1; case 'am': case 'bh': case 'fil': case 'fr': case 'gun': case 'hi': case 'hy': case 'ln': case 'mg': case 'nso': case 'pt_BR': case 'ti': case 'wa': return ($number < 2) ? 0 : 1; case 'be': case 'bs': case 'hr': case 'ru': case 'sh': case 'sr': case 'uk': return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'cs': case 'sk': return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); case 'ga': return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2); case 'lt': return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'sl': return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)); case 'mk': return (1 == $number % 10) ? 0 : 1; case 'mt': return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); case 'lv': return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2); case 'pl': return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); case 'cy': return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)); case 'ro': return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); case 'ar': return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); default: return 0; } } } translation-contracts/CHANGELOG.md000064400000000235150432043210012703 0ustar00CHANGELOG ========= The changelog is maintained for all Symfony contracts at the following URL: https://github.com/symfony/contracts/blob/main/CHANGELOG.md translation-contracts/.gitignore000064400000000042150432043210013056 0ustar00vendor/ composer.lock phpunit.xml translation-contracts/TranslatorInterface.php000064400000004764150432043210015570 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Translation; /** * @author Fabien Potencier * * @method string getLocale() Returns the default locale */ interface TranslatorInterface { /** * Translates the given message. * * When a number is provided as a parameter named "%count%", the message is parsed for plural * forms and a translation is chosen according to this number using the following rules: * * Given a message with different plural translations separated by a * pipe (|), this method returns the correct portion of the message based * on the given number, locale and the pluralization rules in the message * itself. * * The message supports two different types of pluralization rules: * * interval: {0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples * indexed: There is one apple|There are %count% apples * * The indexed solution can also contain labels (e.g. one: There is one apple). * This is purely for making the translations more clear - it does not * affect the functionality. * * The two methods can also be mixed: * {0} There are no apples|one: There is one apple|more: There are %count% apples * * An interval can represent a finite set of numbers: * {1,2,3,4} * * An interval can represent numbers between two numbers: * [1, +Inf] * ]-1,2[ * * The left delimiter can be [ (inclusive) or ] (exclusive). * The right delimiter can be [ (exclusive) or ] (inclusive). * Beside numbers, you can use -Inf and +Inf for the infinite. * * @see https://en.wikipedia.org/wiki/ISO_31-11 * * @param string $id The message id (may also be an object that can be cast to string) * @param array $parameters An array of parameters for the message * @param string|null $domain The domain for the message or null to use the default * @param string|null $locale The locale or null to use the default * * @return string * * @throws \InvalidArgumentException If the locale contains invalid characters */ public function trans(string $id, array $parameters = [], string $domain = null, string $locale = null); } translation-contracts/composer.json000064400000001760150432043210013620 0ustar00{ "name": "symfony/translation-contracts", "type": "library", "description": "Generic abstractions related to translation", "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5" }, "suggest": { "symfony/translation-implementation": "" }, "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" } }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", "url": "https://github.com/symfony/contracts" } } } translation-contracts/LICENSE000064400000002051150432043210012075 0ustar00Copyright (c) 2018-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. translation-contracts/Test/TranslatorTest.php000064400000037100150432043210015514 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Translation\Test; use PHPUnit\Framework\TestCase; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorTrait; /** * Test should cover all languages mentioned on http://translate.sourceforge.net/wiki/l10n/pluralforms * and Plural forms mentioned on http://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms. * * See also https://developer.mozilla.org/en/Localization_and_Plurals which mentions 15 rules having a maximum of 6 forms. * The mozilla code is also interesting to check for. * * As mentioned by chx http://drupal.org/node/1273968 we can cover all by testing number from 0 to 199 * * The goal to cover all languages is to far fetched so this test case is smaller. * * @author Clemens Tolboom clemens@build2be.nl */ class TranslatorTest extends TestCase { private $defaultLocale; protected function setUp(): void { $this->defaultLocale = \Locale::getDefault(); \Locale::setDefault('en'); } protected function tearDown(): void { \Locale::setDefault($this->defaultLocale); } /** * @return TranslatorInterface */ public function getTranslator() { return new class() implements TranslatorInterface { use TranslatorTrait; }; } /** * @dataProvider getTransTests */ public function testTrans($expected, $id, $parameters) { $translator = $this->getTranslator(); $this->assertEquals($expected, $translator->trans($id, $parameters)); } /** * @dataProvider getTransChoiceTests */ public function testTransChoiceWithExplicitLocale($expected, $id, $number) { $translator = $this->getTranslator(); $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number])); } /** * @requires extension intl * * @dataProvider getTransChoiceTests */ public function testTransChoiceWithDefaultLocale($expected, $id, $number) { $translator = $this->getTranslator(); $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number])); } /** * @dataProvider getTransChoiceTests */ public function testTransChoiceWithEnUsPosix($expected, $id, $number) { $translator = $this->getTranslator(); $translator->setLocale('en_US_POSIX'); $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number])); } public function testGetSetLocale() { $translator = $this->getTranslator(); $this->assertEquals('en', $translator->getLocale()); } /** * @requires extension intl */ public function testGetLocaleReturnsDefaultLocaleIfNotSet() { $translator = $this->getTranslator(); \Locale::setDefault('pt_BR'); $this->assertEquals('pt_BR', $translator->getLocale()); \Locale::setDefault('en'); $this->assertEquals('en', $translator->getLocale()); } public function getTransTests() { return [ ['Symfony is great!', 'Symfony is great!', []], ['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']], ]; } public function getTransChoiceTests() { return [ ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1], ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], ['There are 0 apples', 'There is 1 apple|There are %count% apples', 0], ['There is 1 apple', 'There is 1 apple|There are %count% apples', 1], ['There are 10 apples', 'There is 1 apple|There are %count% apples', 10], // custom validation messages may be coded with a fixed value ['There are 2 apples', 'There are 2 apples', 2], ]; } /** * @dataProvider getInternal */ public function testInterval($expected, $number, $interval) { $translator = $this->getTranslator(); $this->assertEquals($expected, $translator->trans($interval.' foo|[1,Inf[ bar', ['%count%' => $number])); } public function getInternal() { return [ ['foo', 3, '{1,2, 3 ,4}'], ['bar', 10, '{1,2, 3 ,4}'], ['bar', 3, '[1,2]'], ['foo', 1, '[1,2]'], ['foo', 2, '[1,2]'], ['bar', 1, ']1,2['], ['bar', 2, ']1,2['], ['foo', log(0), '[-Inf,2['], ['foo', -log(0), '[-2,+Inf]'], ]; } /** * @dataProvider getChooseTests */ public function testChoose($expected, $id, $number, $locale = null) { $translator = $this->getTranslator(); $this->assertEquals($expected, $translator->trans($id, ['%count%' => $number], null, $locale)); } public function testReturnMessageIfExactlyOneStandardRuleIsGiven() { $translator = $this->getTranslator(); $this->assertEquals('There are two apples', $translator->trans('There are two apples', ['%count%' => 2])); } /** * @dataProvider getNonMatchingMessages */ public function testThrowExceptionIfMatchingMessageCannotBeFound($id, $number) { $this->expectException(\InvalidArgumentException::class); $translator = $this->getTranslator(); $translator->trans($id, ['%count%' => $number]); } public function getNonMatchingMessages() { return [ ['{0} There are no apples|{1} There is one apple', 2], ['{1} There is one apple|]1,Inf] There are %count% apples', 0], ['{1} There is one apple|]2,Inf] There are %count% apples', 2], ['{0} There are no apples|There is one apple', 2], ]; } public function getChooseTests() { return [ ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], ['There are no apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], ['There are no apples', '{0}There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 0], ['There is one apple', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 1], ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf]There are %count% apples', 10], ['There are 10 apples', '{0} There are no apples|{1} There is one apple|]1,Inf] There are %count% apples', 10], ['There are 0 apples', 'There is one apple|There are %count% apples', 0], ['There is one apple', 'There is one apple|There are %count% apples', 1], ['There are 10 apples', 'There is one apple|There are %count% apples', 10], ['There are 0 apples', 'one: There is one apple|more: There are %count% apples', 0], ['There is one apple', 'one: There is one apple|more: There are %count% apples', 1], ['There are 10 apples', 'one: There is one apple|more: There are %count% apples', 10], ['There are no apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 0], ['There is one apple', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 1], ['There are 10 apples', '{0} There are no apples|one: There is one apple|more: There are %count% apples', 10], ['', '{0}|{1} There is one apple|]1,Inf] There are %count% apples', 0], ['', '{0} There are no apples|{1}|]1,Inf] There are %count% apples', 1], // Indexed only tests which are Gettext PoFile* compatible strings. ['There are 0 apples', 'There is one apple|There are %count% apples', 0], ['There is one apple', 'There is one apple|There are %count% apples', 1], ['There are 2 apples', 'There is one apple|There are %count% apples', 2], // Tests for float numbers ['There is almost one apple', '{0} There are no apples|]0,1[ There is almost one apple|{1} There is one apple|[1,Inf] There is more than one apple', 0.7], ['There is one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1], ['There is more than one apple', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 1.7], ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0], ['There are no apples', '{0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0.0], ['There are no apples', '{0.0} There are no apples|]0,1[There are %count% apples|{1} There is one apple|[1,Inf] There is more than one apple', 0], // Test texts with new-lines // with double-quotes and \n in id & double-quotes and actual newlines in text ["This is a text with a\n new-line in it. Selector = 0.", '{0}This is a text with a new-line in it. Selector = 0.|{1}This is a text with a new-line in it. Selector = 1.|[1,Inf]This is a text with a new-line in it. Selector > 1.', 0], // with double-quotes and \n in id and single-quotes and actual newlines in text ["This is a text with a\n new-line in it. Selector = 1.", '{0}This is a text with a new-line in it. Selector = 0.|{1}This is a text with a new-line in it. Selector = 1.|[1,Inf]This is a text with a new-line in it. Selector > 1.', 1], ["This is a text with a\n new-line in it. Selector > 1.", '{0}This is a text with a new-line in it. Selector = 0.|{1}This is a text with a new-line in it. Selector = 1.|[1,Inf]This is a text with a new-line in it. Selector > 1.', 5], // with double-quotes and id split accros lines ['This is a text with a new-line in it. Selector = 1.', '{0}This is a text with a new-line in it. Selector = 0.|{1}This is a text with a new-line in it. Selector = 1.|[1,Inf]This is a text with a new-line in it. Selector > 1.', 1], // with single-quotes and id split accros lines ['This is a text with a new-line in it. Selector > 1.', '{0}This is a text with a new-line in it. Selector = 0.|{1}This is a text with a new-line in it. Selector = 1.|[1,Inf]This is a text with a new-line in it. Selector > 1.', 5], // with single-quotes and \n in text ['This is a text with a\nnew-line in it. Selector = 0.', '{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.', 0], // with double-quotes and id split accros lines ["This is a text with a\nnew-line in it. Selector = 1.", "{0}This is a text with a\nnew-line in it. Selector = 0.|{1}This is a text with a\nnew-line in it. Selector = 1.|[1,Inf]This is a text with a\nnew-line in it. Selector > 1.", 1], // esacape pipe ['This is a text with | in it. Selector = 0.', '{0}This is a text with || in it. Selector = 0.|{1}This is a text with || in it. Selector = 1.', 0], // Empty plural set (2 plural forms) from a .PO file ['', '|', 1], // Empty plural set (3 plural forms) from a .PO file ['', '||', 1], // Floating values ['1.5 liters', '%count% liter|%count% liters', 1.5], ['1.5 litre', '%count% litre|%count% litres', 1.5, 'fr'], // Negative values ['-1 degree', '%count% degree|%count% degrees', -1], ['-1 degré', '%count% degré|%count% degrés', -1], ['-1.5 degrees', '%count% degree|%count% degrees', -1.5], ['-1.5 degré', '%count% degré|%count% degrés', -1.5, 'fr'], ['-2 degrees', '%count% degree|%count% degrees', -2], ['-2 degrés', '%count% degré|%count% degrés', -2], ]; } /** * @dataProvider failingLangcodes */ public function testFailedLangcodes($nplural, $langCodes) { $matrix = $this->generateTestData($langCodes); $this->validateMatrix($nplural, $matrix, false); } /** * @dataProvider successLangcodes */ public function testLangcodes($nplural, $langCodes) { $matrix = $this->generateTestData($langCodes); $this->validateMatrix($nplural, $matrix); } /** * This array should contain all currently known langcodes. * * As it is impossible to have this ever complete we should try as hard as possible to have it almost complete. * * @return array */ public function successLangcodes() { return [ ['1', ['ay', 'bo', 'cgg', 'dz', 'id', 'ja', 'jbo', 'ka', 'kk', 'km', 'ko', 'ky']], ['2', ['nl', 'fr', 'en', 'de', 'de_GE', 'hy', 'hy_AM', 'en_US_POSIX']], ['3', ['be', 'bs', 'cs', 'hr']], ['4', ['cy', 'mt', 'sl']], ['6', ['ar']], ]; } /** * This array should be at least empty within the near future. * * This both depends on a complete list trying to add above as understanding * the plural rules of the current failing languages. * * @return array with nplural together with langcodes */ public function failingLangcodes() { return [ ['1', ['fa']], ['2', ['jbo']], ['3', ['cbs']], ['4', ['gd', 'kw']], ['5', ['ga']], ]; } /** * We validate only on the plural coverage. Thus the real rules is not tested. * * @param string $nplural Plural expected * @param array $matrix Containing langcodes and their plural index values * @param bool $expectSuccess */ protected function validateMatrix($nplural, $matrix, $expectSuccess = true) { foreach ($matrix as $langCode => $data) { $indexes = array_flip($data); if ($expectSuccess) { $this->assertEquals($nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); } else { $this->assertNotEquals((int) $nplural, \count($indexes), "Langcode '$langCode' has '$nplural' plural forms."); } } } protected function generateTestData($langCodes) { $translator = new class() { use TranslatorTrait { getPluralizationRule as public; } }; $matrix = []; foreach ($langCodes as $langCode) { for ($count = 0; $count < 200; ++$count) { $plural = $translator->getPluralizationRule($count, $langCode); $matrix[$langCode][$count] = $plural; } } return $matrix; } } service-contracts/README.md000064400000000514150432043210011453 0ustar00Symfony Service Contracts ========================= A set of abstractions extracted out of the Symfony components. Can be used to build on semantics that the Symfony components proved useful - and that already have battle tested implementations. See https://github.com/symfony/contracts/blob/main/README.md for more information. service-contracts/Attribute/SubscribedService.php000064400000001440150432043210016255 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service\Attribute; use Symfony\Contracts\Service\ServiceSubscriberTrait; /** * Use with {@see ServiceSubscriberTrait} to mark a method's return type * as a subscribed service. * * @author Kevin Bond */ #[\Attribute(\Attribute::TARGET_METHOD)] final class SubscribedService { /** * @param string|null $key The key to use for the service * If null, use "ClassName::methodName" */ public function __construct( public ?string $key = null ) { } } service-contracts/Attribute/Required.php000064400000001221150432043210014424 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service\Attribute; /** * A required dependency. * * This attribute indicates that a property holds a required dependency. The annotated property or method should be * considered during the instantiation process of the containing class. * * @author Alexander M. Turek */ #[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)] final class Required { } service-contracts/ResetInterface.php000064400000001747150432043210013621 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service; /** * Provides a way to reset an object to its initial state. * * When calling the "reset()" method on an object, it should be put back to its * initial state. This usually means clearing any internal buffers and forwarding * the call to internal dependencies. All properties of the object should be put * back to the same state it had when it was first ready to use. * * This method could be called, for example, to recycle objects that are used as * services, so that they can be used to handle several requests in the same * process loop (note that we advise making your services stateless instead of * implementing this interface when possible.) */ interface ResetInterface { public function reset(); } service-contracts/ServiceSubscriberTrait.php000064400000007701150432043210015342 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service; use Psr\Container\ContainerInterface; use Symfony\Contracts\Service\Attribute\SubscribedService; /** * Implementation of ServiceSubscriberInterface that determines subscribed services from * method return types. Service ids are available as "ClassName::methodName". * * @author Kevin Bond */ trait ServiceSubscriberTrait { /** @var ContainerInterface */ protected $container; /** * {@inheritdoc} */ public static function getSubscribedServices(): array { static $services; if (null !== $services) { return $services; } $services = \is_callable(['parent', __FUNCTION__]) ? parent::getSubscribedServices() : []; $attributeOptIn = false; if (\PHP_VERSION_ID >= 80000) { foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { if (self::class !== $method->getDeclaringClass()->name) { continue; } if (!$attribute = $method->getAttributes(SubscribedService::class)[0] ?? null) { continue; } if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { throw new \LogicException(sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name)); } if (!$returnType = $method->getReturnType()) { throw new \LogicException(sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); } $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; if ($returnType->allowsNull()) { $serviceId = '?'.$serviceId; } $services[$attribute->newInstance()->key ?? self::class.'::'.$method->name] = $serviceId; $attributeOptIn = true; } } if (!$attributeOptIn) { foreach ((new \ReflectionClass(self::class))->getMethods() as $method) { if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) { continue; } if (self::class !== $method->getDeclaringClass()->name) { continue; } if (!($returnType = $method->getReturnType()) instanceof \ReflectionNamedType) { continue; } if ($returnType->isBuiltin()) { continue; } if (\PHP_VERSION_ID >= 80000) { trigger_deprecation('symfony/service-contracts', '2.5', 'Using "%s" in "%s" without using the "%s" attribute on any method is deprecated.', ServiceSubscriberTrait::class, self::class, SubscribedService::class); } $services[self::class.'::'.$method->name] = '?'.($returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType); } } return $services; } /** * @required * * @return ContainerInterface|null */ public function setContainer(ContainerInterface $container) { $this->container = $container; if (\is_callable(['parent', __FUNCTION__])) { return parent::setContainer($container); } return null; } } service-contracts/CHANGELOG.md000064400000000235150432043210012005 0ustar00CHANGELOG ========= The changelog is maintained for all Symfony contracts at the following URL: https://github.com/symfony/contracts/blob/main/CHANGELOG.md service-contracts/.gitignore000064400000000042150432043210012160 0ustar00vendor/ composer.lock phpunit.xml service-contracts/composer.json000064400000002162150432043210012717 0ustar00{ "name": "symfony/service-contracts", "type": "library", "description": "Generic abstractions related to writing services", "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "psr/container": "^1.1", "symfony/deprecation-contracts": "^2.1" }, "conflict": { "ext-psr": "<1.1|>=2" }, "suggest": { "symfony/service-implementation": "" }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" } }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "2.5-dev" }, "thanks": { "name": "symfony/contracts", "url": "https://github.com/symfony/contracts" } } } service-contracts/ServiceProviderInterface.php000064400000002272150432043210015644 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service; use Psr\Container\ContainerInterface; /** * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container. * * @author Nicolas Grekas * @author Mateusz Sip */ interface ServiceProviderInterface extends ContainerInterface { /** * Returns an associative array of service types keyed by the identifiers provided by the current container. * * Examples: * * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface * * ['foo' => '?'] means the container provides service name "foo" of unspecified type * * ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null * * @return string[] The provided service types, keyed by service names */ public function getProvidedServices(): array; } service-contracts/ServiceLocatorTrait.php000064400000007274150432043210014647 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; // Help opcache.preload discover always-needed symbols class_exists(ContainerExceptionInterface::class); class_exists(NotFoundExceptionInterface::class); /** * A trait to help implement ServiceProviderInterface. * * @author Robin Chalas * @author Nicolas Grekas */ trait ServiceLocatorTrait { private $factories; private $loading = []; private $providedTypes; /** * @param callable[] $factories */ public function __construct(array $factories) { $this->factories = $factories; } /** * {@inheritdoc} * * @return bool */ public function has(string $id) { return isset($this->factories[$id]); } /** * {@inheritdoc} * * @return mixed */ public function get(string $id) { if (!isset($this->factories[$id])) { throw $this->createNotFoundException($id); } if (isset($this->loading[$id])) { $ids = array_values($this->loading); $ids = \array_slice($this->loading, array_search($id, $ids)); $ids[] = $id; throw $this->createCircularReferenceException($id, $ids); } $this->loading[$id] = $id; try { return $this->factories[$id]($this); } finally { unset($this->loading[$id]); } } /** * {@inheritdoc} */ public function getProvidedServices(): array { if (null === $this->providedTypes) { $this->providedTypes = []; foreach ($this->factories as $name => $factory) { if (!\is_callable($factory)) { $this->providedTypes[$name] = '?'; } else { $type = (new \ReflectionFunction($factory))->getReturnType(); $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '').($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?'; } } } return $this->providedTypes; } private function createNotFoundException(string $id): NotFoundExceptionInterface { if (!$alternatives = array_keys($this->factories)) { $message = 'is empty...'; } else { $last = array_pop($alternatives); if ($alternatives) { $message = sprintf('only knows about the "%s" and "%s" services.', implode('", "', $alternatives), $last); } else { $message = sprintf('only knows about the "%s" service.', $last); } } if ($this->loading) { $message = sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', end($this->loading), $id, $message); } else { $message = sprintf('Service "%s" not found: the current service locator %s', $id, $message); } return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface { }; } private function createCircularReferenceException(string $id, array $path): ContainerExceptionInterface { return new class(sprintf('Circular reference detected for service "%s", path: "%s".', $id, implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface { }; } } service-contracts/ServiceSubscriberInterface.php000064400000004311150432043210016151 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service; /** * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method. * * The getSubscribedServices method returns an array of service types required by such instances, * optionally keyed by the service names used internally. Service types that start with an interrogation * mark "?" are optional, while the other ones are mandatory service dependencies. * * The injected service locators SHOULD NOT allow access to any other services not specified by the method. * * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally. * This interface does not dictate any injection method for these service locators, although constructor * injection is recommended. * * @author Nicolas Grekas */ interface ServiceSubscriberInterface { /** * Returns an array of service types required by such instances, optionally keyed by the service names used internally. * * For mandatory dependencies: * * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name * internally to fetch a service which must implement Psr\Log\LoggerInterface. * * ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name * internally to fetch an iterable of Psr\Log\LoggerInterface instances. * * ['Psr\Log\LoggerInterface'] is a shortcut for * * ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface'] * * otherwise: * * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency * * ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency * * ['?Psr\Log\LoggerInterface'] is a shortcut for * * ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface'] * * @return string[] The required service types, optionally keyed by service names */ public static function getSubscribedServices(); } service-contracts/LICENSE000064400000002051150432043210011177 0ustar00Copyright (c) 2018-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. service-contracts/Test/ServiceLocatorTest.php000064400000005615150432043210015417 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Contracts\Service\Test; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Contracts\Service\ServiceLocatorTrait; abstract class ServiceLocatorTest extends TestCase { /** * @return ContainerInterface */ protected function getServiceLocator(array $factories) { return new class($factories) implements ContainerInterface { use ServiceLocatorTrait; }; } public function testHas() { $locator = $this->getServiceLocator([ 'foo' => function () { return 'bar'; }, 'bar' => function () { return 'baz'; }, function () { return 'dummy'; }, ]); $this->assertTrue($locator->has('foo')); $this->assertTrue($locator->has('bar')); $this->assertFalse($locator->has('dummy')); } public function testGet() { $locator = $this->getServiceLocator([ 'foo' => function () { return 'bar'; }, 'bar' => function () { return 'baz'; }, ]); $this->assertSame('bar', $locator->get('foo')); $this->assertSame('baz', $locator->get('bar')); } public function testGetDoesNotMemoize() { $i = 0; $locator = $this->getServiceLocator([ 'foo' => function () use (&$i) { ++$i; return 'bar'; }, ]); $this->assertSame('bar', $locator->get('foo')); $this->assertSame('bar', $locator->get('foo')); $this->assertSame(2, $i); } public function testThrowsOnUndefinedInternalService() { if (!$this->getExpectedException()) { $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.'); } $locator = $this->getServiceLocator([ 'foo' => function () use (&$locator) { return $locator->get('bar'); }, ]); $locator->get('foo'); } public function testThrowsOnCircularReference() { $this->expectException(\Psr\Container\ContainerExceptionInterface::class); $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".'); $locator = $this->getServiceLocator([ 'foo' => function () use (&$locator) { return $locator->get('bar'); }, 'bar' => function () use (&$locator) { return $locator->get('baz'); }, 'baz' => function () use (&$locator) { return $locator->get('bar'); }, ]); $locator->get('foo'); } } polyfill-php73/Resources/stubs/JsonException.php000064400000000430150432043210015737 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ class JsonException extends Exception { } polyfill-php73/README.md000064400000001061150432043210010604 0ustar00Symfony Polyfill / Php73 ======================== This component provides functions added to PHP 7.3 core: - [`array_key_first`](https://php.net/array_key_first) - [`array_key_last`](https://php.net/array_key_last) - [`hrtime`](https://php.net/function.hrtime) - [`is_countable`](https://php.net/is_countable) - [`JsonException`](https://php.net/JsonException) More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= This library is released under the [MIT license](LICENSE). polyfill-php73/Php73.php000064400000001542150432043210010743 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Php73; /** * @author Gabriel Caruso * @author Ion Bazan * * @internal */ final class Php73 { public static $startAt = 1533462603; /** * @param bool $asNum * * @return array|float|int */ public static function hrtime($asNum = false) { $ns = microtime(false); $s = substr($ns, 11) - self::$startAt; $ns = 1E9 * (float) $ns; if ($asNum) { $ns += $s * 1E9; return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; } return [$s, (int) $ns]; } } polyfill-php73/bootstrap.php000064400000001763150432043210012064 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Php73 as p; if (\PHP_VERSION_ID >= 70300) { return; } if (!function_exists('is_countable')) { function is_countable($value) { return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement; } } if (!function_exists('hrtime')) { require_once __DIR__.'/Php73.php'; p\Php73::$startAt = (int) microtime(true); function hrtime($as_number = false) { return p\Php73::hrtime($as_number); } } if (!function_exists('array_key_first')) { function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } } if (!function_exists('array_key_last')) { function array_key_last(array $array) { return key(array_slice($array, -1, 1, true)); } } polyfill-php73/composer.json000064400000001734150432043210012056 0ustar00{ "name": "symfony/polyfill-php73", "type": "library", "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "keywords": ["polyfill", "shim", "compatibility", "portable"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, "files": [ "bootstrap.php" ], "classmap": [ "Resources/stubs" ] }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-php73/LICENSE000064400000002051150432043210010332 0ustar00Copyright (c) 2018-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. string/Resources/data/wcswidth_table_wide.php000064400000030117150432043210015455 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String; if (!\function_exists(u::class)) { function u(?string $string = ''): UnicodeString { return new UnicodeString($string ?? ''); } } if (!\function_exists(b::class)) { function b(?string $string = ''): ByteString { return new ByteString($string ?? ''); } } if (!\function_exists(s::class)) { /** * @return UnicodeString|ByteString */ function s(?string $string = ''): AbstractString { $string = $string ?? ''; return preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string); } } string/LazyString.php000064400000011451150432043210010665 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String; /** * A string whose value is computed lazily by a callback. * * @author Nicolas Grekas */ class LazyString implements \Stringable, \JsonSerializable { private $value; /** * @param callable|array $callback A callable or a [Closure, method] lazy-callable * * @return static */ public static function fromCallable($callback, ...$arguments): self { if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) { throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, get_debug_type($callback))); } $lazyString = new static(); $lazyString->value = static function () use (&$callback, &$arguments, &$value): string { if (null !== $arguments) { if (!\is_callable($callback)) { $callback[0] = $callback[0](); $callback[1] = $callback[1] ?? '__invoke'; } $value = $callback(...$arguments); $callback = self::getPrettyName($callback); $arguments = null; } return $value ?? ''; }; return $lazyString; } /** * @param string|int|float|bool|\Stringable $value * * @return static */ public static function fromStringable($value): self { if (!self::isStringable($value)) { throw new \TypeError(sprintf('Argument 1 passed to "%s()" must be a scalar or a stringable object, "%s" given.', __METHOD__, get_debug_type($value))); } if (\is_object($value)) { return static::fromCallable([$value, '__toString']); } $lazyString = new static(); $lazyString->value = (string) $value; return $lazyString; } /** * Tells whether the provided value can be cast to string. */ final public static function isStringable($value): bool { return \is_string($value) || $value instanceof self || (\is_object($value) ? method_exists($value, '__toString') : is_scalar($value)); } /** * Casts scalars and stringable objects to strings. * * @param object|string|int|float|bool $value * * @throws \TypeError When the provided value is not stringable */ final public static function resolve($value): string { return $value; } /** * @return string */ public function __toString() { if (\is_string($this->value)) { return $this->value; } try { return $this->value = ($this->value)(); } catch (\Throwable $e) { if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) { $type = explode(', ', $e->getMessage()); $type = substr(array_pop($type), 0, -\strlen(' returned')); $r = new \ReflectionFunction($this->value); $callback = $r->getStaticVariables()['callback']; $e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type)); } if (\PHP_VERSION_ID < 70400) { // leverage the ErrorHandler component with graceful fallback when it's not available return trigger_error($e, \E_USER_ERROR); } throw $e; } } public function __sleep(): array { $this->__toString(); return ['value']; } public function jsonSerialize(): string { return $this->__toString(); } private function __construct() { } private static function getPrettyName(callable $callback): string { if (\is_string($callback)) { return $callback; } if (\is_array($callback)) { $class = \is_object($callback[0]) ? get_debug_type($callback[0]) : $callback[0]; $method = $callback[1]; } elseif ($callback instanceof \Closure) { $r = new \ReflectionFunction($callback); if (false !== strpos($r->name, '{closure}') || !$class = $r->getClosureScopeClass()) { return $r->name; } $class = $class->name; $method = $r->name; } else { $class = get_debug_type($callback); $method = '__invoke'; } return $class.'::'.$method; } } string/README.md000064400000001053150432043210007322 0ustar00String Component ================ The String component provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way. Resources --------- * [Documentation](https://symfony.com/doc/current/components/string.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) string/AbstractString.php000064400000047305150432043210011520 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String; use Symfony\Component\String\Exception\ExceptionInterface; use Symfony\Component\String\Exception\InvalidArgumentException; use Symfony\Component\String\Exception\RuntimeException; /** * Represents a string of abstract characters. * * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). * This class is the abstract type to use as a type-hint when the logic you want to * implement doesn't care about the exact variant it deals with. * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ abstract class AbstractString implements \Stringable, \JsonSerializable { public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER; public const PREG_SET_ORDER = \PREG_SET_ORDER; public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE; public const PREG_UNMATCHED_AS_NULL = \PREG_UNMATCHED_AS_NULL; public const PREG_SPLIT = 0; public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY; public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE; public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE; protected $string = ''; protected $ignoreCase = false; abstract public function __construct(string $string = ''); /** * Unwraps instances of AbstractString back to strings. * * @return string[]|array */ public static function unwrap(array $values): array { foreach ($values as $k => $v) { if ($v instanceof self) { $values[$k] = $v->__toString(); } elseif (\is_array($v) && $values[$k] !== $v = static::unwrap($v)) { $values[$k] = $v; } } return $values; } /** * Wraps (and normalizes) strings in instances of AbstractString. * * @return static[]|array */ public static function wrap(array $values): array { $i = 0; $keys = null; foreach ($values as $k => $v) { if (\is_string($k) && '' !== $k && $k !== $j = (string) new static($k)) { $keys = $keys ?? array_keys($values); $keys[$i] = $j; } if (\is_string($v)) { $values[$k] = new static($v); } elseif (\is_array($v) && $values[$k] !== $v = static::wrap($v)) { $values[$k] = $v; } ++$i; } return null !== $keys ? array_combine($keys, $values) : $values; } /** * @param string|string[] $needle * * @return static */ public function after($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = \PHP_INT_MAX; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); if (null !== $j && $j < $i) { $i = $j; $str->string = $n; } } if (\PHP_INT_MAX === $i) { return $str; } if (!$includeNeedle) { $i += $str->length(); } return $this->slice($i); } /** * @param string|string[] $needle * * @return static */ public function afterLast($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = null; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; $str->string = $n; } } if (null === $i) { return $str; } if (!$includeNeedle) { $i += $str->length(); } return $this->slice($i); } /** * @return static */ abstract public function append(string ...$suffix): self; /** * @param string|string[] $needle * * @return static */ public function before($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = \PHP_INT_MAX; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOf($n, $offset); if (null !== $j && $j < $i) { $i = $j; $str->string = $n; } } if (\PHP_INT_MAX === $i) { return $str; } if ($includeNeedle) { $i += $str->length(); } return $this->slice(0, $i); } /** * @param string|string[] $needle * * @return static */ public function beforeLast($needle, bool $includeNeedle = false, int $offset = 0): self { $str = clone $this; $i = null; foreach ((array) $needle as $n) { $n = (string) $n; $j = $this->indexOfLast($n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; $str->string = $n; } } if (null === $i) { return $str; } if ($includeNeedle) { $i += $str->length(); } return $this->slice(0, $i); } /** * @return int[] */ public function bytesAt(int $offset): array { $str = $this->slice($offset, 1); return '' === $str->string ? [] : array_values(unpack('C*', $str->string)); } /** * @return static */ abstract public function camel(): self; /** * @return static[] */ abstract public function chunk(int $length = 1): array; /** * @return static */ public function collapseWhitespace(): self { $str = clone $this; $str->string = trim(preg_replace('/(?:\s{2,}+|[^\S ])/', ' ', $str->string)); return $str; } /** * @param string|string[] $needle */ public function containsAny($needle): bool { return null !== $this->indexOf($needle); } /** * @param string|string[] $suffix */ public function endsWith($suffix): bool { if (!\is_array($suffix) && !$suffix instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($suffix as $s) { if ($this->endsWith((string) $s)) { return true; } } return false; } /** * @return static */ public function ensureEnd(string $suffix): self { if (!$this->endsWith($suffix)) { return $this->append($suffix); } $suffix = preg_quote($suffix); $regex = '{('.$suffix.')(?:'.$suffix.')++$}D'; return $this->replaceMatches($regex.($this->ignoreCase ? 'i' : ''), '$1'); } /** * @return static */ public function ensureStart(string $prefix): self { $prefix = new static($prefix); if (!$this->startsWith($prefix)) { return $this->prepend($prefix); } $str = clone $this; $i = $prefixLen = $prefix->length(); while ($this->indexOf($prefix, $i) === $i) { $str = $str->slice($prefixLen); $i += $prefixLen; } return $str; } /** * @param string|string[] $string */ public function equalsTo($string): bool { if (!\is_array($string) && !$string instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($string as $s) { if ($this->equalsTo((string) $s)) { return true; } } return false; } /** * @return static */ abstract public function folded(): self; /** * @return static */ public function ignoreCase(): self { $str = clone $this; $str->ignoreCase = true; return $str; } /** * @param string|string[] $needle */ public function indexOf($needle, int $offset = 0): ?int { if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } $i = \PHP_INT_MAX; foreach ($needle as $n) { $j = $this->indexOf((string) $n, $offset); if (null !== $j && $j < $i) { $i = $j; } } return \PHP_INT_MAX === $i ? null : $i; } /** * @param string|string[] $needle */ public function indexOfLast($needle, int $offset = 0): ?int { if (!\is_array($needle) && !$needle instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } $i = null; foreach ($needle as $n) { $j = $this->indexOfLast((string) $n, $offset); if (null !== $j && $j >= $i) { $i = $offset = $j; } } return $i; } public function isEmpty(): bool { return '' === $this->string; } /** * @return static */ abstract public function join(array $strings, string $lastGlue = null): self; public function jsonSerialize(): string { return $this->string; } abstract public function length(): int; /** * @return static */ abstract public function lower(): self; /** * Matches the string using a regular expression. * * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression. * * @return array All matches in a multi-dimensional array ordered according to flags */ abstract public function match(string $regexp, int $flags = 0, int $offset = 0): array; /** * @return static */ abstract public function padBoth(int $length, string $padStr = ' '): self; /** * @return static */ abstract public function padEnd(int $length, string $padStr = ' '): self; /** * @return static */ abstract public function padStart(int $length, string $padStr = ' '): self; /** * @return static */ abstract public function prepend(string ...$prefix): self; /** * @return static */ public function repeat(int $multiplier): self { if (0 > $multiplier) { throw new InvalidArgumentException(sprintf('Multiplier must be positive, %d given.', $multiplier)); } $str = clone $this; $str->string = str_repeat($str->string, $multiplier); return $str; } /** * @return static */ abstract public function replace(string $from, string $to): self; /** * @param string|callable $to * * @return static */ abstract public function replaceMatches(string $fromRegexp, $to): self; /** * @return static */ abstract public function reverse(): self; /** * @return static */ abstract public function slice(int $start = 0, int $length = null): self; /** * @return static */ abstract public function snake(): self; /** * @return static */ abstract public function splice(string $replacement, int $start = 0, int $length = null): self; /** * @return static[] */ public function split(string $delimiter, int $limit = null, int $flags = null): array { if (null === $flags) { throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.'); } if ($this->ignoreCase) { $delimiter .= 'i'; } set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (false === $chunks = preg_split($delimiter, $this->string, $limit, $flags)) { $lastError = preg_last_error(); foreach (get_defined_constants(true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === substr($k, -6)) { throw new RuntimeException('Splitting failed with '.$k.'.'); } } throw new RuntimeException('Splitting failed with unknown error code.'); } } finally { restore_error_handler(); } $str = clone $this; if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) { foreach ($chunks as &$chunk) { $str->string = $chunk[0]; $chunk[0] = clone $str; } } else { foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } } return $chunks; } /** * @param string|string[] $prefix */ public function startsWith($prefix): bool { if (!\is_array($prefix) && !$prefix instanceof \Traversable) { throw new \TypeError(sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class)); } foreach ($prefix as $prefix) { if ($this->startsWith((string) $prefix)) { return true; } } return false; } /** * @return static */ abstract public function title(bool $allWords = false): self; public function toByteString(string $toEncoding = null): ByteString { $b = new ByteString(); $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], true) ? 'UTF-8' : $toEncoding; if (null === $toEncoding || $toEncoding === $fromEncoding = $this instanceof AbstractUnicodeString || preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252') { $b->string = $this->string; return $b; } set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { try { $b->string = mb_convert_encoding($this->string, $toEncoding, 'UTF-8'); } catch (InvalidArgumentException $e) { if (!\function_exists('iconv')) { throw $e; } $b->string = iconv('UTF-8', $toEncoding, $this->string); } } finally { restore_error_handler(); } return $b; } public function toCodePointString(): CodePointString { return new CodePointString($this->string); } public function toString(): string { return $this->string; } public function toUnicodeString(): UnicodeString { return new UnicodeString($this->string); } /** * @return static */ abstract public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; /** * @return static */ abstract public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; /** * @param string|string[] $prefix * * @return static */ public function trimPrefix($prefix): self { if (\is_array($prefix) || $prefix instanceof \Traversable) { foreach ($prefix as $s) { $t = $this->trimPrefix($s); if ($t->string !== $this->string) { return $t; } } return clone $this; } $str = clone $this; if ($prefix instanceof self) { $prefix = $prefix->string; } else { $prefix = (string) $prefix; } if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) { $str->string = substr($this->string, \strlen($prefix)); } return $str; } /** * @return static */ abstract public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): self; /** * @param string|string[] $suffix * * @return static */ public function trimSuffix($suffix): self { if (\is_array($suffix) || $suffix instanceof \Traversable) { foreach ($suffix as $s) { $t = $this->trimSuffix($s); if ($t->string !== $this->string) { return $t; } } return clone $this; } $str = clone $this; if ($suffix instanceof self) { $suffix = $suffix->string; } else { $suffix = (string) $suffix; } if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) { $str->string = substr($this->string, 0, -\strlen($suffix)); } return $str; } /** * @return static */ public function truncate(int $length, string $ellipsis = '', bool $cut = true): self { $stringLength = $this->length(); if ($stringLength <= $length) { return clone $this; } $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0; if ($length < $ellipsisLength) { $ellipsisLength = 0; } if (!$cut) { if (null === $length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1)) { return clone $this; } $length += $ellipsisLength; } $str = $this->slice(0, $length - $ellipsisLength); return $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str; } /** * @return static */ abstract public function upper(): self; /** * Returns the printable length on a terminal. */ abstract public function width(bool $ignoreAnsiDecoration = true): int; /** * @return static */ public function wordwrap(int $width = 75, string $break = "\n", bool $cut = false): self { $lines = '' !== $break ? $this->split($break) : [clone $this]; $chars = []; $mask = ''; if (1 === \count($lines) && '' === $lines[0]->string) { return $lines[0]; } foreach ($lines as $i => $line) { if ($i) { $chars[] = $break; $mask .= '#'; } foreach ($line->chunk() as $char) { $chars[] = $char->string; $mask .= ' ' === $char->string ? ' ' : '?'; } } $string = ''; $j = 0; $b = $i = -1; $mask = wordwrap($mask, $width, '#', $cut); while (false !== $b = strpos($mask, '#', $b + 1)) { for (++$i; $i < $b; ++$i) { $string .= $chars[$j]; unset($chars[$j++]); } if ($break === $chars[$j] || ' ' === $chars[$j]) { unset($chars[$j++]); } $string .= $break; } $str = clone $this; $str->string = $string.implode('', $chars); return $str; } public function __sleep(): array { return ['string']; } public function __clone() { $this->ignoreCase = false; } public function __toString(): string { return $this->string; } } string/ByteString.php000064400000035720150432043210010656 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String; use Symfony\Component\String\Exception\ExceptionInterface; use Symfony\Component\String\Exception\InvalidArgumentException; use Symfony\Component\String\Exception\RuntimeException; /** * Represents a binary-safe string of bytes. * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ class ByteString extends AbstractString { private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; public function __construct(string $string = '') { $this->string = $string; } /* * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03) * * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16 * * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE). * * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/) */ public static function fromRandom(int $length = 16, string $alphabet = null): self { if ($length <= 0) { throw new InvalidArgumentException(sprintf('A strictly positive length is expected, "%d" given.', $length)); } $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC; $alphabetSize = \strlen($alphabet); $bits = (int) ceil(log($alphabetSize, 2.0)); if ($bits <= 0 || $bits > 56) { throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.'); } $ret = ''; while ($length > 0) { $urandomLength = (int) ceil(2 * $length * $bits / 8.0); $data = random_bytes($urandomLength); $unpackedData = 0; $unpackedBits = 0; for ($i = 0; $i < $urandomLength && $length > 0; ++$i) { // Unpack 8 bits $unpackedData = ($unpackedData << 8) | \ord($data[$i]); $unpackedBits += 8; // While we have enough bits to select a character from the alphabet, keep // consuming the random data for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) { $index = ($unpackedData & ((1 << $bits) - 1)); $unpackedData >>= $bits; // Unfortunately, the alphabet size is not necessarily a power of two. // Worst case, it is 2^k + 1, which means we need (k+1) bits and we // have around a 50% chance of missing as k gets larger if ($index < $alphabetSize) { $ret .= $alphabet[$index]; --$length; } } } } return new static($ret); } public function bytesAt(int $offset): array { $str = $this->string[$offset] ?? ''; return '' === $str ? [] : [\ord($str)]; } public function append(string ...$suffix): parent { $str = clone $this; $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); return $str; } public function camel(): parent { $str = clone $this; $str->string = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->string)))); return $str; } public function chunk(int $length = 1): array { if (1 > $length) { throw new InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $str = clone $this; $chunks = []; foreach (str_split($this->string, $length) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function endsWith($suffix): bool { if ($suffix instanceof parent) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase); } public function equalsTo($string): bool { if ($string instanceof parent) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { return 0 === strcasecmp($string, $this->string); } return $string === $this->string; } public function folded(): parent { $str = clone $this; $str->string = strtolower($str->string); return $str; } public function indexOf($needle, int $offset = 0): ?int { if ($needle instanceof parent) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? stripos($this->string, $needle, $offset) : strpos($this->string, $needle, $offset); return false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0): ?int { if ($needle instanceof parent) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? strripos($this->string, $needle, $offset) : strrpos($this->string, $needle, $offset); return false === $i ? null : $i; } public function isUtf8(): bool { return '' === $this->string || preg_match('//u', $this->string); } public function join(array $strings, string $lastGlue = null): parent { $str = clone $this; $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; $str->string = implode($this->string, $strings).$tail; return $str; } public function length(): int { return \strlen($this->string); } public function lower(): parent { $str = clone $this; $str->string = strtolower($str->string); return $str; } public function match(string $regexp, int $flags = 0, int $offset = 0): array { $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; if ($this->ignoreCase) { $regexp .= 'i'; } set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (false === $match($regexp, $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { $lastError = preg_last_error(); foreach (get_defined_constants(true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === substr($k, -6)) { throw new RuntimeException('Matching failed with '.$k.'.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { restore_error_handler(); } return $matches; } public function padBoth(int $length, string $padStr = ' '): parent { $str = clone $this; $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_BOTH); return $str; } public function padEnd(int $length, string $padStr = ' '): parent { $str = clone $this; $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT); return $str; } public function padStart(int $length, string $padStr = ' '): parent { $str = clone $this; $str->string = str_pad($this->string, $length, $padStr, \STR_PAD_LEFT); return $str; } public function prepend(string ...$prefix): parent { $str = clone $this; $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$str->string; return $str; } public function replace(string $from, string $to): parent { $str = clone $this; if ('' !== $from) { $str->string = $this->ignoreCase ? str_ireplace($from, $to, $this->string) : str_replace($from, $to, $this->string); } return $str; } public function replaceMatches(string $fromRegexp, $to): parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } if (\is_array($to)) { if (!\is_callable($to)) { throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); } $replace = 'preg_replace_callback'; } else { $replace = $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace'; } set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (null === $string = $replace($fromRegexp, $to, $this->string)) { $lastError = preg_last_error(); foreach (get_defined_constants(true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === substr($k, -6)) { throw new RuntimeException('Matching failed with '.$k.'.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { restore_error_handler(); } $str = clone $this; $str->string = $string; return $str; } public function reverse(): parent { $str = clone $this; $str->string = strrev($str->string); return $str; } public function slice(int $start = 0, int $length = null): parent { $str = clone $this; $str->string = (string) substr($this->string, $start, $length ?? \PHP_INT_MAX); return $str; } public function snake(): parent { $str = $this->camel()->title(); $str->string = strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], '\1_\2', $str->string)); return $str; } public function splice(string $replacement, int $start = 0, int $length = null): parent { $str = clone $this; $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); return $str; } public function split(string $delimiter, int $limit = null, int $flags = null): array { if (1 > $limit = $limit ?? \PHP_INT_MAX) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter, $limit, $flags); } $str = clone $this; $chunks = $this->ignoreCase ? preg_split('{'.preg_quote($delimiter).'}iD', $this->string, $limit) : explode($delimiter, $this->string, $limit); foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } return $chunks; } public function startsWith($prefix): bool { if ($prefix instanceof parent) { $prefix = $prefix->string; } elseif (!\is_string($prefix)) { return parent::startsWith($prefix); } return '' !== $prefix && 0 === ($this->ignoreCase ? strncasecmp($this->string, $prefix, \strlen($prefix)) : strncmp($this->string, $prefix, \strlen($prefix))); } public function title(bool $allWords = false): parent { $str = clone $this; $str->string = $allWords ? ucwords($str->string) : ucfirst($str->string); return $str; } public function toUnicodeString(string $fromEncoding = null): UnicodeString { return new UnicodeString($this->toCodePointString($fromEncoding)->string); } public function toCodePointString(string $fromEncoding = null): CodePointString { $u = new CodePointString(); if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], true) && preg_match('//u', $this->string)) { $u->string = $this->string; return $u; } set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { try { $validEncoding = false !== mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', true); } catch (InvalidArgumentException $e) { if (!\function_exists('iconv')) { throw $e; } $u->string = iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string); return $u; } } finally { restore_error_handler(); } if (!$validEncoding) { throw new InvalidArgumentException(sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252')); } $u->string = mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252'); return $u; } public function trim(string $chars = " \t\n\r\0\x0B\x0C"): parent { $str = clone $this; $str->string = trim($str->string, $chars); return $str; } public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C"): parent { $str = clone $this; $str->string = rtrim($str->string, $chars); return $str; } public function trimStart(string $chars = " \t\n\r\0\x0B\x0C"): parent { $str = clone $this; $str->string = ltrim($str->string, $chars); return $str; } public function upper(): parent { $str = clone $this; $str->string = strtoupper($str->string); return $str; } public function width(bool $ignoreAnsiDecoration = true): int { $string = preg_match('//u', $this->string) ? $this->string : preg_replace('/[\x80-\xFF]/', '?', $this->string); return (new CodePointString($string))->width($ignoreAnsiDecoration); } } string/AbstractUnicodeString.php000064400000065553150432043210013034 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String; use Symfony\Component\String\Exception\ExceptionInterface; use Symfony\Component\String\Exception\InvalidArgumentException; use Symfony\Component\String\Exception\RuntimeException; /** * Represents a string of abstract Unicode characters. * * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters). * This class is the abstract type to use as a type-hint when the logic you want to * implement is Unicode-aware but doesn't care about code points vs grapheme clusters. * * @author Nicolas Grekas * * @throws ExceptionInterface */ abstract class AbstractUnicodeString extends AbstractString { public const NFC = \Normalizer::NFC; public const NFD = \Normalizer::NFD; public const NFKC = \Normalizer::NFKC; public const NFKD = \Normalizer::NFKD; // all ASCII letters sorted by typical frequency of occurrence private const ASCII = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; // the subset of folded case mappings that is not in lower case mappings private const FOLD_FROM = ['İ', 'µ', 'ſ', "\xCD\x85", 'ς', 'ϐ', 'ϑ', 'ϕ', 'ϖ', 'ϰ', 'ϱ', 'ϵ', 'ẛ', "\xE1\xBE\xBE", 'ß', 'İ', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'և', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ẞ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'ᾐ', 'ᾑ', 'ᾒ', 'ᾓ', 'ᾔ', 'ᾕ', 'ᾖ', 'ᾗ', 'ᾘ', 'ᾙ', 'ᾚ', 'ᾛ', 'ᾜ', 'ᾝ', 'ᾞ', 'ᾟ', 'ᾠ', 'ᾡ', 'ᾢ', 'ᾣ', 'ᾤ', 'ᾥ', 'ᾦ', 'ᾧ', 'ᾨ', 'ᾩ', 'ᾪ', 'ᾫ', 'ᾬ', 'ᾭ', 'ᾮ', 'ᾯ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'ᾼ', 'ῂ', 'ῃ', 'ῄ', 'ῆ', 'ῇ', 'ῌ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῲ', 'ῳ', 'ῴ', 'ῶ', 'ῷ', 'ῼ', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ']; private const FOLD_TO = ['i̇', 'μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', 'ṡ', 'ι', 'ss', 'i̇', 'ʼn', 'ǰ', 'ΐ', 'ΰ', 'եւ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'aʾ', 'ss', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἀι', 'ἁι', 'ἂι', 'ἃι', 'ἄι', 'ἅι', 'ἆι', 'ἇι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ἠι', 'ἡι', 'ἢι', 'ἣι', 'ἤι', 'ἥι', 'ἦι', 'ἧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὠι', 'ὡι', 'ὢι', 'ὣι', 'ὤι', 'ὥι', 'ὦι', 'ὧι', 'ὰι', 'αι', 'άι', 'ᾶ', 'ᾶι', 'αι', 'ὴι', 'ηι', 'ήι', 'ῆ', 'ῆι', 'ηι', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ὼι', 'ωι', 'ώι', 'ῶ', 'ῶι', 'ωι', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'մն', 'մե', 'մի', 'վն', 'մխ']; // the subset of upper case mappings that map one code point to many code points private const UPPER_FROM = ['ß', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'ſt', 'st', 'և', 'ﬓ', 'ﬔ', 'ﬕ', 'ﬖ', 'ﬗ', 'ʼn', 'ΐ', 'ΰ', 'ǰ', 'ẖ', 'ẗ', 'ẘ', 'ẙ', 'ẚ', 'ὐ', 'ὒ', 'ὔ', 'ὖ', 'ᾶ', 'ῆ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'ῢ', 'ΰ', 'ῤ', 'ῦ', 'ῧ', 'ῶ']; private const UPPER_TO = ['SS', 'FF', 'FI', 'FL', 'FFI', 'FFL', 'ST', 'ST', 'ԵՒ', 'ՄՆ', 'ՄԵ', 'ՄԻ', 'ՎՆ', 'ՄԽ', 'ʼN', 'Ϊ́', 'Ϋ́', 'J̌', 'H̱', 'T̈', 'W̊', 'Y̊', 'Aʾ', 'Υ̓', 'Υ̓̀', 'Υ̓́', 'Υ̓͂', 'Α͂', 'Η͂', 'Ϊ̀', 'Ϊ́', 'Ι͂', 'Ϊ͂', 'Ϋ̀', 'Ϋ́', 'Ρ̓', 'Υ͂', 'Ϋ͂', 'Ω͂']; // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD private const TRANSLIT_FROM = ['Æ', 'Ð', 'Ø', 'Þ', 'ß', 'æ', 'ð', 'ø', 'þ', 'Đ', 'đ', 'Ħ', 'ħ', 'ı', 'ĸ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'ʼn', 'Ŋ', 'ŋ', 'Œ', 'œ', 'Ŧ', 'ŧ', 'ƀ', 'Ɓ', 'Ƃ', 'ƃ', 'Ƈ', 'ƈ', 'Ɖ', 'Ɗ', 'Ƌ', 'ƌ', 'Ɛ', 'Ƒ', 'ƒ', 'Ɠ', 'ƕ', 'Ɩ', 'Ɨ', 'Ƙ', 'ƙ', 'ƚ', 'Ɲ', 'ƞ', 'Ƣ', 'ƣ', 'Ƥ', 'ƥ', 'ƫ', 'Ƭ', 'ƭ', 'Ʈ', 'Ʋ', 'Ƴ', 'ƴ', 'Ƶ', 'ƶ', 'DŽ', 'Dž', 'dž', 'Ǥ', 'ǥ', 'ȡ', 'Ȥ', 'ȥ', 'ȴ', 'ȵ', 'ȶ', 'ȷ', 'ȸ', 'ȹ', 'Ⱥ', 'Ȼ', 'ȼ', 'Ƚ', 'Ⱦ', 'ȿ', 'ɀ', 'Ƀ', 'Ʉ', 'Ɇ', 'ɇ', 'Ɉ', 'ɉ', 'Ɍ', 'ɍ', 'Ɏ', 'ɏ', 'ɓ', 'ɕ', 'ɖ', 'ɗ', 'ɛ', 'ɟ', 'ɠ', 'ɡ', 'ɢ', 'ɦ', 'ɧ', 'ɨ', 'ɪ', 'ɫ', 'ɬ', 'ɭ', 'ɱ', 'ɲ', 'ɳ', 'ɴ', 'ɶ', 'ɼ', 'ɽ', 'ɾ', 'ʀ', 'ʂ', 'ʈ', 'ʉ', 'ʋ', 'ʏ', 'ʐ', 'ʑ', 'ʙ', 'ʛ', 'ʜ', 'ʝ', 'ʟ', 'ʠ', 'ʣ', 'ʥ', 'ʦ', 'ʪ', 'ʫ', 'ᴀ', 'ᴁ', 'ᴃ', 'ᴄ', 'ᴅ', 'ᴆ', 'ᴇ', 'ᴊ', 'ᴋ', 'ᴌ', 'ᴍ', 'ᴏ', 'ᴘ', 'ᴛ', 'ᴜ', 'ᴠ', 'ᴡ', 'ᴢ', 'ᵫ', 'ᵬ', 'ᵭ', 'ᵮ', 'ᵯ', 'ᵰ', 'ᵱ', 'ᵲ', 'ᵳ', 'ᵴ', 'ᵵ', 'ᵶ', 'ᵺ', 'ᵻ', 'ᵽ', 'ᵾ', 'ᶀ', 'ᶁ', 'ᶂ', 'ᶃ', 'ᶄ', 'ᶅ', 'ᶆ', 'ᶇ', 'ᶈ', 'ᶉ', 'ᶊ', 'ᶌ', 'ᶍ', 'ᶎ', 'ᶏ', 'ᶑ', 'ᶒ', 'ᶓ', 'ᶖ', 'ᶙ', 'ẚ', 'ẜ', 'ẝ', 'ẞ', 'Ỻ', 'ỻ', 'Ỽ', 'ỽ', 'Ỿ', 'ỿ', '©', '®', '₠', '₢', '₣', '₤', '₧', '₺', '₹', 'ℌ', '℞', '㎧', '㎮', '㏆', '㏗', '㏞', '㏟', '¼', '½', '¾', '⅓', '⅔', '⅕', '⅖', '⅗', '⅘', '⅙', '⅚', '⅛', '⅜', '⅝', '⅞', '⅟', '〇', '‘', '’', '‚', '‛', '“', '”', '„', '‟', '′', '″', '〝', '〞', '«', '»', '‹', '›', '‐', '‑', '‒', '–', '—', '―', '︱', '︲', '﹘', '‖', '⁄', '⁅', '⁆', '⁎', '、', '。', '〈', '〉', '《', '》', '〔', '〕', '〘', '〙', '〚', '〛', '︑', '︒', '︹', '︺', '︽', '︾', '︿', '﹀', '﹑', '﹝', '﹞', '⦅', '⦆', '。', '、', '×', '÷', '−', '∕', '∖', '∣', '∥', '≪', '≫', '⦅', '⦆']; private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))']; private static $transliterators = []; /** * @return static */ public static function fromCodePoints(int ...$codes): self { $string = ''; foreach ($codes as $code) { if (0x80 > $code %= 0x200000) { $string .= \chr($code); } elseif (0x800 > $code) { $string .= \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); } elseif (0x10000 > $code) { $string .= \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } else { $string .= \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } } return new static($string); } /** * Generic UTF-8 to ASCII transliteration. * * Install the intl extension for best results. * * @param string[]|\Transliterator[]|\Closure[] $rules See "*-Latin" rules from Transliterator::listIDs() */ public function ascii(array $rules = []): self { $str = clone $this; $s = $str->string; $str->string = ''; array_unshift($rules, 'nfd'); $rules[] = 'latin-ascii'; if (\function_exists('transliterator_transliterate')) { $rules[] = 'any-latin/bgn'; } $rules[] = 'nfkd'; $rules[] = '[:nonspacing mark:] remove'; while (\strlen($s) - 1 > $i = strspn($s, self::ASCII)) { if (0 < --$i) { $str->string .= substr($s, 0, $i); $s = substr($s, $i); } if (!$rule = array_shift($rules)) { $rules = []; // An empty rule interrupts the next ones } if ($rule instanceof \Transliterator) { $s = $rule->transliterate($s); } elseif ($rule instanceof \Closure) { $s = $rule($s); } elseif ($rule) { if ('nfd' === $rule = strtolower($rule)) { normalizer_is_normalized($s, self::NFD) ?: $s = normalizer_normalize($s, self::NFD); } elseif ('nfkd' === $rule) { normalizer_is_normalized($s, self::NFKD) ?: $s = normalizer_normalize($s, self::NFKD); } elseif ('[:nonspacing mark:] remove' === $rule) { $s = preg_replace('/\p{Mn}++/u', '', $s); } elseif ('latin-ascii' === $rule) { $s = str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s); } elseif ('de-ascii' === $rule) { $s = preg_replace("/([AUO])\u{0308}(?=\p{Ll})/u", '$1e', $s); $s = str_replace(["a\u{0308}", "o\u{0308}", "u\u{0308}", "A\u{0308}", "O\u{0308}", "U\u{0308}"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s); } elseif (\function_exists('transliterator_transliterate')) { if (null === $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule)) { if ('any-latin/bgn' === $rule) { $rule = 'any-latin'; $transliterator = self::$transliterators[$rule] ?? self::$transliterators[$rule] = \Transliterator::create($rule); } if (null === $transliterator) { throw new InvalidArgumentException(sprintf('Unknown transliteration rule "%s".', $rule)); } self::$transliterators['any-latin/bgn'] = $transliterator; } $s = $transliterator->transliterate($s); } } elseif (!\function_exists('iconv')) { $s = preg_replace('/[^\x00-\x7F]/u', '?', $s); } else { $s = @preg_replace_callback('/[^\x00-\x7F]/u', static function ($c) { $c = (string) iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]); if ('' === $c && '' === iconv('UTF-8', 'ASCII//TRANSLIT', '²')) { throw new \LogicException(sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class)); } return 1 < \strlen($c) ? ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?'); }, $s); } } $str->string .= $s; return $str; } public function camel(): parent { $str = clone $this; $str->string = str_replace(' ', '', preg_replace_callback('/\b./u', static function ($m) use (&$i) { return 1 === ++$i ? ('İ' === $m[0] ? 'i̇' : mb_strtolower($m[0], 'UTF-8')) : mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); }, preg_replace('/[^\pL0-9]++/u', ' ', $this->string))); return $str; } /** * @return int[] */ public function codePointsAt(int $offset): array { $str = $this->slice($offset, 1); if ('' === $str->string) { return []; } $codePoints = []; foreach (preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { $codePoints[] = mb_ord($c, 'UTF-8'); } return $codePoints; } public function folded(bool $compat = true): parent { $str = clone $this; if (!$compat || \PHP_VERSION_ID < 70300 || !\defined('Normalizer::NFKC_CF')) { $str->string = normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC); $str->string = mb_strtolower(str_replace(self::FOLD_FROM, self::FOLD_TO, $this->string), 'UTF-8'); } else { $str->string = normalizer_normalize($str->string, \Normalizer::NFKC_CF); } return $str; } public function join(array $strings, string $lastGlue = null): parent { $str = clone $this; $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue.array_pop($strings) : ''; $str->string = implode($this->string, $strings).$tail; if (!preg_match('//u', $str->string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function lower(): parent { $str = clone $this; $str->string = mb_strtolower(str_replace('İ', 'i̇', $str->string), 'UTF-8'); return $str; } public function match(string $regexp, int $flags = 0, int $offset = 0): array { $match = ((\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags) ? 'preg_match_all' : 'preg_match'; if ($this->ignoreCase) { $regexp .= 'i'; } set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (false === $match($regexp.'u', $this->string, $matches, $flags | \PREG_UNMATCHED_AS_NULL, $offset)) { $lastError = preg_last_error(); foreach (get_defined_constants(true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === substr($k, -6)) { throw new RuntimeException('Matching failed with '.$k.'.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { restore_error_handler(); } return $matches; } /** * @return static */ public function normalize(int $form = self::NFC): self { if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) { throw new InvalidArgumentException('Unsupported normalization form.'); } $str = clone $this; normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); return $str; } public function padBoth(int $length, string $padStr = ' '): parent { if ('' === $padStr || !preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_BOTH); } public function padEnd(int $length, string $padStr = ' '): parent { if ('' === $padStr || !preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_RIGHT); } public function padStart(int $length, string $padStr = ' '): parent { if ('' === $padStr || !preg_match('//u', $padStr)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $pad = clone $this; $pad->string = $padStr; return $this->pad($length, $pad, \STR_PAD_LEFT); } public function replaceMatches(string $fromRegexp, $to): parent { if ($this->ignoreCase) { $fromRegexp .= 'i'; } if (\is_array($to) || $to instanceof \Closure) { if (!\is_callable($to)) { throw new \TypeError(sprintf('Argument 2 passed to "%s::replaceMatches()" must be callable, array given.', static::class)); } $replace = 'preg_replace_callback'; $to = static function (array $m) use ($to): string { $to = $to($m); if ('' !== $to && (!\is_string($to) || !preg_match('//u', $to))) { throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.'); } return $to; }; } elseif ('' !== $to && !preg_match('//u', $to)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } else { $replace = 'preg_replace'; } set_error_handler(static function ($t, $m) { throw new InvalidArgumentException($m); }); try { if (null === $string = $replace($fromRegexp.'u', $to, $this->string)) { $lastError = preg_last_error(); foreach (get_defined_constants(true)['pcre'] as $k => $v) { if ($lastError === $v && '_ERROR' === substr($k, -6)) { throw new RuntimeException('Matching failed with '.$k.'.'); } } throw new RuntimeException('Matching failed with unknown error code.'); } } finally { restore_error_handler(); } $str = clone $this; $str->string = $string; return $str; } public function reverse(): parent { $str = clone $this; $str->string = implode('', array_reverse(preg_split('/(\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY))); return $str; } public function snake(): parent { $str = $this->camel()->title(); $str->string = mb_strtolower(preg_replace(['/(\p{Lu}+)(\p{Lu}\p{Ll})/u', '/([\p{Ll}0-9])(\p{Lu})/u'], '\1_\2', $str->string), 'UTF-8'); return $str; } public function title(bool $allWords = false): parent { $str = clone $this; $limit = $allWords ? -1 : 1; $str->string = preg_replace_callback('/\b./u', static function (array $m): string { return mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8'); }, $str->string, $limit); return $str; } public function trim(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent { if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = preg_quote($chars); $str = clone $this; $str->string = preg_replace("{^[$chars]++|[$chars]++$}uD", '', $str->string); return $str; } public function trimEnd(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent { if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = preg_quote($chars); $str = clone $this; $str->string = preg_replace("{[$chars]++$}uD", '', $str->string); return $str; } public function trimPrefix($prefix): parent { if (!$this->ignoreCase) { return parent::trimPrefix($prefix); } $str = clone $this; if ($prefix instanceof \Traversable) { $prefix = iterator_to_array($prefix, false); } elseif ($prefix instanceof parent) { $prefix = $prefix->string; } $prefix = implode('|', array_map('preg_quote', (array) $prefix)); $str->string = preg_replace("{^(?:$prefix)}iuD", '', $this->string); return $str; } public function trimStart(string $chars = " \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}"): parent { if (" \t\n\r\0\x0B\x0C\u{A0}\u{FEFF}" !== $chars && !preg_match('//u', $chars)) { throw new InvalidArgumentException('Invalid UTF-8 chars.'); } $chars = preg_quote($chars); $str = clone $this; $str->string = preg_replace("{^[$chars]++}uD", '', $str->string); return $str; } public function trimSuffix($suffix): parent { if (!$this->ignoreCase) { return parent::trimSuffix($suffix); } $str = clone $this; if ($suffix instanceof \Traversable) { $suffix = iterator_to_array($suffix, false); } elseif ($suffix instanceof parent) { $suffix = $suffix->string; } $suffix = implode('|', array_map('preg_quote', (array) $suffix)); $str->string = preg_replace("{(?:$suffix)$}iuD", '', $this->string); return $str; } public function upper(): parent { $str = clone $this; $str->string = mb_strtoupper($str->string, 'UTF-8'); if (\PHP_VERSION_ID < 70300) { $str->string = str_replace(self::UPPER_FROM, self::UPPER_TO, $str->string); } return $str; } public function width(bool $ignoreAnsiDecoration = true): int { $width = 0; $s = str_replace(["\x00", "\x05", "\x07"], '', $this->string); if (false !== strpos($s, "\r")) { $s = str_replace(["\r\n", "\r"], "\n", $s); } if (!$ignoreAnsiDecoration) { $s = preg_replace('/[\p{Cc}\x7F]++/u', '', $s); } foreach (explode("\n", $s) as $s) { if ($ignoreAnsiDecoration) { $s = preg_replace('/(?:\x1B(?: \[ [\x30-\x3F]*+ [\x20-\x2F]*+ [0x40-\x7E] | [P\]X^_] .*? \x1B\\\\ | [\x41-\x7E] )|[\p{Cc}\x7F]++)/xu', '', $s); } // Non printable characters have been dropped, so wcswidth cannot logically return -1. $width += $this->wcswidth($s); } return $width; } /** * @return static */ private function pad(int $len, self $pad, int $type): parent { $sLen = $this->length(); if ($len <= $sLen) { return clone $this; } $padLen = $pad->length(); $freeLen = $len - $sLen; $len = $freeLen % $padLen; switch ($type) { case \STR_PAD_RIGHT: return $this->append(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); case \STR_PAD_LEFT: return $this->prepend(str_repeat($pad->string, intdiv($freeLen, $padLen)).($len ? $pad->slice(0, $len) : '')); case \STR_PAD_BOTH: $freeLen /= 2; $rightLen = ceil($freeLen); $len = $rightLen % $padLen; $str = $this->append(str_repeat($pad->string, intdiv($rightLen, $padLen)).($len ? $pad->slice(0, $len) : '')); $leftLen = floor($freeLen); $len = $leftLen % $padLen; return $str->prepend(str_repeat($pad->string, intdiv($leftLen, $padLen)).($len ? $pad->slice(0, $len) : '')); default: throw new InvalidArgumentException('Invalid padding type.'); } } /** * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c. */ private function wcswidth(string $string): int { $width = 0; foreach (preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) { $codePoint = mb_ord($c, 'UTF-8'); if (0 === $codePoint // NULL || 0x034F === $codePoint // COMBINING GRAPHEME JOINER || (0x200B <= $codePoint && 0x200F >= $codePoint) // ZERO WIDTH SPACE to RIGHT-TO-LEFT MARK || 0x2028 === $codePoint // LINE SEPARATOR || 0x2029 === $codePoint // PARAGRAPH SEPARATOR || (0x202A <= $codePoint && 0x202E >= $codePoint) // LEFT-TO-RIGHT EMBEDDING to RIGHT-TO-LEFT OVERRIDE || (0x2060 <= $codePoint && 0x2063 >= $codePoint) // WORD JOINER to INVISIBLE SEPARATOR ) { continue; } // Non printable characters if (32 > $codePoint // C0 control characters || (0x07F <= $codePoint && 0x0A0 > $codePoint) // C1 control characters and DEL ) { return -1; } static $tableZero; if (null === $tableZero) { $tableZero = require __DIR__.'/Resources/data/wcswidth_table_zero.php'; } if ($codePoint >= $tableZero[0][0] && $codePoint <= $tableZero[$ubound = \count($tableZero) - 1][1]) { $lbound = 0; while ($ubound >= $lbound) { $mid = floor(($lbound + $ubound) / 2); if ($codePoint > $tableZero[$mid][1]) { $lbound = $mid + 1; } elseif ($codePoint < $tableZero[$mid][0]) { $ubound = $mid - 1; } else { continue 2; } } } static $tableWide; if (null === $tableWide) { $tableWide = require __DIR__.'/Resources/data/wcswidth_table_wide.php'; } if ($codePoint >= $tableWide[0][0] && $codePoint <= $tableWide[$ubound = \count($tableWide) - 1][1]) { $lbound = 0; while ($ubound >= $lbound) { $mid = floor(($lbound + $ubound) / 2); if ($codePoint > $tableWide[$mid][1]) { $lbound = $mid + 1; } elseif ($codePoint < $tableWide[$mid][0]) { $ubound = $mid - 1; } else { $width += 2; continue 2; } } } ++$width; } return $width; } } string/CHANGELOG.md000064400000001504150432043210007655 0ustar00CHANGELOG ========= 5.4 --- * Add `trimSuffix()` and `trimPrefix()` methods 5.3 --- * Made `AsciiSlugger` fallback to parent locale's symbolsMap 5.2.0 ----- * added a `FrenchInflector` class 5.1.0 ----- * added the `AbstractString::reverse()` method * made `AbstractString::width()` follow POSIX.1-2001 * added `LazyString` which provides memoizing stringable objects * The component is not marked as `@experimental` anymore * added the `s()` helper method to get either an `UnicodeString` or `ByteString` instance, depending of the input string UTF-8 compliancy * added `$cut` parameter to `Symfony\Component\String\AbstractString::truncate()` * added `AbstractString::containsAny()` * allow passing a string of custom characters to `ByteString::fromRandom()` 5.0.0 ----- * added the component as experimental string/Inflector/InflectorInterface.php000064400000001503150432043210014247 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Inflector; interface InflectorInterface { /** * Returns the singular forms of a string. * * If the method can't determine the form with certainty, several possible singulars are returned. * * @return string[] */ public function singularize(string $plural): array; /** * Returns the plural forms of a string. * * If the method can't determine the form with certainty, several possible plurals are returned. * * @return string[] */ public function pluralize(string $singular): array; } string/Inflector/FrenchInflector.php000064400000013617150432043210013565 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Inflector; /** * French inflector. * * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix". */ final class FrenchInflector implements InflectorInterface { /** * A list of all rules for pluralise. * * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php */ private const PLURALIZE_REGEXP = [ // First entry: regexp // Second entry: replacement // Words finishing with "s", "x" or "z" are invariables // Les mots finissant par "s", "x" ou "z" sont invariables ['/(s|x|z)$/i', '\1'], // Words finishing with "eau" are pluralized with a "x" // Les mots finissant par "eau" prennent tous un "x" au pluriel ['/(eau)$/i', '\1x'], // Words finishing with "au" are pluralized with a "x" excepted "landau" // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" ['/^(landau)$/i', '\1s'], ['/(au)$/i', '\1x'], // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" ['/^(pneu|bleu|émeu)$/i', '\1s'], ['/(eu)$/i', '\1x'], // Words finishing with "al" are pluralized with a "aux" excepted // Les mots finissant en "al" se terminent en "aux" sauf ['/^(bal|carnaval|caracal|chacal|choral|corral|étal|festival|récital|val)$/i', '\1s'], ['/al$/i', '\1aux'], // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux ['/^(aspir|b|cor|ém|ferm|soupir|trav|vant|vitr)ail$/i', '\1aux'], // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\1oux'], // Invariable words ['/^(cinquante|soixante|mille)$/i', '\1'], // French titles ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'mes\2s'], ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'Mes\2s'], ]; /** * A list of all rules for singularize. */ private const SINGULARIZE_REGEXP = [ // First entry: regexp // Second entry: replacement // Aspirail, bail, corail, émail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux ['/((aspir|b|cor|ém|ferm|soupir|trav|vant|vitr))aux$/i', '\1ail'], // Words finishing with "eau" are pluralized with a "x" // Les mots finissant par "eau" prennent tous un "x" au pluriel ['/(eau)x$/i', '\1'], // Words finishing with "al" are pluralized with a "aux" expected // Les mots finissant en "al" se terminent en "aux" sauf ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|génér|hopit|hôpit|idé|journ|littor|loc|m|mét|minér|princip|radic|termin)aux$/i', '\1al'], // Words finishing with "au" are pluralized with a "x" excepted "landau" // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau" ['/(au)x$/i', '\1'], // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "émeu" // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "émeu" ['/(eu)x$/i', '\1'], // Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\1ou'], // French titles ['/^mes(dame|demoiselle)s$/', 'ma\1'], ['/^Mes(dame|demoiselle)s$/', 'Ma\1'], ['/^mes(sieur|seigneur)s$/', 'mon\1'], ['/^Mes(sieur|seigneur)s$/', 'Mon\1'], //Default rule ['/s$/i', ''], ]; /** * A list of words which should not be inflected. * This list is only used by singularize. */ private const UNINFLECTED = '/^(abcès|accès|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprès|décès|devis|discours|dos|embarras|engrais|entrelacs|excès|fils|fois|gâchis|gars|glas|héros|intrus|jars|jus|kermès|lacis|legs|lilas|marais|mars|matelas|mépris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrès|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocéros|repas|rubis|sas|secours|sens|souris|succès|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i'; /** * {@inheritdoc} */ public function singularize(string $plural): array { if ($this->isInflectedWord($plural)) { return [$plural]; } foreach (self::SINGULARIZE_REGEXP as $rule) { [$regexp, $replace] = $rule; if (1 === preg_match($regexp, $plural)) { return [preg_replace($regexp, $replace, $plural)]; } } return [$plural]; } /** * {@inheritdoc} */ public function pluralize(string $singular): array { if ($this->isInflectedWord($singular)) { return [$singular]; } foreach (self::PLURALIZE_REGEXP as $rule) { [$regexp, $replace] = $rule; if (1 === preg_match($regexp, $singular)) { return [preg_replace($regexp, $replace, $singular)]; } } return [$singular.'s']; } private function isInflectedWord(string $word): bool { return 1 === preg_match(self::UNINFLECTED, $word); } } string/Inflector/EnglishInflector.php000064400000036302150432043210013745 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Inflector; final class EnglishInflector implements InflectorInterface { /** * Map English plural to singular suffixes. * * @see http://english-zone.com/spelling/plurals.html */ private const PLURAL_MAP = [ // First entry: plural suffix, reversed // Second entry: length of plural suffix // Third entry: Whether the suffix may succeed a vocal // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: singular suffix, normal // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['a', 1, true, true, ['on', 'um']], // nebulae (nebula) ['ea', 2, true, true, 'a'], // services (service) ['secivres', 8, true, true, 'service'], // mice (mouse), lice (louse) ['eci', 3, false, true, 'ouse'], // geese (goose) ['esee', 4, false, true, 'oose'], // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) ['i', 1, true, true, 'us'], // men (man), women (woman) ['nem', 3, true, true, 'man'], // children (child) ['nerdlihc', 8, true, true, 'child'], // oxen (ox) ['nexo', 4, false, false, 'ox'], // indices (index), appendices (appendix), prices (price) ['seci', 4, false, true, ['ex', 'ix', 'ice']], // selfies (selfie) ['seifles', 7, true, true, 'selfie'], // zombies (zombie) ['seibmoz', 7, true, true, 'zombie'], // movies (movie) ['seivom', 6, true, true, 'movie'], // conspectuses (conspectus), prospectuses (prospectus) ['sesutcep', 8, true, true, 'pectus'], // feet (foot) ['teef', 4, true, true, 'foot'], // geese (goose) ['eseeg', 5, true, true, 'goose'], // teeth (tooth) ['hteet', 5, true, true, 'tooth'], // news (news) ['swen', 4, true, true, 'news'], // series (series) ['seires', 6, true, true, 'series'], // babies (baby) ['sei', 3, false, true, 'y'], // accesses (access), addresses (address), kisses (kiss) ['sess', 4, true, false, 'ss'], // analyses (analysis), ellipses (ellipsis), fungi (fungus), // neuroses (neurosis), theses (thesis), emphases (emphasis), // oases (oasis), crises (crisis), houses (house), bases (base), // atlases (atlas) ['ses', 3, true, true, ['s', 'se', 'sis']], // objectives (objective), alternative (alternatives) ['sevit', 5, true, true, 'tive'], // drives (drive) ['sevird', 6, false, true, 'drive'], // lives (life), wives (wife) ['sevi', 4, false, true, 'ife'], // moves (move) ['sevom', 5, true, true, 'move'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff) ['sev', 3, true, true, ['f', 've', 'ff']], // axes (axis), axes (ax), axes (axe) ['sexa', 4, false, false, ['ax', 'axe', 'axis']], // indexes (index), matrixes (matrix) ['sex', 3, true, false, 'x'], // quizzes (quiz) ['sezz', 4, true, false, 'z'], // bureaus (bureau) ['suae', 4, false, true, 'eau'], // fees (fee), trees (tree), employees (employee) ['see', 3, true, true, 'ee'], // edges (edge) ['segd', 4, true, true, 'dge'], // roses (rose), garages (garage), cassettes (cassette), // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), // shoes (shoe) ['se', 2, true, true, ['', 'e']], // tags (tag) ['s', 1, true, true, ''], // chateaux (chateau) ['xuae', 4, false, true, 'eau'], // people (person) ['elpoep', 6, true, true, 'person'], ]; /** * Map English singular to plural suffixes. * * @see http://english-zone.com/spelling/plurals.html */ private const SINGULAR_MAP = [ // First entry: singular suffix, reversed // Second entry: length of singular suffix // Third entry: Whether the suffix may succeed a vocal // Fourth entry: Whether the suffix may succeed a consonant // Fifth entry: plural suffix, normal // criterion (criteria) ['airetirc', 8, false, false, 'criterion'], // nebulae (nebula) ['aluben', 6, false, false, 'nebulae'], // children (child) ['dlihc', 5, true, true, 'children'], // prices (price) ['eci', 3, false, true, 'ices'], // services (service) ['ecivres', 7, true, true, 'services'], // lives (life), wives (wife) ['efi', 3, false, true, 'ives'], // selfies (selfie) ['eifles', 6, true, true, 'selfies'], // movies (movie) ['eivom', 5, true, true, 'movies'], // lice (louse) ['esuol', 5, false, true, 'lice'], // mice (mouse) ['esuom', 5, false, true, 'mice'], // geese (goose) ['esoo', 4, false, true, 'eese'], // houses (house), bases (base) ['es', 2, true, true, 'ses'], // geese (goose) ['esoog', 5, true, true, 'geese'], // caves (cave) ['ev', 2, true, true, 'ves'], // drives (drive) ['evird', 5, false, true, 'drives'], // objectives (objective), alternative (alternatives) ['evit', 4, true, true, 'tives'], // moves (move) ['evom', 4, true, true, 'moves'], // staves (staff) ['ffats', 5, true, true, 'staves'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) ['ff', 2, true, true, 'ffs'], // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) ['f', 1, true, true, ['fs', 'ves']], // arches (arch) ['hc', 2, true, true, 'ches'], // bushes (bush) ['hs', 2, true, true, 'shes'], // teeth (tooth) ['htoot', 5, true, true, 'teeth'], // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['mu', 2, true, true, 'a'], // men (man), women (woman) ['nam', 3, true, true, 'men'], // people (person) ['nosrep', 6, true, true, ['persons', 'people']], // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['noi', 3, true, true, 'ions'], // coupon (coupons) ['nop', 3, true, true, 'pons'], // seasons (season), treasons (treason), poisons (poison), lessons (lesson) ['nos', 3, true, true, 'sons'], // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) ['no', 2, true, true, 'a'], // echoes (echo) ['ohce', 4, true, true, 'echoes'], // heroes (hero) ['oreh', 4, true, true, 'heroes'], // atlases (atlas) ['salta', 5, true, true, 'atlases'], // irises (iris) ['siri', 4, true, true, 'irises'], // analyses (analysis), ellipses (ellipsis), neuroses (neurosis) // theses (thesis), emphases (emphasis), oases (oasis), // crises (crisis) ['sis', 3, true, true, 'ses'], // accesses (access), addresses (address), kisses (kiss) ['ss', 2, true, false, 'sses'], // syllabi (syllabus) ['suballys', 8, true, true, 'syllabi'], // buses (bus) ['sub', 3, true, true, 'buses'], // circuses (circus) ['suc', 3, true, true, 'cuses'], // conspectuses (conspectus), prospectuses (prospectus) ['sutcep', 6, true, true, 'pectuses'], // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) ['su', 2, true, true, 'i'], // news (news) ['swen', 4, true, true, 'news'], // feet (foot) ['toof', 4, true, true, 'feet'], // chateaux (chateau), bureaus (bureau) ['uae', 3, false, true, ['eaus', 'eaux']], // oxen (ox) ['xo', 2, false, false, 'oxen'], // hoaxes (hoax) ['xaoh', 4, true, false, 'hoaxes'], // indices (index) ['xedni', 5, false, true, ['indicies', 'indexes']], // boxes (box) ['xo', 2, false, true, 'oxes'], // indexes (index), matrixes (matrix) ['x', 1, true, false, ['cies', 'xes']], // appendices (appendix) ['xi', 2, false, true, 'ices'], // babies (baby) ['y', 1, false, true, 'ies'], // quizzes (quiz) ['ziuq', 4, true, false, 'quizzes'], // waltzes (waltz) ['z', 1, true, true, 'zes'], ]; /** * A list of words which should not be inflected, reversed. */ private const UNINFLECTED = [ '', // data 'atad', // deer 'reed', // feedback 'kcabdeef', // fish 'hsif', // info 'ofni', // moose 'esoom', // series 'seires', // sheep 'peehs', // species 'seiceps', ]; /** * {@inheritdoc} */ public function singularize(string $plural): array { $pluralRev = strrev($plural); $lowerPluralRev = strtolower($pluralRev); $pluralLength = \strlen($lowerPluralRev); // Check if the word is one which is not inflected, return early if so if (\in_array($lowerPluralRev, self::UNINFLECTED, true)) { return [$plural]; } // The outer loop iterates over the entries of the plural table // The inner loop $j iterates over the characters of the plural suffix // in the plural table to compare them with the characters of the actual // given plural suffix foreach (self::PLURAL_MAP as $map) { $suffix = $map[0]; $suffixLength = $map[1]; $j = 0; // Compare characters in the plural table and of the suffix of the // given plural one by one while ($suffix[$j] === $lowerPluralRev[$j]) { // Let $j point to the next character ++$j; // Successfully compared the last character // Add an entry with the singular suffix to the singular array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $pluralLength) { $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); if (!$map[2] && $nextIsVocal) { // suffix may not succeed a vocal but next char is one break; } if (!$map[3] && !$nextIsVocal) { // suffix may not succeed a consonant but next char is one break; } } $newBase = substr($plural, 0, $pluralLength - $suffixLength); $newSuffix = $map[4]; // Check whether the first character in the plural suffix // is uppercased. If yes, uppercase the first character in // the singular suffix too $firstUpper = ctype_upper($pluralRev[$j - 1]); if (\is_array($newSuffix)) { $singulars = []; foreach ($newSuffix as $newSuffixEntry) { $singulars[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); } return $singulars; } return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; } // Suffix is longer than word if ($j === $pluralLength) { break; } } } // Assume that plural and singular is identical return [$plural]; } /** * {@inheritdoc} */ public function pluralize(string $singular): array { $singularRev = strrev($singular); $lowerSingularRev = strtolower($singularRev); $singularLength = \strlen($lowerSingularRev); // Check if the word is one which is not inflected, return early if so if (\in_array($lowerSingularRev, self::UNINFLECTED, true)) { return [$singular]; } // The outer loop iterates over the entries of the singular table // The inner loop $j iterates over the characters of the singular suffix // in the singular table to compare them with the characters of the actual // given singular suffix foreach (self::SINGULAR_MAP as $map) { $suffix = $map[0]; $suffixLength = $map[1]; $j = 0; // Compare characters in the singular table and of the suffix of the // given plural one by one while ($suffix[$j] === $lowerSingularRev[$j]) { // Let $j point to the next character ++$j; // Successfully compared the last character // Add an entry with the plural suffix to the plural array if ($j === $suffixLength) { // Is there any character preceding the suffix in the plural string? if ($j < $singularLength) { $nextIsVocal = false !== strpos('aeiou', $lowerSingularRev[$j]); if (!$map[2] && $nextIsVocal) { // suffix may not succeed a vocal but next char is one break; } if (!$map[3] && !$nextIsVocal) { // suffix may not succeed a consonant but next char is one break; } } $newBase = substr($singular, 0, $singularLength - $suffixLength); $newSuffix = $map[4]; // Check whether the first character in the singular suffix // is uppercased. If yes, uppercase the first character in // the singular suffix too $firstUpper = ctype_upper($singularRev[$j - 1]); if (\is_array($newSuffix)) { $plurals = []; foreach ($newSuffix as $newSuffixEntry) { $plurals[] = $newBase.($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); } return $plurals; } return [$newBase.($firstUpper ? ucfirst($newSuffix) : $newSuffix)]; } // Suffix is longer than word if ($j === $singularLength) { break; } } } // Assume that plural is singular with a trailing `s` return [$singular.'s']; } } string/composer.json000064400000002556150432043210010576 0ustar00{ "name": "symfony/string", "type": "library", "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", "keywords": ["string", "utf8", "utf-8", "grapheme", "i18n", "unicode"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "~1.15" }, "require-dev": { "symfony/error-handler": "^4.4|^5.0|^6.0", "symfony/http-client": "^4.4|^5.0|^6.0", "symfony/translation-contracts": "^1.1|^2", "symfony/var-exporter": "^4.4|^5.0|^6.0" }, "conflict": { "symfony/translation-contracts": ">=3.0" }, "autoload": { "psr-4": { "Symfony\\Component\\String\\": "" }, "files": [ "Resources/functions.php" ], "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } string/UnicodeString.php000064400000031103150432043210011330 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String; use Symfony\Component\String\Exception\ExceptionInterface; use Symfony\Component\String\Exception\InvalidArgumentException; /** * Represents a string of Unicode grapheme clusters encoded as UTF-8. * * A letter followed by combining characters (accents typically) form what Unicode defines * as a grapheme cluster: a character as humans mean it in written texts. This class knows * about the concept and won't split a letter apart from its combining accents. It also * ensures all string comparisons happen on their canonically-composed representation, * ignoring e.g. the order in which accents are listed when a letter has many of them. * * @see https://unicode.org/reports/tr15/ * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ class UnicodeString extends AbstractUnicodeString { public function __construct(string $string = '') { $this->string = normalizer_is_normalized($string) ? $string : normalizer_normalize($string); if (false === $this->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } } public function append(string ...$suffix): AbstractString { $str = clone $this; $str->string = $this->string.(1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix)); normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function chunk(int $length = 1): array { if (1 > $length) { throw new InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $rx = '/('; while (65535 < $length) { $rx .= '\X{65535}'; $length -= 65535; } $rx .= '\X{'.$length.'})/u'; $str = clone $this; $chunks = []; foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function endsWith($suffix): bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; normalizer_is_normalized($suffix, $form) ?: $suffix = normalizer_normalize($suffix, $form); if ('' === $suffix || false === $suffix) { return false; } if ($this->ignoreCase) { return 0 === mb_stripos(grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8'); } return $suffix === grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)); } public function equalsTo($string): bool { if ($string instanceof AbstractString) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; normalizer_is_normalized($string, $form) ?: $string = normalizer_normalize($string, $form); if ('' !== $string && false !== $string && $this->ignoreCase) { return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); } return $string === $this->string; } public function indexOf($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); if ('' === $needle || false === $needle) { return null; } try { $i = $this->ignoreCase ? grapheme_stripos($this->string, $needle, $offset) : grapheme_strpos($this->string, $needle, $offset); } catch (\ValueError $e) { return null; } return false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; normalizer_is_normalized($needle, $form) ?: $needle = normalizer_normalize($needle, $form); if ('' === $needle || false === $needle) { return null; } $string = $this->string; if (0 > $offset) { // workaround https://bugs.php.net/74264 if (0 > $offset += grapheme_strlen($needle)) { $string = grapheme_substr($string, 0, $offset); } $offset = 0; } $i = $this->ignoreCase ? grapheme_strripos($string, $needle, $offset) : grapheme_strrpos($string, $needle, $offset); return false === $i ? null : $i; } public function join(array $strings, string $lastGlue = null): AbstractString { $str = parent::join($strings, $lastGlue); normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); return $str; } public function length(): int { return grapheme_strlen($this->string); } /** * @return static */ public function normalize(int $form = self::NFC): parent { $str = clone $this; if (\in_array($form, [self::NFC, self::NFKC], true)) { normalizer_is_normalized($str->string, $form) ?: $str->string = normalizer_normalize($str->string, $form); } elseif (!\in_array($form, [self::NFD, self::NFKD], true)) { throw new InvalidArgumentException('Unsupported normalization form.'); } elseif (!normalizer_is_normalized($str->string, $form)) { $str->string = normalizer_normalize($str->string, $form); $str->ignoreCase = null; } return $str; } public function prepend(string ...$prefix): AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function replace(string $from, string $to): AbstractString { $str = clone $this; normalizer_is_normalized($from) ?: $from = normalizer_normalize($from); if ('' !== $from && false !== $from) { $tail = $str->string; $result = ''; $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; while ('' !== $tail && false !== $i = $indexOf($tail, $from)) { $slice = grapheme_substr($tail, 0, $i); $result .= $slice.$to; $tail = substr($tail, \strlen($slice) + \strlen($from)); } $str->string = $result.$tail; normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } } return $str; } public function replaceMatches(string $fromRegexp, $to): AbstractString { $str = parent::replaceMatches($fromRegexp, $to); normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); return $str; } public function slice(int $start = 0, int $length = null): AbstractString { $str = clone $this; if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) { $start = 0; } $str->string = (string) grapheme_substr($this->string, $start, $length ?? 2147483647); return $str; } public function splice(string $replacement, int $start = 0, int $length = null): AbstractString { $str = clone $this; if (\PHP_VERSION_ID < 80000 && 0 > $start && grapheme_strlen($this->string) < -$start) { $start = 0; } $start = $start ? \strlen(grapheme_substr($this->string, 0, $start)) : 0; $length = $length ? \strlen(grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length; $str->string = substr_replace($this->string, $replacement, $start, $length ?? 2147483647); normalizer_is_normalized($str->string) ?: $str->string = normalizer_normalize($str->string); if (false === $str->string) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function split(string $delimiter, int $limit = null, int $flags = null): array { if (1 > $limit = $limit ?? 2147483647) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter.'u', $limit, $flags); } normalizer_is_normalized($delimiter) ?: $delimiter = normalizer_normalize($delimiter); if (false === $delimiter) { throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); } $str = clone $this; $tail = $this->string; $chunks = []; $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos'; while (1 < $limit && false !== $i = $indexOf($tail, $delimiter)) { $str->string = grapheme_substr($tail, 0, $i); $chunks[] = clone $str; $tail = substr($tail, \strlen($str->string) + \strlen($delimiter)); --$limit; } $str->string = $tail; $chunks[] = clone $str; return $chunks; } public function startsWith($prefix): bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); } else { $prefix = (string) $prefix; } $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC; normalizer_is_normalized($prefix, $form) ?: $prefix = normalizer_normalize($prefix, $form); if ('' === $prefix || false === $prefix) { return false; } if ($this->ignoreCase) { return 0 === mb_stripos(grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8'); } return $prefix === grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES); } public function __wakeup() { if (!\is_string($this->string)) { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); } public function __clone() { if (null === $this->ignoreCase) { normalizer_is_normalized($this->string) ?: $this->string = normalizer_normalize($this->string); } $this->ignoreCase = false; } } string/Slugger/SluggerInterface.php000064400000001313150432043210013414 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Slugger; use Symfony\Component\String\AbstractUnicodeString; /** * Creates a URL-friendly slug from a given string. * * @author Titouan Galopin */ interface SluggerInterface { /** * Creates a slug for the given string and locale, using appropriate transliteration when needed. */ public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString; } string/Slugger/AsciiSlugger.php000064400000013763150432043210012560 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Slugger; use Symfony\Component\String\AbstractUnicodeString; use Symfony\Component\String\UnicodeString; use Symfony\Contracts\Translation\LocaleAwareInterface; if (!interface_exists(LocaleAwareInterface::class)) { throw new \LogicException('You cannot use the "Symfony\Component\String\Slugger\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".'); } /** * @author Titouan Galopin */ class AsciiSlugger implements SluggerInterface, LocaleAwareInterface { private const LOCALE_TO_TRANSLITERATOR_ID = [ 'am' => 'Amharic-Latin', 'ar' => 'Arabic-Latin', 'az' => 'Azerbaijani-Latin', 'be' => 'Belarusian-Latin', 'bg' => 'Bulgarian-Latin', 'bn' => 'Bengali-Latin', 'de' => 'de-ASCII', 'el' => 'Greek-Latin', 'fa' => 'Persian-Latin', 'he' => 'Hebrew-Latin', 'hy' => 'Armenian-Latin', 'ka' => 'Georgian-Latin', 'kk' => 'Kazakh-Latin', 'ky' => 'Kirghiz-Latin', 'ko' => 'Korean-Latin', 'mk' => 'Macedonian-Latin', 'mn' => 'Mongolian-Latin', 'or' => 'Oriya-Latin', 'ps' => 'Pashto-Latin', 'ru' => 'Russian-Latin', 'sr' => 'Serbian-Latin', 'sr_Cyrl' => 'Serbian-Latin', 'th' => 'Thai-Latin', 'tk' => 'Turkmen-Latin', 'uk' => 'Ukrainian-Latin', 'uz' => 'Uzbek-Latin', 'zh' => 'Han-Latin', ]; private $defaultLocale; private $symbolsMap = [ 'en' => ['@' => 'at', '&' => 'and'], ]; /** * Cache of transliterators per locale. * * @var \Transliterator[] */ private $transliterators = []; /** * @param array|\Closure|null $symbolsMap */ public function __construct(string $defaultLocale = null, $symbolsMap = null) { if (null !== $symbolsMap && !\is_array($symbolsMap) && !$symbolsMap instanceof \Closure) { throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be array, Closure or null, "%s" given.', __METHOD__, \gettype($symbolsMap))); } $this->defaultLocale = $defaultLocale; $this->symbolsMap = $symbolsMap ?? $this->symbolsMap; } /** * {@inheritdoc} */ public function setLocale($locale) { $this->defaultLocale = $locale; } /** * {@inheritdoc} */ public function getLocale() { return $this->defaultLocale; } /** * {@inheritdoc} */ public function slug(string $string, string $separator = '-', string $locale = null): AbstractUnicodeString { $locale = $locale ?? $this->defaultLocale; $transliterator = []; if ($locale && ('de' === $locale || 0 === strpos($locale, 'de_'))) { // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl) $transliterator = ['de-ASCII']; } elseif (\function_exists('transliterator_transliterate') && $locale) { $transliterator = (array) $this->createTransliterator($locale); } if ($this->symbolsMap instanceof \Closure) { // If the symbols map is passed as a closure, there is no need to fallback to the parent locale // as the closure can just provide substitutions for all locales of interest. $symbolsMap = $this->symbolsMap; array_unshift($transliterator, static function ($s) use ($symbolsMap, $locale) { return $symbolsMap($s, $locale); }); } $unicodeString = (new UnicodeString($string))->ascii($transliterator); if (\is_array($this->symbolsMap)) { $map = null; if (isset($this->symbolsMap[$locale])) { $map = $this->symbolsMap[$locale]; } else { $parent = self::getParentLocale($locale); if ($parent && isset($this->symbolsMap[$parent])) { $map = $this->symbolsMap[$parent]; } } if ($map) { foreach ($map as $char => $replace) { $unicodeString = $unicodeString->replace($char, ' '.$replace.' '); } } } return $unicodeString ->replaceMatches('/[^A-Za-z0-9]++/', $separator) ->trim($separator) ; } private function createTransliterator(string $locale): ?\Transliterator { if (\array_key_exists($locale, $this->transliterators)) { return $this->transliterators[$locale]; } // Exact locale supported, cache and return if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) { return $this->transliterators[$locale] = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); } // Locale not supported and no parent, fallback to any-latin if (!$parent = self::getParentLocale($locale)) { return $this->transliterators[$locale] = null; } // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) { $transliterator = \Transliterator::create($id.'/BGN') ?? \Transliterator::create($id); } return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null; } private static function getParentLocale(?string $locale): ?string { if (!$locale) { return null; } if (false === $str = strrchr($locale, '_')) { // no parent locale return null; } return substr($locale, 0, -\strlen($str)); } } string/LICENSE000064400000002051150432043210007047 0ustar00Copyright (c) 2019-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. string/Exception/RuntimeException.php000064400000000560150432043210014016 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Exception; class RuntimeException extends \RuntimeException implements ExceptionInterface { } string/Exception/ExceptionInterface.php000064400000000521150432043210014270 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Exception; interface ExceptionInterface extends \Throwable { } string/Exception/InvalidArgumentException.php000064400000000600150432043210015457 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String\Exception; class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } string/CodePointString.php000064400000017573150432043210011645 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\String; use Symfony\Component\String\Exception\ExceptionInterface; use Symfony\Component\String\Exception\InvalidArgumentException; /** * Represents a string of Unicode code points encoded as UTF-8. * * @author Nicolas Grekas * @author Hugo Hamon * * @throws ExceptionInterface */ class CodePointString extends AbstractUnicodeString { public function __construct(string $string = '') { if ('' !== $string && !preg_match('//u', $string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $this->string = $string; } public function append(string ...$suffix): AbstractString { $str = clone $this; $str->string .= 1 >= \count($suffix) ? ($suffix[0] ?? '') : implode('', $suffix); if (!preg_match('//u', $str->string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function chunk(int $length = 1): array { if (1 > $length) { throw new InvalidArgumentException('The chunk length must be greater than zero.'); } if ('' === $this->string) { return []; } $rx = '/('; while (65535 < $length) { $rx .= '.{65535}'; $length -= 65535; } $rx .= '.{'.$length.'})/us'; $str = clone $this; $chunks = []; foreach (preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) { $str->string = $chunk; $chunks[] = clone $str; } return $chunks; } public function codePointsAt(int $offset): array { $str = $offset ? $this->slice($offset, 1) : $this; return '' === $str->string ? [] : [mb_ord($str->string, 'UTF-8')]; } public function endsWith($suffix): bool { if ($suffix instanceof AbstractString) { $suffix = $suffix->string; } elseif (\is_array($suffix) || $suffix instanceof \Traversable) { return parent::endsWith($suffix); } else { $suffix = (string) $suffix; } if ('' === $suffix || !preg_match('//u', $suffix)) { return false; } if ($this->ignoreCase) { return preg_match('{'.preg_quote($suffix).'$}iuD', $this->string); } return \strlen($this->string) >= \strlen($suffix) && 0 === substr_compare($this->string, $suffix, -\strlen($suffix)); } public function equalsTo($string): bool { if ($string instanceof AbstractString) { $string = $string->string; } elseif (\is_array($string) || $string instanceof \Traversable) { return parent::equalsTo($string); } else { $string = (string) $string; } if ('' !== $string && $this->ignoreCase) { return \strlen($string) === \strlen($this->string) && 0 === mb_stripos($this->string, $string, 0, 'UTF-8'); } return $string === $this->string; } public function indexOf($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOf($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? mb_stripos($this->string, $needle, $offset, 'UTF-8') : mb_strpos($this->string, $needle, $offset, 'UTF-8'); return false === $i ? null : $i; } public function indexOfLast($needle, int $offset = 0): ?int { if ($needle instanceof AbstractString) { $needle = $needle->string; } elseif (\is_array($needle) || $needle instanceof \Traversable) { return parent::indexOfLast($needle, $offset); } else { $needle = (string) $needle; } if ('' === $needle) { return null; } $i = $this->ignoreCase ? mb_strripos($this->string, $needle, $offset, 'UTF-8') : mb_strrpos($this->string, $needle, $offset, 'UTF-8'); return false === $i ? null : $i; } public function length(): int { return mb_strlen($this->string, 'UTF-8'); } public function prepend(string ...$prefix): AbstractString { $str = clone $this; $str->string = (1 >= \count($prefix) ? ($prefix[0] ?? '') : implode('', $prefix)).$this->string; if (!preg_match('//u', $str->string)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } return $str; } public function replace(string $from, string $to): AbstractString { $str = clone $this; if ('' === $from || !preg_match('//u', $from)) { return $str; } if ('' !== $to && !preg_match('//u', $to)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } if ($this->ignoreCase) { $str->string = implode($to, preg_split('{'.preg_quote($from).'}iuD', $this->string)); } else { $str->string = str_replace($from, $to, $this->string); } return $str; } public function slice(int $start = 0, int $length = null): AbstractString { $str = clone $this; $str->string = mb_substr($this->string, $start, $length, 'UTF-8'); return $str; } public function splice(string $replacement, int $start = 0, int $length = null): AbstractString { if (!preg_match('//u', $replacement)) { throw new InvalidArgumentException('Invalid UTF-8 string.'); } $str = clone $this; $start = $start ? \strlen(mb_substr($this->string, 0, $start, 'UTF-8')) : 0; $length = $length ? \strlen(mb_substr($this->string, $start, $length, 'UTF-8')) : $length; $str->string = substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX); return $str; } public function split(string $delimiter, int $limit = null, int $flags = null): array { if (1 > $limit = $limit ?? \PHP_INT_MAX) { throw new InvalidArgumentException('Split limit must be a positive integer.'); } if ('' === $delimiter) { throw new InvalidArgumentException('Split delimiter is empty.'); } if (null !== $flags) { return parent::split($delimiter.'u', $limit, $flags); } if (!preg_match('//u', $delimiter)) { throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.'); } $str = clone $this; $chunks = $this->ignoreCase ? preg_split('{'.preg_quote($delimiter).'}iuD', $this->string, $limit) : explode($delimiter, $this->string, $limit); foreach ($chunks as &$chunk) { $str->string = $chunk; $chunk = clone $str; } return $chunks; } public function startsWith($prefix): bool { if ($prefix instanceof AbstractString) { $prefix = $prefix->string; } elseif (\is_array($prefix) || $prefix instanceof \Traversable) { return parent::startsWith($prefix); } else { $prefix = (string) $prefix; } if ('' === $prefix || !preg_match('//u', $prefix)) { return false; } if ($this->ignoreCase) { return 0 === mb_stripos($this->string, $prefix, 0, 'UTF-8'); } return 0 === strncmp($this->string, $prefix, \strlen($prefix)); } } css-selector/README.md000064400000001260150432043210010422 0ustar00CssSelector Component ===================== The CssSelector component converts CSS selectors to XPath expressions. Resources --------- * [Documentation](https://symfony.com/doc/current/components/css_selector.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) Credits ------- This component is a port of the Python cssselect library [v0.7.1](https://github.com/SimonSapin/cssselect/releases/tag/v0.7.1), which is distributed under the BSD license. css-selector/CHANGELOG.md000064400000000372150432043210010757 0ustar00CHANGELOG ========= 4.4.0 ----- * Added support for `*:only-of-type` 2.8.0 ----- * Added the `CssSelectorConverter` class as a non-static API for the component. * Deprecated the `CssSelector` static API of the component. 2.1.0 ----- * none css-selector/CssSelectorConverter.php000064400000004151150432043210013777 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector; use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser; use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser; use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser; use Symfony\Component\CssSelector\Parser\Shortcut\HashParser; use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension; use Symfony\Component\CssSelector\XPath\Translator; /** * CssSelectorConverter is the main entry point of the component and can convert CSS * selectors to XPath expressions. * * @author Christophe Coevoet */ class CssSelectorConverter { private $translator; private $cache; private static $xmlCache = []; private static $htmlCache = []; /** * @param bool $html Whether HTML support should be enabled. Disable it for XML documents */ public function __construct(bool $html = true) { $this->translator = new Translator(); if ($html) { $this->translator->registerExtension(new HtmlExtension($this->translator)); $this->cache = &self::$htmlCache; } else { $this->cache = &self::$xmlCache; } $this->translator ->registerParserShortcut(new EmptyStringParser()) ->registerParserShortcut(new ElementParser()) ->registerParserShortcut(new ClassParser()) ->registerParserShortcut(new HashParser()) ; } /** * Translates a CSS expression to its XPath equivalent. * * Optionally, a prefix can be added to the resulting XPath * expression with the $prefix parameter. * * @return string */ public function toXPath(string $cssExpr, string $prefix = 'descendant-or-self::') { return $this->cache[$prefix][$cssExpr] ?? $this->cache[$prefix][$cssExpr] = $this->translator->cssToXPath($cssExpr, $prefix); } } css-selector/Parser/Shortcut/ElementParser.php000064400000002554150432043210015500 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector element parser shortcut. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class ElementParser implements ParserInterface { /** * {@inheritdoc} */ public function parse(string $source): array { // Matches an optional namespace, required element or `*` // $source = 'testns|testel'; // $matches = array (size=3) // 0 => string 'testns|testel' (length=13) // 1 => string 'testns' (length=6) // 2 => string 'testel' (length=6) if (preg_match('/^(?:([a-z]++)\|)?([\w-]++|\*)$/i', trim($source), $matches)) { return [new SelectorNode(new ElementNode($matches[1] ?: null, $matches[2]))]; } return []; } } css-selector/Parser/Shortcut/HashParser.php000064400000003064150432043210014767 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\HashNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector hash parser shortcut. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class HashParser implements ParserInterface { /** * {@inheritdoc} */ public function parse(string $source): array { // Matches an optional namespace, optional element, and required id // $source = 'test|input#ab6bd_field'; // $matches = array (size=4) // 0 => string 'test|input#ab6bd_field' (length=22) // 1 => string 'test' (length=4) // 2 => string 'input' (length=5) // 3 => string 'ab6bd_field' (length=11) if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+#([\w-]++)$/i', trim($source), $matches)) { return [ new SelectorNode(new HashNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), ]; } return []; } } css-selector/Parser/Shortcut/ClassParser.php000064400000003074150432043210015152 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ClassNode; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector class parser shortcut. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class ClassParser implements ParserInterface { /** * {@inheritdoc} */ public function parse(string $source): array { // Matches an optional namespace, optional element, and required class // $source = 'test|input.ab6bd_field'; // $matches = array (size=4) // 0 => string 'test|input.ab6bd_field' (length=22) // 1 => string 'test' (length=4) // 2 => string 'input' (length=5) // 3 => string 'ab6bd_field' (length=11) if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+\.([\w-]++)$/i', trim($source), $matches)) { return [ new SelectorNode(new ClassNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), ]; } return []; } } css-selector/Parser/Shortcut/EmptyStringParser.php000064400000002316150432043210016370 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Shortcut; use Symfony\Component\CssSelector\Node\ElementNode; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * CSS selector class parser shortcut. * * This shortcut ensure compatibility with previous version. * - The parser fails to parse an empty string. * - In the previous version, an empty string matches each tags. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class EmptyStringParser implements ParserInterface { /** * {@inheritdoc} */ public function parse(string $source): array { // Matches an empty string if ('' == $source) { return [new SelectorNode(new ElementNode(null, '*'))]; } return []; } } css-selector/Parser/TokenStream.php000064400000006567150432043210013363 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Exception\InternalErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; /** * CSS selector token stream. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class TokenStream { /** * @var Token[] */ private $tokens = []; /** * @var Token[] */ private $used = []; /** * @var int */ private $cursor = 0; /** * @var Token|null */ private $peeked; /** * @var bool */ private $peeking = false; /** * Pushes a token. * * @return $this */ public function push(Token $token): self { $this->tokens[] = $token; return $this; } /** * Freezes stream. * * @return $this */ public function freeze(): self { return $this; } /** * Returns next token. * * @throws InternalErrorException If there is no more token */ public function getNext(): Token { if ($this->peeking) { $this->peeking = false; $this->used[] = $this->peeked; return $this->peeked; } if (!isset($this->tokens[$this->cursor])) { throw new InternalErrorException('Unexpected token stream end.'); } return $this->tokens[$this->cursor++]; } /** * Returns peeked token. */ public function getPeek(): Token { if (!$this->peeking) { $this->peeked = $this->getNext(); $this->peeking = true; } return $this->peeked; } /** * Returns used tokens. * * @return Token[] */ public function getUsed(): array { return $this->used; } /** * Returns next identifier token. * * @return string * * @throws SyntaxErrorException If next token is not an identifier */ public function getNextIdentifier(): string { $next = $this->getNext(); if (!$next->isIdentifier()) { throw SyntaxErrorException::unexpectedToken('identifier', $next); } return $next->getValue(); } /** * Returns next identifier or null if star delimiter token is found. * * @return string|null * * @throws SyntaxErrorException If next token is not an identifier or a star delimiter */ public function getNextIdentifierOrStar(): ?string { $next = $this->getNext(); if ($next->isIdentifier()) { return $next->getValue(); } if ($next->isDelimiter(['*'])) { return null; } throw SyntaxErrorException::unexpectedToken('identifier or "*"', $next); } /** * Skips next whitespace if any. */ public function skipWhitespace() { $peek = $this->getPeek(); if ($peek->isWhitespace()) { $this->getNext(); } } } css-selector/Parser/Reader.php000064400000003532150432043210012316 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; /** * CSS selector reader. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class Reader { private $source; private $length; private $position = 0; public function __construct(string $source) { $this->source = $source; $this->length = \strlen($source); } public function isEOF(): bool { return $this->position >= $this->length; } public function getPosition(): int { return $this->position; } public function getRemainingLength(): int { return $this->length - $this->position; } public function getSubstring(int $length, int $offset = 0): string { return substr($this->source, $this->position + $offset, $length); } public function getOffset(string $string) { $position = strpos($this->source, $string, $this->position); return false === $position ? false : $position - $this->position; } /** * @return array|false */ public function findPattern(string $pattern) { $source = substr($this->source, $this->position); if (preg_match($pattern, $source, $matches)) { return $matches; } return false; } public function moveForward(int $length) { $this->position += $length; } public function moveToEnd() { $this->position = $this->length; } } css-selector/Parser/ParserInterface.php000064400000001451150432043210014167 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Node\SelectorNode; /** * CSS selector parser interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ interface ParserInterface { /** * Parses given selector source into an array of tokens. * * @return SelectorNode[] */ public function parse(string $source): array; } css-selector/Parser/Token.php000064400000004714150432043210012177 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; /** * CSS selector token. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class Token { public const TYPE_FILE_END = 'eof'; public const TYPE_DELIMITER = 'delimiter'; public const TYPE_WHITESPACE = 'whitespace'; public const TYPE_IDENTIFIER = 'identifier'; public const TYPE_HASH = 'hash'; public const TYPE_NUMBER = 'number'; public const TYPE_STRING = 'string'; private $type; private $value; private $position; public function __construct(?string $type, ?string $value, ?int $position) { $this->type = $type; $this->value = $value; $this->position = $position; } public function getType(): ?int { return $this->type; } public function getValue(): ?string { return $this->value; } public function getPosition(): ?int { return $this->position; } public function isFileEnd(): bool { return self::TYPE_FILE_END === $this->type; } public function isDelimiter(array $values = []): bool { if (self::TYPE_DELIMITER !== $this->type) { return false; } if (empty($values)) { return true; } return \in_array($this->value, $values); } public function isWhitespace(): bool { return self::TYPE_WHITESPACE === $this->type; } public function isIdentifier(): bool { return self::TYPE_IDENTIFIER === $this->type; } public function isHash(): bool { return self::TYPE_HASH === $this->type; } public function isNumber(): bool { return self::TYPE_NUMBER === $this->type; } public function isString(): bool { return self::TYPE_STRING === $this->type; } public function __toString(): string { if ($this->value) { return sprintf('<%s "%s" at %s>', $this->type, $this->value, $this->position); } return sprintf('<%s at %s>', $this->type, $this->position); } } css-selector/Parser/Parser.php000064400000026542150432043210012356 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\Parser\Tokenizer\Tokenizer; /** * CSS selector parser. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class Parser implements ParserInterface { private $tokenizer; public function __construct(Tokenizer $tokenizer = null) { $this->tokenizer = $tokenizer ?? new Tokenizer(); } /** * {@inheritdoc} */ public function parse(string $source): array { $reader = new Reader($source); $stream = $this->tokenizer->tokenize($reader); return $this->parseSelectorList($stream); } /** * Parses the arguments for ":nth-child()" and friends. * * @param Token[] $tokens * * @throws SyntaxErrorException */ public static function parseSeries(array $tokens): array { foreach ($tokens as $token) { if ($token->isString()) { throw SyntaxErrorException::stringAsFunctionArgument(); } } $joined = trim(implode('', array_map(function (Token $token) { return $token->getValue(); }, $tokens))); $int = function ($string) { if (!is_numeric($string)) { throw SyntaxErrorException::stringAsFunctionArgument(); } return (int) $string; }; switch (true) { case 'odd' === $joined: return [2, 1]; case 'even' === $joined: return [2, 0]; case 'n' === $joined: return [1, 0]; case !str_contains($joined, 'n'): return [0, $int($joined)]; } $split = explode('n', $joined); $first = $split[0] ?? null; return [ $first ? ('-' === $first || '+' === $first ? $int($first.'1') : $int($first)) : 1, isset($split[1]) && $split[1] ? $int($split[1]) : 0, ]; } private function parseSelectorList(TokenStream $stream): array { $stream->skipWhitespace(); $selectors = []; while (true) { $selectors[] = $this->parserSelectorNode($stream); if ($stream->getPeek()->isDelimiter([','])) { $stream->getNext(); $stream->skipWhitespace(); } else { break; } } return $selectors; } private function parserSelectorNode(TokenStream $stream): Node\SelectorNode { [$result, $pseudoElement] = $this->parseSimpleSelector($stream); while (true) { $stream->skipWhitespace(); $peek = $stream->getPeek(); if ($peek->isFileEnd() || $peek->isDelimiter([','])) { break; } if (null !== $pseudoElement) { throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); } if ($peek->isDelimiter(['+', '>', '~'])) { $combinator = $stream->getNext()->getValue(); $stream->skipWhitespace(); } else { $combinator = ' '; } [$nextSelector, $pseudoElement] = $this->parseSimpleSelector($stream); $result = new Node\CombinedSelectorNode($result, $combinator, $nextSelector); } return new Node\SelectorNode($result, $pseudoElement); } /** * Parses next simple node (hash, class, pseudo, negation). * * @throws SyntaxErrorException */ private function parseSimpleSelector(TokenStream $stream, bool $insideNegation = false): array { $stream->skipWhitespace(); $selectorStart = \count($stream->getUsed()); $result = $this->parseElementNode($stream); $pseudoElement = null; while (true) { $peek = $stream->getPeek(); if ($peek->isWhitespace() || $peek->isFileEnd() || $peek->isDelimiter([',', '+', '>', '~']) || ($insideNegation && $peek->isDelimiter([')'])) ) { break; } if (null !== $pseudoElement) { throw SyntaxErrorException::pseudoElementFound($pseudoElement, 'not at the end of a selector'); } if ($peek->isHash()) { $result = new Node\HashNode($result, $stream->getNext()->getValue()); } elseif ($peek->isDelimiter(['.'])) { $stream->getNext(); $result = new Node\ClassNode($result, $stream->getNextIdentifier()); } elseif ($peek->isDelimiter(['['])) { $stream->getNext(); $result = $this->parseAttributeNode($result, $stream); } elseif ($peek->isDelimiter([':'])) { $stream->getNext(); if ($stream->getPeek()->isDelimiter([':'])) { $stream->getNext(); $pseudoElement = $stream->getNextIdentifier(); continue; } $identifier = $stream->getNextIdentifier(); if (\in_array(strtolower($identifier), ['first-line', 'first-letter', 'before', 'after'])) { // Special case: CSS 2.1 pseudo-elements can have a single ':'. // Any new pseudo-element must have two. $pseudoElement = $identifier; continue; } if (!$stream->getPeek()->isDelimiter(['('])) { $result = new Node\PseudoNode($result, $identifier); continue; } $stream->getNext(); $stream->skipWhitespace(); if ('not' === strtolower($identifier)) { if ($insideNegation) { throw SyntaxErrorException::nestedNot(); } [$argument, $argumentPseudoElement] = $this->parseSimpleSelector($stream, true); $next = $stream->getNext(); if (null !== $argumentPseudoElement) { throw SyntaxErrorException::pseudoElementFound($argumentPseudoElement, 'inside ::not()'); } if (!$next->isDelimiter([')'])) { throw SyntaxErrorException::unexpectedToken('")"', $next); } $result = new Node\NegationNode($result, $argument); } else { $arguments = []; $next = null; while (true) { $stream->skipWhitespace(); $next = $stream->getNext(); if ($next->isIdentifier() || $next->isString() || $next->isNumber() || $next->isDelimiter(['+', '-']) ) { $arguments[] = $next; } elseif ($next->isDelimiter([')'])) { break; } else { throw SyntaxErrorException::unexpectedToken('an argument', $next); } } if (empty($arguments)) { throw SyntaxErrorException::unexpectedToken('at least one argument', $next); } $result = new Node\FunctionNode($result, $identifier, $arguments); } } else { throw SyntaxErrorException::unexpectedToken('selector', $peek); } } if (\count($stream->getUsed()) === $selectorStart) { throw SyntaxErrorException::unexpectedToken('selector', $stream->getPeek()); } return [$result, $pseudoElement]; } private function parseElementNode(TokenStream $stream): Node\ElementNode { $peek = $stream->getPeek(); if ($peek->isIdentifier() || $peek->isDelimiter(['*'])) { if ($peek->isIdentifier()) { $namespace = $stream->getNext()->getValue(); } else { $stream->getNext(); $namespace = null; } if ($stream->getPeek()->isDelimiter(['|'])) { $stream->getNext(); $element = $stream->getNextIdentifierOrStar(); } else { $element = $namespace; $namespace = null; } } else { $element = $namespace = null; } return new Node\ElementNode($namespace, $element); } private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream): Node\AttributeNode { $stream->skipWhitespace(); $attribute = $stream->getNextIdentifierOrStar(); if (null === $attribute && !$stream->getPeek()->isDelimiter(['|'])) { throw SyntaxErrorException::unexpectedToken('"|"', $stream->getPeek()); } if ($stream->getPeek()->isDelimiter(['|'])) { $stream->getNext(); if ($stream->getPeek()->isDelimiter(['='])) { $namespace = null; $stream->getNext(); $operator = '|='; } else { $namespace = $attribute; $attribute = $stream->getNextIdentifier(); $operator = null; } } else { $namespace = $operator = null; } if (null === $operator) { $stream->skipWhitespace(); $next = $stream->getNext(); if ($next->isDelimiter([']'])) { return new Node\AttributeNode($selector, $namespace, $attribute, 'exists', null); } elseif ($next->isDelimiter(['='])) { $operator = '='; } elseif ($next->isDelimiter(['^', '$', '*', '~', '|', '!']) && $stream->getPeek()->isDelimiter(['=']) ) { $operator = $next->getValue().'='; $stream->getNext(); } else { throw SyntaxErrorException::unexpectedToken('operator', $next); } } $stream->skipWhitespace(); $value = $stream->getNext(); if ($value->isNumber()) { // if the value is a number, it's casted into a string $value = new Token(Token::TYPE_STRING, (string) $value->getValue(), $value->getPosition()); } if (!($value->isIdentifier() || $value->isString())) { throw SyntaxErrorException::unexpectedToken('string or identifier', $value); } $stream->skipWhitespace(); $next = $stream->getNext(); if (!$next->isDelimiter([']'])) { throw SyntaxErrorException::unexpectedToken('"]"', $next); } return new Node\AttributeNode($selector, $namespace, $attribute, $operator, $value->getValue()); } } css-selector/Parser/Tokenizer/Tokenizer.php000064400000003762150432043210015045 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; use Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector tokenizer. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class Tokenizer { /** * @var Handler\HandlerInterface[] */ private $handlers; public function __construct() { $patterns = new TokenizerPatterns(); $escaping = new TokenizerEscaping($patterns); $this->handlers = [ new Handler\WhitespaceHandler(), new Handler\IdentifierHandler($patterns, $escaping), new Handler\HashHandler($patterns, $escaping), new Handler\StringHandler($patterns, $escaping), new Handler\NumberHandler($patterns), new Handler\CommentHandler(), ]; } /** * Tokenize selector source code. */ public function tokenize(Reader $reader): TokenStream { $stream = new TokenStream(); while (!$reader->isEOF()) { foreach ($this->handlers as $handler) { if ($handler->handle($reader, $stream)) { continue 2; } } $stream->push(new Token(Token::TYPE_DELIMITER, $reader->getSubstring(1), $reader->getPosition())); $reader->moveForward(1); } return $stream ->push(new Token(Token::TYPE_FILE_END, null, $reader->getPosition())) ->freeze(); } } css-selector/Parser/Tokenizer/TokenizerPatterns.php000064400000005331150432043210016560 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; /** * CSS selector tokenizer patterns builder. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class TokenizerPatterns { private $unicodeEscapePattern; private $simpleEscapePattern; private $newLineEscapePattern; private $escapePattern; private $stringEscapePattern; private $nonAsciiPattern; private $nmCharPattern; private $nmStartPattern; private $identifierPattern; private $hashPattern; private $numberPattern; private $quotedStringPattern; public function __construct() { $this->unicodeEscapePattern = '\\\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?'; $this->simpleEscapePattern = '\\\\(.)'; $this->newLineEscapePattern = '\\\\(?:\n|\r\n|\r|\f)'; $this->escapePattern = $this->unicodeEscapePattern.'|\\\\[^\n\r\f0-9a-f]'; $this->stringEscapePattern = $this->newLineEscapePattern.'|'.$this->escapePattern; $this->nonAsciiPattern = '[^\x00-\x7F]'; $this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->identifierPattern = '-?(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*'; $this->hashPattern = '#((?:'.$this->nmCharPattern.')+)'; $this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)'; $this->quotedStringPattern = '([^\n\r\f%s]|'.$this->stringEscapePattern.')*'; } public function getNewLineEscapePattern(): string { return '~^'.$this->newLineEscapePattern.'~'; } public function getSimpleEscapePattern(): string { return '~^'.$this->simpleEscapePattern.'~'; } public function getUnicodeEscapePattern(): string { return '~^'.$this->unicodeEscapePattern.'~i'; } public function getIdentifierPattern(): string { return '~^'.$this->identifierPattern.'~i'; } public function getHashPattern(): string { return '~^'.$this->hashPattern.'~i'; } public function getNumberPattern(): string { return '~^'.$this->numberPattern.'~'; } public function getQuotedStringPattern(string $quote): string { return '~^'.sprintf($this->quotedStringPattern, $quote).'~i'; } } css-selector/Parser/Tokenizer/TokenizerEscaping.php000064400000003360150432043210016511 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Tokenizer; /** * CSS selector tokenizer escaping applier. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class TokenizerEscaping { private $patterns; public function __construct(TokenizerPatterns $patterns) { $this->patterns = $patterns; } public function escapeUnicode(string $value): string { $value = $this->replaceUnicodeSequences($value); return preg_replace($this->patterns->getSimpleEscapePattern(), '$1', $value); } public function escapeUnicodeAndNewLine(string $value): string { $value = preg_replace($this->patterns->getNewLineEscapePattern(), '', $value); return $this->escapeUnicode($value); } private function replaceUnicodeSequences(string $value): string { return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function ($match) { $c = hexdec($match[1]); if (0x80 > $c %= 0x200000) { return \chr($c); } if (0x800 > $c) { return \chr(0xC0 | $c >> 6).\chr(0x80 | $c & 0x3F); } if (0x10000 > $c) { return \chr(0xE0 | $c >> 12).\chr(0x80 | $c >> 6 & 0x3F).\chr(0x80 | $c & 0x3F); } return ''; }, $value); } } css-selector/Parser/Handler/HandlerInterface.php000064400000001410150432043210015660 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector handler interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ interface HandlerInterface { public function handle(Reader $reader, TokenStream $stream): bool; } css-selector/Parser/Handler/IdentifierHandler.php000064400000003126150432043210016050 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector comment handler. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class IdentifierHandler implements HandlerInterface { private $patterns; private $escaping; public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern($this->patterns->getIdentifierPattern()); if (!$match) { return false; } $value = $this->escaping->escapeUnicode($match[0]); $stream->push(new Token(Token::TYPE_IDENTIFIER, $value, $reader->getPosition())); $reader->moveForward(\strlen($match[0])); return true; } } css-selector/Parser/Handler/StringHandler.php000064400000004607150432043210015241 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Exception\InternalErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector comment handler. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class StringHandler implements HandlerInterface { private $patterns; private $escaping; public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream): bool { $quote = $reader->getSubstring(1); if (!\in_array($quote, ["'", '"'])) { return false; } $reader->moveForward(1); $match = $reader->findPattern($this->patterns->getQuotedStringPattern($quote)); if (!$match) { throw new InternalErrorException(sprintf('Should have found at least an empty match at %d.', $reader->getPosition())); } // check unclosed strings if (\strlen($match[0]) === $reader->getRemainingLength()) { throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); } // check quotes pairs validity if ($quote !== $reader->getSubstring(1, \strlen($match[0]))) { throw SyntaxErrorException::unclosedString($reader->getPosition() - 1); } $string = $this->escaping->escapeUnicodeAndNewLine($match[0]); $stream->push(new Token(Token::TYPE_STRING, $string, $reader->getPosition())); $reader->moveForward(\strlen($match[0]) + 1); return true; } } css-selector/Parser/Handler/WhitespaceHandler.php000064400000002247150432043210016065 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector whitespace handler. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class WhitespaceHandler implements HandlerInterface { /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern('~^[ \t\r\n\f]+~'); if (false === $match) { return false; } $stream->push(new Token(Token::TYPE_WHITESPACE, $match[0], $reader->getPosition())); $reader->moveForward(\strlen($match[0])); return true; } } css-selector/Parser/Handler/NumberHandler.php000064400000002562150432043210015221 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector comment handler. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class NumberHandler implements HandlerInterface { private $patterns; public function __construct(TokenizerPatterns $patterns) { $this->patterns = $patterns; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern($this->patterns->getNumberPattern()); if (!$match) { return false; } $stream->push(new Token(Token::TYPE_NUMBER, $match[0], $reader->getPosition())); $reader->moveForward(\strlen($match[0])); return true; } } css-selector/Parser/Handler/CommentHandler.php000064400000002162150432043210015367 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector comment handler. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class CommentHandler implements HandlerInterface { /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream): bool { if ('/*' !== $reader->getSubstring(2)) { return false; } $offset = $reader->getOffset('*/'); if (false === $offset) { $reader->moveToEnd(); } else { $reader->moveForward($offset + 2); } return true; } } css-selector/Parser/Handler/HashHandler.php000064400000003104150432043210014645 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Parser\Handler; use Symfony\Component\CssSelector\Parser\Reader; use Symfony\Component\CssSelector\Parser\Token; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerEscaping; use Symfony\Component\CssSelector\Parser\Tokenizer\TokenizerPatterns; use Symfony\Component\CssSelector\Parser\TokenStream; /** * CSS selector comment handler. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class HashHandler implements HandlerInterface { private $patterns; private $escaping; public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $escaping) { $this->patterns = $patterns; $this->escaping = $escaping; } /** * {@inheritdoc} */ public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern($this->patterns->getHashPattern()); if (!$match) { return false; } $value = $this->escaping->escapeUnicode($match[1]); $stream->push(new Token(Token::TYPE_HASH, $value, $reader->getPosition())); $reader->moveForward(\strlen($match[0])); return true; } } css-selector/composer.json000064400000001530150432043210011665 0ustar00{ "name": "symfony/css-selector", "type": "library", "description": "Converts CSS selectors to XPath expressions", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Jean-François Simon", "email": "jeanfrancois.simon@sensiolabs.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "autoload": { "psr-4": { "Symfony\\Component\\CssSelector\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } css-selector/Node/SelectorNode.php000064400000002651150432043210013134 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "(::|:)" node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class SelectorNode extends AbstractNode { private $tree; private $pseudoElement; public function __construct(NodeInterface $tree, string $pseudoElement = null) { $this->tree = $tree; $this->pseudoElement = $pseudoElement ? strtolower($pseudoElement) : null; } public function getTree(): NodeInterface { return $this->tree; } public function getPseudoElement(): ?string { return $this->pseudoElement; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->tree->getSpecificity()->plus(new Specificity(0, 0, $this->pseudoElement ? 1 : 0)); } public function __toString(): string { return sprintf('%s[%s%s]', $this->getNodeName(), $this->tree, $this->pseudoElement ? '::'.$this->pseudoElement : ''); } } css-selector/Node/ClassNode.php000064400000002422150432043210012415 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "." node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class ClassNode extends AbstractNode { private $selector; private $name; public function __construct(NodeInterface $selector, string $name) { $this->selector = $selector; $this->name = $name; } public function getSelector(): NodeInterface { return $this->selector; } public function getName(): string { return $this->name; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } public function __toString(): string { return sprintf('%s[%s.%s]', $this->getNodeName(), $this->selector, $this->name); } } css-selector/Node/PseudoNode.php000064400000002517150432043210012614 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a ":" node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class PseudoNode extends AbstractNode { private $selector; private $identifier; public function __construct(NodeInterface $selector, string $identifier) { $this->selector = $selector; $this->identifier = strtolower($identifier); } public function getSelector(): NodeInterface { return $this->selector; } public function getIdentifier(): string { return $this->identifier; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } public function __toString(): string { return sprintf('%s[%s:%s]', $this->getNodeName(), $this->selector, $this->identifier); } } css-selector/Node/ElementNode.php000064400000002545150432043210012747 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "|" node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class ElementNode extends AbstractNode { private $namespace; private $element; public function __construct(string $namespace = null, string $element = null) { $this->namespace = $namespace; $this->element = $element; } public function getNamespace(): ?string { return $this->namespace; } public function getElement(): ?string { return $this->element; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return new Specificity(0, 0, $this->element ? 1 : 0); } public function __toString(): string { $element = $this->element ?: '*'; return sprintf('%s[%s]', $this->getNodeName(), $this->namespace ? $this->namespace.'|'.$element : $element); } } css-selector/Node/Specificity.php000064400000003414150432043210013017 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a node specificity. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @see http://www.w3.org/TR/selectors/#specificity * * @author Jean-François Simon * * @internal */ class Specificity { public const A_FACTOR = 100; public const B_FACTOR = 10; public const C_FACTOR = 1; private $a; private $b; private $c; public function __construct(int $a, int $b, int $c) { $this->a = $a; $this->b = $b; $this->c = $c; } public function plus(self $specificity): self { return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c); } public function getValue(): int { return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR; } /** * Returns -1 if the object specificity is lower than the argument, * 0 if they are equal, and 1 if the argument is lower. */ public function compareTo(self $specificity): int { if ($this->a !== $specificity->a) { return $this->a > $specificity->a ? 1 : -1; } if ($this->b !== $specificity->b) { return $this->b > $specificity->b ? 1 : -1; } if ($this->c !== $specificity->c) { return $this->c > $specificity->c ? 1 : -1; } return 0; } } css-selector/Node/NodeInterface.php000064400000001313150432043210013246 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Interface for nodes. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ interface NodeInterface { public function getNodeName(): string; public function getSpecificity(): Specificity; public function __toString(): string; } css-selector/Node/NegationNode.php000064400000002560150432043210013117 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a ":not()" node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class NegationNode extends AbstractNode { private $selector; private $subSelector; public function __construct(NodeInterface $selector, NodeInterface $subSelector) { $this->selector = $selector; $this->subSelector = $subSelector; } public function getSelector(): NodeInterface { return $this->selector; } public function getSubSelector(): NodeInterface { return $this->subSelector; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } public function __toString(): string { return sprintf('%s[%s:not(%s)]', $this->getNodeName(), $this->selector, $this->subSelector); } } css-selector/Node/HashNode.php000064400000002401150432043210012230 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "#" node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class HashNode extends AbstractNode { private $selector; private $id; public function __construct(NodeInterface $selector, string $id) { $this->selector = $selector; $this->id = $id; } public function getSelector(): NodeInterface { return $this->selector; } public function getId(): string { return $this->id; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(1, 0, 0)); } public function __toString(): string { return sprintf('%s[%s#%s]', $this->getNodeName(), $this->selector, $this->id); } } css-selector/Node/FunctionNode.php000064400000003445150432043210013143 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\Parser\Token; /** * Represents a ":()" node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class FunctionNode extends AbstractNode { private $selector; private $name; private $arguments; /** * @param Token[] $arguments */ public function __construct(NodeInterface $selector, string $name, array $arguments = []) { $this->selector = $selector; $this->name = strtolower($name); $this->arguments = $arguments; } public function getSelector(): NodeInterface { return $this->selector; } public function getName(): string { return $this->name; } /** * @return Token[] */ public function getArguments(): array { return $this->arguments; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } public function __toString(): string { $arguments = implode(', ', array_map(function (Token $token) { return "'".$token->getValue()."'"; }, $this->arguments)); return sprintf('%s[%s:%s(%s)]', $this->getNodeName(), $this->selector, $this->name, $arguments ? '['.$arguments.']' : ''); } } css-selector/Node/AttributeNode.php000064400000004114150432043210013313 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a "[| ]" node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class AttributeNode extends AbstractNode { private $selector; private $namespace; private $attribute; private $operator; private $value; public function __construct(NodeInterface $selector, ?string $namespace, string $attribute, string $operator, ?string $value) { $this->selector = $selector; $this->namespace = $namespace; $this->attribute = $attribute; $this->operator = $operator; $this->value = $value; } public function getSelector(): NodeInterface { return $this->selector; } public function getNamespace(): ?string { return $this->namespace; } public function getAttribute(): string { return $this->attribute; } public function getOperator(): string { return $this->operator; } public function getValue(): ?string { return $this->value; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } public function __toString(): string { $attribute = $this->namespace ? $this->namespace.'|'.$this->attribute : $this->attribute; return 'exists' === $this->operator ? sprintf('%s[%s[%s]]', $this->getNodeName(), $this->selector, $attribute) : sprintf("%s[%s[%s %s '%s']]", $this->getNodeName(), $this->selector, $attribute, $this->operator, $this->value); } } css-selector/Node/AbstractNode.php000064400000001603150432043210013113 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Abstract base node class. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ abstract class AbstractNode implements NodeInterface { /** * @var string */ private $nodeName; public function getNodeName(): string { if (null === $this->nodeName) { $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', static::class); } return $this->nodeName; } } css-selector/Node/CombinedSelectorNode.php000064400000003163150432043210014574 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Node; /** * Represents a combined node. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class CombinedSelectorNode extends AbstractNode { private $selector; private $combinator; private $subSelector; public function __construct(NodeInterface $selector, string $combinator, NodeInterface $subSelector) { $this->selector = $selector; $this->combinator = $combinator; $this->subSelector = $subSelector; } public function getSelector(): NodeInterface { return $this->selector; } public function getCombinator(): string { return $this->combinator; } public function getSubSelector(): NodeInterface { return $this->subSelector; } /** * {@inheritdoc} */ public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } public function __toString(): string { $combinator = ' ' === $this->combinator ? '' : $this->combinator; return sprintf('%s[%s %s %s]', $this->getNodeName(), $this->selector, $combinator, $this->subSelector); } } css-selector/LICENSE000064400000002051150432043210010147 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. css-selector/Exception/InternalErrorException.php000064400000001177150432043210016266 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class InternalErrorException extends ParseException { } css-selector/Exception/ExpressionErrorException.php000064400000001201150432043210016635 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class ExpressionErrorException extends ParseException { } css-selector/Exception/ExceptionInterface.php000064400000001123150432043210015367 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * Interface for exceptions. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ interface ExceptionInterface extends \Throwable { } css-selector/Exception/SyntaxErrorException.php000064400000003204150432043210015771 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; use Symfony\Component\CssSelector\Parser\Token; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon */ class SyntaxErrorException extends ParseException { /** * @return self */ public static function unexpectedToken(string $expectedValue, Token $foundToken) { return new self(sprintf('Expected %s, but %s found.', $expectedValue, $foundToken)); } /** * @return self */ public static function pseudoElementFound(string $pseudoElement, string $unexpectedLocation) { return new self(sprintf('Unexpected pseudo-element "::%s" found %s.', $pseudoElement, $unexpectedLocation)); } /** * @return self */ public static function unclosedString(int $position) { return new self(sprintf('Unclosed/invalid string at %s.', $position)); } /** * @return self */ public static function nestedNot() { return new self('Got nested ::not().'); } /** * @return self */ public static function stringAsFunctionArgument() { return new self('String not allowed as function argument.'); } } css-selector/Exception/ParseException.php000064400000001176150432043210014551 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\Exception; /** * ParseException is thrown when a CSS selector syntax is not valid. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Fabien Potencier */ class ParseException extends \Exception implements ExceptionInterface { } css-selector/XPath/Extension/FunctionExtension.php000064400000012154150432043210016342 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator function extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class FunctionExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getFunctionTranslators(): array { return [ 'nth-child' => [$this, 'translateNthChild'], 'nth-last-child' => [$this, 'translateNthLastChild'], 'nth-of-type' => [$this, 'translateNthOfType'], 'nth-last-of-type' => [$this, 'translateNthLastOfType'], 'contains' => [$this, 'translateContains'], 'lang' => [$this, 'translateLang'], ]; } /** * @throws ExpressionErrorException */ public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr { try { [$a, $b] = Parser::parseSeries($function->getArguments()); } catch (SyntaxErrorException $e) { throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e); } $xpath->addStarPrefix(); if ($addNameTest) { $xpath->addNameTest(); } if (0 === $a) { return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); } if ($a < 0) { if ($b < 1) { return $xpath->addCondition('false()'); } $sign = '<='; } else { $sign = '>='; } $expr = 'position()'; if ($last) { $expr = 'last() - '.$expr; --$b; } if (0 !== $b) { $expr .= ' - '.$b; } $conditions = [sprintf('%s %s 0', $expr, $sign)]; if (1 !== $a && -1 !== $a) { $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); } return $xpath->addCondition(implode(' and ', $conditions)); // todo: handle an+b, odd, even // an+b means every-a, plus b, e.g., 2n+1 means odd // 0n+b means b // n+0 means a=1, i.e., all elements // an means every a elements, i.e., 2n means even // -n means -1n // -1n+6 means elements 6 and previous } public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function): XPathExpr { return $this->translateNthChild($xpath, $function, true); } public function translateNthOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr { return $this->translateNthChild($xpath, $function, false, false); } /** * @throws ExpressionErrorException */ public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); } return $this->translateNthChild($xpath, $function, true, false); } /** * @throws ExpressionErrorException */ public function translateContains(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'contains(string(.), %s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'lang(%s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * {@inheritdoc} */ public function getName(): string { return 'function'; } } css-selector/XPath/Extension/AbstractExtension.php000064400000002365150432043210016323 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator abstract extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ abstract class AbstractExtension implements ExtensionInterface { /** * {@inheritdoc} */ public function getNodeTranslators(): array { return []; } /** * {@inheritdoc} */ public function getCombinationTranslators(): array { return []; } /** * {@inheritdoc} */ public function getFunctionTranslators(): array { return []; } /** * {@inheritdoc} */ public function getPseudoClassTranslators(): array { return []; } /** * {@inheritdoc} */ public function getAttributeMatchingTranslators(): array { return []; } } css-selector/XPath/Extension/PseudoClassExtension.php000064400000006525150432043210017007 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator pseudo-class extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class PseudoClassExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getPseudoClassTranslators(): array { return [ 'root' => [$this, 'translateRoot'], 'first-child' => [$this, 'translateFirstChild'], 'last-child' => [$this, 'translateLastChild'], 'first-of-type' => [$this, 'translateFirstOfType'], 'last-of-type' => [$this, 'translateLastOfType'], 'only-child' => [$this, 'translateOnlyChild'], 'only-of-type' => [$this, 'translateOnlyOfType'], 'empty' => [$this, 'translateEmpty'], ]; } public function translateRoot(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('not(parent::*)'); } public function translateFirstChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = 1'); } public function translateLastChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = last()'); } /** * @throws ExpressionErrorException */ public function translateFirstOfType(XPathExpr $xpath): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = 1'); } /** * @throws ExpressionErrorException */ public function translateLastOfType(XPathExpr $xpath): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = last()'); } public function translateOnlyChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('last() = 1'); } public function translateOnlyOfType(XPathExpr $xpath): XPathExpr { $element = $xpath->getElement(); return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element)); } public function translateEmpty(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('not(*) and not(string-length())'); } /** * {@inheritdoc} */ public function getName(): string { return 'pseudo-class'; } } css-selector/XPath/Extension/CombinationExtension.php000064400000003625150432043210017022 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator combination extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class CombinationExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getCombinationTranslators(): array { return [ ' ' => [$this, 'translateDescendant'], '>' => [$this, 'translateChild'], '+' => [$this, 'translateDirectAdjacent'], '~' => [$this, 'translateIndirectAdjacent'], ]; } public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/descendant-or-self::*/', $combinedXpath); } public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/', $combinedXpath); } public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath ->join('/following-sibling::', $combinedXpath) ->addNameTest() ->addCondition('position() = 1'); } public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/following-sibling::', $combinedXpath); } /** * {@inheritdoc} */ public function getName(): string { return 'combination'; } } css-selector/XPath/Extension/HtmlExtension.php000064400000013426150432043210015464 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator HTML extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class HtmlExtension extends AbstractExtension { public function __construct(Translator $translator) { $translator ->getExtension('node') ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true) ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true); } /** * {@inheritdoc} */ public function getPseudoClassTranslators(): array { return [ 'checked' => [$this, 'translateChecked'], 'link' => [$this, 'translateLink'], 'disabled' => [$this, 'translateDisabled'], 'enabled' => [$this, 'translateEnabled'], 'selected' => [$this, 'translateSelected'], 'invalid' => [$this, 'translateInvalid'], 'hover' => [$this, 'translateHover'], 'visited' => [$this, 'translateVisited'], ]; } /** * {@inheritdoc} */ public function getFunctionTranslators(): array { return [ 'lang' => [$this, 'translateLang'], ]; } public function translateChecked(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(@checked ' ."and (name(.) = 'input' or name(.) = 'command')" ."and (@type = 'checkbox' or @type = 'radio'))" ); } public function translateLink(XPathExpr $xpath): XPathExpr { return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); } public function translateDisabled(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(' .'@disabled and' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" ." or name(.) = 'option'" .')' .') or (' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" .')' .' and ancestor::fieldset[@disabled]' ); // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." } public function translateEnabled(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(' .'@href and (' ."name(.) = 'a'" ." or name(.) = 'link'" ." or name(.) = 'area'" .')' .') or (' .'(' ."name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" .')' .' and not(@disabled)' .') or (' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'keygen'" .')' .' and not (@disabled or ancestor::fieldset[@disabled])' .') or (' ."name(.) = 'option' and not(" .'@disabled or ancestor::optgroup[@disabled]' .')' .')' ); } /** * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'ancestor-or-self::*[@lang][1][starts-with(concat(' ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" .', %s)]', 'lang', Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') )); } public function translateSelected(XPathExpr $xpath): XPathExpr { return $xpath->addCondition("(@selected and name(.) = 'option')"); } public function translateInvalid(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function translateHover(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function translateVisited(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } /** * {@inheritdoc} */ public function getName(): string { return 'html'; } } css-selector/XPath/Extension/ExtensionInterface.php000064400000003005150432043210016450 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator extension interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ interface ExtensionInterface { /** * Returns node translators. * * These callables will receive the node as first argument and the translator as second argument. * * @return callable[] */ public function getNodeTranslators(): array; /** * Returns combination translators. * * @return callable[] */ public function getCombinationTranslators(): array; /** * Returns function translators. * * @return callable[] */ public function getFunctionTranslators(): array; /** * Returns pseudo-class translators. * * @return callable[] */ public function getPseudoClassTranslators(): array; /** * Returns attribute operation translators. * * @return callable[] */ public function getAttributeMatchingTranslators(): array; /** * Returns extension name. */ public function getName(): string; } css-selector/XPath/Extension/AttributeMatchingExtension.php000064400000007356150432043210020203 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator attribute extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class AttributeMatchingExtension extends AbstractExtension { /** * {@inheritdoc} */ public function getAttributeMatchingTranslators(): array { return [ 'exists' => [$this, 'translateExists'], '=' => [$this, 'translateEquals'], '~=' => [$this, 'translateIncludes'], '|=' => [$this, 'translateDashMatch'], '^=' => [$this, 'translatePrefixMatch'], '$=' => [$this, 'translateSuffixMatch'], '*=' => [$this, 'translateSubstringMatch'], '!=' => [$this, 'translateDifferent'], ]; } public function translateExists(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($attribute); } public function translateEquals(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value))); } public function translateIncludes(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)', $attribute, Translator::getXpathLiteral(' '.$value.' ') ) : '0'); } public function translateDashMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf( '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))', $attribute, Translator::getXpathLiteral($value), Translator::getXpathLiteral($value.'-') )); } public function translatePrefixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and starts-with(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } public function translateSuffixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s', $attribute, \strlen($value) - 1, Translator::getXpathLiteral($value) ) : '0'); } public function translateSubstringMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and contains(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } public function translateDifferent(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf( $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s', $attribute, Translator::getXpathLiteral($value) )); } /** * {@inheritdoc} */ public function getName(): string { return 'attribute-matching'; } } css-selector/XPath/Extension/NodeExtension.php000064400000013373150432043210015446 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator node extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class NodeExtension extends AbstractExtension { public const ELEMENT_NAME_IN_LOWER_CASE = 1; public const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; public const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; private $flags; public function __construct(int $flags = 0) { $this->flags = $flags; } /** * @return $this */ public function setFlag(int $flag, bool $on): self { if ($on && !$this->hasFlag($flag)) { $this->flags += $flag; } if (!$on && $this->hasFlag($flag)) { $this->flags -= $flag; } return $this; } public function hasFlag(int $flag): bool { return (bool) ($this->flags & $flag); } /** * {@inheritdoc} */ public function getNodeTranslators(): array { return [ 'Selector' => [$this, 'translateSelector'], 'CombinedSelector' => [$this, 'translateCombinedSelector'], 'Negation' => [$this, 'translateNegation'], 'Function' => [$this, 'translateFunction'], 'Pseudo' => [$this, 'translatePseudo'], 'Attribute' => [$this, 'translateAttribute'], 'Class' => [$this, 'translateClass'], 'Hash' => [$this, 'translateHash'], 'Element' => [$this, 'translateElement'], ]; } public function translateSelector(Node\SelectorNode $node, Translator $translator): XPathExpr { return $translator->nodeToXPath($node->getTree()); } public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator): XPathExpr { return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); } public function translateNegation(Node\NegationNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); $subXpath = $translator->nodeToXPath($node->getSubSelector()); $subXpath->addNameTest(); if ($subXpath->getCondition()) { return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); } return $xpath->addCondition('0'); } public function translateFunction(Node\FunctionNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addFunction($xpath, $node); } public function translatePseudo(Node\PseudoNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addPseudoClass($xpath, $node->getIdentifier()); } public function translateAttribute(Node\AttributeNode $node, Translator $translator): XPathExpr { $name = $node->getAttribute(); $safe = $this->isSafeName($name); if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { $name = strtolower($name); } if ($node->getNamespace()) { $name = sprintf('%s:%s', $node->getNamespace(), $name); $safe = $safe && $this->isSafeName($node->getNamespace()); } $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); $value = $node->getValue(); $xpath = $translator->nodeToXPath($node->getSelector()); if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { $value = strtolower($value); } return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); } public function translateClass(Node\ClassNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); } public function translateHash(Node\HashNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); } public function translateElement(Node\ElementNode $node): XPathExpr { $element = $node->getElement(); if ($element && $this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { $element = strtolower($element); } if ($element) { $safe = $this->isSafeName($element); } else { $element = '*'; $safe = true; } if ($node->getNamespace()) { $element = sprintf('%s:%s', $node->getNamespace(), $element); $safe = $safe && $this->isSafeName($node->getNamespace()); } $xpath = new XPathExpr('', $element); if (!$safe) { $xpath->addNameTest(); } return $xpath; } /** * {@inheritdoc} */ public function getName(): string { return 'node'; } private function isSafeName(string $name): bool { return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); } } css-selector/XPath/TranslatorInterface.php000064400000001773150432043210014663 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Node\SelectorNode; /** * XPath expression translator interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ interface TranslatorInterface { /** * Translates a CSS selector to an XPath expression. */ public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string; /** * Translates a parsed selector node to an XPath expression. */ public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string; } css-selector/XPath/XPathExpr.php000064400000004670150432043210012573 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; /** * XPath expression translator interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class XPathExpr { private $path; private $element; private $condition; public function __construct(string $path = '', string $element = '*', string $condition = '', bool $starPrefix = false) { $this->path = $path; $this->element = $element; $this->condition = $condition; if ($starPrefix) { $this->addStarPrefix(); } } public function getElement(): string { return $this->element; } /** * @return $this */ public function addCondition(string $condition): self { $this->condition = $this->condition ? sprintf('(%s) and (%s)', $this->condition, $condition) : $condition; return $this; } public function getCondition(): string { return $this->condition; } /** * @return $this */ public function addNameTest(): self { if ('*' !== $this->element) { $this->addCondition('name() = '.Translator::getXpathLiteral($this->element)); $this->element = '*'; } return $this; } /** * @return $this */ public function addStarPrefix(): self { $this->path .= '*/'; return $this; } /** * Joins another XPathExpr with a combiner. * * @return $this */ public function join(string $combiner, self $expr): self { $path = $this->__toString().$combiner; if ('*/' !== $expr->path) { $path .= $expr->path; } $this->path = $path; $this->element = $expr->element; $this->condition = $expr->condition; return $this; } public function __toString(): string { $path = $this->path.$this->element; $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']'; return $path.$condition; } } css-selector/XPath/Translator.php000064400000016237150432043210013043 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Node\NodeInterface; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * XPath expression translator interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon * * @internal */ class Translator implements TranslatorInterface { private $mainParser; /** * @var ParserInterface[] */ private $shortcutParsers = []; /** * @var Extension\ExtensionInterface[] */ private $extensions = []; private $nodeTranslators = []; private $combinationTranslators = []; private $functionTranslators = []; private $pseudoClassTranslators = []; private $attributeMatchingTranslators = []; public function __construct(ParserInterface $parser = null) { $this->mainParser = $parser ?? new Parser(); $this ->registerExtension(new Extension\NodeExtension()) ->registerExtension(new Extension\CombinationExtension()) ->registerExtension(new Extension\FunctionExtension()) ->registerExtension(new Extension\PseudoClassExtension()) ->registerExtension(new Extension\AttributeMatchingExtension()) ; } public static function getXpathLiteral(string $element): string { if (!str_contains($element, "'")) { return "'".$element."'"; } if (!str_contains($element, '"')) { return '"'.$element.'"'; } $string = $element; $parts = []; while (true) { if (false !== $pos = strpos($string, "'")) { $parts[] = sprintf("'%s'", substr($string, 0, $pos)); $parts[] = "\"'\""; $string = substr($string, $pos + 1); } else { $parts[] = "'$string'"; break; } } return sprintf('concat(%s)', implode(', ', $parts)); } /** * {@inheritdoc} */ public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string { $selectors = $this->parseSelectors($cssExpr); /** @var SelectorNode $selector */ foreach ($selectors as $index => $selector) { if (null !== $selector->getPseudoElement()) { throw new ExpressionErrorException('Pseudo-elements are not supported.'); } $selectors[$index] = $this->selectorToXPath($selector, $prefix); } return implode(' | ', $selectors); } /** * {@inheritdoc} */ public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string { return ($prefix ?: '').$this->nodeToXPath($selector); } /** * @return $this */ public function registerExtension(Extension\ExtensionInterface $extension): self { $this->extensions[$extension->getName()] = $extension; $this->nodeTranslators = array_merge($this->nodeTranslators, $extension->getNodeTranslators()); $this->combinationTranslators = array_merge($this->combinationTranslators, $extension->getCombinationTranslators()); $this->functionTranslators = array_merge($this->functionTranslators, $extension->getFunctionTranslators()); $this->pseudoClassTranslators = array_merge($this->pseudoClassTranslators, $extension->getPseudoClassTranslators()); $this->attributeMatchingTranslators = array_merge($this->attributeMatchingTranslators, $extension->getAttributeMatchingTranslators()); return $this; } /** * @throws ExpressionErrorException */ public function getExtension(string $name): Extension\ExtensionInterface { if (!isset($this->extensions[$name])) { throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name)); } return $this->extensions[$name]; } /** * @return $this */ public function registerParserShortcut(ParserInterface $shortcut): self { $this->shortcutParsers[] = $shortcut; return $this; } /** * @throws ExpressionErrorException */ public function nodeToXPath(NodeInterface $node): XPathExpr { if (!isset($this->nodeTranslators[$node->getNodeName()])) { throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName())); } return $this->nodeTranslators[$node->getNodeName()]($node, $this); } /** * @throws ExpressionErrorException */ public function addCombination(string $combiner, NodeInterface $xpath, NodeInterface $combinedXpath): XPathExpr { if (!isset($this->combinationTranslators[$combiner])) { throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner)); } return $this->combinationTranslators[$combiner]($this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath)); } /** * @throws ExpressionErrorException */ public function addFunction(XPathExpr $xpath, FunctionNode $function): XPathExpr { if (!isset($this->functionTranslators[$function->getName()])) { throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName())); } return $this->functionTranslators[$function->getName()]($xpath, $function); } /** * @throws ExpressionErrorException */ public function addPseudoClass(XPathExpr $xpath, string $pseudoClass): XPathExpr { if (!isset($this->pseudoClassTranslators[$pseudoClass])) { throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass)); } return $this->pseudoClassTranslators[$pseudoClass]($xpath); } /** * @throws ExpressionErrorException */ public function addAttributeMatching(XPathExpr $xpath, string $operator, string $attribute, ?string $value): XPathExpr { if (!isset($this->attributeMatchingTranslators[$operator])) { throw new ExpressionErrorException(sprintf('Attribute matcher operator "%s" not supported.', $operator)); } return $this->attributeMatchingTranslators[$operator]($xpath, $attribute, $value); } /** * @return SelectorNode[] */ private function parseSelectors(string $css): array { foreach ($this->shortcutParsers as $shortcut) { $tokens = $shortcut->parse($css); if (!empty($tokens)) { return $tokens; } } return $this->mainParser->parse($css); } } process/ProcessUtils.php000064400000003471150432043210011371 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; /** * ProcessUtils is a bunch of utility methods. * * This class contains static methods only and is not meant to be instantiated. * * @author Martin Hasoň */ class ProcessUtils { /** * This class should not be instantiated. */ private function __construct() { } /** * Validates and normalizes a Process input. * * @param string $caller The name of method call that validates the input * @param mixed $input The input to validate * * @return mixed * * @throws InvalidArgumentException In case the input is not valid */ public static function validateInput(string $caller, $input) { if (null !== $input) { if (\is_resource($input)) { return $input; } if (\is_string($input)) { return $input; } if (is_scalar($input)) { return (string) $input; } if ($input instanceof Process) { return $input->getIterator($input::ITER_SKIP_ERR); } if ($input instanceof \Iterator) { return $input; } if ($input instanceof \Traversable) { return new \IteratorIterator($input); } throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller)); } return $input; } } process/README.md000064400000001663150432043210007501 0ustar00Process Component ================= The Process component executes commands in sub-processes. Sponsor ------- The Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2]. As the creator of Symfony, SensioLabs supports companies using Symfony, with an offering encompassing consultancy, expertise, services, training, and technical assistance to ensure the success of web application development projects. Help Symfony by [sponsoring][3] its development! Resources --------- * [Documentation](https://symfony.com/doc/current/components/process.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) [1]: https://symfony.com/backers [2]: https://sensiolabs.com [3]: https://symfony.com/sponsor process/InputStream.php000064400000004542150432043210011205 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\RuntimeException; /** * Provides a way to continuously write to the input of a Process until the InputStream is closed. * * @author Nicolas Grekas * * @implements \IteratorAggregate */ class InputStream implements \IteratorAggregate { /** @var callable|null */ private $onEmpty = null; private $input = []; private $open = true; /** * Sets a callback that is called when the write buffer becomes empty. */ public function onEmpty(callable $onEmpty = null) { $this->onEmpty = $onEmpty; } /** * Appends an input to the write buffer. * * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar, * stream resource or \Traversable */ public function write($input) { if (null === $input) { return; } if ($this->isClosed()) { throw new RuntimeException(sprintf('"%s" is closed.', static::class)); } $this->input[] = ProcessUtils::validateInput(__METHOD__, $input); } /** * Closes the write buffer. */ public function close() { $this->open = false; } /** * Tells whether the write buffer is closed or not. */ public function isClosed() { return !$this->open; } /** * @return \Traversable */ #[\ReturnTypeWillChange] public function getIterator() { $this->open = true; while ($this->open || $this->input) { if (!$this->input) { yield ''; continue; } $current = array_shift($this->input); if ($current instanceof \Iterator) { yield from $current; } else { yield $current; } if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) { $this->write($onEmpty($this)); } } } } process/Process.php000064400000146117150432043210010355 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Exception\ProcessSignaledException; use Symfony\Component\Process\Exception\ProcessTimedOutException; use Symfony\Component\Process\Exception\RuntimeException; use Symfony\Component\Process\Pipes\PipesInterface; use Symfony\Component\Process\Pipes\UnixPipes; use Symfony\Component\Process\Pipes\WindowsPipes; /** * Process is a thin wrapper around proc_* functions to easily * start independent PHP processes. * * @author Fabien Potencier * @author Romain Neutron * * @implements \IteratorAggregate */ class Process implements \IteratorAggregate { public const ERR = 'err'; public const OUT = 'out'; public const STATUS_READY = 'ready'; public const STATUS_STARTED = 'started'; public const STATUS_TERMINATED = 'terminated'; public const STDIN = 0; public const STDOUT = 1; public const STDERR = 2; // Timeout Precision in seconds. public const TIMEOUT_PRECISION = 0.2; public const ITER_NON_BLOCKING = 1; // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking public const ITER_KEEP_OUTPUT = 2; // By default, outputs are cleared while iterating, use this flag to keep them in memory public const ITER_SKIP_OUT = 4; // Use this flag to skip STDOUT while iterating public const ITER_SKIP_ERR = 8; // Use this flag to skip STDERR while iterating private $callback; private $hasCallback = false; private $commandline; private $cwd; private $env; private $input; private $starttime; private $lastOutputTime; private $timeout; private $idleTimeout; private $exitcode; private $fallbackStatus = []; private $processInformation; private $outputDisabled = false; private $stdout; private $stderr; private $process; private $status = self::STATUS_READY; private $incrementalOutputOffset = 0; private $incrementalErrorOutputOffset = 0; private $tty = false; private $pty; private $options = ['suppress_errors' => true, 'bypass_shell' => true]; private $useFileHandles = false; /** @var PipesInterface */ private $processPipes; private $latestSignal; private static $sigchild; /** * Exit codes translation table. * * User-defined errors must use exit codes in the 64-113 range. */ public static $exitCodes = [ 0 => 'OK', 1 => 'General error', 2 => 'Misuse of shell builtins', 126 => 'Invoked command cannot execute', 127 => 'Command not found', 128 => 'Invalid exit argument', // signals 129 => 'Hangup', 130 => 'Interrupt', 131 => 'Quit and dump core', 132 => 'Illegal instruction', 133 => 'Trace/breakpoint trap', 134 => 'Process aborted', 135 => 'Bus error: "access to undefined portion of memory object"', 136 => 'Floating point exception: "erroneous arithmetic operation"', 137 => 'Kill (terminate immediately)', 138 => 'User-defined 1', 139 => 'Segmentation violation', 140 => 'User-defined 2', 141 => 'Write to pipe with no one reading', 142 => 'Signal raised by alarm', 143 => 'Termination (request to terminate)', // 144 - not defined 145 => 'Child process terminated, stopped (or continued*)', 146 => 'Continue if stopped', 147 => 'Stop executing temporarily', 148 => 'Terminal stop signal', 149 => 'Background process attempting to read from tty ("in")', 150 => 'Background process attempting to write to tty ("out")', 151 => 'Urgent data available on socket', 152 => 'CPU time limit exceeded', 153 => 'File size limit exceeded', 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"', 155 => 'Profiling timer expired', // 156 - not defined 157 => 'Pollable event', // 158 - not defined 159 => 'Bad syscall', ]; /** * @param array $command The command to run and its arguments listed as separate entries * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to use the same environment as the current PHP process * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input * @param int|float|null $timeout The timeout in seconds or null to disable * * @throws LogicException When proc_open is not installed */ public function __construct(array $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { if (!\function_exists('proc_open')) { throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.'); } $this->commandline = $command; $this->cwd = $cwd; // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected // @see : https://bugs.php.net/51800 // @see : https://bugs.php.net/50524 if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) { $this->cwd = getcwd(); } if (null !== $env) { $this->setEnv($env); } $this->setInput($input); $this->setTimeout($timeout); $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR; $this->pty = false; } /** * Creates a Process instance as a command-line to be run in a shell wrapper. * * Command-lines are parsed by the shell of your OS (/bin/sh on Unix-like, cmd.exe on Windows.) * This allows using e.g. pipes or conditional execution. In this mode, signals are sent to the * shell wrapper and not to your commands. * * In order to inject dynamic values into command-lines, we strongly recommend using placeholders. * This will save escaping values, which is not portable nor secure anyway: * * $process = Process::fromShellCommandline('my_command "$MY_VAR"'); * $process->run(null, ['MY_VAR' => $theValue]); * * @param string $command The command line to pass to the shell of the OS * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to use the same environment as the current PHP process * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input * @param int|float|null $timeout The timeout in seconds or null to disable * * @return static * * @throws LogicException When proc_open is not installed */ public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { $process = new static([], $cwd, $env, $input, $timeout); $process->commandline = $command; return $process; } /** * @return array */ public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { if ($this->options['create_new_console'] ?? false) { $this->processPipes->close(); } else { $this->stop(0); } } public function __clone() { $this->resetProcessData(); } /** * Runs the process. * * The callback receives the type of output (out or err) and * some bytes from the output in real-time. It allows to have feedback * from the independent process during execution. * * The STDOUT and STDERR are also available after the process is finished * via the getOutput() and getErrorOutput() methods. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return int The exit status code * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * @throws ProcessTimedOutException When process timed out * @throws ProcessSignaledException When process stopped after receiving signal * @throws LogicException In case a callback is provided and output has been disabled * * @final */ public function run(callable $callback = null, array $env = []): int { $this->start($callback, $env); return $this->wait(); } /** * Runs the process. * * This is identical to run() except that an exception is thrown if the process * exits with a non-zero exit code. * * @return $this * * @throws ProcessFailedException if the process didn't terminate successfully * * @final */ public function mustRun(callable $callback = null, array $env = []): self { if (0 !== $this->run($callback, $env)) { throw new ProcessFailedException($this); } return $this; } /** * Starts the process and returns after writing the input to STDIN. * * This method blocks until all STDIN data is sent to the process then it * returns while the process runs in the background. * * The termination of the process can be awaited with wait(). * * The callback receives the type of output (out or err) and some bytes from * the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * @throws LogicException In case a callback is provided and output has been disabled */ public function start(callable $callback = null, array $env = []) { if ($this->isRunning()) { throw new RuntimeException('Process is already running.'); } $this->resetProcessData(); $this->starttime = $this->lastOutputTime = microtime(true); $this->callback = $this->buildCallback($callback); $this->hasCallback = null !== $callback; $descriptors = $this->getDescriptors(); if ($this->env) { $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env; } $env += '\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv(); if (\is_array($commandline = $this->commandline)) { $commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline)); if ('\\' !== \DIRECTORY_SEPARATOR) { // exec is mandatory to deal with sending a signal to the process $commandline = 'exec '.$commandline; } } else { $commandline = $this->replacePlaceholders($commandline, $env); } if ('\\' === \DIRECTORY_SEPARATOR) { $commandline = $this->prepareWindowsCommandLine($commandline, $env); } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild $descriptors[3] = ['pipe', 'w']; // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;'; $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code'; // Workaround for the bug, when PTS functionality is enabled. // @see : https://bugs.php.net/69442 $ptsWorkaround = fopen(__FILE__, 'r'); } $envPairs = []; foreach ($env as $k => $v) { if (false !== $v && 'argc' !== $k && 'argv' !== $k) { $envPairs[] = $k.'='.$v; } } if (!is_dir($this->cwd)) { throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd)); } $this->process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); if (!\is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); } $this->status = self::STATUS_STARTED; if (isset($descriptors[3])) { $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]); } if ($this->tty) { return; } $this->updateStatus(false); $this->checkTimeout(); } /** * Restarts the process. * * Be warned that the process is cloned before being started. * * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR * * @return static * * @throws RuntimeException When process can't be launched * @throws RuntimeException When process is already running * * @see start() * * @final */ public function restart(callable $callback = null, array $env = []): self { if ($this->isRunning()) { throw new RuntimeException('Process is already running.'); } $process = clone $this; $process->start($callback, $env); return $process; } /** * Waits for the process to terminate. * * The callback receives the type of output (out or err) and some bytes * from the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * * @param callable|null $callback A valid PHP callback * * @return int The exitcode of the process * * @throws ProcessTimedOutException When process timed out * @throws ProcessSignaledException When process stopped after receiving signal * @throws LogicException When process is not yet started */ public function wait(callable $callback = null) { $this->requireProcessIsStarted(__FUNCTION__); $this->updateStatus(false); if (null !== $callback) { if (!$this->processPipes->haveReadSupport()) { $this->stop(0); throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait".'); } $this->callback = $this->buildCallback($callback); } do { $this->checkTimeout(); $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); } while ($running); while ($this->isRunning()) { $this->checkTimeout(); usleep(1000); } if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) { throw new ProcessSignaledException($this); } return $this->exitcode; } /** * Waits until the callback returns true. * * The callback receives the type of output (out or err) and some bytes * from the output in real-time while writing the standard input to the process. * It allows to have feedback from the independent process during execution. * * @throws RuntimeException When process timed out * @throws LogicException When process is not yet started * @throws ProcessTimedOutException In case the timeout was reached */ public function waitUntil(callable $callback): bool { $this->requireProcessIsStarted(__FUNCTION__); $this->updateStatus(false); if (!$this->processPipes->haveReadSupport()) { $this->stop(0); throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::waitUntil".'); } $callback = $this->buildCallback($callback); $ready = false; while (true) { $this->checkTimeout(); $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); $output = $this->processPipes->readAndWrite($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); foreach ($output as $type => $data) { if (3 !== $type) { $ready = $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data) || $ready; } elseif (!isset($this->fallbackStatus['signaled'])) { $this->fallbackStatus['exitcode'] = (int) $data; } } if ($ready) { return true; } if (!$running) { return false; } usleep(1000); } } /** * Returns the Pid (process identifier), if applicable. * * @return int|null The process id if running, null otherwise */ public function getPid() { return $this->isRunning() ? $this->processInformation['pid'] : null; } /** * Sends a POSIX signal to the process. * * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants) * * @return $this * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed * @throws RuntimeException In case of failure */ public function signal(int $signal) { $this->doSignal($signal, true); return $this; } /** * Disables fetching output and error output from the underlying process. * * @return $this * * @throws RuntimeException In case the process is already running * @throws LogicException if an idle timeout is set */ public function disableOutput() { if ($this->isRunning()) { throw new RuntimeException('Disabling output while the process is running is not possible.'); } if (null !== $this->idleTimeout) { throw new LogicException('Output cannot be disabled while an idle timeout is set.'); } $this->outputDisabled = true; return $this; } /** * Enables fetching output and error output from the underlying process. * * @return $this * * @throws RuntimeException In case the process is already running */ public function enableOutput() { if ($this->isRunning()) { throw new RuntimeException('Enabling output while the process is running is not possible.'); } $this->outputDisabled = false; return $this; } /** * Returns true in case the output is disabled, false otherwise. * * @return bool */ public function isOutputDisabled() { return $this->outputDisabled; } /** * Returns the current output of the process (STDOUT). * * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started */ public function getOutput() { $this->readPipesForOutput(__FUNCTION__); if (false === $ret = stream_get_contents($this->stdout, -1, 0)) { return ''; } return $ret; } /** * Returns the output incrementally. * * In comparison with the getOutput method which always return the whole * output, this one returns the new output since the last call. * * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started */ public function getIncrementalOutput() { $this->readPipesForOutput(__FUNCTION__); $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset); $this->incrementalOutputOffset = ftell($this->stdout); if (false === $latest) { return ''; } return $latest; } /** * Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR). * * @param int $flags A bit field of Process::ITER_* flags * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started * * @return \Generator */ #[\ReturnTypeWillChange] public function getIterator(int $flags = 0) { $this->readPipesForOutput(__FUNCTION__, false); $clearOutput = !(self::ITER_KEEP_OUTPUT & $flags); $blocking = !(self::ITER_NON_BLOCKING & $flags); $yieldOut = !(self::ITER_SKIP_OUT & $flags); $yieldErr = !(self::ITER_SKIP_ERR & $flags); while (null !== $this->callback || ($yieldOut && !feof($this->stdout)) || ($yieldErr && !feof($this->stderr))) { if ($yieldOut) { $out = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset); if (isset($out[0])) { if ($clearOutput) { $this->clearOutput(); } else { $this->incrementalOutputOffset = ftell($this->stdout); } yield self::OUT => $out; } } if ($yieldErr) { $err = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset); if (isset($err[0])) { if ($clearOutput) { $this->clearErrorOutput(); } else { $this->incrementalErrorOutputOffset = ftell($this->stderr); } yield self::ERR => $err; } } if (!$blocking && !isset($out[0]) && !isset($err[0])) { yield self::OUT => ''; } $this->checkTimeout(); $this->readPipesForOutput(__FUNCTION__, $blocking); } } /** * Clears the process output. * * @return $this */ public function clearOutput() { ftruncate($this->stdout, 0); fseek($this->stdout, 0); $this->incrementalOutputOffset = 0; return $this; } /** * Returns the current error output of the process (STDERR). * * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started */ public function getErrorOutput() { $this->readPipesForOutput(__FUNCTION__); if (false === $ret = stream_get_contents($this->stderr, -1, 0)) { return ''; } return $ret; } /** * Returns the errorOutput incrementally. * * In comparison with the getErrorOutput method which always return the * whole error output, this one returns the new error output since the last * call. * * @return string * * @throws LogicException in case the output has been disabled * @throws LogicException In case the process is not started */ public function getIncrementalErrorOutput() { $this->readPipesForOutput(__FUNCTION__); $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset); $this->incrementalErrorOutputOffset = ftell($this->stderr); if (false === $latest) { return ''; } return $latest; } /** * Clears the process output. * * @return $this */ public function clearErrorOutput() { ftruncate($this->stderr, 0); fseek($this->stderr, 0); $this->incrementalErrorOutputOffset = 0; return $this; } /** * Returns the exit code returned by the process. * * @return int|null The exit status code, null if the Process is not terminated */ public function getExitCode() { $this->updateStatus(false); return $this->exitcode; } /** * Returns a string representation for the exit code returned by the process. * * This method relies on the Unix exit code status standardization * and might not be relevant for other operating systems. * * @return string|null A string representation for the exit status code, null if the Process is not terminated * * @see http://tldp.org/LDP/abs/html/exitcodes.html * @see http://en.wikipedia.org/wiki/Unix_signal */ public function getExitCodeText() { if (null === $exitcode = $this->getExitCode()) { return null; } return self::$exitCodes[$exitcode] ?? 'Unknown error'; } /** * Checks if the process ended successfully. * * @return bool */ public function isSuccessful() { return 0 === $this->getExitCode(); } /** * Returns true if the child process has been terminated by an uncaught signal. * * It always returns false on Windows. * * @return bool * * @throws LogicException In case the process is not terminated */ public function hasBeenSignaled() { $this->requireProcessIsTerminated(__FUNCTION__); return $this->processInformation['signaled']; } /** * Returns the number of the signal that caused the child process to terminate its execution. * * It is only meaningful if hasBeenSignaled() returns true. * * @return int * * @throws RuntimeException In case --enable-sigchild is activated * @throws LogicException In case the process is not terminated */ public function getTermSignal() { $this->requireProcessIsTerminated(__FUNCTION__); if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.'); } return $this->processInformation['termsig']; } /** * Returns true if the child process has been stopped by a signal. * * It always returns false on Windows. * * @return bool * * @throws LogicException In case the process is not terminated */ public function hasBeenStopped() { $this->requireProcessIsTerminated(__FUNCTION__); return $this->processInformation['stopped']; } /** * Returns the number of the signal that caused the child process to stop its execution. * * It is only meaningful if hasBeenStopped() returns true. * * @return int * * @throws LogicException In case the process is not terminated */ public function getStopSignal() { $this->requireProcessIsTerminated(__FUNCTION__); return $this->processInformation['stopsig']; } /** * Checks if the process is currently running. * * @return bool */ public function isRunning() { if (self::STATUS_STARTED !== $this->status) { return false; } $this->updateStatus(false); return $this->processInformation['running']; } /** * Checks if the process has been started with no regard to the current state. * * @return bool */ public function isStarted() { return self::STATUS_READY != $this->status; } /** * Checks if the process is terminated. * * @return bool */ public function isTerminated() { $this->updateStatus(false); return self::STATUS_TERMINATED == $this->status; } /** * Gets the process status. * * The status is one of: ready, started, terminated. * * @return string */ public function getStatus() { $this->updateStatus(false); return $this->status; } /** * Stops the process. * * @param int|float $timeout The timeout in seconds * @param int $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9) * * @return int|null The exit-code of the process or null if it's not running */ public function stop(float $timeout = 10, int $signal = null) { $timeoutMicro = microtime(true) + $timeout; if ($this->isRunning()) { // given SIGTERM may not be defined and that "proc_terminate" uses the constant value and not the constant itself, we use the same here $this->doSignal(15, false); do { usleep(1000); } while ($this->isRunning() && microtime(true) < $timeoutMicro); if ($this->isRunning()) { // Avoid exception here: process is supposed to be running, but it might have stopped just // after this line. In any case, let's silently discard the error, we cannot do anything. $this->doSignal($signal ?: 9, false); } } if ($this->isRunning()) { if (isset($this->fallbackStatus['pid'])) { unset($this->fallbackStatus['pid']); return $this->stop(0, $signal); } $this->close(); } return $this->exitcode; } /** * Adds a line to the STDOUT stream. * * @internal */ public function addOutput(string $line) { $this->lastOutputTime = microtime(true); fseek($this->stdout, 0, \SEEK_END); fwrite($this->stdout, $line); fseek($this->stdout, $this->incrementalOutputOffset); } /** * Adds a line to the STDERR stream. * * @internal */ public function addErrorOutput(string $line) { $this->lastOutputTime = microtime(true); fseek($this->stderr, 0, \SEEK_END); fwrite($this->stderr, $line); fseek($this->stderr, $this->incrementalErrorOutputOffset); } /** * Gets the last output time in seconds. * * @return float|null */ public function getLastOutputTime(): ?float { return $this->lastOutputTime; } /** * Gets the command line to be executed. * * @return string */ public function getCommandLine() { return \is_array($this->commandline) ? implode(' ', array_map([$this, 'escapeArgument'], $this->commandline)) : $this->commandline; } /** * Gets the process timeout in seconds (max. runtime). * * @return float|null */ public function getTimeout() { return $this->timeout; } /** * Gets the process idle timeout in seconds (max. time since last output). * * @return float|null */ public function getIdleTimeout() { return $this->idleTimeout; } /** * Sets the process timeout (max. runtime) in seconds. * * To disable the timeout, set this value to null. * * @return $this * * @throws InvalidArgumentException if the timeout is negative */ public function setTimeout(?float $timeout) { $this->timeout = $this->validateTimeout($timeout); return $this; } /** * Sets the process idle timeout (max. time since last output) in seconds. * * To disable the timeout, set this value to null. * * @return $this * * @throws LogicException if the output is disabled * @throws InvalidArgumentException if the timeout is negative */ public function setIdleTimeout(?float $timeout) { if (null !== $timeout && $this->outputDisabled) { throw new LogicException('Idle timeout cannot be set while the output is disabled.'); } $this->idleTimeout = $this->validateTimeout($timeout); return $this; } /** * Enables or disables the TTY mode. * * @return $this * * @throws RuntimeException In case the TTY mode is not supported */ public function setTty(bool $tty) { if ('\\' === \DIRECTORY_SEPARATOR && $tty) { throw new RuntimeException('TTY mode is not supported on Windows platform.'); } if ($tty && !self::isTtySupported()) { throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); } $this->tty = $tty; return $this; } /** * Checks if the TTY mode is enabled. * * @return bool */ public function isTty() { return $this->tty; } /** * Sets PTY mode. * * @return $this */ public function setPty(bool $bool) { $this->pty = $bool; return $this; } /** * Returns PTY state. * * @return bool */ public function isPty() { return $this->pty; } /** * Gets the working directory. * * @return string|null */ public function getWorkingDirectory() { if (null === $this->cwd) { // getcwd() will return false if any one of the parent directories does not have // the readable or search mode set, even if the current directory does return getcwd() ?: null; } return $this->cwd; } /** * Sets the current working directory. * * @return $this */ public function setWorkingDirectory(string $cwd) { $this->cwd = $cwd; return $this; } /** * Gets the environment variables. * * @return array */ public function getEnv() { return $this->env; } /** * Sets the environment variables. * * @param array $env The new environment variables * * @return $this */ public function setEnv(array $env) { $this->env = $env; return $this; } /** * Gets the Process input. * * @return resource|string|\Iterator|null */ public function getInput() { return $this->input; } /** * Sets the input. * * This content will be passed to the underlying process standard input. * * @param string|int|float|bool|resource|\Traversable|null $input The content * * @return $this * * @throws LogicException In case the process is running */ public function setInput($input) { if ($this->isRunning()) { throw new LogicException('Input cannot be set while the process is running.'); } $this->input = ProcessUtils::validateInput(__METHOD__, $input); return $this; } /** * Performs a check between the timeout definition and the time the process started. * * In case you run a background process (with the start method), you should * trigger this method regularly to ensure the process timeout * * @throws ProcessTimedOutException In case the timeout was reached */ public function checkTimeout() { if (self::STATUS_STARTED !== $this->status) { return; } if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL); } if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) { $this->stop(0); throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE); } } /** * @throws LogicException in case process is not started */ public function getStartTime(): float { if (!$this->isStarted()) { throw new LogicException('Start time is only available after process start.'); } return $this->starttime; } /** * Defines options to pass to the underlying proc_open(). * * @see https://php.net/proc_open for the options supported by PHP. * * Enabling the "create_new_console" option allows a subprocess to continue * to run after the main process exited, on both Windows and *nix */ public function setOptions(array $options) { if ($this->isRunning()) { throw new RuntimeException('Setting options while the process is running is not possible.'); } $defaultOptions = $this->options; $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console']; foreach ($options as $key => $value) { if (!\in_array($key, $existingOptions)) { $this->options = $defaultOptions; throw new LogicException(sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, implode('", "', $existingOptions))); } $this->options[$key] = $value; } } /** * Returns whether TTY is supported on the current operating system. */ public static function isTtySupported(): bool { static $isTtySupported; if (null === $isTtySupported) { $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); } return $isTtySupported; } /** * Returns whether PTY is supported on the current operating system. * * @return bool */ public static function isPtySupported() { static $result; if (null !== $result) { return $result; } if ('\\' === \DIRECTORY_SEPARATOR) { return $result = false; } return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes); } /** * Creates the descriptors needed by the proc_open. */ private function getDescriptors(): array { if ($this->input instanceof \Iterator) { $this->input->rewind(); } if ('\\' === \DIRECTORY_SEPARATOR) { $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback); } else { $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback); } return $this->processPipes->getDescriptors(); } /** * Builds up the callback used by wait(). * * The callbacks adds all occurred output to the specific buffer and calls * the user callback (if present) with the received output. * * @param callable|null $callback The user defined PHP callback * * @return \Closure */ protected function buildCallback(callable $callback = null) { if ($this->outputDisabled) { return function ($type, $data) use ($callback): bool { return null !== $callback && $callback($type, $data); }; } $out = self::OUT; return function ($type, $data) use ($callback, $out): bool { if ($out == $type) { $this->addOutput($data); } else { $this->addErrorOutput($data); } return null !== $callback && $callback($type, $data); }; } /** * Updates the status of the process, reads pipes. * * @param bool $blocking Whether to use a blocking read call */ protected function updateStatus(bool $blocking) { if (self::STATUS_STARTED !== $this->status) { return; } $this->processInformation = proc_get_status($this->process); $running = $this->processInformation['running']; $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running); if ($this->fallbackStatus && $this->isSigchildEnabled()) { $this->processInformation = $this->fallbackStatus + $this->processInformation; } if (!$running) { $this->close(); } } /** * Returns whether PHP has been compiled with the '--enable-sigchild' option or not. * * @return bool */ protected function isSigchildEnabled() { if (null !== self::$sigchild) { return self::$sigchild; } if (!\function_exists('phpinfo')) { return self::$sigchild = false; } ob_start(); phpinfo(\INFO_GENERAL); return self::$sigchild = str_contains(ob_get_clean(), '--enable-sigchild'); } /** * Reads pipes for the freshest output. * * @param string $caller The name of the method that needs fresh outputs * @param bool $blocking Whether to use blocking calls or not * * @throws LogicException in case output has been disabled or process is not started */ private function readPipesForOutput(string $caller, bool $blocking = false) { if ($this->outputDisabled) { throw new LogicException('Output has been disabled.'); } $this->requireProcessIsStarted($caller); $this->updateStatus($blocking); } /** * Validates and returns the filtered timeout. * * @throws InvalidArgumentException if the given timeout is a negative number */ private function validateTimeout(?float $timeout): ?float { $timeout = (float) $timeout; if (0.0 === $timeout) { $timeout = null; } elseif ($timeout < 0) { throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); } return $timeout; } /** * Reads pipes, executes callback. * * @param bool $blocking Whether to use blocking calls or not * @param bool $close Whether to close file handles or not */ private function readPipes(bool $blocking, bool $close) { $result = $this->processPipes->readAndWrite($blocking, $close); $callback = $this->callback; foreach ($result as $type => $data) { if (3 !== $type) { $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data); } elseif (!isset($this->fallbackStatus['signaled'])) { $this->fallbackStatus['exitcode'] = (int) $data; } } } /** * Closes process resource, closes file handles, sets the exitcode. * * @return int The exitcode */ private function close(): int { $this->processPipes->close(); if (\is_resource($this->process)) { proc_close($this->process); } $this->exitcode = $this->processInformation['exitcode']; $this->status = self::STATUS_TERMINATED; if (-1 === $this->exitcode) { if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { // if process has been signaled, no exitcode but a valid termsig, apply Unix convention $this->exitcode = 128 + $this->processInformation['termsig']; } elseif ($this->isSigchildEnabled()) { $this->processInformation['signaled'] = true; $this->processInformation['termsig'] = -1; } } // Free memory from self-reference callback created by buildCallback // Doing so in other contexts like __destruct or by garbage collector is ineffective // Now pipes are closed, so the callback is no longer necessary $this->callback = null; return $this->exitcode; } /** * Resets data related to the latest run of the process. */ private function resetProcessData() { $this->starttime = null; $this->callback = null; $this->exitcode = null; $this->fallbackStatus = []; $this->processInformation = null; $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+'); $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+'); $this->process = null; $this->latestSignal = null; $this->status = self::STATUS_READY; $this->incrementalOutputOffset = 0; $this->incrementalErrorOutputOffset = 0; } /** * Sends a POSIX signal to the process. * * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants) * @param bool $throwException Whether to throw exception in case signal failed * * @return bool * * @throws LogicException In case the process is not running * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed * @throws RuntimeException In case of failure */ private function doSignal(int $signal, bool $throwException): bool { if (null === $pid = $this->getPid()) { if ($throwException) { throw new LogicException('Cannot send signal on a non running process.'); } return false; } if ('\\' === \DIRECTORY_SEPARATOR) { exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode); if ($exitCode && $this->isRunning()) { if ($throwException) { throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output))); } return false; } } else { if (!$this->isSigchildEnabled()) { $ok = @proc_terminate($this->process, $signal); } elseif (\function_exists('posix_kill')) { $ok = @posix_kill($pid, $signal); } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) { $ok = false === fgets($pipes[2]); } if (!$ok) { if ($throwException) { throw new RuntimeException(sprintf('Error while sending signal "%s".', $signal)); } return false; } } $this->latestSignal = $signal; $this->fallbackStatus['signaled'] = true; $this->fallbackStatus['exitcode'] = -1; $this->fallbackStatus['termsig'] = $this->latestSignal; return true; } private function prepareWindowsCommandLine(string $cmd, array &$env): string { $uid = uniqid('', true); $varCount = 0; $varCache = []; $cmd = preg_replace_callback( '/"(?:( [^"%!^]*+ (?: (?: !LF! | "(?:\^[%!^])?+" ) [^"%!^]*+ )++ ) | [^"]*+ )"/x', function ($m) use (&$env, &$varCache, &$varCount, $uid) { if (!isset($m[1])) { return $m[0]; } if (isset($varCache[$m[0]])) { return $varCache[$m[0]]; } if (str_contains($value = $m[1], "\0")) { $value = str_replace("\0", '?', $value); } if (false === strpbrk($value, "\"%!\n")) { return '"'.$value.'"'; } $value = str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value); $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"'; $var = $uid.++$varCount; $env[$var] = $value; return $varCache[$m[0]] = '!'.$var.'!'; }, $cmd ); $cmd = 'cmd /V:ON /E:ON /D /C ('.str_replace("\n", ' ', $cmd).')'; foreach ($this->processPipes->getFiles() as $offset => $filename) { $cmd .= ' '.$offset.'>"'.$filename.'"'; } return $cmd; } /** * Ensures the process is running or terminated, throws a LogicException if the process has a not started. * * @throws LogicException if the process has not run */ private function requireProcessIsStarted(string $functionName) { if (!$this->isStarted()) { throw new LogicException(sprintf('Process must be started before calling "%s()".', $functionName)); } } /** * Ensures the process is terminated, throws a LogicException if the process has a status different than "terminated". * * @throws LogicException if the process is not yet terminated */ private function requireProcessIsTerminated(string $functionName) { if (!$this->isTerminated()) { throw new LogicException(sprintf('Process must be terminated before calling "%s()".', $functionName)); } } /** * Escapes a string to be used as a shell argument. */ private function escapeArgument(?string $argument): string { if ('' === $argument || null === $argument) { return '""'; } if ('\\' !== \DIRECTORY_SEPARATOR) { return "'".str_replace("'", "'\\''", $argument)."'"; } if (str_contains($argument, "\0")) { $argument = str_replace("\0", '?', $argument); } if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) { return $argument; } $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument); return '"'.str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument).'"'; } private function replacePlaceholders(string $commandline, array $env) { return preg_replace_callback('/"\$\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\}"/', function ($matches) use ($commandline, $env) { if (!isset($env[$matches[1]]) || false === $env[$matches[1]]) { throw new InvalidArgumentException(sprintf('Command line is missing a value for parameter "%s": ', $matches[1]).$commandline); } return $this->escapeArgument($env[$matches[1]]); }, $commandline); } private function getDefaultEnv(): array { $env = getenv(); $env = ('\\' === \DIRECTORY_SEPARATOR ? array_intersect_ukey($env, $_SERVER, 'strcasecmp') : array_intersect_key($env, $_SERVER)) ?: $env; return $_ENV + ('\\' === \DIRECTORY_SEPARATOR ? array_diff_ukey($env, $_ENV, 'strcasecmp') : $env); } } process/Pipes/WindowsPipes.php000064400000013640150432043210012444 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; use Symfony\Component\Process\Exception\RuntimeException; use Symfony\Component\Process\Process; /** * WindowsPipes implementation uses temporary files as handles. * * @see https://bugs.php.net/51800 * @see https://bugs.php.net/65650 * * @author Romain Neutron * * @internal */ class WindowsPipes extends AbstractPipes { private $files = []; private $fileHandles = []; private $lockHandles = []; private $readBytes = [ Process::STDOUT => 0, Process::STDERR => 0, ]; private $haveReadSupport; public function __construct($input, bool $haveReadSupport) { $this->haveReadSupport = $haveReadSupport; if ($this->haveReadSupport) { // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. // Workaround for this problem is to use temporary files instead of pipes on Windows platform. // // @see https://bugs.php.net/51800 $pipes = [ Process::STDOUT => Process::OUT, Process::STDERR => Process::ERR, ]; $tmpDir = sys_get_temp_dir(); $lastError = 'unknown reason'; set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; }); for ($i = 0;; ++$i) { foreach ($pipes as $pipe => $name) { $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name); if (!$h = fopen($file.'.lock', 'w')) { if (file_exists($file.'.lock')) { continue 2; } restore_error_handler(); throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError); } if (!flock($h, \LOCK_EX | \LOCK_NB)) { continue 2; } if (isset($this->lockHandles[$pipe])) { flock($this->lockHandles[$pipe], \LOCK_UN); fclose($this->lockHandles[$pipe]); } $this->lockHandles[$pipe] = $h; if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) { flock($this->lockHandles[$pipe], \LOCK_UN); fclose($this->lockHandles[$pipe]); unset($this->lockHandles[$pipe]); continue 2; } $this->fileHandles[$pipe] = $h; $this->files[$pipe] = $file; } break; } restore_error_handler(); } parent::__construct($input); } public function __sleep(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { $this->close(); } /** * {@inheritdoc} */ public function getDescriptors(): array { if (!$this->haveReadSupport) { $nullstream = fopen('NUL', 'c'); return [ ['pipe', 'r'], $nullstream, $nullstream, ]; } // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800) // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650 // So we redirect output within the commandline and pass the nul device to the process return [ ['pipe', 'r'], ['file', 'NUL', 'w'], ['file', 'NUL', 'w'], ]; } /** * {@inheritdoc} */ public function getFiles(): array { return $this->files; } /** * {@inheritdoc} */ public function readAndWrite(bool $blocking, bool $close = false): array { $this->unblock(); $w = $this->write(); $read = $r = $e = []; if ($blocking) { if ($w) { @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); } elseif ($this->fileHandles) { usleep(Process::TIMEOUT_PRECISION * 1E6); } } foreach ($this->fileHandles as $type => $fileHandle) { $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]); if (isset($data[0])) { $this->readBytes[$type] += \strlen($data); $read[$type] = $data; } if ($close) { ftruncate($fileHandle, 0); fclose($fileHandle); flock($this->lockHandles[$type], \LOCK_UN); fclose($this->lockHandles[$type]); unset($this->fileHandles[$type], $this->lockHandles[$type]); } } return $read; } /** * {@inheritdoc} */ public function haveReadSupport(): bool { return $this->haveReadSupport; } /** * {@inheritdoc} */ public function areOpen(): bool { return $this->pipes && $this->fileHandles; } /** * {@inheritdoc} */ public function close() { parent::close(); foreach ($this->fileHandles as $type => $handle) { ftruncate($handle, 0); fclose($handle); flock($this->lockHandles[$type], \LOCK_UN); fclose($this->lockHandles[$type]); } $this->fileHandles = $this->lockHandles = []; } } process/Pipes/UnixPipes.php000064400000007506150432043210011741 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; use Symfony\Component\Process\Process; /** * UnixPipes implementation uses unix pipes as handles. * * @author Romain Neutron * * @internal */ class UnixPipes extends AbstractPipes { private $ttyMode; private $ptyMode; private $haveReadSupport; public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport) { $this->ttyMode = $ttyMode; $this->ptyMode = $ptyMode; $this->haveReadSupport = $haveReadSupport; parent::__construct($input); } public function __sleep(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { $this->close(); } /** * {@inheritdoc} */ public function getDescriptors(): array { if (!$this->haveReadSupport) { $nullstream = fopen('/dev/null', 'c'); return [ ['pipe', 'r'], $nullstream, $nullstream, ]; } if ($this->ttyMode) { return [ ['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w'], ]; } if ($this->ptyMode && Process::isPtySupported()) { return [ ['pty'], ['pty'], ['pty'], ]; } return [ ['pipe', 'r'], ['pipe', 'w'], // stdout ['pipe', 'w'], // stderr ]; } /** * {@inheritdoc} */ public function getFiles(): array { return []; } /** * {@inheritdoc} */ public function readAndWrite(bool $blocking, bool $close = false): array { $this->unblock(); $w = $this->write(); $read = $e = []; $r = $this->pipes; unset($r[0]); // let's have a look if something changed in streams set_error_handler([$this, 'handleError']); if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { restore_error_handler(); // if a system call has been interrupted, forget about it, let's try again // otherwise, an error occurred, let's reset pipes if (!$this->hasSystemCallBeenInterrupted()) { $this->pipes = []; } return $read; } restore_error_handler(); foreach ($r as $pipe) { // prior PHP 5.4 the array passed to stream_select is modified and // lose key association, we have to find back the key $read[$type = array_search($pipe, $this->pipes, true)] = ''; do { $data = @fread($pipe, self::CHUNK_SIZE); $read[$type] .= $data; } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1]))); if (!isset($read[$type][0])) { unset($read[$type]); } if ($close && feof($pipe)) { fclose($pipe); unset($this->pipes[$type]); } } return $read; } /** * {@inheritdoc} */ public function haveReadSupport(): bool { return $this->haveReadSupport; } /** * {@inheritdoc} */ public function areOpen(): bool { return (bool) $this->pipes; } } process/Pipes/AbstractPipes.php000064400000011625150432043210012556 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; use Symfony\Component\Process\Exception\InvalidArgumentException; /** * @author Romain Neutron * * @internal */ abstract class AbstractPipes implements PipesInterface { public $pipes = []; private $inputBuffer = ''; private $input; private $blocked = true; private $lastError; /** * @param resource|string|int|float|bool|\Iterator|null $input */ public function __construct($input) { if (\is_resource($input) || $input instanceof \Iterator) { $this->input = $input; } elseif (\is_string($input)) { $this->inputBuffer = $input; } else { $this->inputBuffer = (string) $input; } } /** * {@inheritdoc} */ public function close() { foreach ($this->pipes as $pipe) { fclose($pipe); } $this->pipes = []; } /** * Returns true if a system call has been interrupted. */ protected function hasSystemCallBeenInterrupted(): bool { $lastError = $this->lastError; $this->lastError = null; // stream_select returns false when the `select` system call is interrupted by an incoming signal return null !== $lastError && false !== stripos($lastError, 'interrupted system call'); } /** * Unblocks streams. */ protected function unblock() { if (!$this->blocked) { return; } foreach ($this->pipes as $pipe) { stream_set_blocking($pipe, 0); } if (\is_resource($this->input)) { stream_set_blocking($this->input, 0); } $this->blocked = false; } /** * Writes input to stdin. * * @throws InvalidArgumentException When an input iterator yields a non supported value */ protected function write(): ?array { if (!isset($this->pipes[0])) { return null; } $input = $this->input; if ($input instanceof \Iterator) { if (!$input->valid()) { $input = null; } elseif (\is_resource($input = $input->current())) { stream_set_blocking($input, 0); } elseif (!isset($this->inputBuffer[0])) { if (!\is_string($input)) { if (!is_scalar($input)) { throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input))); } $input = (string) $input; } $this->inputBuffer = $input; $this->input->next(); $input = null; } else { $input = null; } } $r = $e = []; $w = [$this->pipes[0]]; // let's have a look if something changed in streams if (false === @stream_select($r, $w, $e, 0, 0)) { return null; } foreach ($w as $stdin) { if (isset($this->inputBuffer[0])) { $written = fwrite($stdin, $this->inputBuffer); $this->inputBuffer = substr($this->inputBuffer, $written); if (isset($this->inputBuffer[0])) { return [$this->pipes[0]]; } } if ($input) { for (;;) { $data = fread($input, self::CHUNK_SIZE); if (!isset($data[0])) { break; } $written = fwrite($stdin, $data); $data = substr($data, $written); if (isset($data[0])) { $this->inputBuffer = $data; return [$this->pipes[0]]; } } if (feof($input)) { if ($this->input instanceof \Iterator) { $this->input->next(); } else { $this->input = null; } } } } // no input to read on resource, buffer is empty if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) { $this->input = null; fclose($this->pipes[0]); unset($this->pipes[0]); } elseif (!$w) { return [$this->pipes[0]]; } return null; } /** * @internal */ public function handleError(int $type, string $msg) { $this->lastError = $msg; } } process/Pipes/PipesInterface.php000064400000002730150432043210012710 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Pipes; /** * PipesInterface manages descriptors and pipes for the use of proc_open. * * @author Romain Neutron * * @internal */ interface PipesInterface { public const CHUNK_SIZE = 16384; /** * Returns an array of descriptors for the use of proc_open. */ public function getDescriptors(): array; /** * Returns an array of filenames indexed by their related stream in case these pipes use temporary files. * * @return string[] */ public function getFiles(): array; /** * Reads data in file handles and pipes. * * @param bool $blocking Whether to use blocking calls or not * @param bool $close Whether to close pipes if they've reached EOF * * @return string[] An array of read data indexed by their fd */ public function readAndWrite(bool $blocking, bool $close = false): array; /** * Returns if the current state has open file handles or pipes. */ public function areOpen(): bool; /** * Returns if pipes are able to read output. */ public function haveReadSupport(): bool; /** * Closes file handles and pipes. */ public function close(); } process/CHANGELOG.md000064400000007724150432043210010037 0ustar00CHANGELOG ========= 5.2.0 ----- * added `Process::setOptions()` to set `Process` specific options * added option `create_new_console` to allow a subprocess to continue to run after the main script exited, both on Linux and on Windows 5.1.0 ----- * added `Process::getStartTime()` to retrieve the start time of the process as float 5.0.0 ----- * removed `Process::inheritEnvironmentVariables()` * removed `PhpProcess::setPhpBinary()` * `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell * removed `Process::setCommandLine()` 4.4.0 ----- * deprecated `Process::inheritEnvironmentVariables()`: env variables are always inherited. * added `Process::getLastOutputTime()` method 4.2.0 ----- * added the `Process::fromShellCommandline()` to run commands in a shell wrapper * deprecated passing a command as string when creating a `Process` instance * deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods * added the `Process::waitUntil()` method to wait for the process only for a specific output, then continue the normal execution of your application 4.1.0 ----- * added the `Process::isTtySupported()` method that allows to check for TTY support * made `PhpExecutableFinder` look for the `PHP_BINARY` env var when searching the php binary * added the `ProcessSignaledException` class to properly catch signaled process errors 4.0.0 ----- * environment variables will always be inherited * added a second `array $env = []` argument to the `start()`, `run()`, `mustRun()`, and `restart()` methods of the `Process` class * added a second `array $env = []` argument to the `start()` method of the `PhpProcess` class * the `ProcessUtils::escapeArgument()` method has been removed * the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()` methods of the `Process` class have been removed * support for passing `proc_open()` options has been removed * removed the `ProcessBuilder` class, use the `Process` class instead * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class * passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not supported anymore 3.4.0 ----- * deprecated the ProcessBuilder class * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor) 3.3.0 ----- * added command line arrays in the `Process` class * added `$env` argument to `Process::start()`, `run()`, `mustRun()` and `restart()` methods * deprecated the `ProcessUtils::escapeArgument()` method * deprecated not inheriting environment variables * deprecated configuring `proc_open()` options * deprecated configuring enhanced Windows compatibility * deprecated configuring enhanced sigchild compatibility 2.5.0 ----- * added support for PTY mode * added the convenience method "mustRun" * deprecation: Process::setStdin() is deprecated in favor of Process::setInput() * deprecation: Process::getStdin() is deprecated in favor of Process::getInput() * deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types 2.4.0 ----- * added the ability to define an idle timeout 2.3.0 ----- * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows * added Process::signal() * added Process::getPid() * added support for a TTY mode 2.2.0 ----- * added ProcessBuilder::setArguments() to reset the arguments on a builder * added a way to retrieve the standard and error output incrementally * added Process:restart() 2.1.0 ----- * added support for non-blocking processes (start(), wait(), isRunning(), stop()) * enhanced Windows compatibility * added Process::getExitCodeText() that returns a string representation for the exit code returned by the process * added ProcessBuilder process/PhpExecutableFinder.php000064400000004700150432043210012607 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * An executable finder specifically designed for the PHP executable. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class PhpExecutableFinder { private $executableFinder; public function __construct() { $this->executableFinder = new ExecutableFinder(); } /** * Finds The PHP executable. * * @return string|false */ public function find(bool $includeArgs = true) { if ($php = getenv('PHP_BINARY')) { if (!is_executable($php)) { $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { if (!is_executable($php)) { return false; } } else { return false; } } return $php; } $args = $this->findArguments(); $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; // PHP_BINARY return the current sapi executable if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) { return \PHP_BINARY.$args; } if ($php = getenv('PHP_PATH')) { if (!@is_executable($php)) { return false; } return $php; } if ($php = getenv('PHP_PEAR_PHP_BIN')) { if (@is_executable($php)) { return $php; } } if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) { return $php; } $dirs = [\PHP_BINDIR]; if ('\\' === \DIRECTORY_SEPARATOR) { $dirs[] = 'C:\xampp\php\\'; } return $this->executableFinder->find('php', false, $dirs); } /** * Finds the PHP executable arguments. * * @return array */ public function findArguments() { $arguments = []; if ('phpdbg' === \PHP_SAPI) { $arguments[] = '-qrr'; } return $arguments; } } process/PhpProcess.php000064400000004636150432043210011024 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; use Symfony\Component\Process\Exception\LogicException; use Symfony\Component\Process\Exception\RuntimeException; /** * PhpProcess runs a PHP script in an independent process. * * $p = new PhpProcess(''); * $p->run(); * print $p->getOutput()."\n"; * * @author Fabien Potencier */ class PhpProcess extends Process { /** * @param string $script The PHP script to run (as a string) * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to use the same environment as the current PHP process * @param int $timeout The timeout in seconds * @param array|null $php Path to the PHP binary to use with any additional arguments */ public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null) { if (null === $php) { $executableFinder = new PhpExecutableFinder(); $php = $executableFinder->find(false); $php = false === $php ? null : array_merge([$php], $executableFinder->findArguments()); } if ('phpdbg' === \PHP_SAPI) { $file = tempnam(sys_get_temp_dir(), 'dbg'); file_put_contents($file, $script); register_shutdown_function('unlink', $file); $php[] = $file; $script = null; } parent::__construct($php, $cwd, $env, $script, $timeout); } /** * {@inheritdoc} */ public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) { throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class)); } /** * {@inheritdoc} */ public function start(callable $callback = null, array $env = []) { if (null === $this->getCommandLine()) { throw new RuntimeException('Unable to find the PHP executable.'); } parent::start($callback, $env); } } process/ExecutableFinder.php000064400000004756150432043210012152 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process; /** * Generic executable finder. * * @author Fabien Potencier * @author Johannes M. Schmitt */ class ExecutableFinder { private $suffixes = ['.exe', '.bat', '.cmd', '.com']; /** * Replaces default suffixes of executable. */ public function setSuffixes(array $suffixes) { $this->suffixes = $suffixes; } /** * Adds new possible suffix to check for executable. */ public function addSuffix(string $suffix) { $this->suffixes[] = $suffix; } /** * Finds an executable by name. * * @param string $name The executable name (without the extension) * @param string|null $default The default to return if no executable is found * @param array $extraDirs Additional dirs to check into * * @return string|null */ public function find(string $name, string $default = null, array $extraDirs = []) { if (ini_get('open_basedir')) { $searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs); $dirs = []; foreach ($searchPath as $path) { // Silencing against https://bugs.php.net/69240 if (@is_dir($path)) { $dirs[] = $path; } else { if (basename($path) == $name && @is_executable($path)) { return $path; } } } } else { $dirs = array_merge( explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), $extraDirs ); } $suffixes = ['']; if ('\\' === \DIRECTORY_SEPARATOR) { $pathExt = getenv('PATHEXT'); $suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) { return $file; } } } return $default; } } process/composer.json000064400000001314150432043210010735 0ustar00{ "name": "symfony/process", "type": "library", "description": "Executes commands in sub-processes", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/polyfill-php80": "^1.16" }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } process/LICENSE000064400000002051150432043210007217 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. process/Exception/RuntimeException.php000064400000000741150432043210014167 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * RuntimeException for the Process Component. * * @author Johannes M. Schmitt */ class RuntimeException extends \RuntimeException implements ExceptionInterface { } process/Exception/ExceptionInterface.php000064400000000702150432043210014441 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * Marker Interface for the Process Component. * * @author Johannes M. Schmitt */ interface ExceptionInterface extends \Throwable { } process/Exception/ProcessSignaledException.php000064400000001661150432043210015633 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception that is thrown when a process has been signaled. * * @author Sullivan Senechal */ final class ProcessSignaledException extends RuntimeException { private $process; public function __construct(Process $process) { $this->process = $process; parent::__construct(sprintf('The process has been signaled with signal "%s".', $process->getTermSignal())); } public function getProcess(): Process { return $this->process; } public function getSignal(): int { return $this->getProcess()->getTermSignal(); } } process/Exception/ProcessTimedOutException.php000064400000003215150432043210015634 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception that is thrown when a process times out. * * @author Johannes M. Schmitt */ class ProcessTimedOutException extends RuntimeException { public const TYPE_GENERAL = 1; public const TYPE_IDLE = 2; private $process; private $timeoutType; public function __construct(Process $process, int $timeoutType) { $this->process = $process; $this->timeoutType = $timeoutType; parent::__construct(sprintf( 'The process "%s" exceeded the timeout of %s seconds.', $process->getCommandLine(), $this->getExceededTimeout() )); } public function getProcess() { return $this->process; } public function isGeneralTimeout() { return self::TYPE_GENERAL === $this->timeoutType; } public function isIdleTimeout() { return self::TYPE_IDLE === $this->timeoutType; } public function getExceededTimeout() { switch ($this->timeoutType) { case self::TYPE_GENERAL: return $this->process->getTimeout(); case self::TYPE_IDLE: return $this->process->getIdleTimeout(); default: throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType)); } } } process/Exception/ProcessFailedException.php000064400000002615150432043210015271 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; use Symfony\Component\Process\Process; /** * Exception for failed processes. * * @author Johannes M. Schmitt */ class ProcessFailedException extends RuntimeException { private $process; public function __construct(Process $process) { if ($process->isSuccessful()) { throw new InvalidArgumentException('Expected a failed process, but the given process was successful.'); } $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s", $process->getCommandLine(), $process->getExitCode(), $process->getExitCodeText(), $process->getWorkingDirectory() ); if (!$process->isOutputDisabled()) { $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", $process->getOutput(), $process->getErrorOutput() ); } parent::__construct($error); $this->process = $process; } public function getProcess() { return $this->process; } } process/Exception/InvalidArgumentException.php000064400000000760150432043210015636 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * InvalidArgumentException for the Process Component. * * @author Romain Neutron */ class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } process/Exception/LogicException.php000064400000000722150432043210013600 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Process\Exception; /** * LogicException for the Process Component. * * @author Romain Neutron */ class LogicException extends \LogicException implements ExceptionInterface { } polyfill-php81/Resources/stubs/ReturnTypeWillChange.php000064400000000201150432043210017221 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Php81 as p; if (\PHP_VERSION_ID >= 80100) { return; } if (defined('MYSQLI_REFRESH_SLAVE') && !defined('MYSQLI_REFRESH_REPLICA')) { define('MYSQLI_REFRESH_REPLICA', 64); } if (!function_exists('array_is_list')) { function array_is_list(array $array): bool { return p\Php81::array_is_list($array); } } if (!function_exists('enum_exists')) { function enum_exists(string $enum, bool $autoload = true): bool { return $autoload && class_exists($enum) && false; } } polyfill-php81/composer.json000064400000001734150432043210012055 0ustar00{ "name": "symfony/polyfill-php81", "type": "library", "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "keywords": ["polyfill", "shim", "compatibility", "portable"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php81\\": "" }, "files": [ "bootstrap.php" ], "classmap": [ "Resources/stubs" ] }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-php81/Php81.php000064400000001243150432043210010737 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Php81; /** * @author Nicolas Grekas * * @internal */ final class Php81 { public static function array_is_list(array $array): bool { if ([] === $array) { return true; } $nextKey = -1; foreach ($array as $k => $v) { if ($k !== ++$nextKey) { return false; } } return true; } } polyfill-php81/LICENSE000064400000002044150432043210010333 0ustar00Copyright (c) 2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. polyfill-intl-grapheme/README.md000064400000003115150432043210012401 0ustar00Symfony Polyfill / Intl: Grapheme ================================= This component provides a partial, native PHP implementation of the [Grapheme functions](https://php.net/intl.grapheme) from the [Intl](https://php.net/intl) extension. - [`grapheme_extract`](https://php.net/grapheme_extract): Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8 - [`grapheme_stripos`](https://php.net/grapheme_stripos): Find position (in grapheme units) of first occurrence of a case-insensitive string - [`grapheme_stristr`](https://php.net/grapheme_stristr): Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack - [`grapheme_strlen`](https://php.net/grapheme_strlen): Get string length in grapheme units - [`grapheme_strpos`](https://php.net/grapheme_strpos): Find position (in grapheme units) of first occurrence of a string - [`grapheme_strripos`](https://php.net/grapheme_strripos): Find position (in grapheme units) of last occurrence of a case-insensitive string - [`grapheme_strrpos`](https://php.net/grapheme_strrpos): Find position (in grapheme units) of last occurrence of a string - [`grapheme_strstr`](https://php.net/grapheme_strstr): Returns part of haystack string from the first occurrence of needle to the end of haystack - [`grapheme_substr`](https://php.net/grapheme_substr): Return part of a string More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). License ======= This library is released under the [MIT license](LICENSE). polyfill-intl-grapheme/bootstrap80.php000064400000005147150432043210014027 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Intl\Grapheme as p; if (!defined('GRAPHEME_EXTR_COUNT')) { define('GRAPHEME_EXTR_COUNT', 0); } if (!defined('GRAPHEME_EXTR_MAXBYTES')) { define('GRAPHEME_EXTR_MAXBYTES', 1); } if (!defined('GRAPHEME_EXTR_MAXCHARS')) { define('GRAPHEME_EXTR_MAXCHARS', 2); } if (!function_exists('grapheme_extract')) { function grapheme_extract(?string $haystack, ?int $size, ?int $type = GRAPHEME_EXTR_COUNT, ?int $offset = 0, &$next = null): string|false { return p\Grapheme::grapheme_extract((string) $haystack, (int) $size, (int) $type, (int) $offset, $next); } } if (!function_exists('grapheme_stripos')) { function grapheme_stripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_stripos((string) $haystack, (string) $needle, (int) $offset); } } if (!function_exists('grapheme_stristr')) { function grapheme_stristr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_stristr((string) $haystack, (string) $needle, (bool) $beforeNeedle); } } if (!function_exists('grapheme_strlen')) { function grapheme_strlen(?string $string): int|false|null { return p\Grapheme::grapheme_strlen((string) $string); } } if (!function_exists('grapheme_strpos')) { function grapheme_strpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strpos((string) $haystack, (string) $needle, (int) $offset); } } if (!function_exists('grapheme_strripos')) { function grapheme_strripos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strripos((string) $haystack, (string) $needle, (int) $offset); } } if (!function_exists('grapheme_strrpos')) { function grapheme_strrpos(?string $haystack, ?string $needle, ?int $offset = 0): int|false { return p\Grapheme::grapheme_strrpos((string) $haystack, (string) $needle, (int) $offset); } } if (!function_exists('grapheme_strstr')) { function grapheme_strstr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false): string|false { return p\Grapheme::grapheme_strstr((string) $haystack, (string) $needle, (bool) $beforeNeedle); } } if (!function_exists('grapheme_substr')) { function grapheme_substr(?string $string, ?int $offset, ?int $length = null): string|false { return p\Grapheme::grapheme_substr((string) $string, (int) $offset, $length); } } polyfill-intl-grapheme/bootstrap.php000064400000004345150432043210013656 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ use Symfony\Polyfill\Intl\Grapheme as p; if (extension_loaded('intl')) { return; } if (\PHP_VERSION_ID >= 80000) { return require __DIR__.'/bootstrap80.php'; } if (!defined('GRAPHEME_EXTR_COUNT')) { define('GRAPHEME_EXTR_COUNT', 0); } if (!defined('GRAPHEME_EXTR_MAXBYTES')) { define('GRAPHEME_EXTR_MAXBYTES', 1); } if (!defined('GRAPHEME_EXTR_MAXCHARS')) { define('GRAPHEME_EXTR_MAXCHARS', 2); } if (!function_exists('grapheme_extract')) { function grapheme_extract($haystack, $size, $type = 0, $start = 0, &$next = 0) { return p\Grapheme::grapheme_extract($haystack, $size, $type, $start, $next); } } if (!function_exists('grapheme_stripos')) { function grapheme_stripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_stripos($haystack, $needle, $offset); } } if (!function_exists('grapheme_stristr')) { function grapheme_stristr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_stristr($haystack, $needle, $beforeNeedle); } } if (!function_exists('grapheme_strlen')) { function grapheme_strlen($input) { return p\Grapheme::grapheme_strlen($input); } } if (!function_exists('grapheme_strpos')) { function grapheme_strpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strpos($haystack, $needle, $offset); } } if (!function_exists('grapheme_strripos')) { function grapheme_strripos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strripos($haystack, $needle, $offset); } } if (!function_exists('grapheme_strrpos')) { function grapheme_strrpos($haystack, $needle, $offset = 0) { return p\Grapheme::grapheme_strrpos($haystack, $needle, $offset); } } if (!function_exists('grapheme_strstr')) { function grapheme_strstr($haystack, $needle, $beforeNeedle = false) { return p\Grapheme::grapheme_strstr($haystack, $needle, $beforeNeedle); } } if (!function_exists('grapheme_substr')) { function grapheme_substr($string, $offset, $length = null) { return p\Grapheme::grapheme_substr($string, $offset, $length); } } polyfill-intl-grapheme/composer.json000064400000002000150432043210013634 0ustar00{ "name": "symfony/polyfill-intl-grapheme", "type": "library", "description": "Symfony polyfill for intl's grapheme_* functions", "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "grapheme"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.1" }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" }, "files": [ "bootstrap.php" ] }, "suggest": { "ext-intl": "For best performance" }, "minimum-stability": "dev", "extra": { "branch-alias": { "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } } } polyfill-intl-grapheme/LICENSE000064400000002051150432043210012125 0ustar00Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. polyfill-intl-grapheme/Grapheme.php000064400000022761150432043210013373 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Polyfill\Intl\Grapheme; \define('SYMFONY_GRAPHEME_CLUSTER_RX', \PCRE_VERSION >= '8.32' ? '\X' : Grapheme::GRAPHEME_CLUSTER_RX); /** * Partial intl implementation in pure PHP. * * Implemented: * - grapheme_extract - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8 * - grapheme_stripos - Find position (in grapheme units) of first occurrence of a case-insensitive string * - grapheme_stristr - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack * - grapheme_strlen - Get string length in grapheme units * - grapheme_strpos - Find position (in grapheme units) of first occurrence of a string * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string * - grapheme_strrpos - Find position (in grapheme units) of last occurrence of a string * - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack * - grapheme_substr - Return part of a string * * @author Nicolas Grekas * * @internal */ final class Grapheme { // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control]) // This regular expression is a work around for http://bugs.exim.org/1279 public const GRAPHEME_CLUSTER_RX = '(?:\r\n|(?:[ -~\x{200C}\x{200D}]|[ᆨ-ᇹ]+|[ᄀ-ᅟ]*(?:[가개갸걔거게겨계고과괘괴교구궈궤귀규그긔기까깨꺄꺠꺼께껴꼐꼬꽈꽤꾀꾜꾸꿔꿰뀌뀨끄끠끼나내냐냬너네녀녜노놔놰뇌뇨누눠눼뉘뉴느늬니다대댜댸더데뎌뎨도돠돼되됴두둬뒈뒤듀드듸디따때땨떄떠떼뗘뗴또똬뙈뙤뚀뚜뚸뛔뛰뜌뜨띄띠라래랴럐러레려례로롸뢔뢰료루뤄뤠뤼류르릐리마매먀먜머메며몌모뫄뫠뫼묘무뭐뭬뮈뮤므믜미바배뱌뱨버베벼볘보봐봬뵈뵤부붜붸뷔뷰브븨비빠빼뺘뺴뻐뻬뼈뼤뽀뽜뽸뾔뾰뿌뿨쀄쀠쀼쁘쁴삐사새샤섀서세셔셰소솨쇄쇠쇼수숴쉐쉬슈스싀시싸쌔쌰썌써쎄쎠쎼쏘쏴쐐쐬쑈쑤쒀쒜쒸쓔쓰씌씨아애야얘어에여예오와왜외요우워웨위유으의이자재쟈쟤저제져졔조좌좨죄죠주줘줴쥐쥬즈즤지짜째쨔쨰쩌쩨쪄쪠쪼쫘쫴쬐쬬쭈쭤쮀쮜쮸쯔쯰찌차채챠챼처체쳐쳬초촤쵀최쵸추춰췌취츄츠츼치카캐캬컈커케켜켸코콰쾌쾨쿄쿠쿼퀘퀴큐크킈키타태탸턔터테텨톄토톼퇘퇴툐투퉈퉤튀튜트틔티파패퍄퍠퍼페펴폐포퐈퐤푀표푸풔풰퓌퓨프픠피하해햐햬허헤혀혜호화홰회효후훠훼휘휴흐희히]?[ᅠ-ᆢ]+|[가-힣])[ᆨ-ᇹ]*|[ᄀ-ᅟ]+|[^\p{Cc}\p{Cf}\p{Zl}\p{Zp}])[\p{Mn}\p{Me}\x{09BE}\x{09D7}\x{0B3E}\x{0B57}\x{0BBE}\x{0BD7}\x{0CC2}\x{0CD5}\x{0CD6}\x{0D3E}\x{0D57}\x{0DCF}\x{0DDF}\x{200C}\x{200D}\x{1D165}\x{1D16E}-\x{1D172}]*|[\p{Cc}\p{Cf}\p{Zl}\p{Zp}])'; private const CASE_FOLD = [ ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"], ['μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1", 'ι'], ]; public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0) { if (0 > $start) { $start = \strlen($s) + $start; } if (!is_scalar($s)) { $hasError = false; set_error_handler(function () use (&$hasError) { $hasError = true; }); $next = substr($s, $start); restore_error_handler(); if ($hasError) { substr($s, $start); $s = ''; } else { $s = $next; } } else { $s = substr($s, $start); } $size = (int) $size; $type = (int) $type; $start = (int) $start; if (\GRAPHEME_EXTR_COUNT !== $type && \GRAPHEME_EXTR_MAXBYTES !== $type && \GRAPHEME_EXTR_MAXCHARS !== $type) { if (80000 > \PHP_VERSION_ID) { return false; } throw new \ValueError('grapheme_extract(): Argument #3 ($type) must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS'); } if (!isset($s[0]) || 0 > $size || 0 > $start) { return false; } if (0 === $size) { return ''; } $next = $start; $s = preg_split('/('.SYMFONY_GRAPHEME_CLUSTER_RX.')/u', "\r\n".$s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE); if (!isset($s[1])) { return false; } $i = 1; $ret = ''; do { if (\GRAPHEME_EXTR_COUNT === $type) { --$size; } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) { $size -= \strlen($s[$i]); } else { $size -= iconv_strlen($s[$i], 'UTF-8//IGNORE'); } if ($size >= 0) { $ret .= $s[$i]; } } while (isset($s[++$i]) && $size > 0); $next += \strlen($ret); return $ret; } public static function grapheme_strlen($s) { preg_replace('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', '', $s, -1, $len); return 0 === $len && '' !== $s ? null : $len; } public static function grapheme_substr($s, $start, $len = null) { if (null === $len) { $len = 2147483647; } preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s, $s); $slen = \count($s[0]); $start = (int) $start; if (0 > $start) { $start += $slen; } if (0 > $start) { if (\PHP_VERSION_ID < 80000) { return false; } $start = 0; } if ($start >= $slen) { return \PHP_VERSION_ID >= 80000 ? '' : false; } $rem = $slen - $start; if (0 > $len) { $len += $rem; } if (0 === $len) { return ''; } if (0 > $len) { return \PHP_VERSION_ID >= 80000 ? '' : false; } if ($len > $rem) { $len = $rem; } return implode('', \array_slice($s[0], $start, $len)); } public static function grapheme_strpos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 0); } public static function grapheme_stripos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 1); } public static function grapheme_strrpos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 2); } public static function grapheme_strripos($s, $needle, $offset = 0) { return self::grapheme_position($s, $needle, $offset, 3); } public static function grapheme_stristr($s, $needle, $beforeNeedle = false) { return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8'); } public static function grapheme_strstr($s, $needle, $beforeNeedle = false) { return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8'); } private static function grapheme_position($s, $needle, $offset, $mode) { $needle = (string) $needle; if (80000 > \PHP_VERSION_ID && !preg_match('/./us', $needle)) { return false; } $s = (string) $s; if (!preg_match('/./us', $s)) { return false; } if ($offset > 0) { $s = self::grapheme_substr($s, $offset); } elseif ($offset < 0) { if (2 > $mode) { $offset += self::grapheme_strlen($s); $s = self::grapheme_substr($s, $offset); if (0 > $offset) { $offset = 0; } } elseif (0 > $offset += self::grapheme_strlen($needle)) { $s = self::grapheme_substr($s, 0, $offset); $offset = 0; } else { $offset = 0; } } // As UTF-8 is self-synchronizing, and we have ensured the strings are valid UTF-8, // we can use normal binary string functions here. For case-insensitive searches, // case fold the strings first. $caseInsensitive = $mode & 1; $reverse = $mode & 2; if ($caseInsensitive) { // Use the same case folding mode as mbstring does for mb_stripos(). // Stick to SIMPLE case folding to avoid changing the length of the string, which // might result in offsets being shifted. $mode = \defined('MB_CASE_FOLD_SIMPLE') ? \MB_CASE_FOLD_SIMPLE : \MB_CASE_LOWER; $s = mb_convert_case($s, $mode, 'UTF-8'); $needle = mb_convert_case($needle, $mode, 'UTF-8'); if (!\defined('MB_CASE_FOLD_SIMPLE')) { $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s); $needle = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $needle); } } if ($reverse) { $needlePos = strrpos($s, $needle); } else { $needlePos = strpos($s, $needle); } return false !== $needlePos ? self::grapheme_strlen(substr($s, 0, $needlePos)) + $offset : false; } } routing/Matcher/CompiledUrlMatcher.php000064400000001535150432043210014050 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** * Matches URLs based on rules dumped by CompiledUrlMatcherDumper. * * @author Nicolas Grekas */ class CompiledUrlMatcher extends UrlMatcher { use CompiledUrlMatcherTrait; public function __construct(array $compiledRoutes, RequestContext $context) { $this->context = $context; [$this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition] = $compiledRoutes; } } routing/Matcher/RequestMatcherInterface.php000064400000002366150432043210015105 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; /** * RequestMatcherInterface is the interface that all request matcher classes must implement. * * @author Fabien Potencier */ interface RequestMatcherInterface { /** * Tries to match a request with a set of routes. * * If the matcher cannot find information, it must throw one of the exceptions documented * below. * * @return array * * @throws NoConfigurationException If no routing configuration could be found * @throws ResourceNotFoundException If no matching resource could be found * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed */ public function matchRequest(Request $request); } routing/Matcher/RedirectableUrlMatcherInterface.php000064400000001564150432043210016524 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; /** * RedirectableUrlMatcherInterface knows how to redirect the user. * * @author Fabien Potencier */ interface RedirectableUrlMatcherInterface { /** * Redirects the user to another URL and returns the parameters for the redirection. * * @param string $path The path info to redirect to * @param string $route The route name that matched * @param string|null $scheme The URL scheme (null to keep the current one) * * @return array */ public function redirect(string $path, string $route, string $scheme = null); } routing/Matcher/RedirectableUrlMatcher.php000064400000004062150432043210014677 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\ExceptionInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; /** * @author Fabien Potencier */ abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface { /** * {@inheritdoc} */ public function match(string $pathinfo) { try { return parent::match($pathinfo); } catch (ResourceNotFoundException $e) { if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { throw $e; } if ($this->allowSchemes) { redirect_scheme: $scheme = $this->context->getScheme(); $this->context->setScheme(current($this->allowSchemes)); try { $ret = parent::match($pathinfo); return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret; } catch (ExceptionInterface $e2) { throw $e; } finally { $this->context->setScheme($scheme); } } elseif ('/' === $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { throw $e; } else { try { $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; $ret = parent::match($pathinfo); return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret; } catch (ExceptionInterface $e2) { if ($this->allowSchemes) { goto redirect_scheme; } throw $e; } } } } } routing/Matcher/UrlMatcher.php000064400000021760150432043210012375 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * UrlMatcher matches URL based on a set of routes. * * @author Fabien Potencier */ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface { public const REQUIREMENT_MATCH = 0; public const REQUIREMENT_MISMATCH = 1; public const ROUTE_MATCH = 2; /** @var RequestContext */ protected $context; /** * Collects HTTP methods that would be allowed for the request. */ protected $allow = []; /** * Collects URI schemes that would be allowed for the request. * * @internal */ protected $allowSchemes = []; protected $routes; protected $request; protected $expressionLanguage; /** * @var ExpressionFunctionProviderInterface[] */ protected $expressionLanguageProviders = []; public function __construct(RouteCollection $routes, RequestContext $context) { $this->routes = $routes; $this->context = $context; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function match(string $pathinfo) { $this->allow = $this->allowSchemes = []; if ($ret = $this->matchCollection(rawurldecode($pathinfo) ?: '/', $this->routes)) { return $ret; } if ('/' === $pathinfo && !$this->allow && !$this->allowSchemes) { throw new NoConfigurationException(); } throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); } /** * {@inheritdoc} */ public function matchRequest(Request $request) { $this->request = $request; $ret = $this->match($request->getPathInfo()); $this->request = null; return $ret; } public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) { $this->expressionLanguageProviders[] = $provider; } /** * Tries to match a URL with a set of routes. * * @param string $pathinfo The path info to be parsed * * @return array * * @throws NoConfigurationException If no routing configuration could be found * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed */ protected function matchCollection(string $pathinfo, RouteCollection $routes) { // HEAD and GET are equivalent as per RFC if ('HEAD' === $method = $this->context->getMethod()) { $method = 'GET'; } $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); $requiredMethods = $route->getMethods(); // check the static prefix of the URL first. Only use the more expensive preg_match when it matches if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) { continue; } $regex = $compiledRoute->getRegex(); $pos = strrpos($regex, '$'); $hasTrailingSlash = '/' === $regex[$pos - 1]; $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); if (!preg_match($regex, $pathinfo, $matches)) { continue; } $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { if ($hasTrailingSlash) { $matches = $m; } else { $hasTrailingVar = false; } } $hostMatches = []; if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { continue; } $status = $this->handleRouteRequirements($pathinfo, $name, $route); if (self::REQUIREMENT_MISMATCH === $status[0]) { continue; } if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { return $this->allow = $this->allowSchemes = []; } continue; } if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); continue; } if ($requiredMethods && !\in_array($method, $requiredMethods)) { $this->allow = array_merge($this->allow, $requiredMethods); continue; } return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, $status[1] ?? [])); } return []; } /** * Returns an array of values to use as request attributes. * * As this method requires the Route object, it is not available * in matchers that do not have access to the matched Route instance * (like the PHP and Apache matcher dumpers). * * @return array */ protected function getAttributes(Route $route, string $name, array $attributes) { $defaults = $route->getDefaults(); if (isset($defaults['_canonical_route'])) { $name = $defaults['_canonical_route']; unset($defaults['_canonical_route']); } $attributes['_route'] = $name; return $this->mergeDefaults($attributes, $defaults); } /** * Handles specific route requirements. * * @return array The first element represents the status, the second contains additional information */ protected function handleRouteRequirements(string $pathinfo, string $name, Route $route) { // expression condition if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) { return [self::REQUIREMENT_MISMATCH, null]; } return [self::REQUIREMENT_MATCH, null]; } /** * Get merged default parameters. * * @return array */ protected function mergeDefaults(array $params, array $defaults) { foreach ($params as $key => $value) { if (!\is_int($key) && null !== $value) { $defaults[$key] = $value; } } return $defaults; } protected function getExpressionLanguage() { if (null === $this->expressionLanguage) { if (!class_exists(ExpressionLanguage::class)) { throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); } return $this->expressionLanguage; } /** * @internal */ protected function createRequest(string $pathinfo): ?Request { if (!class_exists(Request::class)) { return null; } return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], [ 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), 'SCRIPT_NAME' => $this->context->getBaseUrl(), ]); } } routing/Matcher/Dumper/StaticPrefixCollection.php000064400000015602150432043210016202 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\RouteCollection; /** * Prefix tree of routes preserving routes order. * * @author Frank de Jonge * @author Nicolas Grekas * * @internal */ class StaticPrefixCollection { private $prefix; /** * @var string[] */ private $staticPrefixes = []; /** * @var string[] */ private $prefixes = []; /** * @var array[]|self[] */ private $items = []; public function __construct(string $prefix = '/') { $this->prefix = $prefix; } public function getPrefix(): string { return $this->prefix; } /** * @return array[]|self[] */ public function getRoutes(): array { return $this->items; } /** * Adds a route to a group. * * @param array|self $route */ public function addRoute(string $prefix, $route) { [$prefix, $staticPrefix] = $this->getCommonPrefix($prefix, $prefix); for ($i = \count($this->items) - 1; 0 <= $i; --$i) { $item = $this->items[$i]; [$commonPrefix, $commonStaticPrefix] = $this->getCommonPrefix($prefix, $this->prefixes[$i]); if ($this->prefix === $commonPrefix) { // the new route and a previous one have no common prefix, let's see if they are exclusive to each others if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) { // the new route and the previous one have exclusive static prefixes continue; } if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) { // the new route and the previous one have no static prefix break; } if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) { // the previous route is non-static and has no static prefix break; } if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) { // the new route is non-static and has no static prefix break; } continue; } if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) { // the new route is a child of a previous one, let's nest it $item->addRoute($prefix, $route); } else { // the new route and a previous one have a common prefix, let's merge them $child = new self($commonPrefix); [$child->prefixes[0], $child->staticPrefixes[0]] = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); [$child->prefixes[1], $child->staticPrefixes[1]] = $child->getCommonPrefix($prefix, $prefix); $child->items = [$this->items[$i], $route]; $this->staticPrefixes[$i] = $commonStaticPrefix; $this->prefixes[$i] = $commonPrefix; $this->items[$i] = $child; } return; } // No optimised case was found, in this case we simple add the route for possible // grouping when new routes are added. $this->staticPrefixes[] = $staticPrefix; $this->prefixes[] = $prefix; $this->items[] = $route; } /** * Linearizes back a set of nested routes into a collection. */ public function populateCollection(RouteCollection $routes): RouteCollection { foreach ($this->items as $route) { if ($route instanceof self) { $route->populateCollection($routes); } else { $routes->add(...$route); } } return $routes; } /** * Gets the full and static common prefixes between two route patterns. * * The static prefix stops at last at the first opening bracket. */ private function getCommonPrefix(string $prefix, string $anotherPrefix): array { $baseLength = \strlen($this->prefix); $end = min(\strlen($prefix), \strlen($anotherPrefix)); $staticLength = null; set_error_handler([__CLASS__, 'handleError']); try { for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) { if ('(' === $prefix[$i]) { $staticLength = $staticLength ?? $i; for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) { if ($prefix[$j] !== $anotherPrefix[$j]) { break 2; } if ('(' === $prefix[$j]) { ++$n; } elseif (')' === $prefix[$j]) { --$n; } elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) { --$j; break; } } if (0 < $n) { break; } if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) { break; } $subPattern = substr($prefix, $i, $j - $i); if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) { do { // Prevent cutting in the middle of an UTF-8 characters --$i; } while (0b10 === (\ord($prefix[$i]) >> 6)); } return [substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)]; } public static function handleError(int $type, string $msg) { return str_contains($msg, 'Compilation failed: lookbehind assertion is not fixed length'); } } routing/Matcher/Dumper/MatcherDumperInterface.php000064400000001564150432043210016144 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\RouteCollection; /** * MatcherDumperInterface is the interface that all matcher dumper classes must implement. * * @author Fabien Potencier */ interface MatcherDumperInterface { /** * Dumps a set of routes to a string representation of executable code * that can then be used to match a request against these routes. * * @return string */ public function dump(array $options = []); /** * Gets the routes to dump. * * @return RouteCollection */ public function getRoutes(); } routing/Matcher/Dumper/CompiledUrlMatcherTrait.php000064400000016676150432043210016324 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; use Symfony\Component\Routing\RequestContext; /** * @author Nicolas Grekas * * @internal * * @property RequestContext $context */ trait CompiledUrlMatcherTrait { private $matchHost = false; private $staticRoutes = []; private $regexpList = []; private $dynamicRoutes = []; /** * @var callable|null */ private $checkCondition; public function match(string $pathinfo): array { $allow = $allowSchemes = []; if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { return $ret; } if ($allow) { throw new MethodNotAllowedException(array_keys($allow)); } if (!$this instanceof RedirectableUrlMatcherInterface) { throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); } if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { // no-op } elseif ($allowSchemes) { redirect_scheme: $scheme = $this->context->getScheme(); $this->context->setScheme(key($allowSchemes)); try { if ($ret = $this->doMatch($pathinfo)) { return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret; } } finally { $this->context->setScheme($scheme); } } elseif ('/' !== $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { return $this->redirect($pathinfo, $ret['_route']) + $ret; } if ($allowSchemes) { goto redirect_scheme; } } throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); } private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array { $allow = $allowSchemes = []; $pathinfo = rawurldecode($pathinfo) ?: '/'; $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; $context = $this->context; $requestMethod = $canonicalMethod = $context->getMethod(); if ($this->matchHost) { $host = strtolower($context->getHost()); } if ('HEAD' === $requestMethod) { $canonicalMethod = 'GET'; } $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface; foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as [$ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition]) { if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { continue; } if ($requiredHost) { if ('{' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) { continue; } if ('{' === $requiredHost[0] && $hostMatches) { $hostMatches['_route'] = $ret['_route']; $ret = $this->mergeDefaults($hostMatches, $ret); } } if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { return $allow = $allowSchemes = []; } continue; } $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]); if ($hasRequiredScheme && $requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { $allow += $requiredMethods; continue; } if (!$hasRequiredScheme) { $allowSchemes += $requiredSchemes; continue; } return $ret; } $matchedPathinfo = $this->matchHost ? $host.'.'.$pathinfo : $pathinfo; foreach ($this->regexpList as $offset => $regex) { while (preg_match($regex, $matchedPathinfo, $matches)) { foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as [$ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition]) { if (null !== $condition) { if (0 === $condition) { // marks the last route in the regexp continue 3; } if (!($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { continue; } } $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar; if ($hasTrailingVar && ($hasTrailingSlash || (null === $n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { if ($hasTrailingSlash) { $matches = $n; } else { $hasTrailingVar = false; } } if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { return $allow = $allowSchemes = []; } continue; } foreach ($vars as $i => $v) { if (isset($matches[1 + $i])) { $ret[$v] = $matches[1 + $i]; } } if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) { $allowSchemes += $requiredSchemes; continue; } if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { $allow += $requiredMethods; continue; } return $ret; } $regex = substr_replace($regex, 'F', $m - $offset, 1 + \strlen($m)); $offset += \strlen($m); } } if ('/' === $pathinfo && !$allow && !$allowSchemes) { throw new NoConfigurationException(); } return []; } } routing/Matcher/Dumper/MatcherDumper.php000064400000001407150432043210014317 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\Routing\RouteCollection; /** * MatcherDumper is the abstract class for all built-in matcher dumpers. * * @author Fabien Potencier */ abstract class MatcherDumper implements MatcherDumperInterface { private $routes; public function __construct(RouteCollection $routes) { $this->routes = $routes; } /** * {@inheritdoc} */ public function getRoutes() { return $this->routes; } } routing/Matcher/Dumper/CompiledUrlMatcherDumper.php000064400000045113150432043210016461 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher\Dumper; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher. * * @author Fabien Potencier * @author Tobias Schultze * @author Arnaud Le Blanc * @author Nicolas Grekas */ class CompiledUrlMatcherDumper extends MatcherDumper { private $expressionLanguage; private $signalingException; /** * @var ExpressionFunctionProviderInterface[] */ private $expressionLanguageProviders = []; /** * {@inheritdoc} */ public function dump(array $options = []) { return <<generateCompiledRoutes()}]; EOF; } public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) { $this->expressionLanguageProviders[] = $provider; } /** * Generates the arrays for CompiledUrlMatcher's constructor. */ public function getCompiledRoutes(bool $forDump = false): array { // Group hosts by same-suffix, re-order when possible $matchHost = false; $routes = new StaticPrefixCollection(); foreach ($this->getRoutes()->all() as $name => $route) { if ($host = $route->getHost()) { $matchHost = true; $host = '/'.strtr(strrev($host), '}.{', '(/)'); } $routes->addRoute($host ?: '/(.*)', [$name, $route]); } if ($matchHost) { $compiledRoutes = [true]; $routes = $routes->populateCollection(new RouteCollection()); } else { $compiledRoutes = [false]; $routes = $this->getRoutes(); } [$staticRoutes, $dynamicRoutes] = $this->groupStaticRoutes($routes); $conditions = [null]; $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); $chunkLimit = \count($dynamicRoutes); while (true) { try { $this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large'); $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions)); break; } catch (\Exception $e) { if (1 < $chunkLimit && $this->signalingException === $e) { $chunkLimit = 1 + ($chunkLimit >> 1); continue; } throw $e; } } if ($forDump) { $compiledRoutes[2] = $compiledRoutes[4]; } unset($conditions[0]); if ($conditions) { foreach ($conditions as $expression => $condition) { $conditions[$expression] = "case {$condition}: return {$expression};"; } $checkConditionCode = <<indent(implode("\n", $conditions), 3)} } } EOF; $compiledRoutes[4] = $forDump ? $checkConditionCode.",\n" : eval('return '.$checkConditionCode.';'); } else { $compiledRoutes[4] = $forDump ? " null, // \$checkCondition\n" : null; } return $compiledRoutes; } private function generateCompiledRoutes(): string { [$matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode] = $this->getCompiledRoutes(true); $code = self::export($matchHost).', // $matchHost'."\n"; $code .= '[ // $staticRoutes'."\n"; foreach ($staticRoutes as $path => $routes) { $code .= sprintf(" %s => [\n", self::export($path)); foreach ($routes as $route) { $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); } $code .= " ],\n"; } $code .= "],\n"; $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode); $code .= '[ // $dynamicRoutes'."\n"; foreach ($dynamicRoutes as $path => $routes) { $code .= sprintf(" %s => [\n", self::export($path)); foreach ($routes as $route) { $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); } $code .= " ],\n"; } $code .= "],\n"; $code = preg_replace('/ => \[\n (\[.+?),\n \],/', ' => [$1],', $code); return $this->indent($code, 1).$checkConditionCode; } /** * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. */ private function groupStaticRoutes(RouteCollection $collection): array { $staticRoutes = $dynamicRegex = []; $dynamicRoutes = new RouteCollection(); foreach ($collection->all() as $name => $route) { $compiledRoute = $route->compile(); $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); $hostRegex = $compiledRoute->getHostRegex(); $regex = $compiledRoute->getRegex(); if ($hasTrailingSlash = '/' !== $route->getPath()) { $pos = strrpos($regex, '$'); $hasTrailingSlash = '/' === $regex[$pos - 1]; $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); } if (!$compiledRoute->getPathVariables()) { $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; $url = $route->getPath(); if ($hasTrailingSlash) { $url = substr($url, 0, -1); } foreach ($dynamicRegex as [$hostRx, $rx, $prefix]) { if (('' === $prefix || str_starts_with($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url.'/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) { $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; $dynamicRoutes->add($name, $route); continue 2; } } $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; } else { $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; $dynamicRoutes->add($name, $route); } } return [$staticRoutes, $dynamicRoutes]; } /** * Compiles static routes in a switch statement. * * Condition-less paths are put in a static array in the switch's default, with generic matching logic. * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. * * @throws \LogicException */ private function compileStaticRoutes(array $staticRoutes, array &$conditions): array { if (!$staticRoutes) { return []; } $compiledRoutes = []; foreach ($staticRoutes as $url => $routes) { $compiledRoutes[$url] = []; foreach ($routes as $name => [$route, $hasTrailingSlash]) { $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions); } } return $compiledRoutes; } /** * Compiles a regular expression followed by a switch statement to match dynamic routes. * * The regular expression matches both the host and the pathinfo at the same time. For stellar performance, * it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible. * * Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23). * This name is used to "switch" to the additional logic required to match the final route. * * Condition-less paths are put in a static array in the switch's default, with generic matching logic. * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. * * Last but not least: * - Because it is not possible to mix unicode/non-unicode patterns in a single regexp, several of them can be generated. * - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the * matching-but-failing subpattern is excluded by replacing its name by "(*F)", which forces a failure-to-match. * To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur. */ private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit, array &$conditions): array { if (!$collection->all()) { return [[], [], '']; } $regexpList = []; $code = ''; $state = (object) [ 'regexMark' => 0, 'regex' => [], 'routes' => [], 'mark' => 0, 'markTail' => 0, 'hostVars' => [], 'vars' => [], ]; $state->getVars = static function ($m) use ($state) { if ('_route' === $m[1]) { return '?:'; } $state->vars[] = $m[1]; return ''; }; $chunkSize = 0; $prev = null; $perModifiers = []; foreach ($collection->all() as $name => $route) { preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) { $chunkSize = 1; $routes = new RouteCollection(); $perModifiers[] = [$rx[0], $routes]; $prev = $rx[0]; } $routes->add($name, $route); } foreach ($perModifiers as [$modifiers, $routes]) { $prev = false; $perHost = []; foreach ($routes->all() as $name => $route) { $regex = $route->compile()->getHostRegex(); if ($prev !== $regex) { $routes = new RouteCollection(); $perHost[] = [$regex, $routes]; $prev = $regex; } $routes->add($name, $route); } $prev = false; $rx = '{^(?'; $code .= "\n {$state->mark} => ".self::export($rx); $startingMark = $state->mark; $state->mark += \strlen($rx); $state->regex = $rx; foreach ($perHost as [$hostRegex, $routes]) { if ($matchHost) { if ($hostRegex) { preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); $state->vars = []; $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; $state->hostVars = $state->vars; } else { $hostRegex = '(?:(?:[^./]*+\.)++)'; $state->hostVars = []; } $state->mark += \strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?"); $code .= "\n .".self::export($rx); $state->regex .= $rx; $prev = true; } $tree = new StaticPrefixCollection(); foreach ($routes->all() as $name => $route) { preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); $state->vars = []; $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { $regex = substr($regex, 0, -1); } $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); } $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); } if ($matchHost) { $code .= "\n .')'"; $state->regex .= ')'; } $rx = ")/?$}{$modifiers}"; $code .= "\n .'{$rx}',"; $state->regex .= $rx; $state->markTail = 0; // if the regex is too large, throw a signaling exception to recompute with smaller chunk size set_error_handler(function ($type, $message) { throw str_contains($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); }); try { preg_match($state->regex, ''); } finally { restore_error_handler(); } $regexpList[$startingMark] = $state->regex; } $state->routes[$state->mark][] = [null, null, null, null, false, false, 0]; unset($state->getVars); return [$regexpList, $state->routes, $code]; } /** * Compiles a regexp tree of subpatterns that matches nested same-prefix routes. * * @param \stdClass $state A simple state object that keeps track of the progress of the compilation, * and gathers the generated switch's "case" and "default" statements */ private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen, array &$conditions): string { $code = ''; $prevRegex = null; $routes = $tree->getRoutes(); foreach ($routes as $i => $route) { if ($route instanceof StaticPrefixCollection) { $prevRegex = null; $prefix = substr($route->getPrefix(), $prefixLen); $state->mark += \strlen($rx = "|{$prefix}(?"); $code .= "\n .".self::export($rx); $state->regex .= $rx; $code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix), $conditions)); $code .= "\n .')'"; $state->regex .= ')'; ++$state->markTail; continue; } [$name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar] = $route; $compiledRoute = $route->compile(); $vars = array_merge($state->hostVars, $vars); if ($compiledRoute->getRegex() === $prevRegex) { $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions); continue; } $state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen; $state->markTail = 2 + \strlen($state->mark); $rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark); $code .= "\n .".self::export($rx); $state->regex .= $rx; $prevRegex = $compiledRoute->getRegex(); $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)]; } return $code; } /** * Compiles a single Route to PHP code used to match it against the path info. */ private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array { $defaults = $route->getDefaults(); if (isset($defaults['_canonical_route'])) { $name = $defaults['_canonical_route']; unset($defaults['_canonical_route']); } if ($condition = $route->getCondition()) { $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); $condition = $conditions[$condition] ?? $conditions[$condition] = (str_contains($condition, '$request') ? 1 : -1) * \count($conditions); } else { $condition = null; } return [ ['_route' => $name] + $defaults, $vars, array_flip($route->getMethods()) ?: null, array_flip($route->getSchemes()) ?: null, $hasTrailingSlash, $hasTrailingVar, $condition, ]; } private function getExpressionLanguage(): ExpressionLanguage { if (null === $this->expressionLanguage) { if (!class_exists(ExpressionLanguage::class)) { throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); } return $this->expressionLanguage; } private function indent(string $code, int $level = 1): string { return preg_replace('/^./m', str_repeat(' ', $level).'$0', $code); } /** * @internal */ public static function export($value): string { if (null === $value) { return 'null'; } if (!\is_array($value)) { if (\is_object($value)) { throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.'); } return str_replace("\n", '\'."\n".\'', var_export($value, true)); } if (!$value) { return '[]'; } $i = 0; $export = '['; foreach ($value as $k => $v) { if ($i === $k) { ++$i; } else { $export .= self::export($k).' => '; if (\is_int($k) && $i < $k) { $i = 1 + $k; } } $export .= self::export($v).', '; } return substr_replace($export, ']', -2); } } routing/Matcher/TraceableUrlMatcher.php000064400000015252150432043210014177 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\ExceptionInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * TraceableUrlMatcher helps debug path info matching by tracing the match. * * @author Fabien Potencier */ class TraceableUrlMatcher extends UrlMatcher { public const ROUTE_DOES_NOT_MATCH = 0; public const ROUTE_ALMOST_MATCHES = 1; public const ROUTE_MATCHES = 2; protected $traces; public function getTraces(string $pathinfo) { $this->traces = []; try { $this->match($pathinfo); } catch (ExceptionInterface $e) { } return $this->traces; } public function getTracesForRequest(Request $request) { $this->request = $request; $traces = $this->getTraces($request->getPathInfo()); $this->request = null; return $traces; } protected function matchCollection(string $pathinfo, RouteCollection $routes) { // HEAD and GET are equivalent as per RFC if ('HEAD' === $method = $this->context->getMethod()) { $method = 'GET'; } $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); $requiredMethods = $route->getMethods(); // check the static prefix of the URL first. Only use the more expensive preg_match when it matches if ('' !== $staticPrefix && !str_starts_with($trimmedPathinfo, $staticPrefix)) { $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); continue; } $regex = $compiledRoute->getRegex(); $pos = strrpos($regex, '$'); $hasTrailingSlash = '/' === $regex[$pos - 1]; $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); if (!preg_match($regex, $pathinfo, $matches)) { // does it match without any requirements? $r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions()); $cr = $r->compile(); if (!preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); continue; } foreach ($route->getRequirements() as $n => $regex) { $r = new Route($route->getPath(), $route->getDefaults(), [$n => $regex], $route->getOptions()); $cr = $r->compile(); if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); continue 2; } } continue; } $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { if ($hasTrailingSlash) { $matches = $m; } else { $hasTrailingVar = false; } } $hostMatches = []; if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } $status = $this->handleRouteRequirements($pathinfo, $name, $route); if (self::REQUIREMENT_MISMATCH === $status[0]) { $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); return $this->allow = $this->allowSchemes = []; } $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); continue; } if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } if ($requiredMethods && !\in_array($method, $requiredMethods)) { $this->allow = array_merge($this->allow, $requiredMethods); $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; } $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, $status[1] ?? [])); } return []; } private function addTrace(string $log, int $level = self::ROUTE_DOES_NOT_MATCH, string $name = null, Route $route = null) { $this->traces[] = [ 'log' => $log, 'name' => $name, 'level' => $level, 'path' => null !== $route ? $route->getPath() : null, ]; } } routing/Matcher/ExpressionLanguageProvider.php000064400000003240150432043210015636 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\ExpressionLanguage\ExpressionFunction; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; use Symfony\Contracts\Service\ServiceProviderInterface; /** * Exposes functions defined in the request context to route conditions. * * @author Ahmed TAILOULOUTE */ class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface { private $functions; public function __construct(ServiceProviderInterface $functions) { $this->functions = $functions; } /** * {@inheritdoc} */ public function getFunctions() { $functions = []; foreach ($this->functions->getProvidedServices() as $function => $type) { $functions[] = new ExpressionFunction( $function, static function (...$args) use ($function) { return sprintf('($context->getParameter(\'_functions\')->get(%s)(%s))', var_export($function, true), implode(', ', $args)); }, function ($values, ...$args) use ($function) { return $values['context']->getParameter('_functions')->get($function)(...$args); } ); } return $functions; } public function get(string $function): callable { return $this->functions->get($function); } } routing/Matcher/UrlMatcherInterface.php000064400000002557150432043210014221 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\RequestContextAwareInterface; /** * UrlMatcherInterface is the interface that all URL matcher classes must implement. * * @author Fabien Potencier */ interface UrlMatcherInterface extends RequestContextAwareInterface { /** * Tries to match a URL path with a set of routes. * * If the matcher cannot find information, it must throw one of the exceptions documented * below. * * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) * * @return array * * @throws NoConfigurationException If no routing configuration could be found * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed */ public function match(string $pathinfo); } routing/README.md000064400000002767150432043210007520 0ustar00Routing Component ================= The Routing component maps an HTTP request to a set of configuration variables. Getting Started --------------- ``` $ composer require symfony/routing ``` ```php use App\Controller\BlogController; use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; $route = new Route('/blog/{slug}', ['_controller' => BlogController::class]); $routes = new RouteCollection(); $routes->add('blog_show', $route); $context = new RequestContext(); // Routing can match routes with incoming requests $matcher = new UrlMatcher($routes, $context); $parameters = $matcher->match('/blog/lorem-ipsum'); // $parameters = [ // '_controller' => 'App\Controller\BlogController', // 'slug' => 'lorem-ipsum', // '_route' => 'blog_show' // ] // Routing can also generate URLs for a given route $generator = new UrlGenerator($routes, $context); $url = $generator->generate('blog_show', [ 'slug' => 'my-blog-post', ]); // $url = '/blog/my-blog-post' ``` Resources --------- * [Documentation](https://symfony.com/doc/current/routing.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) routing/RouteCollectionBuilder.php000064400000022711150432043210013362 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Config\Exception\LoaderLoadException; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; trigger_deprecation('symfony/routing', '5.1', 'The "%s" class is deprecated, use "%s" instead.', RouteCollectionBuilder::class, RoutingConfigurator::class); /** * Helps add and import routes into a RouteCollection. * * @author Ryan Weaver * * @deprecated since Symfony 5.1, use RoutingConfigurator instead */ class RouteCollectionBuilder { /** * @var Route[]|RouteCollectionBuilder[] */ private $routes = []; private $loader; private $defaults = []; private $prefix; private $host; private $condition; private $requirements = []; private $options = []; private $schemes; private $methods; private $resources = []; public function __construct(LoaderInterface $loader = null) { $this->loader = $loader; } /** * Import an external routing resource and returns the RouteCollectionBuilder. * * $routes->import('blog.yml', '/blog'); * * @param mixed $resource * * @return self * * @throws LoaderLoadException */ public function import($resource, string $prefix = '/', string $type = null) { /** @var RouteCollection[] $collections */ $collections = $this->load($resource, $type); // create a builder from the RouteCollection $builder = $this->createBuilder(); foreach ($collections as $collection) { if (null === $collection) { continue; } foreach ($collection->all() as $name => $route) { $builder->addRoute($route, $name); } foreach ($collection->getResources() as $resource) { $builder->addResource($resource); } } // mount into this builder $this->mount($prefix, $builder); return $builder; } /** * Adds a route and returns it for future modification. * * @return Route */ public function add(string $path, string $controller, string $name = null) { $route = new Route($path); $route->setDefault('_controller', $controller); $this->addRoute($route, $name); return $route; } /** * Returns a RouteCollectionBuilder that can be configured and then added with mount(). * * @return self */ public function createBuilder() { return new self($this->loader); } /** * Add a RouteCollectionBuilder. */ public function mount(string $prefix, self $builder) { $builder->prefix = trim(trim($prefix), '/'); $this->routes[] = $builder; } /** * Adds a Route object to the builder. * * @return $this */ public function addRoute(Route $route, string $name = null) { if (null === $name) { // used as a flag to know which routes will need a name later $name = '_unnamed_route_'.spl_object_hash($route); } $this->routes[$name] = $route; return $this; } /** * Sets the host on all embedded routes (unless already set). * * @return $this */ public function setHost(?string $pattern) { $this->host = $pattern; return $this; } /** * Sets a condition on all embedded routes (unless already set). * * @return $this */ public function setCondition(?string $condition) { $this->condition = $condition; return $this; } /** * Sets a default value that will be added to all embedded routes (unless that * default value is already set). * * @param mixed $value * * @return $this */ public function setDefault(string $key, $value) { $this->defaults[$key] = $value; return $this; } /** * Sets a requirement that will be added to all embedded routes (unless that * requirement is already set). * * @param mixed $regex * * @return $this */ public function setRequirement(string $key, $regex) { $this->requirements[$key] = $regex; return $this; } /** * Sets an option that will be added to all embedded routes (unless that * option is already set). * * @param mixed $value * * @return $this */ public function setOption(string $key, $value) { $this->options[$key] = $value; return $this; } /** * Sets the schemes on all embedded routes (unless already set). * * @param array|string $schemes * * @return $this */ public function setSchemes($schemes) { $this->schemes = $schemes; return $this; } /** * Sets the methods on all embedded routes (unless already set). * * @param array|string $methods * * @return $this */ public function setMethods($methods) { $this->methods = $methods; return $this; } /** * Adds a resource for this collection. * * @return $this */ private function addResource(ResourceInterface $resource): self { $this->resources[] = $resource; return $this; } /** * Creates the final RouteCollection and returns it. * * @return RouteCollection */ public function build() { $routeCollection = new RouteCollection(); foreach ($this->routes as $name => $route) { if ($route instanceof Route) { $route->setDefaults(array_merge($this->defaults, $route->getDefaults())); $route->setOptions(array_merge($this->options, $route->getOptions())); foreach ($this->requirements as $key => $val) { if (!$route->hasRequirement($key)) { $route->setRequirement($key, $val); } } if (null !== $this->prefix) { $route->setPath('/'.$this->prefix.$route->getPath()); } if (!$route->getHost()) { $route->setHost($this->host); } if (!$route->getCondition()) { $route->setCondition($this->condition); } if (!$route->getSchemes()) { $route->setSchemes($this->schemes); } if (!$route->getMethods()) { $route->setMethods($this->methods); } // auto-generate the route name if it's been marked if ('_unnamed_route_' === substr($name, 0, 15)) { $name = $this->generateRouteName($route); } $routeCollection->add($name, $route); } else { /* @var self $route */ $subCollection = $route->build(); if (null !== $this->prefix) { $subCollection->addPrefix($this->prefix); } $routeCollection->addCollection($subCollection); } } foreach ($this->resources as $resource) { $routeCollection->addResource($resource); } return $routeCollection; } /** * Generates a route name based on details of this route. */ private function generateRouteName(Route $route): string { $methods = implode('_', $route->getMethods()).'_'; $routeName = $methods.$route->getPath(); $routeName = str_replace(['/', ':', '|', '-'], '_', $routeName); $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); // Collapse consecutive underscores down into a single underscore. $routeName = preg_replace('/_+/', '_', $routeName); return $routeName; } /** * Finds a loader able to load an imported resource and loads it. * * @param mixed $resource A resource * @param string|null $type The resource type or null if unknown * * @return RouteCollection[] * * @throws LoaderLoadException If no loader is found */ private function load($resource, string $type = null): array { if (null === $this->loader) { throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.'); } if ($this->loader->supports($resource, $type)) { $collections = $this->loader->load($resource, $type); return \is_array($collections) ? $collections : [$collections]; } if (null === $resolver = $this->loader->getResolver()) { throw new LoaderLoadException($resource, null, 0, null, $type); } if (false === $loader = $resolver->resolve($resource, $type)) { throw new LoaderLoadException($resource, null, 0, null, $type); } $collections = $loader->load($resource, $type); return \is_array($collections) ? $collections : [$collections]; } } routing/RequestContextAwareInterface.php000064400000001042150432043210014531 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; interface RequestContextAwareInterface { /** * Sets the request context. */ public function setContext(RequestContext $context); /** * Gets the request context. * * @return RequestContext */ public function getContext(); } routing/Generator/UrlGeneratorInterface.php000064400000006641150432043210015125 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; use Symfony\Component\Routing\Exception\InvalidParameterException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\RequestContextAwareInterface; /** * UrlGeneratorInterface is the interface that all URL generator classes must implement. * * The constants in this interface define the different types of resource references that * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 * We are using the term "URL" instead of "URI" as this is more common in web applications * and we do not need to distinguish them as the difference is mostly semantical and * less technical. Generating URIs, i.e. representation-independent resource identifiers, * is also possible. * * @author Fabien Potencier * @author Tobias Schultze */ interface UrlGeneratorInterface extends RequestContextAwareInterface { /** * Generates an absolute URL, e.g. "http://example.com/dir/file". */ public const ABSOLUTE_URL = 0; /** * Generates an absolute path, e.g. "/dir/file". */ public const ABSOLUTE_PATH = 1; /** * Generates a relative path based on the current request path, e.g. "../parent-file". * * @see UrlGenerator::getRelativePath() */ public const RELATIVE_PATH = 2; /** * Generates a network path, e.g. "//example.com/dir/file". * Such reference reuses the current scheme but specifies the host. */ public const NETWORK_PATH = 3; /** * Generates a URL or path for a specific route based on the given parameters. * * Parameters that reference placeholders in the route pattern will substitute them in the * path or host. Extra params are added as query string to the URL. * * When the passed reference type cannot be generated for the route because it requires a different * host or scheme than the current one, the method will return a more comprehensive reference * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH * but the route requires the https scheme whereas the current scheme is http, it will instead return an * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches * the route in any case. * * If there is no route with the given name, the generator must throw the RouteNotFoundException. * * The special parameter _fragment will be used as the document fragment suffixed to the final URL. * * @return string * * @throws RouteNotFoundException If the named route doesn't exist * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement */ public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH); } routing/Generator/Dumper/GeneratorDumperInterface.php000064400000001566150432043210017054 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; use Symfony\Component\Routing\RouteCollection; /** * GeneratorDumperInterface is the interface that all generator dumper classes must implement. * * @author Fabien Potencier */ interface GeneratorDumperInterface { /** * Dumps a set of routes to a string representation of executable code * that can then be used to generate a URL of such a route. * * @return string */ public function dump(array $options = []); /** * Gets the routes to dump. * * @return RouteCollection */ public function getRoutes(); } routing/Generator/Dumper/GeneratorDumper.php000064400000001415150432043210015224 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; use Symfony\Component\Routing\RouteCollection; /** * GeneratorDumper is the base class for all built-in generator dumpers. * * @author Fabien Potencier */ abstract class GeneratorDumper implements GeneratorDumperInterface { private $routes; public function __construct(RouteCollection $routes) { $this->routes = $routes; } /** * {@inheritdoc} */ public function getRoutes() { return $this->routes; } } routing/Generator/Dumper/CompiledUrlGeneratorDumper.php000064400000007620150432043210017370 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator\Dumper; use Symfony\Component\Routing\Exception\RouteCircularReferenceException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; /** * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator. * * @author Fabien Potencier * @author Tobias Schultze * @author Nicolas Grekas */ class CompiledUrlGeneratorDumper extends GeneratorDumper { public function getCompiledRoutes(): array { $compiledRoutes = []; foreach ($this->getRoutes()->all() as $name => $route) { $compiledRoute = $route->compile(); $compiledRoutes[$name] = [ $compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $compiledRoute->getHostTokens(), $route->getSchemes(), [], ]; } return $compiledRoutes; } public function getCompiledAliases(): array { $routes = $this->getRoutes(); $compiledAliases = []; foreach ($routes->getAliases() as $name => $alias) { $deprecations = $alias->isDeprecated() ? [$alias->getDeprecation($name)] : []; $currentId = $alias->getId(); $visited = []; while (null !== $alias = $routes->getAlias($currentId) ?? null) { if (false !== $searchKey = array_search($currentId, $visited)) { $visited[] = $currentId; throw new RouteCircularReferenceException($currentId, \array_slice($visited, $searchKey)); } if ($alias->isDeprecated()) { $deprecations[] = $deprecation = $alias->getDeprecation($currentId); trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); } $visited[] = $currentId; $currentId = $alias->getId(); } if (null === $target = $routes->get($currentId)) { throw new RouteNotFoundException(sprintf('Target route "%s" for alias "%s" does not exist.', $currentId, $name)); } $compiledTarget = $target->compile(); $compiledAliases[$name] = [ $compiledTarget->getVariables(), $target->getDefaults(), $target->getRequirements(), $compiledTarget->getTokens(), $compiledTarget->getHostTokens(), $target->getSchemes(), $deprecations, ]; } return $compiledAliases; } /** * {@inheritdoc} */ public function dump(array $options = []) { return <<generateDeclaredRoutes()} ]; EOF; } /** * Generates PHP code representing an array of defined routes * together with the routes properties (e.g. requirements). */ private function generateDeclaredRoutes(): string { $routes = ''; foreach ($this->getCompiledRoutes() as $name => $properties) { $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties)); } foreach ($this->getCompiledAliases() as $alias => $properties) { $routes .= sprintf("\n '%s' => %s,", $alias, CompiledUrlMatcherDumper::export($properties)); } return $routes; } } routing/Generator/CompiledUrlGenerator.php000064400000004733150432043210014761 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; use Psr\Log\LoggerInterface; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\RequestContext; /** * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper. */ class CompiledUrlGenerator extends UrlGenerator { private $compiledRoutes = []; private $defaultLocale; public function __construct(array $compiledRoutes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) { $this->compiledRoutes = $compiledRoutes; $this->context = $context; $this->logger = $logger; $this->defaultLocale = $defaultLocale; } public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) { $locale = $parameters['_locale'] ?? $this->context->getParameter('_locale') ?: $this->defaultLocale; if (null !== $locale) { do { if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { $name .= '.'.$locale; break; } } while (false !== $locale = strstr($locale, '_', true)); } if (!isset($this->compiledRoutes[$name])) { throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); } [$variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes, $deprecations] = $this->compiledRoutes[$name] + [6 => []]; foreach ($deprecations as $deprecation) { trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); } if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) { if (!\in_array('_locale', $variables, true)) { unset($parameters['_locale']); } elseif (!isset($parameters['_locale'])) { $parameters['_locale'] = $defaults['_locale']; } } return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes); } } routing/Generator/UrlGenerator.php000064400000036336150432043210013310 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; use Psr\Log\LoggerInterface; use Symfony\Component\Routing\Exception\InvalidParameterException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; /** * UrlGenerator can generate a URL or a path for any route in the RouteCollection * based on the passed parameters. * * @author Fabien Potencier * @author Tobias Schultze */ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface { private const QUERY_FRAGMENT_DECODED = [ // RFC 3986 explicitly allows those in the query/fragment to reference other URIs unencoded '%2F' => '/', '%3F' => '?', // reserved chars that have no special meaning for HTTP URIs in a query or fragment // this excludes esp. "&", "=" and also "+" because PHP would treat it as a space (form-encoded) '%40' => '@', '%3A' => ':', '%21' => '!', '%3B' => ';', '%2C' => ',', '%2A' => '*', ]; protected $routes; protected $context; /** * @var bool|null */ protected $strictRequirements = true; protected $logger; private $defaultLocale; /** * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. * * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. * "?" and "#" (would be interpreted wrongly as query and fragment identifier), * "'" and """ (are used as delimiters in HTML). */ protected $decodedChars = [ // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning // some webservers don't allow the slash in encoded form in the path for security reasons anyway // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss '%2F' => '/', '%252F' => '%2F', // the following chars are general delimiters in the URI specification but have only special meaning in the authority component // so they can safely be used in the path in unencoded form '%40' => '@', '%3A' => ':', // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability '%3B' => ';', '%2C' => ',', '%3D' => '=', '%2B' => '+', '%21' => '!', '%2A' => '*', '%7C' => '|', ]; public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) { $this->routes = $routes; $this->context = $context; $this->logger = $logger; $this->defaultLocale = $defaultLocale; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * {@inheritdoc} */ public function setStrictRequirements(?bool $enabled) { $this->strictRequirements = $enabled; } /** * {@inheritdoc} */ public function isStrictRequirements() { return $this->strictRequirements; } /** * {@inheritdoc} */ public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) { $route = null; $locale = $parameters['_locale'] ?? $this->context->getParameter('_locale') ?: $this->defaultLocale; if (null !== $locale) { do { if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) { break; } } while (false !== $locale = strstr($locale, '_', true)); } if (null === $route = $route ?? $this->routes->get($name)) { throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); } // the Route has a cache of its own and is not recompiled as long as it does not get modified $compiledRoute = $route->compile(); $defaults = $route->getDefaults(); $variables = $compiledRoute->getVariables(); if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) { if (!\in_array('_locale', $variables, true)) { unset($parameters['_locale']); } elseif (!isset($parameters['_locale'])) { $parameters['_locale'] = $defaults['_locale']; } } return $this->doGenerate($variables, $defaults, $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes()); } /** * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement * * @return string */ protected function doGenerate(array $variables, array $defaults, array $requirements, array $tokens, array $parameters, string $name, int $referenceType, array $hostTokens, array $requiredSchemes = []) { $variables = array_flip($variables); $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); // all params must be given if ($diff = array_diff_key($variables, $mergedParams)) { throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); } $url = ''; $optional = true; $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.'; foreach ($tokens as $token) { if ('variable' === $token[0]) { $varName = $token[3]; // variable is not important by default $important = $token[5] ?? false; if (!$optional || $important || !\array_key_exists($varName, $defaults) || (null !== $mergedParams[$varName] && (string) $mergedParams[$varName] !== (string) $defaults[$varName])) { // check requirement (while ignoring look-around patterns) if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { throw new InvalidParameterException(strtr($message, ['{parameter}' => $varName, '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$varName]])); } if ($this->logger) { $this->logger->error($message, ['parameter' => $varName, 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$varName]]); } return ''; } $url = $token[1].$mergedParams[$varName].$url; $optional = false; } } else { // static text $url = $token[1].$url; $optional = false; } } if ('' === $url) { $url = '/'; } // the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request) $url = strtr(rawurlencode($url), $this->decodedChars); // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 // so we need to encode them as they are not used for this purpose here // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']); if (str_ends_with($url, '/..')) { $url = substr($url, 0, -2).'%2E%2E'; } elseif (str_ends_with($url, '/.')) { $url = substr($url, 0, -1).'%2E'; } $schemeAuthority = ''; $host = $this->context->getHost(); $scheme = $this->context->getScheme(); if ($requiredSchemes) { if (!\in_array($scheme, $requiredSchemes, true)) { $referenceType = self::ABSOLUTE_URL; $scheme = current($requiredSchemes); } } if ($hostTokens) { $routeHost = ''; foreach ($hostTokens as $token) { if ('variable' === $token[0]) { // check requirement (while ignoring look-around patterns) if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|strictRequirements) { throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); } if ($this->logger) { $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]); } return ''; } $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; } else { $routeHost = $token[1].$routeHost; } } if ($routeHost !== $host) { $host = $routeHost; if (self::ABSOLUTE_URL !== $referenceType) { $referenceType = self::NETWORK_PATH; } } } if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { if ('' !== $host || ('' !== $scheme && 'http' !== $scheme && 'https' !== $scheme)) { $port = ''; if ('http' === $scheme && 80 !== $this->context->getHttpPort()) { $port = ':'.$this->context->getHttpPort(); } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) { $port = ':'.$this->context->getHttpsPort(); } $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "$scheme://"; $schemeAuthority .= $host.$port; } } if (self::RELATIVE_PATH === $referenceType) { $url = self::getRelativePath($this->context->getPathInfo(), $url); } else { $url = $schemeAuthority.$this->context->getBaseUrl().$url; } // add a query string if needed $extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) { return $a == $b ? 0 : 1; }); array_walk_recursive($extra, $caster = static function (&$v) use (&$caster) { if (\is_object($v)) { if ($vars = get_object_vars($v)) { array_walk_recursive($vars, $caster); $v = $vars; } elseif (method_exists($v, '__toString')) { $v = (string) $v; } } }); // extract fragment $fragment = $defaults['_fragment'] ?? ''; if (isset($extra['_fragment'])) { $fragment = $extra['_fragment']; unset($extra['_fragment']); } if ($extra && $query = http_build_query($extra, '', '&', \PHP_QUERY_RFC3986)) { $url .= '?'.strtr($query, self::QUERY_FRAGMENT_DECODED); } if ('' !== $fragment) { $url .= '#'.strtr(rawurlencode($fragment), self::QUERY_FRAGMENT_DECODED); } return $url; } /** * Returns the target path as relative reference from the base path. * * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. * Both paths must be absolute and not contain relative parts. * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. * Furthermore, they can be used to reduce the link size in documents. * * Example target paths, given a base path of "/a/b/c/d": * - "/a/b/c/d" -> "" * - "/a/b/c/" -> "./" * - "/a/b/" -> "../" * - "/a/b/c/other" -> "other" * - "/a/x/y" -> "../../x/y" * * @param string $basePath The base path * @param string $targetPath The target path * * @return string */ public static function getRelativePath(string $basePath, string $targetPath) { if ($basePath === $targetPath) { return ''; } $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); array_pop($sourceDirs); $targetFile = array_pop($targetDirs); foreach ($sourceDirs as $i => $dir) { if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { unset($sourceDirs[$i], $targetDirs[$i]); } else { break; } } $targetDirs[] = $targetFile; $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); // A reference to the same base directory or an empty subdirectory must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used // as the first segment of a relative-path reference, as it would be mistaken for a scheme name // (see http://tools.ietf.org/html/rfc3986#section-4.2). return '' === $path || '/' === $path[0] || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) ? "./$path" : $path; } } routing/Generator/ConfigurableRequirementsInterface.php000064400000004275150432043210017521 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Generator; /** * ConfigurableRequirementsInterface must be implemented by URL generators that * can be configured whether an exception should be generated when the parameters * do not match the requirements. It is also possible to disable the requirements * check for URL generation completely. * * The possible configurations and use-cases: * - setStrictRequirements(true): Throw an exception for mismatching requirements. This * is mostly useful in development environment. * - setStrictRequirements(false): Don't throw an exception but return an empty string as URL for * mismatching requirements and log the problem. Useful when you cannot control all * params because they come from third party libs but don't want to have a 404 in * production environment. It should log the mismatch so one can review it. * - setStrictRequirements(null): Return the URL with the given parameters without * checking the requirements at all. When generating a URL you should either trust * your params or you validated them beforehand because otherwise it would break your * link anyway. So in production environment you should know that params always pass * the requirements. Thus this option allows to disable the check on URL generation for * performance reasons (saving a preg_match for each requirement every time a URL is * generated). * * @author Fabien Potencier * @author Tobias Schultze */ interface ConfigurableRequirementsInterface { /** * Enables or disables the exception on incorrect parameters. * Passing null will deactivate the requirements check completely. */ public function setStrictRequirements(?bool $enabled); /** * Returns whether to throw an exception on incorrect parameters. * Null means the requirements check is deactivated completely. * * @return bool|null */ public function isStrictRequirements(); } routing/RouteCompilerInterface.php000064400000001362150432043210013352 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. * * @author Fabien Potencier */ interface RouteCompilerInterface { /** * Compiles the current route instance. * * @return CompiledRoute * * @throws \LogicException If the Route cannot be compiled because the * path or host pattern is invalid */ public static function compile(Route $route); } routing/RouterInterface.php000064400000001767150432043210012052 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; /** * RouterInterface is the interface that all Router classes must implement. * * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. * * @author Fabien Potencier */ interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface { /** * Gets the RouteCollection instance associated with this Router. * * WARNING: This method should never be used at runtime as it is SLOW. * You might use it in a cache warmer though. * * @return RouteCollection */ public function getRouteCollection(); } routing/DependencyInjection/RoutingResolverPass.php000064400000003165150432043210016664 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; /** * Adds tagged routing.loader services to routing.resolver service. * * @author Fabien Potencier */ class RoutingResolverPass implements CompilerPassInterface { use PriorityTaggedServiceTrait; private $resolverServiceId; private $loaderTag; public function __construct(string $resolverServiceId = 'routing.resolver', string $loaderTag = 'routing.loader') { if (0 < \func_num_args()) { trigger_deprecation('symfony/routing', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->resolverServiceId = $resolverServiceId; $this->loaderTag = $loaderTag; } public function process(ContainerBuilder $container) { if (false === $container->hasDefinition($this->resolverServiceId)) { return; } $definition = $container->getDefinition($this->resolverServiceId); foreach ($this->findAndSortTaggedServices($this->loaderTag, $container) as $id) { $definition->addMethodCall('addLoader', [new Reference($id)]); } } } routing/CHANGELOG.md000064400000027766150432043210010060 0ustar00CHANGELOG ========= 5.3 --- * Already encoded slashes are not decoded nor double-encoded anymore when generating URLs * Add support for per-env configuration in XML and Yaml loaders * Deprecate creating instances of the `Route` annotation class by passing an array of parameters * Add `RoutingConfigurator::env()` to get the current environment 5.2.0 ----- * Added support for inline definition of requirements and defaults for host * Added support for `\A` and `\z` as regex start and end for route requirement * Added support for `#[Route]` attributes 5.1.0 ----- * added the protected method `PhpFileLoader::callConfigurator()` as extension point to ease custom routing configuration * deprecated `RouteCollectionBuilder` in favor of `RoutingConfigurator`. * added "priority" option to annotated routes * added argument `$priority` to `RouteCollection::add()` * deprecated the `RouteCompiler::REGEX_DELIMITER` constant * added `ExpressionLanguageProvider` to expose extra functions to route conditions * added support for a `stateless` keyword for configuring route stateless in PHP, YAML and XML configurations. * added the "hosts" option to be able to configure the host per locale. * added `RequestContext::fromUri()` to ease building the default context 5.0.0 ----- * removed `PhpGeneratorDumper` and `PhpMatcherDumper` * removed `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options * `Serializable` implementing methods for `Route` and `CompiledRoute` are final * removed referencing service route loaders with a single colon * Removed `ServiceRouterLoader` and `ObjectRouteLoader`. 4.4.0 ----- * Deprecated `ServiceRouterLoader` in favor of `ContainerLoader`. * Deprecated `ObjectRouteLoader` in favor of `ObjectLoader`. * Added a way to exclude patterns of resources from being imported by the `import()` method 4.3.0 ----- * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper` * deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options * `Serializable` implementing methods for `Route` and `CompiledRoute` are marked as `@internal` and `@final`. Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible with the new serialization methods in PHP 7.4. * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators * added support for invokable service route loaders 4.2.0 ----- * added fallback to cultureless locale for internationalized routes 4.0.0 ----- * dropped support for using UTF-8 route patterns without using the `utf8` option * dropped support for using UTF-8 route requirements without using the `utf8` option 3.4.0 ----- * Added `NoConfigurationException`. * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_") * Added support for prioritized routing loaders. * Add matched and default parameters to redirect responses * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. 3.3.0 ----- * [DEPRECATION] Class parameters have been deprecated and will be removed in 4.0. * router.options.generator_class * router.options.generator_base_class * router.options.generator_dumper_class * router.options.matcher_class * router.options.matcher_base_class * router.options.matcher_dumper_class * router.options.matcher.cache_class * router.options.generator.cache_class 3.2.0 ----- * Added support for `bool`, `int`, `float`, `string`, `list` and `map` defaults in XML configurations. * Added support for UTF-8 requirements 2.8.0 ----- * allowed specifying a directory to recursively load all routing configuration files it contains * Added ObjectRouteLoader and ServiceRouteLoader that allow routes to be loaded by calling a method on an object/service. * [DEPRECATION] Deprecated the hardcoded value for the `$referenceType` argument of the `UrlGeneratorInterface::generate` method. Use the constants defined in the `UrlGeneratorInterface` instead. Before: ```php $router->generate('blog_show', ['slug' => 'my-blog-post'], true); ``` After: ```php use Symfony\Component\Routing\Generator\UrlGeneratorInterface; $router->generate('blog_show', ['slug' => 'my-blog-post'], UrlGeneratorInterface::ABSOLUTE_URL); ``` 2.5.0 ----- * [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and will be removed in Symfony 3.0, since the performance gains were minimal and it's hard to replicate the behavior of PHP implementation. 2.3.0 ----- * added RequestContext::getQueryString() 2.2.0 ----- * [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0): * The `pattern` setting for a route has been deprecated in favor of `path` * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings Before: ```yaml article_edit: pattern: /article/{id} requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' } ``` ```xml POST|PUT https \d+ ``` ```php $route = new Route(); $route->setPattern('/article/{id}'); $route->setRequirement('_method', 'POST|PUT'); $route->setRequirement('_scheme', 'https'); ``` After: ```yaml article_edit: path: /article/{id} methods: [POST, PUT] schemes: https requirements: { 'id': '\d+' } ``` ```xml \d+ ``` ```php $route = new Route(); $route->setPath('/article/{id}'); $route->setMethods(['POST', 'PUT']); $route->setSchemes('https'); ``` * [BC BREAK] RouteCollection does not behave like a tree structure anymore but as a flat array of Routes. So when using PHP to build the RouteCollection, you must make sure to add routes to the sub-collection before adding it to the parent collection (this is not relevant when using YAML or XML for Route definitions). Before: ```php $rootCollection = new RouteCollection(); $subCollection = new RouteCollection(); $rootCollection->addCollection($subCollection); $subCollection->add('foo', new Route('/foo')); ``` After: ```php $rootCollection = new RouteCollection(); $subCollection = new RouteCollection(); $subCollection->add('foo', new Route('/foo')); $rootCollection->addCollection($subCollection); ``` Also one must call `addCollection` from the bottom to the top hierarchy. So the correct sequence is the following (and not the reverse): ```php $childCollection->addCollection($grandchildCollection); $rootCollection->addCollection($childCollection); ``` * [DEPRECATION] The methods `RouteCollection::getParent()` and `RouteCollection::getRoot()` have been deprecated and will be removed in Symfony 2.3. * [BC BREAK] Misusing the `RouteCollection::addPrefix` method to add defaults, requirements or options without adding a prefix is not supported anymore. So if you called `addPrefix` with an empty prefix or `/` only (both have no relevance), like `addPrefix('', $defaultsArray, $requirementsArray, $optionsArray)` you need to use the new dedicated methods `addDefaults($defaultsArray)`, `addRequirements($requirementsArray)` or `addOptions($optionsArray)` instead. * [DEPRECATION] The `$options` parameter to `RouteCollection::addPrefix()` has been deprecated because adding options has nothing to do with adding a path prefix. If you want to add options to all child routes of a RouteCollection, you can use `addOptions()`. * [DEPRECATION] The method `RouteCollection::getPrefix()` has been deprecated because it suggested that all routes in the collection would have this prefix, which is not necessarily true. On top of that, since there is no tree structure anymore, this method is also useless. Don't worry about performance, prefix optimization for matching is still done in the dumper, which was also improved in 2.2.0 to find even more grouping possibilities. * [DEPRECATION] `RouteCollection::addCollection(RouteCollection $collection)` should now only be used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options` will still work, but have been deprecated. The `addPrefix` method should be used for this use-case instead. Before: `$parentCollection->addCollection($collection, '/prefix', [...], [...])` After: ```php $collection->addPrefix('/prefix', [...], [...]); $parentCollection->addCollection($collection); ``` * added support for the method default argument values when defining a @Route * Adjacent placeholders without separator work now, e.g. `/{x}{y}{z}.{_format}`. * Characters that function as separator between placeholders are now whitelisted to fix routes with normal text around a variable, e.g. `/prefix{var}suffix`. * [BC BREAK] The default requirement of a variable has been changed slightly. Previously it disallowed the previous and the next char around a variable. Now it disallows the slash (`/`) and the next char. Using the previous char added no value and was problematic because the route `/index.{_format}` would be matched by `/index.ht/ml`. * The default requirement now uses possessive quantifiers when possible which improves matching performance by up to 20% because it prevents backtracking when it's not needed. * The ConfigurableRequirementsInterface can now also be used to disable the requirements check on URL generation completely by calling `setStrictRequirements(null)`. It improves performance in production environment as you should know that params always pass the requirements (otherwise it would break your link anyway). * There is no restriction on the route name anymore. So non-alphanumeric characters are now also allowed. * [BC BREAK] `RouteCompilerInterface::compile(Route $route)` was made static (only relevant if you implemented your own RouteCompiler). * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g. "../parent-file" and "//example.com/dir/file". The third parameter in `UrlGeneratorInterface::generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)` now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for claritiy. The old method calls with a Boolean parameter will continue to work because they equal the signature using the constants. 2.1.0 ----- * added RequestMatcherInterface * added RequestContext::fromRequest() * the UrlMatcher does not throw a \LogicException anymore when the required scheme is not the current one * added TraceableUrlMatcher * added the possibility to define options, default values and requirements for placeholders in prefix, including imported routes * added RouterInterface::getRouteCollection * [BC BREAK] the UrlMatcher urldecodes the route parameters only once, they were decoded twice before. Note that the `urldecode()` calls have been changed for a single `rawurldecode()` in order to support `+` for input paths. * added RouteCollection::getRoot method to retrieve the root of a RouteCollection tree * [BC BREAK] made RouteCollection::setParent private which could not have been used anyway without creating inconsistencies * [BC BREAK] RouteCollection::remove also removes a route from parent collections (not only from its children) * added ConfigurableRequirementsInterface that allows to disable exceptions (and generate empty URLs instead) when generating a route with an invalid parameter value routing/Route.php000064400000030306150432043210010036 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * A Route describes a route and its parameters. * * @author Fabien Potencier * @author Tobias Schultze */ class Route implements \Serializable { private $path = '/'; private $host = ''; private $schemes = []; private $methods = []; private $defaults = []; private $requirements = []; private $options = []; private $condition = ''; /** * @var CompiledRoute|null */ private $compiled; /** * Constructor. * * Available options: * * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) * * utf8: Whether UTF-8 matching is enforced ot not * * @param string $path The path pattern to match * @param array $defaults An array of default parameter values * @param array $requirements An array of requirements for parameters (regexes) * @param array $options An array of options * @param string|null $host The host pattern to match * @param string|string[] $schemes A required URI scheme or an array of restricted schemes * @param string|string[] $methods A required HTTP method or an array of restricted methods * @param string|null $condition A condition that should evaluate to true for the route to match */ public function __construct(string $path, array $defaults = [], array $requirements = [], array $options = [], ?string $host = '', $schemes = [], $methods = [], ?string $condition = '') { $this->setPath($path); $this->addDefaults($defaults); $this->addRequirements($requirements); $this->setOptions($options); $this->setHost($host); $this->setSchemes($schemes); $this->setMethods($methods); $this->setCondition($condition); } public function __serialize(): array { return [ 'path' => $this->path, 'host' => $this->host, 'defaults' => $this->defaults, 'requirements' => $this->requirements, 'options' => $this->options, 'schemes' => $this->schemes, 'methods' => $this->methods, 'condition' => $this->condition, 'compiled' => $this->compiled, ]; } /** * @internal */ final public function serialize(): string { return serialize($this->__serialize()); } public function __unserialize(array $data): void { $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; $this->requirements = $data['requirements']; $this->options = $data['options']; $this->schemes = $data['schemes']; $this->methods = $data['methods']; if (isset($data['condition'])) { $this->condition = $data['condition']; } if (isset($data['compiled'])) { $this->compiled = $data['compiled']; } } /** * @internal */ final public function unserialize($serialized) { $this->__unserialize(unserialize($serialized)); } /** * @return string */ public function getPath() { return $this->path; } /** * @return $this */ public function setPath(string $pattern) { $pattern = $this->extractInlineDefaultsAndRequirements($pattern); // A pattern must start with a slash and must not have multiple slashes at the beginning because the // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. $this->path = '/'.ltrim(trim($pattern), '/'); $this->compiled = null; return $this; } /** * @return string */ public function getHost() { return $this->host; } /** * @return $this */ public function setHost(?string $pattern) { $this->host = $this->extractInlineDefaultsAndRequirements((string) $pattern); $this->compiled = null; return $this; } /** * Returns the lowercased schemes this route is restricted to. * So an empty array means that any scheme is allowed. * * @return string[] */ public function getSchemes() { return $this->schemes; } /** * Sets the schemes (e.g. 'https') this route is restricted to. * So an empty array means that any scheme is allowed. * * @param string|string[] $schemes The scheme or an array of schemes * * @return $this */ public function setSchemes($schemes) { $this->schemes = array_map('strtolower', (array) $schemes); $this->compiled = null; return $this; } /** * Checks if a scheme requirement has been set. * * @return bool */ public function hasScheme(string $scheme) { return \in_array(strtolower($scheme), $this->schemes, true); } /** * Returns the uppercased HTTP methods this route is restricted to. * So an empty array means that any method is allowed. * * @return string[] */ public function getMethods() { return $this->methods; } /** * Sets the HTTP methods (e.g. 'POST') this route is restricted to. * So an empty array means that any method is allowed. * * @param string|string[] $methods The method or an array of methods * * @return $this */ public function setMethods($methods) { $this->methods = array_map('strtoupper', (array) $methods); $this->compiled = null; return $this; } /** * @return array */ public function getOptions() { return $this->options; } /** * @return $this */ public function setOptions(array $options) { $this->options = [ 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', ]; return $this->addOptions($options); } /** * @return $this */ public function addOptions(array $options) { foreach ($options as $name => $option) { $this->options[$name] = $option; } $this->compiled = null; return $this; } /** * Sets an option value. * * @param mixed $value The option value * * @return $this */ public function setOption(string $name, $value) { $this->options[$name] = $value; $this->compiled = null; return $this; } /** * Returns the option value or null when not found. * * @return mixed */ public function getOption(string $name) { return $this->options[$name] ?? null; } /** * @return bool */ public function hasOption(string $name) { return \array_key_exists($name, $this->options); } /** * @return array */ public function getDefaults() { return $this->defaults; } /** * @return $this */ public function setDefaults(array $defaults) { $this->defaults = []; return $this->addDefaults($defaults); } /** * @return $this */ public function addDefaults(array $defaults) { if (isset($defaults['_locale']) && $this->isLocalized()) { unset($defaults['_locale']); } foreach ($defaults as $name => $default) { $this->defaults[$name] = $default; } $this->compiled = null; return $this; } /** * @return mixed */ public function getDefault(string $name) { return $this->defaults[$name] ?? null; } /** * @return bool */ public function hasDefault(string $name) { return \array_key_exists($name, $this->defaults); } /** * Sets a default value. * * @param mixed $default The default value * * @return $this */ public function setDefault(string $name, $default) { if ('_locale' === $name && $this->isLocalized()) { return $this; } $this->defaults[$name] = $default; $this->compiled = null; return $this; } /** * @return array */ public function getRequirements() { return $this->requirements; } /** * @return $this */ public function setRequirements(array $requirements) { $this->requirements = []; return $this->addRequirements($requirements); } /** * @return $this */ public function addRequirements(array $requirements) { if (isset($requirements['_locale']) && $this->isLocalized()) { unset($requirements['_locale']); } foreach ($requirements as $key => $regex) { $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); } $this->compiled = null; return $this; } /** * @return string|null */ public function getRequirement(string $key) { return $this->requirements[$key] ?? null; } /** * @return bool */ public function hasRequirement(string $key) { return \array_key_exists($key, $this->requirements); } /** * @return $this */ public function setRequirement(string $key, string $regex) { if ('_locale' === $key && $this->isLocalized()) { return $this; } $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); $this->compiled = null; return $this; } /** * @return string */ public function getCondition() { return $this->condition; } /** * @return $this */ public function setCondition(?string $condition) { $this->condition = (string) $condition; $this->compiled = null; return $this; } /** * Compiles the route. * * @return CompiledRoute * * @throws \LogicException If the Route cannot be compiled because the * path or host pattern is invalid * * @see RouteCompiler which is responsible for the compilation process */ public function compile() { if (null !== $this->compiled) { return $this->compiled; } $class = $this->getOption('compiler_class'); return $this->compiled = $class::compile($this); } private function extractInlineDefaultsAndRequirements(string $pattern): string { if (false === strpbrk($pattern, '?<')) { return $pattern; } return preg_replace_callback('#\{(!?)(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { if (isset($m[4][0])) { $this->setDefault($m[2], '?' !== $m[4] ? substr($m[4], 1) : null); } if (isset($m[3][0])) { $this->setRequirement($m[2], substr($m[3], 1, -1)); } return '{'.$m[1].$m[2].'}'; }, $pattern); } private function sanitizeRequirement(string $key, string $regex) { if ('' !== $regex) { if ('^' === $regex[0]) { $regex = substr($regex, 1); } elseif (0 === strpos($regex, '\\A')) { $regex = substr($regex, 2); } } if (str_ends_with($regex, '$')) { $regex = substr($regex, 0, -1); } elseif (\strlen($regex) - 2 === strpos($regex, '\\z')) { $regex = substr($regex, 0, -2); } if ('' === $regex) { throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key)); } return $regex; } private function isLocalized(): bool { return isset($this->defaults['_locale']) && isset($this->defaults['_canonical_route']) && ($this->requirements['_locale'] ?? null) === preg_quote($this->defaults['_locale']); } } routing/Router.php000064400000030411150432043210010215 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Psr\Log\LoggerInterface; use Symfony\Component\Config\ConfigCacheFactory; use Symfony\Component\Config\ConfigCacheFactoryInterface; use Symfony\Component\Config\ConfigCacheInterface; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\CompiledUrlGenerator; use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; /** * The Router class is an example of the integration of all pieces of the * routing system for easier use. * * @author Fabien Potencier */ class Router implements RouterInterface, RequestMatcherInterface { /** * @var UrlMatcherInterface|null */ protected $matcher; /** * @var UrlGeneratorInterface|null */ protected $generator; /** * @var RequestContext */ protected $context; /** * @var LoaderInterface */ protected $loader; /** * @var RouteCollection|null */ protected $collection; /** * @var mixed */ protected $resource; /** * @var array */ protected $options = []; /** * @var LoggerInterface|null */ protected $logger; /** * @var string|null */ protected $defaultLocale; /** * @var ConfigCacheFactoryInterface|null */ private $configCacheFactory; /** * @var ExpressionFunctionProviderInterface[] */ private $expressionLanguageProviders = []; private static $cache = []; /** * @param mixed $resource The main resource to load */ public function __construct(LoaderInterface $loader, $resource, array $options = [], RequestContext $context = null, LoggerInterface $logger = null, string $defaultLocale = null) { $this->loader = $loader; $this->resource = $resource; $this->logger = $logger; $this->context = $context ?? new RequestContext(); $this->setOptions($options); $this->defaultLocale = $defaultLocale; } /** * Sets options. * * Available options: * * * cache_dir: The cache directory (or null to disable caching) * * debug: Whether to enable debugging or not (false by default) * * generator_class: The name of a UrlGeneratorInterface implementation * * generator_dumper_class: The name of a GeneratorDumperInterface implementation * * matcher_class: The name of a UrlMatcherInterface implementation * * matcher_dumper_class: The name of a MatcherDumperInterface implementation * * resource_type: Type hint for the main resource (optional) * * strict_requirements: Configure strict requirement checking for generators * implementing ConfigurableRequirementsInterface (default is true) * * @throws \InvalidArgumentException When unsupported option is provided */ public function setOptions(array $options) { $this->options = [ 'cache_dir' => null, 'debug' => false, 'generator_class' => CompiledUrlGenerator::class, 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, 'matcher_class' => CompiledUrlMatcher::class, 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, 'resource_type' => null, 'strict_requirements' => true, ]; // check option names and live merge, if errors are encountered Exception will be thrown $invalid = []; foreach ($options as $key => $value) { if (\array_key_exists($key, $this->options)) { $this->options[$key] = $value; } else { $invalid[] = $key; } } if ($invalid) { throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); } } /** * Sets an option. * * @param mixed $value The value * * @throws \InvalidArgumentException */ public function setOption(string $key, $value) { if (!\array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } $this->options[$key] = $value; } /** * Gets an option value. * * @return mixed * * @throws \InvalidArgumentException */ public function getOption(string $key) { if (!\array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } return $this->options[$key]; } /** * {@inheritdoc} */ public function getRouteCollection() { if (null === $this->collection) { $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); } return $this->collection; } /** * {@inheritdoc} */ public function setContext(RequestContext $context) { $this->context = $context; if (null !== $this->matcher) { $this->getMatcher()->setContext($context); } if (null !== $this->generator) { $this->getGenerator()->setContext($context); } } /** * {@inheritdoc} */ public function getContext() { return $this->context; } /** * Sets the ConfigCache factory to use. */ public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory) { $this->configCacheFactory = $configCacheFactory; } /** * {@inheritdoc} */ public function generate(string $name, array $parameters = [], int $referenceType = self::ABSOLUTE_PATH) { return $this->getGenerator()->generate($name, $parameters, $referenceType); } /** * {@inheritdoc} */ public function match(string $pathinfo) { return $this->getMatcher()->match($pathinfo); } /** * {@inheritdoc} */ public function matchRequest(Request $request) { $matcher = $this->getMatcher(); if (!$matcher instanceof RequestMatcherInterface) { // fallback to the default UrlMatcherInterface return $matcher->match($request->getPathInfo()); } return $matcher->matchRequest($request); } /** * Gets the UrlMatcher or RequestMatcher instance associated with this Router. * * @return UrlMatcherInterface|RequestMatcherInterface */ public function getMatcher() { if (null !== $this->matcher) { return $this->matcher; } if (null === $this->options['cache_dir']) { $routes = $this->getRouteCollection(); $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true); if ($compiled) { $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes(); } $this->matcher = new $this->options['matcher_class']($routes, $this->context); if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { foreach ($this->expressionLanguageProviders as $provider) { $this->matcher->addExpressionLanguageProvider($provider); } } return $this->matcher; } $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_matching_routes.php', function (ConfigCacheInterface $cache) { $dumper = $this->getMatcherDumperInstance(); if (method_exists($dumper, 'addExpressionLanguageProvider')) { foreach ($this->expressionLanguageProviders as $provider) { $dumper->addExpressionLanguageProvider($provider); } } $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); } ); return $this->matcher = new $this->options['matcher_class'](self::getCompiledRoutes($cache->getPath()), $this->context); } /** * Gets the UrlGenerator instance associated with this Router. * * @return UrlGeneratorInterface */ public function getGenerator() { if (null !== $this->generator) { return $this->generator; } if (null === $this->options['cache_dir']) { $routes = $this->getRouteCollection(); $aliases = []; $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true); if ($compiled) { $generatorDumper = new CompiledUrlGeneratorDumper($routes); $routes = $generatorDumper->getCompiledRoutes(); $aliases = $generatorDumper->getCompiledAliases(); } $this->generator = new $this->options['generator_class'](array_merge($routes, $aliases), $this->context, $this->logger, $this->defaultLocale); } else { $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/url_generating_routes.php', function (ConfigCacheInterface $cache) { $dumper = $this->getGeneratorDumperInstance(); $cache->write($dumper->dump(), $this->getRouteCollection()->getResources()); } ); $this->generator = new $this->options['generator_class'](self::getCompiledRoutes($cache->getPath()), $this->context, $this->logger, $this->defaultLocale); } if ($this->generator instanceof ConfigurableRequirementsInterface) { $this->generator->setStrictRequirements($this->options['strict_requirements']); } return $this->generator; } public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) { $this->expressionLanguageProviders[] = $provider; } /** * @return GeneratorDumperInterface */ protected function getGeneratorDumperInstance() { return new $this->options['generator_dumper_class']($this->getRouteCollection()); } /** * @return MatcherDumperInterface */ protected function getMatcherDumperInstance() { return new $this->options['matcher_dumper_class']($this->getRouteCollection()); } /** * Provides the ConfigCache factory implementation, falling back to a * default implementation if necessary. */ private function getConfigCacheFactory(): ConfigCacheFactoryInterface { if (null === $this->configCacheFactory) { $this->configCacheFactory = new ConfigCacheFactory($this->options['debug']); } return $this->configCacheFactory; } private static function getCompiledRoutes(string $path): array { if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) { self::$cache = null; } if (null === self::$cache) { return require $path; } if (isset(self::$cache[$path])) { return self::$cache[$path]; } return self::$cache[$path] = require $path; } } routing/composer.json000064400000003156150432043210010754 0ustar00{ "name": "symfony/routing", "type": "library", "description": "Maps an HTTP request to a set of configuration variables", "keywords": ["routing", "router", "URL", "URI"], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-php80": "^1.16" }, "require-dev": { "symfony/config": "^5.3|^6.0", "symfony/http-foundation": "^4.4|^5.0|^6.0", "symfony/yaml": "^4.4|^5.0|^6.0", "symfony/expression-language": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^4.4|^5.0|^6.0", "doctrine/annotations": "^1.12", "psr/log": "^1|^2|^3" }, "conflict": { "doctrine/annotations": "<1.12", "symfony/config": "<5.3", "symfony/dependency-injection": "<4.4", "symfony/yaml": "<4.4" }, "suggest": { "symfony/http-foundation": "For using a Symfony Request object", "symfony/config": "For using the all-in-one router or any loader", "symfony/yaml": "For using the YAML loader", "symfony/expression-language": "For using expression matching" }, "autoload": { "psr-4": { "Symfony\\Component\\Routing\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } routing/CompiledRoute.php000064400000010340150432043210011507 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * CompiledRoutes are returned by the RouteCompiler class. * * @author Fabien Potencier */ class CompiledRoute implements \Serializable { private $variables; private $tokens; private $staticPrefix; private $regex; private $pathVariables; private $hostVariables; private $hostRegex; private $hostTokens; /** * @param string $staticPrefix The static prefix of the compiled route * @param string $regex The regular expression to use to match this route * @param array $tokens An array of tokens to use to generate URL for this route * @param array $pathVariables An array of path variables * @param string|null $hostRegex Host regex * @param array $hostTokens Host tokens * @param array $hostVariables An array of host variables * @param array $variables An array of variables (variables defined in the path and in the host patterns) */ public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, string $hostRegex = null, array $hostTokens = [], array $hostVariables = [], array $variables = []) { $this->staticPrefix = $staticPrefix; $this->regex = $regex; $this->tokens = $tokens; $this->pathVariables = $pathVariables; $this->hostRegex = $hostRegex; $this->hostTokens = $hostTokens; $this->hostVariables = $hostVariables; $this->variables = $variables; } public function __serialize(): array { return [ 'vars' => $this->variables, 'path_prefix' => $this->staticPrefix, 'path_regex' => $this->regex, 'path_tokens' => $this->tokens, 'path_vars' => $this->pathVariables, 'host_regex' => $this->hostRegex, 'host_tokens' => $this->hostTokens, 'host_vars' => $this->hostVariables, ]; } /** * @internal */ final public function serialize(): string { return serialize($this->__serialize()); } public function __unserialize(array $data): void { $this->variables = $data['vars']; $this->staticPrefix = $data['path_prefix']; $this->regex = $data['path_regex']; $this->tokens = $data['path_tokens']; $this->pathVariables = $data['path_vars']; $this->hostRegex = $data['host_regex']; $this->hostTokens = $data['host_tokens']; $this->hostVariables = $data['host_vars']; } /** * @internal */ final public function unserialize($serialized) { $this->__unserialize(unserialize($serialized, ['allowed_classes' => false])); } /** * Returns the static prefix. * * @return string */ public function getStaticPrefix() { return $this->staticPrefix; } /** * Returns the regex. * * @return string */ public function getRegex() { return $this->regex; } /** * Returns the host regex. * * @return string|null */ public function getHostRegex() { return $this->hostRegex; } /** * Returns the tokens. * * @return array */ public function getTokens() { return $this->tokens; } /** * Returns the host tokens. * * @return array */ public function getHostTokens() { return $this->hostTokens; } /** * Returns the variables. * * @return array */ public function getVariables() { return $this->variables; } /** * Returns the path variables. * * @return array */ public function getPathVariables() { return $this->pathVariables; } /** * Returns the host variables. * * @return array */ public function getHostVariables() { return $this->hostVariables; } } routing/Annotation/Route.php000064400000016756150432043210012165 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Annotation; /** * Annotation class for @Route(). * * @Annotation * @NamedArgumentConstructor * @Target({"CLASS", "METHOD"}) * * @author Fabien Potencier * @author Alexander M. Turek */ #[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD)] class Route { private $path; private $localizedPaths = []; private $name; private $requirements = []; private $options = []; private $defaults = []; private $host; private $methods = []; private $schemes = []; private $condition; private $priority; private $env; /** * @param array|string $data data array managed by the Doctrine Annotations library or the path * @param array|string|null $path * @param string[] $requirements * @param string[]|string $methods * @param string[]|string $schemes * * @throws \BadMethodCallException */ public function __construct( $data = [], $path = null, string $name = null, array $requirements = [], array $options = [], array $defaults = [], string $host = null, $methods = [], $schemes = [], string $condition = null, int $priority = null, string $locale = null, string $format = null, bool $utf8 = null, bool $stateless = null, string $env = null ) { if (\is_string($data)) { $data = ['path' => $data]; } elseif (!\is_array($data)) { throw new \TypeError(sprintf('"%s": Argument $data is expected to be a string or array, got "%s".', __METHOD__, get_debug_type($data))); } elseif ([] !== $data) { $deprecation = false; foreach ($data as $key => $val) { if (\in_array($key, ['path', 'name', 'requirements', 'options', 'defaults', 'host', 'methods', 'schemes', 'condition', 'priority', 'locale', 'format', 'utf8', 'stateless', 'env', 'value'])) { $deprecation = true; } } if ($deprecation) { trigger_deprecation('symfony/routing', '5.3', 'Passing an array as first argument to "%s" is deprecated. Use named arguments instead.', __METHOD__); } else { $localizedPaths = $data; $data = ['path' => $localizedPaths]; } } if (null !== $path && !\is_string($path) && !\is_array($path)) { throw new \TypeError(sprintf('"%s": Argument $path is expected to be a string, array or null, got "%s".', __METHOD__, get_debug_type($path))); } $data['path'] = $data['path'] ?? $path; $data['name'] = $data['name'] ?? $name; $data['requirements'] = $data['requirements'] ?? $requirements; $data['options'] = $data['options'] ?? $options; $data['defaults'] = $data['defaults'] ?? $defaults; $data['host'] = $data['host'] ?? $host; $data['methods'] = $data['methods'] ?? $methods; $data['schemes'] = $data['schemes'] ?? $schemes; $data['condition'] = $data['condition'] ?? $condition; $data['priority'] = $data['priority'] ?? $priority; $data['locale'] = $data['locale'] ?? $locale; $data['format'] = $data['format'] ?? $format; $data['utf8'] = $data['utf8'] ?? $utf8; $data['stateless'] = $data['stateless'] ?? $stateless; $data['env'] = $data['env'] ?? $env; $data = array_filter($data, static function ($value): bool { return null !== $value; }); if (isset($data['localized_paths'])) { throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', static::class)); } if (isset($data['value'])) { $data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value']; unset($data['value']); } if (isset($data['path']) && \is_array($data['path'])) { $data['localized_paths'] = $data['path']; unset($data['path']); } if (isset($data['locale'])) { $data['defaults']['_locale'] = $data['locale']; unset($data['locale']); } if (isset($data['format'])) { $data['defaults']['_format'] = $data['format']; unset($data['format']); } if (isset($data['utf8'])) { $data['options']['utf8'] = filter_var($data['utf8'], \FILTER_VALIDATE_BOOLEAN) ?: false; unset($data['utf8']); } if (isset($data['stateless'])) { $data['defaults']['_stateless'] = filter_var($data['stateless'], \FILTER_VALIDATE_BOOLEAN) ?: false; unset($data['stateless']); } foreach ($data as $key => $value) { $method = 'set'.str_replace('_', '', $key); if (!method_exists($this, $method)) { throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, static::class)); } $this->$method($value); } } public function setPath(string $path) { $this->path = $path; } public function getPath() { return $this->path; } public function setLocalizedPaths(array $localizedPaths) { $this->localizedPaths = $localizedPaths; } public function getLocalizedPaths(): array { return $this->localizedPaths; } public function setHost(string $pattern) { $this->host = $pattern; } public function getHost() { return $this->host; } public function setName(string $name) { $this->name = $name; } public function getName() { return $this->name; } public function setRequirements(array $requirements) { $this->requirements = $requirements; } public function getRequirements() { return $this->requirements; } public function setOptions(array $options) { $this->options = $options; } public function getOptions() { return $this->options; } public function setDefaults(array $defaults) { $this->defaults = $defaults; } public function getDefaults() { return $this->defaults; } public function setSchemes($schemes) { $this->schemes = \is_array($schemes) ? $schemes : [$schemes]; } public function getSchemes() { return $this->schemes; } public function setMethods($methods) { $this->methods = \is_array($methods) ? $methods : [$methods]; } public function getMethods() { return $this->methods; } public function setCondition(?string $condition) { $this->condition = $condition; } public function getCondition() { return $this->condition; } public function setPriority(int $priority): void { $this->priority = $priority; } public function getPriority(): ?int { return $this->priority; } public function setEnv(?string $env): void { $this->env = $env; } public function getEnv(): ?string { return $this->env; } } routing/Loader/ObjectLoader.php000064400000005674150432043210012515 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\RouteCollection; /** * A route loader that calls a method on an object to load the routes. * * @author Ryan Weaver */ abstract class ObjectLoader extends Loader { /** * Returns the object that the method will be called on to load routes. * * For example, if your application uses a service container, * the $id may be a service id. * * @return object */ abstract protected function getObject(string $id); /** * Calls the object method that will load the routes. * * @param string $resource object_id::method * @param string|null $type The resource type * * @return RouteCollection */ public function load($resource, string $type = null) { if (!preg_match('/^[^\:]+(?:::(?:[^\:]+))?$/', $resource)) { throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the %s route loader: use the format "object_id::method" or "object_id" if your object class has an "__invoke" method.', $resource, \is_string($type) ? '"'.$type.'"' : 'object')); } $parts = explode('::', $resource); $method = $parts[1] ?? '__invoke'; $loaderObject = $this->getObject($parts[0]); if (!\is_object($loaderObject)) { throw new \TypeError(sprintf('"%s:getObject()" must return an object: "%s" returned.', static::class, get_debug_type($loaderObject))); } if (!\is_callable([$loaderObject, $method])) { throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s".', $method, get_debug_type($loaderObject), $resource)); } $routeCollection = $loaderObject->$method($this, $this->env); if (!$routeCollection instanceof RouteCollection) { $type = get_debug_type($routeCollection); throw new \LogicException(sprintf('The "%s::%s()" method must return a RouteCollection: "%s" returned.', get_debug_type($loaderObject), $method, $type)); } // make the object file tracked so that if it changes, the cache rebuilds $this->addClassResource(new \ReflectionClass($loaderObject), $routeCollection); return $routeCollection; } private function addClassResource(\ReflectionClass $class, RouteCollection $collection) { do { if (is_file($class->getFileName())) { $collection->addResource(new FileResource($class->getFileName())); } } while ($class = $class->getParentClass()); } } routing/Loader/GlobFileLoader.php000064400000002041150432043210012753 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Routing\RouteCollection; /** * GlobFileLoader loads files from a glob pattern. * * @author Nicolas Grekas */ class GlobFileLoader extends FileLoader { /** * {@inheritdoc} */ public function load($resource, string $type = null) { $collection = new RouteCollection(); foreach ($this->glob($resource, false, $globResource) as $path => $info) { $collection->addCollection($this->import($path)); } $collection->addResource($globResource); return $collection; } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return 'glob' === $type; } } routing/Loader/AnnotationFileLoader.php000064400000010677150432043210014220 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\FileLocatorInterface; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\RouteCollection; /** * AnnotationFileLoader loads routing information from annotations set * on a PHP class and its methods. * * @author Fabien Potencier */ class AnnotationFileLoader extends FileLoader { protected $loader; public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) { if (!\function_exists('token_get_all')) { throw new \LogicException('The Tokenizer extension is required for the routing annotation loaders.'); } parent::__construct($locator); $this->loader = $loader; } /** * Loads from annotations from a file. * * @param string $file A PHP file path * @param string|null $type The resource type * * @return RouteCollection|null * * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed */ public function load($file, string $type = null) { $path = $this->locator->locate($file); $collection = new RouteCollection(); if ($class = $this->findClass($path)) { $refl = new \ReflectionClass($class); if ($refl->isAbstract()) { return null; } $collection->addResource(new FileResource($path)); $collection->addCollection($this->loader->load($class, $type)); } gc_mem_caches(); return $collection; } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); } /** * Returns the full class name for the first class in the file. * * @return string|false */ protected function findClass(string $file) { $class = false; $namespace = false; $tokens = token_get_all(file_get_contents($file)); if (1 === \count($tokens) && \T_INLINE_HTML === $tokens[0][0]) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the " true, \T_STRING => true]; if (\defined('T_NAME_QUALIFIED')) { $nsTokens[\T_NAME_QUALIFIED] = true; } for ($i = 0; isset($tokens[$i]); ++$i) { $token = $tokens[$i]; if (!isset($token[1])) { continue; } if (true === $class && \T_STRING === $token[0]) { return $namespace.'\\'.$token[1]; } if (true === $namespace && isset($nsTokens[$token[0]])) { $namespace = $token[1]; while (isset($tokens[++$i][1], $nsTokens[$tokens[$i][0]])) { $namespace .= $tokens[$i][1]; } $token = $tokens[$i]; } if (\T_CLASS === $token[0]) { // Skip usage of ::class constant and anonymous classes $skipClassToken = false; for ($j = $i - 1; $j > 0; --$j) { if (!isset($tokens[$j][1])) { if ('(' === $tokens[$j] || ',' === $tokens[$j]) { $skipClassToken = true; } break; } if (\T_DOUBLE_COLON === $tokens[$j][0] || \T_NEW === $tokens[$j][0]) { $skipClassToken = true; break; } elseif (!\in_array($tokens[$j][0], [\T_WHITESPACE, \T_DOC_COMMENT, \T_COMMENT])) { break; } } if (!$skipClassToken) { $class = true; } } if (\T_NAMESPACE === $token[0]) { $namespace = true; } } return false; } } routing/Loader/ClosureLoader.php000064400000002046150432043210012711 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\Loader; use Symfony\Component\Routing\RouteCollection; /** * ClosureLoader loads routes from a PHP closure. * * The Closure must return a RouteCollection instance. * * @author Fabien Potencier */ class ClosureLoader extends Loader { /** * Loads a Closure. * * @param \Closure $closure A Closure * @param string|null $type The resource type * * @return RouteCollection */ public function load($closure, string $type = null) { return $closure($this->env); } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return $resource instanceof \Closure && (!$type || 'closure' === $type); } } routing/Loader/YamlFileLoader.php000064400000030171150432043210012777 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait; use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait; use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Yaml\Yaml; /** * YamlFileLoader loads Yaml routing files. * * @author Fabien Potencier * @author Tobias Schultze */ class YamlFileLoader extends FileLoader { use HostTrait; use LocalizedRouteTrait; use PrefixTrait; private const AVAILABLE_KEYS = [ 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', 'exclude', 'stateless', ]; private $yamlParser; /** * Loads a Yaml file. * * @param string $file A Yaml file path * @param string|null $type The resource type * * @return RouteCollection * * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid */ public function load($file, string $type = null) { $path = $this->locator->locate($file); if (!stream_is_local($path)) { throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); } if (!file_exists($path)) { throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); } if (null === $this->yamlParser) { $this->yamlParser = new YamlParser(); } try { $parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML: ', $path).$e->getMessage(), 0, $e); } $collection = new RouteCollection(); $collection->addResource(new FileResource($path)); // empty file if (null === $parsedConfig) { return $collection; } // not an array if (!\is_array($parsedConfig)) { throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); } foreach ($parsedConfig as $name => $config) { if (0 === strpos($name, 'when@')) { if (!$this->env || 'when@'.$this->env !== $name) { continue; } foreach ($config as $name => $config) { $this->validate($config, $name.'" when "@'.$this->env, $path); if (isset($config['resource'])) { $this->parseImport($collection, $config, $path, $file); } else { $this->parseRoute($collection, $name, $config, $path); } } continue; } $this->validate($config, $name, $path); if (isset($config['resource'])) { $this->parseImport($collection, $config, $path, $file); } else { $this->parseRoute($collection, $name, $config, $path); } } return $collection; } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return \is_string($resource) && \in_array(pathinfo($resource, \PATHINFO_EXTENSION), ['yml', 'yaml'], true) && (!$type || 'yaml' === $type); } /** * Parses a route and adds it to the RouteCollection. */ protected function parseRoute(RouteCollection $collection, string $name, array $config, string $path) { if (isset($config['alias'])) { $alias = $collection->addAlias($name, $config['alias']); $deprecation = $config['deprecated'] ?? null; if (null !== $deprecation) { $alias->setDeprecated( $deprecation['package'], $deprecation['version'], $deprecation['message'] ?? '' ); } return; } $defaults = $config['defaults'] ?? []; $requirements = $config['requirements'] ?? []; $options = $config['options'] ?? []; foreach ($requirements as $placeholder => $requirement) { if (\is_int($placeholder)) { throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path)); } } if (isset($config['controller'])) { $defaults['_controller'] = $config['controller']; } if (isset($config['locale'])) { $defaults['_locale'] = $config['locale']; } if (isset($config['format'])) { $defaults['_format'] = $config['format']; } if (isset($config['utf8'])) { $options['utf8'] = $config['utf8']; } if (isset($config['stateless'])) { $defaults['_stateless'] = $config['stateless']; } $routes = $this->createLocalizedRoute($collection, $name, $config['path']); $routes->addDefaults($defaults); $routes->addRequirements($requirements); $routes->addOptions($options); $routes->setSchemes($config['schemes'] ?? []); $routes->setMethods($config['methods'] ?? []); $routes->setCondition($config['condition'] ?? null); if (isset($config['host'])) { $this->addHost($routes, $config['host']); } } /** * Parses an import and adds the routes in the resource to the RouteCollection. */ protected function parseImport(RouteCollection $collection, array $config, string $path, string $file) { $type = $config['type'] ?? null; $prefix = $config['prefix'] ?? ''; $defaults = $config['defaults'] ?? []; $requirements = $config['requirements'] ?? []; $options = $config['options'] ?? []; $host = $config['host'] ?? null; $condition = $config['condition'] ?? null; $schemes = $config['schemes'] ?? null; $methods = $config['methods'] ?? null; $trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true; $namePrefix = $config['name_prefix'] ?? null; $exclude = $config['exclude'] ?? null; if (isset($config['controller'])) { $defaults['_controller'] = $config['controller']; } if (isset($config['locale'])) { $defaults['_locale'] = $config['locale']; } if (isset($config['format'])) { $defaults['_format'] = $config['format']; } if (isset($config['utf8'])) { $options['utf8'] = $config['utf8']; } if (isset($config['stateless'])) { $defaults['_stateless'] = $config['stateless']; } $this->setCurrentDir(\dirname($path)); /** @var RouteCollection[] $imported */ $imported = $this->import($config['resource'], $type, false, $file, $exclude) ?: []; if (!\is_array($imported)) { $imported = [$imported]; } foreach ($imported as $subCollection) { $this->addPrefix($subCollection, $prefix, $trailingSlashOnRoot); if (null !== $host) { $this->addHost($subCollection, $host); } if (null !== $condition) { $subCollection->setCondition($condition); } if (null !== $schemes) { $subCollection->setSchemes($schemes); } if (null !== $methods) { $subCollection->setMethods($methods); } if (null !== $namePrefix) { $subCollection->addNamePrefix($namePrefix); } $subCollection->addDefaults($defaults); $subCollection->addRequirements($requirements); $subCollection->addOptions($options); $collection->addCollection($subCollection); } } /** * Validates the route configuration. * * @param array $config A resource config * @param string $name The config key * @param string $path The loaded file path * * @throws \InvalidArgumentException If one of the provided config keys is not supported, * something is missing or the combination is nonsense */ protected function validate($config, string $name, string $path) { if (!\is_array($config)) { throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); } if (isset($config['alias'])) { $this->validateAlias($config, $name, $path); return; } if ($extraKeys = array_diff(array_keys($config), self::AVAILABLE_KEYS)) { throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::AVAILABLE_KEYS))); } if (isset($config['resource']) && isset($config['path'])) { throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name)); } if (!isset($config['resource']) && isset($config['type'])) { throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path)); } if (!isset($config['resource']) && !isset($config['path'])) { throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path)); } if (isset($config['controller']) && isset($config['defaults']['_controller'])) { throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); } if (isset($config['stateless']) && isset($config['defaults']['_stateless'])) { throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" key and the defaults key "_stateless" for "%s".', $path, $name)); } } /** * @throws \InvalidArgumentException If one of the provided config keys is not supported, * something is missing or the combination is nonsense */ private function validateAlias(array $config, string $name, string $path): void { foreach ($config as $key => $value) { if (!\in_array($key, ['alias', 'deprecated'], true)) { throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify other keys than "alias" and "deprecated" for "%s".', $path, $name)); } if ('deprecated' === $key) { if (!isset($value['package'])) { throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "package" of the "deprecated" option for "%s".', $path, $name)); } if (!isset($value['version'])) { throw new \InvalidArgumentException(sprintf('The routing file "%s" must specify the attribute "version" of the "deprecated" option for "%s".', $path, $name)); } } } } } routing/Loader/PhpFileLoader.php000064400000004410150432043210012621 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Symfony\Component\Routing\RouteCollection; /** * PhpFileLoader loads routes from a PHP file. * * The file must return a RouteCollection instance. * * @author Fabien Potencier * @author Nicolas grekas * @author Jules Pietri */ class PhpFileLoader extends FileLoader { /** * Loads a PHP file. * * @param string $file A PHP file path * @param string|null $type The resource type * * @return RouteCollection */ public function load($file, string $type = null) { $path = $this->locator->locate($file); $this->setCurrentDir(\dirname($path)); // the closure forbids access to the private scope in the included file $loader = $this; $load = \Closure::bind(static function ($file) use ($loader) { return include $file; }, null, ProtectedPhpFileLoader::class); $result = $load($path); if (\is_object($result) && \is_callable($result)) { $collection = $this->callConfigurator($result, $path, $file); } else { $collection = $result; } $collection->addResource(new FileResource($path)); return $collection; } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return \is_string($resource) && 'php' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'php' === $type); } protected function callConfigurator(callable $result, string $path, string $file): RouteCollection { $collection = new RouteCollection(); $result(new RoutingConfigurator($collection, $this, $path, $file, $this->env)); return $collection; } } /** * @internal */ final class ProtectedPhpFileLoader extends PhpFileLoader { } routing/Loader/DirectoryLoader.php000064400000002752150432043210013245 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\Routing\RouteCollection; class DirectoryLoader extends FileLoader { /** * {@inheritdoc} */ public function load($file, string $type = null) { $path = $this->locator->locate($file); $collection = new RouteCollection(); $collection->addResource(new DirectoryResource($path)); foreach (scandir($path) as $dir) { if ('.' !== $dir[0]) { $this->setCurrentDir($path); $subPath = $path.'/'.$dir; $subType = null; if (is_dir($subPath)) { $subPath .= '/'; $subType = 'directory'; } $subCollection = $this->import($subPath, $subType, false, $path); $collection->addCollection($subCollection); } } return $collection; } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { // only when type is forced to directory, not to conflict with AnnotationLoader return 'directory' === $type; } } routing/Loader/schema/routing/routing-1.0.xsd000064400000017066150432043210015077 0ustar00 routing/Loader/AnnotationClassLoader.php000064400000032200150432043210014370 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Doctrine\Common\Annotations\Reader; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Loader\LoaderResolverInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * AnnotationClassLoader loads routing information from a PHP class and its methods. * * You need to define an implementation for the configureRoute() method. Most of the * time, this method should define some PHP callable to be called for the route * (a controller in MVC speak). * * The @Route annotation can be set on the class (for global parameters), * and on each method. * * The @Route annotation main value is the route path. The annotation also * recognizes several parameters: requirements, options, defaults, schemes, * methods, host, and name. The name parameter is mandatory. * Here is an example of how you should be able to use it: * /** * * @Route("/Blog") * * / * class Blog * { * /** * * @Route("/", name="blog_index") * * / * public function index() * { * } * /** * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) * * / * public function show() * { * } * } * * On PHP 8, the annotation class can be used as an attribute as well: * #[Route('/Blog')] * class Blog * { * #[Route('/', name: 'blog_index')] * public function index() * { * } * #[Route('/{id}', name: 'blog_post', requirements: ["id" => '\d+'])] * public function show() * { * } * } * * @author Fabien Potencier * @author Alexander M. Turek */ abstract class AnnotationClassLoader implements LoaderInterface { protected $reader; protected $env; /** * @var string */ protected $routeAnnotationClass = RouteAnnotation::class; /** * @var int */ protected $defaultRouteIndex = 0; public function __construct(Reader $reader = null, string $env = null) { $this->reader = $reader; $this->env = $env; } /** * Sets the annotation class to read route properties from. */ public function setRouteAnnotationClass(string $class) { $this->routeAnnotationClass = $class; } /** * Loads from annotations from a class. * * @param string $class A class name * * @return RouteCollection * * @throws \InvalidArgumentException When route can't be parsed */ public function load($class, string $type = null) { if (!class_exists($class)) { throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); } $class = new \ReflectionClass($class); if ($class->isAbstract()) { throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName())); } $globals = $this->getGlobals($class); $collection = new RouteCollection(); $collection->addResource(new FileResource($class->getFileName())); if ($globals['env'] && $this->env !== $globals['env']) { return $collection; } foreach ($class->getMethods() as $method) { $this->defaultRouteIndex = 0; foreach ($this->getAnnotations($method) as $annot) { $this->addRoute($collection, $annot, $globals, $class, $method); } } if (0 === $collection->count() && $class->hasMethod('__invoke')) { $globals = $this->resetGlobals(); foreach ($this->getAnnotations($class) as $annot) { $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); } } return $collection; } /** * @param RouteAnnotation $annot or an object that exposes a similar interface */ protected function addRoute(RouteCollection $collection, object $annot, array $globals, \ReflectionClass $class, \ReflectionMethod $method) { if ($annot->getEnv() && $annot->getEnv() !== $this->env) { return; } $name = $annot->getName(); if (null === $name) { $name = $this->getDefaultRouteName($class, $method); } $name = $globals['name'].$name; $requirements = $annot->getRequirements(); foreach ($requirements as $placeholder => $requirement) { if (\is_int($placeholder)) { throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName())); } } $defaults = array_replace($globals['defaults'], $annot->getDefaults()); $requirements = array_replace($globals['requirements'], $requirements); $options = array_replace($globals['options'], $annot->getOptions()); $schemes = array_merge($globals['schemes'], $annot->getSchemes()); $methods = array_merge($globals['methods'], $annot->getMethods()); $host = $annot->getHost(); if (null === $host) { $host = $globals['host']; } $condition = $annot->getCondition() ?? $globals['condition']; $priority = $annot->getPriority() ?? $globals['priority']; $path = $annot->getLocalizedPaths() ?: $annot->getPath(); $prefix = $globals['localized_paths'] ?: $globals['path']; $paths = []; if (\is_array($path)) { if (!\is_array($prefix)) { foreach ($path as $locale => $localePath) { $paths[$locale] = $prefix.$localePath; } } elseif ($missing = array_diff_key($prefix, $path)) { throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing)))); } else { foreach ($path as $locale => $localePath) { if (!isset($prefix[$locale])) { throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name)); } $paths[$locale] = $prefix[$locale].$localePath; } } } elseif (\is_array($prefix)) { foreach ($prefix as $locale => $localePrefix) { $paths[$locale] = $localePrefix.$path; } } else { $paths[] = $prefix.$path; } foreach ($method->getParameters() as $param) { if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) { continue; } foreach ($paths as $locale => $path) { if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) { $defaults[$param->name] = $param->getDefaultValue(); break; } } } foreach ($paths as $locale => $path) { $route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); $this->configureRoute($route, $class, $method, $annot); if (0 !== $locale) { $route->setDefault('_locale', $locale); $route->setRequirement('_locale', preg_quote($locale)); $route->setDefault('_canonical_route', $name); $collection->add($name.'.'.$locale, $route, $priority); } else { $collection->add($name, $route, $priority); } } } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); } /** * {@inheritdoc} */ public function setResolver(LoaderResolverInterface $resolver) { } /** * {@inheritdoc} */ public function getResolver() { } /** * Gets the default route name for a class method. * * @return string */ protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) { $name = str_replace('\\', '_', $class->name).'_'.$method->name; $name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name); if ($this->defaultRouteIndex > 0) { $name .= '_'.$this->defaultRouteIndex; } ++$this->defaultRouteIndex; return $name; } protected function getGlobals(\ReflectionClass $class) { $globals = $this->resetGlobals(); $annot = null; if (\PHP_VERSION_ID >= 80000 && ($attribute = $class->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF)[0] ?? null)) { $annot = $attribute->newInstance(); } if (!$annot && $this->reader) { $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass); } if ($annot) { if (null !== $annot->getName()) { $globals['name'] = $annot->getName(); } if (null !== $annot->getPath()) { $globals['path'] = $annot->getPath(); } $globals['localized_paths'] = $annot->getLocalizedPaths(); if (null !== $annot->getRequirements()) { $globals['requirements'] = $annot->getRequirements(); } if (null !== $annot->getOptions()) { $globals['options'] = $annot->getOptions(); } if (null !== $annot->getDefaults()) { $globals['defaults'] = $annot->getDefaults(); } if (null !== $annot->getSchemes()) { $globals['schemes'] = $annot->getSchemes(); } if (null !== $annot->getMethods()) { $globals['methods'] = $annot->getMethods(); } if (null !== $annot->getHost()) { $globals['host'] = $annot->getHost(); } if (null !== $annot->getCondition()) { $globals['condition'] = $annot->getCondition(); } $globals['priority'] = $annot->getPriority() ?? 0; $globals['env'] = $annot->getEnv(); foreach ($globals['requirements'] as $placeholder => $requirement) { if (\is_int($placeholder)) { throw new \InvalidArgumentException(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName())); } } } return $globals; } private function resetGlobals(): array { return [ 'path' => null, 'localized_paths' => [], 'requirements' => [], 'options' => [], 'defaults' => [], 'schemes' => [], 'methods' => [], 'host' => '', 'condition' => '', 'name' => '', 'priority' => 0, 'env' => null, ]; } protected function createRoute(string $path, array $defaults, array $requirements, array $options, ?string $host, array $schemes, array $methods, ?string $condition) { return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); } abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $annot); /** * @param \ReflectionClass|\ReflectionMethod $reflection * * @return iterable */ private function getAnnotations(object $reflection): iterable { if (\PHP_VERSION_ID >= 80000) { foreach ($reflection->getAttributes($this->routeAnnotationClass, \ReflectionAttribute::IS_INSTANCEOF) as $attribute) { yield $attribute->newInstance(); } } if (!$this->reader) { return; } $anntotations = $reflection instanceof \ReflectionClass ? $this->reader->getClassAnnotations($reflection) : $this->reader->getMethodAnnotations($reflection); foreach ($anntotations as $annotation) { if ($annotation instanceof $this->routeAnnotationClass) { yield $annotation; } } } } routing/Loader/XmlFileLoader.php000064400000042514150432043210012641 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\Routing\Loader\Configurator\Traits\HostTrait; use Symfony\Component\Routing\Loader\Configurator\Traits\LocalizedRouteTrait; use Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait; use Symfony\Component\Routing\RouteCollection; /** * XmlFileLoader loads XML routing files. * * @author Fabien Potencier * @author Tobias Schultze */ class XmlFileLoader extends FileLoader { use HostTrait; use LocalizedRouteTrait; use PrefixTrait; public const NAMESPACE_URI = 'http://symfony.com/schema/routing'; public const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; /** * Loads an XML file. * * @param string $file An XML file path * @param string|null $type The resource type * * @return RouteCollection * * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be * parsed because it does not validate against the scheme */ public function load($file, string $type = null) { $path = $this->locator->locate($file); $xml = $this->loadFile($path); $collection = new RouteCollection(); $collection->addResource(new FileResource($path)); // process routes and imports foreach ($xml->documentElement->childNodes as $node) { if (!$node instanceof \DOMElement) { continue; } $this->parseNode($collection, $node, $path, $file); } return $collection; } /** * Parses a node from a loaded XML file. * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseNode(RouteCollection $collection, \DOMElement $node, string $path, string $file) { if (self::NAMESPACE_URI !== $node->namespaceURI) { return; } switch ($node->localName) { case 'route': $this->parseRoute($collection, $node, $path); break; case 'import': $this->parseImport($collection, $node, $path, $file); break; case 'when': if (!$this->env || $node->getAttribute('env') !== $this->env) { break; } foreach ($node->childNodes as $node) { if ($node instanceof \DOMElement) { $this->parseNode($collection, $node, $path, $file); } } break; default: throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); } } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return \is_string($resource) && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'xml' === $type); } /** * Parses a route and adds it to the RouteCollection. * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseRoute(RouteCollection $collection, \DOMElement $node, string $path) { if ('' === $id = $node->getAttribute('id')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have an "id" attribute.', $path)); } if ('' !== $alias = $node->getAttribute('alias')) { $alias = $collection->addAlias($id, $alias); if ($deprecationInfo = $this->parseDeprecation($node, $path)) { $alias->setDeprecated($deprecationInfo['package'], $deprecationInfo['version'], $deprecationInfo['message']); } return; } $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY); $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY); [$defaults, $requirements, $options, $condition, $paths, /* $prefixes */, $hosts] = $this->parseConfigs($node, $path); if (!$paths && '' === $node->getAttribute('path')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "path" attribute or child nodes.', $path)); } if ($paths && '' !== $node->getAttribute('path')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "path" attribute and child nodes.', $path)); } $routes = $this->createLocalizedRoute($collection, $id, $paths ?: $node->getAttribute('path')); $routes->addDefaults($defaults); $routes->addRequirements($requirements); $routes->addOptions($options); $routes->setSchemes($schemes); $routes->setMethods($methods); $routes->setCondition($condition); if (null !== $hosts) { $this->addHost($routes, $hosts); } } /** * Parses an import and adds the routes in the resource to the RouteCollection. * * @throws \InvalidArgumentException When the XML is invalid */ protected function parseImport(RouteCollection $collection, \DOMElement $node, string $path, string $file) { if ('' === $resource = $node->getAttribute('resource')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "resource" attribute.', $path)); } $type = $node->getAttribute('type'); $prefix = $node->getAttribute('prefix'); $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY) : null; $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY) : null; $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true; $namePrefix = $node->getAttribute('name-prefix') ?: null; [$defaults, $requirements, $options, $condition, /* $paths */, $prefixes, $hosts] = $this->parseConfigs($node, $path); if ('' !== $prefix && $prefixes) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must not have both a "prefix" attribute and child nodes.', $path)); } $exclude = []; foreach ($node->childNodes as $child) { if ($child instanceof \DOMElement && $child->localName === $exclude && self::NAMESPACE_URI === $child->namespaceURI) { $exclude[] = $child->nodeValue; } } if ($node->hasAttribute('exclude')) { if ($exclude) { throw new \InvalidArgumentException('You cannot use both the attribute "exclude" and tags at the same time.'); } $exclude = [$node->getAttribute('exclude')]; } $this->setCurrentDir(\dirname($path)); /** @var RouteCollection[] $imported */ $imported = $this->import($resource, ('' !== $type ? $type : null), false, $file, $exclude) ?: []; if (!\is_array($imported)) { $imported = [$imported]; } foreach ($imported as $subCollection) { $this->addPrefix($subCollection, $prefixes ?: $prefix, $trailingSlashOnRoot); if (null !== $hosts) { $this->addHost($subCollection, $hosts); } if (null !== $condition) { $subCollection->setCondition($condition); } if (null !== $schemes) { $subCollection->setSchemes($schemes); } if (null !== $methods) { $subCollection->setMethods($methods); } if (null !== $namePrefix) { $subCollection->addNamePrefix($namePrefix); } $subCollection->addDefaults($defaults); $subCollection->addRequirements($requirements); $subCollection->addOptions($options); $collection->addCollection($subCollection); } } /** * @return \DOMDocument * * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors * or when the XML structure is not as expected by the scheme - * see validate() */ protected function loadFile(string $file) { return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); } /** * Parses the config elements (default, requirement, option). * * @throws \InvalidArgumentException When the XML is invalid */ private function parseConfigs(\DOMElement $node, string $path): array { $defaults = []; $requirements = []; $options = []; $condition = null; $prefixes = []; $paths = []; $hosts = []; /** @var \DOMElement $n */ foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { if ($node !== $n->parentNode) { continue; } switch ($n->localName) { case 'path': $paths[$n->getAttribute('locale')] = trim($n->textContent); break; case 'host': $hosts[$n->getAttribute('locale')] = trim($n->textContent); break; case 'prefix': $prefixes[$n->getAttribute('locale')] = trim($n->textContent); break; case 'default': if ($this->isElementValueNull($n)) { $defaults[$n->getAttribute('key')] = null; } else { $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path); } break; case 'requirement': $requirements[$n->getAttribute('key')] = trim($n->textContent); break; case 'option': $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent)); break; case 'condition': $condition = trim($n->textContent); break; default: throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); } } if ($controller = $node->getAttribute('controller')) { if (isset($defaults['_controller'])) { $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name); } $defaults['_controller'] = $controller; } if ($node->hasAttribute('locale')) { $defaults['_locale'] = $node->getAttribute('locale'); } if ($node->hasAttribute('format')) { $defaults['_format'] = $node->getAttribute('format'); } if ($node->hasAttribute('utf8')) { $options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8')); } if ($stateless = $node->getAttribute('stateless')) { if (isset($defaults['_stateless'])) { $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName); throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "stateless" attribute and the defaults key "_stateless" for ', $path).$name); } $defaults['_stateless'] = XmlUtils::phpize($stateless); } if (!$hosts) { $hosts = $node->hasAttribute('host') ? $node->getAttribute('host') : null; } return [$defaults, $requirements, $options, $condition, $paths, $prefixes, $hosts]; } /** * Parses the "default" elements. * * @return array|bool|float|int|string|null */ private function parseDefaultsConfig(\DOMElement $element, string $path) { if ($this->isElementValueNull($element)) { return null; } // Check for existing element nodes in the default element. There can // only be a single element inside a default element. So this element // (if one was found) can safely be returned. foreach ($element->childNodes as $child) { if (!$child instanceof \DOMElement) { continue; } if (self::NAMESPACE_URI !== $child->namespaceURI) { continue; } return $this->parseDefaultNode($child, $path); } // If the default element doesn't contain a nested "bool", "int", "float", // "string", "list", or "map" element, the element contents will be treated // as the string value of the associated default option. return trim($element->textContent); } /** * Recursively parses the value of a "default" element. * * @return array|bool|float|int|string|null * * @throws \InvalidArgumentException when the XML is invalid */ private function parseDefaultNode(\DOMElement $node, string $path) { if ($this->isElementValueNull($node)) { return null; } switch ($node->localName) { case 'bool': return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue); case 'int': return (int) trim($node->nodeValue); case 'float': return (float) trim($node->nodeValue); case 'string': return trim($node->nodeValue); case 'list': $list = []; foreach ($node->childNodes as $element) { if (!$element instanceof \DOMElement) { continue; } if (self::NAMESPACE_URI !== $element->namespaceURI) { continue; } $list[] = $this->parseDefaultNode($element, $path); } return $list; case 'map': $map = []; foreach ($node->childNodes as $element) { if (!$element instanceof \DOMElement) { continue; } if (self::NAMESPACE_URI !== $element->namespaceURI) { continue; } $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path); } return $map; default: throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path)); } } private function isElementValueNull(\DOMElement $element): bool { $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance'; if (!$element->hasAttributeNS($namespaceUri, 'nil')) { return false; } return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil'); } /** * Parses the deprecation elements. * * @throws \InvalidArgumentException When the XML is invalid */ private function parseDeprecation(\DOMElement $node, string $path): array { $deprecatedNode = null; foreach ($node->childNodes as $child) { if (!$child instanceof \DOMElement || self::NAMESPACE_URI !== $child->namespaceURI) { continue; } if ('deprecated' !== $child->localName) { throw new \InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $node->getAttribute('id'), $path)); } $deprecatedNode = $child; } if (null === $deprecatedNode) { return []; } if (!$deprecatedNode->hasAttribute('package')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "package" attribute.', $path)); } if (!$deprecatedNode->hasAttribute('version')) { throw new \InvalidArgumentException(sprintf('The element in file "%s" must have a "version" attribute.', $path)); } return [ 'package' => $deprecatedNode->getAttribute('package'), 'version' => $deprecatedNode->getAttribute('version'), 'message' => trim($deprecatedNode->nodeValue), ]; } } routing/Loader/ContainerLoader.php000064400000001772150432043210013224 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Psr\Container\ContainerInterface; /** * A route loader that executes a service from a PSR-11 container to load the routes. * * @author Ryan Weaver */ class ContainerLoader extends ObjectLoader { private $container; public function __construct(ContainerInterface $container, string $env = null) { $this->container = $container; parent::__construct($env); } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { return 'service' === $type && \is_string($resource); } /** * {@inheritdoc} */ protected function getObject(string $id) { return $this->container->get($id); } } routing/Loader/AnnotationDirectoryLoader.php000064400000005372150432043210015301 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\Routing\RouteCollection; /** * AnnotationDirectoryLoader loads routing information from annotations set * on PHP classes and methods. * * @author Fabien Potencier */ class AnnotationDirectoryLoader extends AnnotationFileLoader { /** * Loads from annotations from a directory. * * @param string $path A directory path * @param string|null $type The resource type * * @return RouteCollection * * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed */ public function load($path, string $type = null) { if (!is_dir($dir = $this->locator->locate($path))) { return parent::supports($path, $type) ? parent::load($path, $type) : new RouteCollection(); } $collection = new RouteCollection(); $collection->addResource(new DirectoryResource($dir, '/\.php$/')); $files = iterator_to_array(new \RecursiveIteratorIterator( new \RecursiveCallbackFilterIterator( new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS), function (\SplFileInfo $current) { return '.' !== substr($current->getBasename(), 0, 1); } ), \RecursiveIteratorIterator::LEAVES_ONLY )); usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { return (string) $a > (string) $b ? 1 : -1; }); foreach ($files as $file) { if (!$file->isFile() || !str_ends_with($file->getFilename(), '.php')) { continue; } if ($class = $this->findClass($file)) { $refl = new \ReflectionClass($class); if ($refl->isAbstract()) { continue; } $collection->addCollection($this->loader->load($class, $type)); } } return $collection; } /** * {@inheritdoc} */ public function supports($resource, string $type = null) { if ('annotation' === $type) { return true; } if ($type || !\is_string($resource)) { return false; } try { return is_dir($this->locator->locate($resource)); } catch (\Exception $e) { return false; } } } routing/Loader/Configurator/ImportConfigurator.php000064400000003674150432043210016455 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator; use Symfony\Component\Routing\RouteCollection; /** * @author Nicolas Grekas */ class ImportConfigurator { use Traits\HostTrait; use Traits\PrefixTrait; use Traits\RouteTrait; private $parent; public function __construct(RouteCollection $parent, RouteCollection $route) { $this->parent = $parent; $this->route = $route; } /** * @return array */ public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { $this->parent->addCollection($this->route); } /** * Sets the prefix to add to the path of all child routes. * * @param string|array $prefix the prefix, or the localized prefixes * * @return $this */ final public function prefix($prefix, bool $trailingSlashOnRoot = true): self { $this->addPrefix($this->route, $prefix, $trailingSlashOnRoot); return $this; } /** * Sets the prefix to add to the name of all child routes. * * @return $this */ final public function namePrefix(string $namePrefix): self { $this->route->addNamePrefix($namePrefix); return $this; } /** * Sets the host to use for all child routes. * * @param string|array $host the host, or the localized hosts * * @return $this */ final public function host($host): self { $this->addHost($this->route, $host); return $this; } } routing/Loader/Configurator/RouteConfigurator.php000064400000002321150432043210016265 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator; use Symfony\Component\Routing\RouteCollection; /** * @author Nicolas Grekas */ class RouteConfigurator { use Traits\AddTrait; use Traits\HostTrait; use Traits\RouteTrait; protected $parentConfigurator; public function __construct(RouteCollection $collection, RouteCollection $route, string $name = '', CollectionConfigurator $parentConfigurator = null, array $prefixes = null) { $this->collection = $collection; $this->route = $route; $this->name = $name; $this->parentConfigurator = $parentConfigurator; // for GC control $this->prefixes = $prefixes; } /** * Sets the host to use for all child routes. * * @param string|array $host the host, or the localized hosts * * @return $this */ final public function host($host): self { $this->addHost($this->route, $host); return $this; } } routing/Loader/Configurator/Traits/AddTrait.php000064400000003362150432043210015554 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator\Traits; use Symfony\Component\Routing\Loader\Configurator\AliasConfigurator; use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator; use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; use Symfony\Component\Routing\RouteCollection; /** * @author Nicolas Grekas */ trait AddTrait { use LocalizedRouteTrait; /** * @var RouteCollection */ protected $collection; protected $name = ''; protected $prefixes; /** * Adds a route. * * @param string|array $path the path, or the localized paths of the route */ public function add(string $name, $path): RouteConfigurator { $parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null); $route = $this->createLocalizedRoute($this->collection, $name, $path, $this->name, $this->prefixes); return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes); } public function alias(string $name, string $alias): AliasConfigurator { return new AliasConfigurator($this->collection->addAlias($name, $alias)); } /** * Adds a route. * * @param string|array $path the path, or the localized paths of the route */ public function __invoke(string $name, $path): RouteConfigurator { return $this->add($name, $path); } } routing/Loader/Configurator/Traits/RouteTrait.php000064400000006752150432043210016170 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator\Traits; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; trait RouteTrait { /** * @var RouteCollection|Route */ protected $route; /** * Adds defaults. * * @return $this */ final public function defaults(array $defaults): self { $this->route->addDefaults($defaults); return $this; } /** * Adds requirements. * * @return $this */ final public function requirements(array $requirements): self { $this->route->addRequirements($requirements); return $this; } /** * Adds options. * * @return $this */ final public function options(array $options): self { $this->route->addOptions($options); return $this; } /** * Whether paths should accept utf8 encoding. * * @return $this */ final public function utf8(bool $utf8 = true): self { $this->route->addOptions(['utf8' => $utf8]); return $this; } /** * Sets the condition. * * @return $this */ final public function condition(string $condition): self { $this->route->setCondition($condition); return $this; } /** * Sets the pattern for the host. * * @return $this */ final public function host(string $pattern): self { $this->route->setHost($pattern); return $this; } /** * Sets the schemes (e.g. 'https') this route is restricted to. * So an empty array means that any scheme is allowed. * * @param string[] $schemes * * @return $this */ final public function schemes(array $schemes): self { $this->route->setSchemes($schemes); return $this; } /** * Sets the HTTP methods (e.g. 'POST') this route is restricted to. * So an empty array means that any method is allowed. * * @param string[] $methods * * @return $this */ final public function methods(array $methods): self { $this->route->setMethods($methods); return $this; } /** * Adds the "_controller" entry to defaults. * * @param callable|string|array $controller a callable or parseable pseudo-callable * * @return $this */ final public function controller($controller): self { $this->route->addDefaults(['_controller' => $controller]); return $this; } /** * Adds the "_locale" entry to defaults. * * @return $this */ final public function locale(string $locale): self { $this->route->addDefaults(['_locale' => $locale]); return $this; } /** * Adds the "_format" entry to defaults. * * @return $this */ final public function format(string $format): self { $this->route->addDefaults(['_format' => $format]); return $this; } /** * Adds the "_stateless" entry to defaults. * * @return $this */ final public function stateless(bool $stateless = true): self { $this->route->addDefaults(['_stateless' => $stateless]); return $this; } } routing/Loader/Configurator/Traits/LocalizedRouteTrait.php000064400000004745150432043210020017 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator\Traits; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * @internal * * @author Nicolas Grekas * @author Jules Pietri */ trait LocalizedRouteTrait { /** * Creates one or many routes. * * @param string|array $path the path, or the localized paths of the route */ final protected function createLocalizedRoute(RouteCollection $collection, string $name, $path, string $namePrefix = '', array $prefixes = null): RouteCollection { $paths = []; $routes = new RouteCollection(); if (\is_array($path)) { if (null === $prefixes) { $paths = $path; } elseif ($missing = array_diff_key($prefixes, $path)) { throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing)))); } else { foreach ($path as $locale => $localePath) { if (!isset($prefixes[$locale])) { throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); } $paths[$locale] = $prefixes[$locale].$localePath; } } } elseif (null !== $prefixes) { foreach ($prefixes as $locale => $prefix) { $paths[$locale] = $prefix.$path; } } else { $routes->add($namePrefix.$name, $route = $this->createRoute($path)); $collection->add($namePrefix.$name, $route); return $routes; } foreach ($paths as $locale => $path) { $routes->add($name.'.'.$locale, $route = $this->createRoute($path)); $collection->add($namePrefix.$name.'.'.$locale, $route); $route->setDefault('_locale', $locale); $route->setRequirement('_locale', preg_quote($locale)); $route->setDefault('_canonical_route', $namePrefix.$name); } return $routes; } private function createRoute(string $path): Route { return new Route($path); } } routing/Loader/Configurator/Traits/HostTrait.php000064400000003177150432043210016005 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator\Traits; use Symfony\Component\Routing\RouteCollection; /** * @internal */ trait HostTrait { final protected function addHost(RouteCollection $routes, $hosts) { if (!$hosts || !\is_array($hosts)) { $routes->setHost($hosts ?: ''); return; } foreach ($routes->all() as $name => $route) { if (null === $locale = $route->getDefault('_locale')) { $routes->remove($name); foreach ($hosts as $locale => $host) { $localizedRoute = clone $route; $localizedRoute->setDefault('_locale', $locale); $localizedRoute->setRequirement('_locale', preg_quote($locale)); $localizedRoute->setDefault('_canonical_route', $name); $localizedRoute->setHost($host); $routes->add($name.'.'.$locale, $localizedRoute); } } elseif (!isset($hosts[$locale])) { throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding host in its parent collection.', $name, $locale)); } else { $route->setHost($hosts[$locale]); $route->setRequirement('_locale', preg_quote($locale)); $routes->add($name, $route); } } } } routing/Loader/Configurator/Traits/PrefixTrait.php000064400000004536150432043210016325 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator\Traits; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * @internal * * @author Nicolas Grekas */ trait PrefixTrait { final protected function addPrefix(RouteCollection $routes, $prefix, bool $trailingSlashOnRoot) { if (\is_array($prefix)) { foreach ($prefix as $locale => $localePrefix) { $prefix[$locale] = trim(trim($localePrefix), '/'); } foreach ($routes->all() as $name => $route) { if (null === $locale = $route->getDefault('_locale')) { $routes->remove($name); foreach ($prefix as $locale => $localePrefix) { $localizedRoute = clone $route; $localizedRoute->setDefault('_locale', $locale); $localizedRoute->setRequirement('_locale', preg_quote($locale)); $localizedRoute->setDefault('_canonical_route', $name); $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); $routes->add($name.'.'.$locale, $localizedRoute); } } elseif (!isset($prefix[$locale])) { throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); } else { $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); $routes->add($name, $route); } } return; } $routes->addPrefix($prefix); if (!$trailingSlashOnRoot) { $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); foreach ($routes->all() as $route) { if ($route->getPath() === $rootPath) { $route->setPath(rtrim($rootPath, '/')); } } } } } routing/Loader/Configurator/RoutingConfigurator.php000064400000004242150432043210016622 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator; use Symfony\Component\Routing\Loader\PhpFileLoader; use Symfony\Component\Routing\RouteCollection; /** * @author Nicolas Grekas */ class RoutingConfigurator { use Traits\AddTrait; private $loader; private $path; private $file; private $env; public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file, string $env = null) { $this->collection = $collection; $this->loader = $loader; $this->path = $path; $this->file = $file; $this->env = $env; } /** * @param string|string[]|null $exclude Glob patterns to exclude from the import */ final public function import($resource, string $type = null, bool $ignoreErrors = false, $exclude = null): ImportConfigurator { $this->loader->setCurrentDir(\dirname($this->path)); $imported = $this->loader->import($resource, $type, $ignoreErrors, $this->file, $exclude) ?: []; if (!\is_array($imported)) { return new ImportConfigurator($this->collection, $imported); } $mergedCollection = new RouteCollection(); foreach ($imported as $subCollection) { $mergedCollection->addCollection($subCollection); } return new ImportConfigurator($this->collection, $mergedCollection); } final public function collection(string $name = ''): CollectionConfigurator { return new CollectionConfigurator($this->collection, $name); } /** * Get the current environment to be able to write conditional configuration. */ final public function env(): ?string { return $this->env; } /** * @return static */ final public function withPath(string $path): self { $clone = clone $this; $clone->path = $clone->file = $path; return $clone; } } routing/Loader/Configurator/AliasConfigurator.php000064400000002270150432043210016223 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\Routing\Alias; class AliasConfigurator { private $alias; public function __construct(Alias $alias) { $this->alias = $alias; } /** * Whether this alias is deprecated, that means it should not be called anymore. * * @param string $package The name of the composer package that is triggering the deprecation * @param string $version The version of the package that introduced the deprecation * @param string $message The deprecation message to use * * @return $this * * @throws InvalidArgumentException when the message template is invalid */ public function deprecate(string $package, string $version, string $message): self { $this->alias->setDeprecated($package, $version, $message); return $this; } } routing/Loader/Configurator/CollectionConfigurator.php000064400000006744150432043210017277 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Loader\Configurator; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * @author Nicolas Grekas */ class CollectionConfigurator { use Traits\AddTrait; use Traits\HostTrait; use Traits\RouteTrait; private $parent; private $parentConfigurator; private $parentPrefixes; private $host; public function __construct(RouteCollection $parent, string $name, self $parentConfigurator = null, array $parentPrefixes = null) { $this->parent = $parent; $this->name = $name; $this->collection = new RouteCollection(); $this->route = new Route(''); $this->parentConfigurator = $parentConfigurator; // for GC control $this->parentPrefixes = $parentPrefixes; } /** * @return array */ public function __sleep() { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { if (null === $this->prefixes) { $this->collection->addPrefix($this->route->getPath()); } if (null !== $this->host) { $this->addHost($this->collection, $this->host); } $this->parent->addCollection($this->collection); } /** * Creates a sub-collection. */ final public function collection(string $name = ''): self { return new self($this->collection, $this->name.$name, $this, $this->prefixes); } /** * Sets the prefix to add to the path of all child routes. * * @param string|array $prefix the prefix, or the localized prefixes * * @return $this */ final public function prefix($prefix): self { if (\is_array($prefix)) { if (null === $this->parentPrefixes) { // no-op } elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) { throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing)))); } else { foreach ($prefix as $locale => $localePrefix) { if (!isset($this->parentPrefixes[$locale])) { throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale)); } $prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix; } } $this->prefixes = $prefix; $this->route->setPath('/'); } else { $this->prefixes = null; $this->route->setPath($prefix); } return $this; } /** * Sets the host to use for all child routes. * * @param string|array $host the host, or the localized hosts * * @return $this */ final public function host($host): self { $this->host = $host; return $this; } private function createRoute(string $path): Route { return (clone $this->route)->setPath($path); } } routing/Alias.php000064400000005027150432043210007773 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Routing\Exception\InvalidArgumentException; class Alias { private $id; private $deprecation = []; public function __construct(string $id) { $this->id = $id; } /** * @return static */ public function withId(string $id): self { $new = clone $this; $new->id = $id; return $new; } /** * Returns the target name of this alias. * * @return string The target name */ public function getId(): string { return $this->id; } /** * Whether this alias is deprecated, that means it should not be referenced anymore. * * @param string $package The name of the composer package that is triggering the deprecation * @param string $version The version of the package that introduced the deprecation * @param string $message The deprecation message to use * * @return $this * * @throws InvalidArgumentException when the message template is invalid */ public function setDeprecated(string $package, string $version, string $message): self { if ('' !== $message) { if (preg_match('#[\r\n]|\*/#', $message)) { throw new InvalidArgumentException('Invalid characters found in deprecation template.'); } if (!str_contains($message, '%alias_id%')) { throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.'); } } $this->deprecation = [ 'package' => $package, 'version' => $version, 'message' => $message ?: 'The "%alias_id%" route alias is deprecated. You should stop using it, as it will be removed in the future.', ]; return $this; } public function isDeprecated(): bool { return (bool) $this->deprecation; } /** * @param string $name Route name relying on this alias */ public function getDeprecation(string $name): array { return [ 'package' => $this->deprecation['package'], 'version' => $this->deprecation['version'], 'message' => str_replace('%alias_id%', $name, $this->deprecation['message']), ]; } } routing/RequestContext.php000064400000015314150432043210011737 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\HttpFoundation\Request; /** * Holds information about the current request. * * This class implements a fluent interface. * * @author Fabien Potencier * @author Tobias Schultze */ class RequestContext { private $baseUrl; private $pathInfo; private $method; private $host; private $scheme; private $httpPort; private $httpsPort; private $queryString; private $parameters = []; public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '') { $this->setBaseUrl($baseUrl); $this->setMethod($method); $this->setHost($host); $this->setScheme($scheme); $this->setHttpPort($httpPort); $this->setHttpsPort($httpsPort); $this->setPathInfo($path); $this->setQueryString($queryString); } public static function fromUri(string $uri, string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443): self { $uri = parse_url($uri); $scheme = $uri['scheme'] ?? $scheme; $host = $uri['host'] ?? $host; if (isset($uri['port'])) { if ('http' === $scheme) { $httpPort = $uri['port']; } elseif ('https' === $scheme) { $httpsPort = $uri['port']; } } return new self($uri['path'] ?? '', 'GET', $host, $scheme, $httpPort, $httpsPort); } /** * Updates the RequestContext information based on a HttpFoundation Request. * * @return $this */ public function fromRequest(Request $request) { $this->setBaseUrl($request->getBaseUrl()); $this->setPathInfo($request->getPathInfo()); $this->setMethod($request->getMethod()); $this->setHost($request->getHost()); $this->setScheme($request->getScheme()); $this->setHttpPort($request->isSecure() || null === $request->getPort() ? $this->httpPort : $request->getPort()); $this->setHttpsPort($request->isSecure() && null !== $request->getPort() ? $request->getPort() : $this->httpsPort); $this->setQueryString($request->server->get('QUERY_STRING', '')); return $this; } /** * Gets the base URL. * * @return string */ public function getBaseUrl() { return $this->baseUrl; } /** * Sets the base URL. * * @return $this */ public function setBaseUrl(string $baseUrl) { $this->baseUrl = $baseUrl; return $this; } /** * Gets the path info. * * @return string */ public function getPathInfo() { return $this->pathInfo; } /** * Sets the path info. * * @return $this */ public function setPathInfo(string $pathInfo) { $this->pathInfo = $pathInfo; return $this; } /** * Gets the HTTP method. * * The method is always an uppercased string. * * @return string */ public function getMethod() { return $this->method; } /** * Sets the HTTP method. * * @return $this */ public function setMethod(string $method) { $this->method = strtoupper($method); return $this; } /** * Gets the HTTP host. * * The host is always lowercased because it must be treated case-insensitive. * * @return string */ public function getHost() { return $this->host; } /** * Sets the HTTP host. * * @return $this */ public function setHost(string $host) { $this->host = strtolower($host); return $this; } /** * Gets the HTTP scheme. * * @return string */ public function getScheme() { return $this->scheme; } /** * Sets the HTTP scheme. * * @return $this */ public function setScheme(string $scheme) { $this->scheme = strtolower($scheme); return $this; } /** * Gets the HTTP port. * * @return int */ public function getHttpPort() { return $this->httpPort; } /** * Sets the HTTP port. * * @return $this */ public function setHttpPort(int $httpPort) { $this->httpPort = $httpPort; return $this; } /** * Gets the HTTPS port. * * @return int */ public function getHttpsPort() { return $this->httpsPort; } /** * Sets the HTTPS port. * * @return $this */ public function setHttpsPort(int $httpsPort) { $this->httpsPort = $httpsPort; return $this; } /** * Gets the query string without the "?". * * @return string */ public function getQueryString() { return $this->queryString; } /** * Sets the query string. * * @return $this */ public function setQueryString(?string $queryString) { // string cast to be fault-tolerant, accepting null $this->queryString = (string) $queryString; return $this; } /** * Returns the parameters. * * @return array */ public function getParameters() { return $this->parameters; } /** * Sets the parameters. * * @param array $parameters The parameters * * @return $this */ public function setParameters(array $parameters) { $this->parameters = $parameters; return $this; } /** * Gets a parameter value. * * @return mixed */ public function getParameter(string $name) { return $this->parameters[$name] ?? null; } /** * Checks if a parameter value is set for the given parameter. * * @return bool */ public function hasParameter(string $name) { return \array_key_exists($name, $this->parameters); } /** * Sets a parameter value. * * @param mixed $parameter The parameter value * * @return $this */ public function setParameter(string $name, $parameter) { $this->parameters[$name] = $parameter; return $this; } public function isSecure(): bool { return 'https' === $this->scheme; } } routing/LICENSE000064400000002051150432043210007230 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. routing/Exception/RouteCircularReferenceException.php000064400000001056150432043210017157 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; class RouteCircularReferenceException extends RuntimeException { public function __construct(string $routeId, array $path) { parent::__construct(sprintf('Circular reference detected for route "%s", path: "%s".', $routeId, implode(' -> ', $path))); } } routing/Exception/MethodNotAllowedException.php000064400000002476150432043210015775 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * The resource was found but the request method is not allowed. * * This exception should trigger an HTTP 405 response in your application code. * * @author Kris Wallsmith */ class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface { protected $allowedMethods = []; /** * @param string[] $allowedMethods */ public function __construct(array $allowedMethods, ?string $message = '', int $code = 0, \Throwable $previous = null) { if (null === $message) { trigger_deprecation('symfony/routing', '5.3', 'Passing null as $message to "%s()" is deprecated, pass an empty string instead.', __METHOD__); $message = ''; } $this->allowedMethods = array_map('strtoupper', $allowedMethods); parent::__construct($message, $code, $previous); } /** * Gets the allowed HTTP methods. * * @return string[] */ public function getAllowedMethods() { return $this->allowedMethods; } } routing/Exception/RouteNotFoundException.php000064400000000765150432043210015336 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a route does not exist. * * @author Alexandre Salomé */ class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface { } routing/Exception/ResourceNotFoundException.php000064400000001044150432043210016016 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * The resource was not found. * * This exception should trigger an HTTP 404 response in your application code. * * @author Kris Wallsmith */ class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface { } routing/Exception/RuntimeException.php000064400000000561150432043210014200 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; class RuntimeException extends \RuntimeException implements ExceptionInterface { } routing/Exception/ExceptionInterface.php000064400000000656150432043210014462 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * ExceptionInterface. * * @author Alexandre Salomé */ interface ExceptionInterface extends \Throwable { } routing/Exception/NoConfigurationException.php000064400000000721150432043210015657 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when no routes are configured. * * @author Yonel Ceruto */ class NoConfigurationException extends ResourceNotFoundException { } routing/Exception/InvalidArgumentException.php000064400000000601150432043210015641 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface { } routing/Exception/MissingMandatoryParametersException.php000064400000001062150432043210020066 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a route cannot be generated because of missing * mandatory parameters. * * @author Alexandre Salomé */ class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface { } routing/Exception/InvalidParameterException.php000064400000000772150432043210016010 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing\Exception; /** * Exception thrown when a parameter is not valid. * * @author Alexandre Salomé */ class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface { } routing/RouteCollection.php000064400000025257150432043210012063 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Routing\Exception\InvalidArgumentException; use Symfony\Component\Routing\Exception\RouteCircularReferenceException; /** * A RouteCollection represents a set of Route instances. * * When adding a route at the end of the collection, an existing route * with the same name is removed first. So there can only be one route * with a given name. * * @author Fabien Potencier * @author Tobias Schultze * * @implements \IteratorAggregate */ class RouteCollection implements \IteratorAggregate, \Countable { /** * @var array */ private $routes = []; /** * @var array */ private $aliases = []; /** * @var array */ private $resources = []; /** * @var array */ private $priorities = []; public function __clone() { foreach ($this->routes as $name => $route) { $this->routes[$name] = clone $route; } foreach ($this->aliases as $name => $alias) { $this->aliases[$name] = clone $alias; } } /** * Gets the current RouteCollection as an Iterator that includes all routes. * * It implements \IteratorAggregate. * * @see all() * * @return \ArrayIterator */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator($this->all()); } /** * Gets the number of Routes in this collection. * * @return int */ #[\ReturnTypeWillChange] public function count() { return \count($this->routes); } /** * @param int $priority */ public function add(string $name, Route $route/*, int $priority = 0*/) { if (\func_num_args() < 3 && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this, __FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface && !$this instanceof \Mockery\MockInterface) { trigger_deprecation('symfony/routing', '5.1', 'The "%s()" method will have a new "int $priority = 0" argument in version 6.0, not defining it is deprecated.', __METHOD__); } unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); $this->routes[$name] = $route; if ($priority = 3 <= \func_num_args() ? func_get_arg(2) : 0) { $this->priorities[$name] = $priority; } } /** * Returns all routes in this collection. * * @return array */ public function all() { if ($this->priorities) { $priorities = $this->priorities; $keysOrder = array_flip(array_keys($this->routes)); uksort($this->routes, static function ($n1, $n2) use ($priorities, $keysOrder) { return (($priorities[$n2] ?? 0) <=> ($priorities[$n1] ?? 0)) ?: ($keysOrder[$n1] <=> $keysOrder[$n2]); }); } return $this->routes; } /** * Gets a route by name. * * @return Route|null */ public function get(string $name) { $visited = []; while (null !== $alias = $this->aliases[$name] ?? null) { if (false !== $searchKey = array_search($name, $visited)) { $visited[] = $name; throw new RouteCircularReferenceException($name, \array_slice($visited, $searchKey)); } if ($alias->isDeprecated()) { $deprecation = $alias->getDeprecation($name); trigger_deprecation($deprecation['package'], $deprecation['version'], $deprecation['message']); } $visited[] = $name; $name = $alias->getId(); } return $this->routes[$name] ?? null; } /** * Removes a route or an array of routes by name from the collection. * * @param string|string[] $name The route name or an array of route names */ public function remove($name) { foreach ((array) $name as $n) { unset($this->routes[$n], $this->priorities[$n], $this->aliases[$n]); } } /** * Adds a route collection at the end of the current set by appending all * routes of the added collection. */ public function addCollection(self $collection) { // we need to remove all routes with the same names first because just replacing them // would not place the new route at the end of the merged array foreach ($collection->all() as $name => $route) { unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); $this->routes[$name] = $route; if (isset($collection->priorities[$name])) { $this->priorities[$name] = $collection->priorities[$name]; } } foreach ($collection->getAliases() as $name => $alias) { unset($this->routes[$name], $this->priorities[$name], $this->aliases[$name]); $this->aliases[$name] = $alias; } foreach ($collection->getResources() as $resource) { $this->addResource($resource); } } /** * Adds a prefix to the path of all child routes. */ public function addPrefix(string $prefix, array $defaults = [], array $requirements = []) { $prefix = trim(trim($prefix), '/'); if ('' === $prefix) { return; } foreach ($this->routes as $route) { $route->setPath('/'.$prefix.$route->getPath()); $route->addDefaults($defaults); $route->addRequirements($requirements); } } /** * Adds a prefix to the name of all the routes within in the collection. */ public function addNamePrefix(string $prefix) { $prefixedRoutes = []; $prefixedPriorities = []; $prefixedAliases = []; foreach ($this->routes as $name => $route) { $prefixedRoutes[$prefix.$name] = $route; if (null !== $canonicalName = $route->getDefault('_canonical_route')) { $route->setDefault('_canonical_route', $prefix.$canonicalName); } if (isset($this->priorities[$name])) { $prefixedPriorities[$prefix.$name] = $this->priorities[$name]; } } foreach ($this->aliases as $name => $alias) { $prefixedAliases[$prefix.$name] = $alias->withId($prefix.$alias->getId()); } $this->routes = $prefixedRoutes; $this->priorities = $prefixedPriorities; $this->aliases = $prefixedAliases; } /** * Sets the host pattern on all routes. */ public function setHost(?string $pattern, array $defaults = [], array $requirements = []) { foreach ($this->routes as $route) { $route->setHost($pattern); $route->addDefaults($defaults); $route->addRequirements($requirements); } } /** * Sets a condition on all routes. * * Existing conditions will be overridden. */ public function setCondition(?string $condition) { foreach ($this->routes as $route) { $route->setCondition($condition); } } /** * Adds defaults to all routes. * * An existing default value under the same name in a route will be overridden. */ public function addDefaults(array $defaults) { if ($defaults) { foreach ($this->routes as $route) { $route->addDefaults($defaults); } } } /** * Adds requirements to all routes. * * An existing requirement under the same name in a route will be overridden. */ public function addRequirements(array $requirements) { if ($requirements) { foreach ($this->routes as $route) { $route->addRequirements($requirements); } } } /** * Adds options to all routes. * * An existing option value under the same name in a route will be overridden. */ public function addOptions(array $options) { if ($options) { foreach ($this->routes as $route) { $route->addOptions($options); } } } /** * Sets the schemes (e.g. 'https') all child routes are restricted to. * * @param string|string[] $schemes The scheme or an array of schemes */ public function setSchemes($schemes) { foreach ($this->routes as $route) { $route->setSchemes($schemes); } } /** * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. * * @param string|string[] $methods The method or an array of methods */ public function setMethods($methods) { foreach ($this->routes as $route) { $route->setMethods($methods); } } /** * Returns an array of resources loaded to build this collection. * * @return ResourceInterface[] */ public function getResources() { return array_values($this->resources); } /** * Adds a resource for this collection. If the resource already exists * it is not added. */ public function addResource(ResourceInterface $resource) { $key = (string) $resource; if (!isset($this->resources[$key])) { $this->resources[$key] = $resource; } } /** * Sets an alias for an existing route. * * @param string $name The alias to create * @param string $alias The route to alias * * @throws InvalidArgumentException if the alias is for itself */ public function addAlias(string $name, string $alias): Alias { if ($name === $alias) { throw new InvalidArgumentException(sprintf('Route alias "%s" can not reference itself.', $name)); } unset($this->routes[$name], $this->priorities[$name]); return $this->aliases[$name] = new Alias($alias); } /** * @return array */ public function getAliases(): array { return $this->aliases; } public function getAlias(string $name): ?Alias { return $this->aliases[$name] ?? null; } } routing/RouteCompiler.php000064400000035002150432043210011527 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Routing; /** * RouteCompiler compiles Route instances to CompiledRoute instances. * * @author Fabien Potencier * @author Tobias Schultze */ class RouteCompiler implements RouteCompilerInterface { /** * @deprecated since Symfony 5.1, to be removed in 6.0 */ public const REGEX_DELIMITER = '#'; /** * This string defines the characters that are automatically considered separators in front of * optional placeholders (with default and no static text following). Such a single separator * can be left out together with the optional placeholder from matching and generating URLs. */ public const SEPARATORS = '/,;.:-_~+*=@|'; /** * The maximum supported length of a PCRE subpattern name * http://pcre.org/current/doc/html/pcre2pattern.html#SEC16. * * @internal */ public const VARIABLE_MAXIMUM_LENGTH = 32; /** * {@inheritdoc} * * @throws \InvalidArgumentException if a path variable is named _fragment * @throws \LogicException if a variable is referenced more than once * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as * a PCRE subpattern */ public static function compile(Route $route) { $hostVariables = []; $variables = []; $hostRegex = null; $hostTokens = []; if ('' !== $host = $route->getHost()) { $result = self::compilePattern($route, $host, true); $hostVariables = $result['variables']; $variables = $hostVariables; $hostTokens = $result['tokens']; $hostRegex = $result['regex']; } $locale = $route->getDefault('_locale'); if (null !== $locale && null !== $route->getDefault('_canonical_route') && preg_quote($locale) === $route->getRequirement('_locale')) { $requirements = $route->getRequirements(); unset($requirements['_locale']); $route->setRequirements($requirements); $route->setPath(str_replace('{_locale}', $locale, $route->getPath())); } $path = $route->getPath(); $result = self::compilePattern($route, $path, false); $staticPrefix = $result['staticPrefix']; $pathVariables = $result['variables']; foreach ($pathVariables as $pathParam) { if ('_fragment' === $pathParam) { throw new \InvalidArgumentException(sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath())); } } $variables = array_merge($variables, $pathVariables); $tokens = $result['tokens']; $regex = $result['regex']; return new CompiledRoute( $staticPrefix, $regex, $tokens, $pathVariables, $hostRegex, $hostTokens, $hostVariables, array_unique($variables) ); } private static function compilePattern(Route $route, string $pattern, bool $isHost): array { $tokens = []; $variables = []; $matches = []; $pos = 0; $defaultSeparator = $isHost ? '.' : '/'; $useUtf8 = preg_match('//u', $pattern); $needsUtf8 = $route->getOption('utf8'); if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) { throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath())); } if (!$useUtf8 && $needsUtf8) { throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern)); } // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. preg_match_all('#\{(!)?(\w+)\}#', $pattern, $matches, \PREG_OFFSET_CAPTURE | \PREG_SET_ORDER); foreach ($matches as $match) { $important = $match[1][1] >= 0; $varName = $match[2][0]; // get all static text preceding the current variable $precedingText = substr($pattern, $pos, $match[0][1] - $pos); $pos = $match[0][1] + \strlen($match[0][0]); if (!\strlen($precedingText)) { $precedingChar = ''; } elseif ($useUtf8) { preg_match('/.$/u', $precedingText, $precedingChar); $precedingChar = $precedingChar[0]; } else { $precedingChar = substr($precedingText, -1); } $isSeparator = '' !== $precedingChar && str_contains(static::SEPARATORS, $precedingChar); // A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the // variable would not be usable as a Controller action argument. if (preg_match('/^\d/', $varName)) { throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); } if (\in_array($varName, $variables)) { throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); } if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %d characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); } if ($isSeparator && $precedingText !== $precedingChar) { $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))]; } elseif (!$isSeparator && '' !== $precedingText) { $tokens[] = ['text', $precedingText]; } $regexp = $route->getRequirement($varName); if (null === $regexp) { $followingPattern = (string) substr($pattern, $pos); // Find the next static character after the variable that functions as a separator. By default, this separator and '/' // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html']) // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. $nextSeparator = self::findNextSeparator($followingPattern, $useUtf8); $regexp = sprintf( '[^%s%s]+', preg_quote($defaultSeparator), $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator) : '' ); if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is // directly adjacent, e.g. '/{x}{y}'. $regexp .= '+'; } } else { if (!preg_match('//u', $regexp)) { $useUtf8 = false; } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?= 0; --$i) { $token = $tokens[$i]; // variable is optional when it is not important and has a default value if ('variable' === $token[0] && !($token[5] ?? false) && $route->hasDefault($token[3])) { $firstOptional = $i; } else { break; } } } // compute the matching regexp $regexp = ''; for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { $regexp .= self::computeRegexp($tokens, $i, $firstOptional); } $regexp = '{^'.$regexp.'$}sD'.($isHost ? 'i' : ''); // enable Utf8 matching if really required if ($needsUtf8) { $regexp .= 'u'; for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { if ('variable' === $tokens[$i][0]) { $tokens[$i][4] = true; } } } return [ 'staticPrefix' => self::determineStaticPrefix($route, $tokens), 'regex' => $regexp, 'tokens' => array_reverse($tokens), 'variables' => $variables, ]; } /** * Determines the longest static prefix possible for a route. */ private static function determineStaticPrefix(Route $route, array $tokens): string { if ('text' !== $tokens[0][0]) { return ($route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1]) ? '' : $tokens[0][1]; } $prefix = $tokens[0][1]; if (isset($tokens[1][1]) && '/' !== $tokens[1][1] && false === $route->hasDefault($tokens[1][3])) { $prefix .= $tokens[1][1]; } return $prefix; } /** * Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available). */ private static function findNextSeparator(string $pattern, bool $useUtf8): string { if ('' == $pattern) { // return empty string if pattern is empty or false (false which can be returned by substr) return ''; } // first remove all placeholders from the pattern so we can find the next real static character if ('' === $pattern = preg_replace('#\{\w+\}#', '', $pattern)) { return ''; } if ($useUtf8) { preg_match('/^./u', $pattern, $pattern); } return str_contains(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; } /** * Computes the regexp used to match a specific token. It can be static text or a subpattern. * * @param array $tokens The route tokens * @param int $index The index of the current token * @param int $firstOptional The index of the first optional token */ private static function computeRegexp(array $tokens, int $index, int $firstOptional): string { $token = $tokens[$index]; if ('text' === $token[0]) { // Text tokens return preg_quote($token[1]); } else { // Variable tokens if (0 === $index && 0 === $firstOptional) { // When the only token is an optional variable token, the separator is required return sprintf('%s(?P<%s>%s)?', preg_quote($token[1]), $token[3], $token[2]); } else { $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1]), $token[3], $token[2]); if ($index >= $firstOptional) { // Enclose each optional token in a subpattern to make it optional. // "?:" means it is non-capturing, i.e. the portion of the subject string that // matched the optional subpattern is not passed back. $regexp = "(?:$regexp"; $nbTokens = \count($tokens); if ($nbTokens - 1 == $index) { // Close the optional subpatterns $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); } } return $regexp; } } } private static function transformCapturingGroupsToNonCapturings(string $regexp): string { for ($i = 0; $i < \strlen($regexp); ++$i) { if ('\\' === $regexp[$i]) { ++$i; continue; } if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) { continue; } if ('*' === $regexp[++$i] || '?' === $regexp[$i]) { ++$i; continue; } $regexp = substr_replace($regexp, '?:', $i, 0); ++$i; } return $regexp; } } http-kernel/Resources/welcome.html.php000064400000077241150432043210014067 0ustar00 Welcome to Symfony!

    You're seeing this page because you haven't configured any homepage URL and debug mode is enabled.

    Welcome to Symfony

    Your application is now ready and you can start working on it.

    http-kernel/CacheWarmer/CacheWarmerInterface.php000064400000001404150432043210015666 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Interface for classes able to warm up the cache. * * @author Fabien Potencier */ interface CacheWarmerInterface extends WarmableInterface { /** * Checks whether this warmer is optional or not. * * Optional warmers can be ignored on certain conditions. * * A warmer should return true if the cache can be * generated incrementally and on-demand. * * @return bool */ public function isOptional(); } http-kernel/CacheWarmer/CacheWarmer.php000064400000001556150432043210014055 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Abstract cache warmer that knows how to write a file to the cache. * * @author Fabien Potencier */ abstract class CacheWarmer implements CacheWarmerInterface { protected function writeCacheFile(string $file, $content) { $tmpFile = @tempnam(\dirname($file), basename($file)); if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { @chmod($file, 0666 & ~umask()); return; } throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file)); } } http-kernel/CacheWarmer/WarmableInterface.php000064400000001144150432043210015240 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Interface for classes that support warming their cache. * * @author Fabien Potencier */ interface WarmableInterface { /** * Warms up the cache. * * @return string[] A list of classes or files to preload on PHP 7.4+ */ public function warmUp(string $cacheDir); } http-kernel/CacheWarmer/CacheWarmerAggregate.php000064400000007647150432043210015673 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheWarmer; /** * Aggregates several cache warmers into a single one. * * @author Fabien Potencier * * @final */ class CacheWarmerAggregate implements CacheWarmerInterface { private $warmers; private $debug; private $deprecationLogsFilepath; private $optionalsEnabled = false; private $onlyOptionalsEnabled = false; /** * @param iterable $warmers */ public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null) { $this->warmers = $warmers; $this->debug = $debug; $this->deprecationLogsFilepath = $deprecationLogsFilepath; } public function enableOptionalWarmers() { $this->optionalsEnabled = true; } public function enableOnlyOptionalWarmers() { $this->onlyOptionalsEnabled = $this->optionalsEnabled = true; } /** * {@inheritdoc} */ public function warmUp(string $cacheDir): array { if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { $collectedLogs = []; $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { if (\E_USER_DEPRECATED !== $type && \E_DEPRECATED !== $type) { return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; } if (isset($collectedLogs[$message])) { ++$collectedLogs[$message]['count']; return null; } $backtrace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3); // Clean the trace by removing first frames added by the error handler itself. for ($i = 0; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { $backtrace = \array_slice($backtrace, 1 + $i); break; } } $collectedLogs[$message] = [ 'type' => $type, 'message' => $message, 'file' => $file, 'line' => $line, 'trace' => $backtrace, 'count' => 1, ]; return null; }); } $preload = []; try { foreach ($this->warmers as $warmer) { if (!$this->optionalsEnabled && $warmer->isOptional()) { continue; } if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) { continue; } $preload[] = array_values((array) $warmer->warmUp($cacheDir)); } } finally { if ($collectDeprecations) { restore_error_handler(); if (is_file($this->deprecationLogsFilepath)) { $previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath)); if (\is_array($previousLogs)) { $collectedLogs = array_merge($previousLogs, $collectedLogs); } } file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs))); } } return array_values(array_unique(array_merge([], ...$preload))); } /** * {@inheritdoc} */ public function isOptional(): bool { return false; } } http-kernel/Event/TerminateEvent.php000064400000002105150432043210013515 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Allows to execute logic after a response was sent. * * Since it's only triggered on main requests, the `getRequestType()` method * will always return the value of `HttpKernelInterface::MAIN_REQUEST`. * * @author Jordi Boggiano */ final class TerminateEvent extends KernelEvent { private $response; public function __construct(HttpKernelInterface $kernel, Request $request, Response $response) { parent::__construct($kernel, $request, HttpKernelInterface::MAIN_REQUEST); $this->response = $response; } public function getResponse(): Response { return $this->response; } } http-kernel/Event/ControllerArgumentsEvent.php000064400000003057150432043210015605 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Allows filtering of controller arguments. * * You can call getController() to retrieve the controller and getArguments * to retrieve the current arguments. With setArguments() you can replace * arguments that are used to call the controller. * * Arguments set in the event must be compatible with the signature of the * controller. * * @author Christophe Coevoet */ final class ControllerArgumentsEvent extends KernelEvent { private $controller; private $arguments; public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType) { parent::__construct($kernel, $request, $requestType); $this->controller = $controller; $this->arguments = $arguments; } public function getController(): callable { return $this->controller; } public function setController(callable $controller) { $this->controller = $controller; } public function getArguments(): array { return $this->arguments; } public function setArguments(array $arguments) { $this->arguments = $arguments; } } http-kernel/Event/RequestEvent.php000064400000002306150432043210013220 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Response; /** * Allows to create a response for a request. * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * @author Bernhard Schussek */ class RequestEvent extends KernelEvent { private $response; /** * Returns the response object. * * @return Response|null */ public function getResponse() { return $this->response; } /** * Sets a response and stops event propagation. */ public function setResponse(Response $response) { $this->response = $response; $this->stopPropagation(); } /** * Returns whether a response was set. * * @return bool */ public function hasResponse() { return null !== $this->response; } } http-kernel/Event/ControllerEvent.php000064400000002320150432043210013707 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Allows filtering of a controller callable. * * You can call getController() to retrieve the current controller. With * setController() you can set a new controller that is used in the processing * of the request. * * Controllers should be callables. * * @author Bernhard Schussek */ final class ControllerEvent extends KernelEvent { private $controller; public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType) { parent::__construct($kernel, $request, $requestType); $this->setController($controller); } public function getController(): callable { return $this->controller; } public function setController(callable $controller): void { $this->controller = $controller; } } http-kernel/Event/ExceptionEvent.php000064400000003620150432043210013526 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Allows to create a response for a thrown exception. * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * You can also call setThrowable() to replace the thrown exception. This * exception will be thrown if no response is set during processing of this * event. * * @author Bernhard Schussek */ final class ExceptionEvent extends RequestEvent { private $throwable; /** * @var bool */ private $allowCustomResponseCode = false; public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Throwable $e) { parent::__construct($kernel, $request, $requestType); $this->setThrowable($e); } public function getThrowable(): \Throwable { return $this->throwable; } /** * Replaces the thrown exception. * * This exception will be thrown if no response is set in the event. */ public function setThrowable(\Throwable $exception): void { $this->throwable = $exception; } /** * Mark the event as allowing a custom response code. */ public function allowCustomResponseCode(): void { $this->allowCustomResponseCode = true; } /** * Returns true if the event allows a custom response code. */ public function isAllowingCustomResponseCode(): bool { return $this->allowCustomResponseCode; } } http-kernel/Event/ResponseEvent.php000064400000002251150432043210013365 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Allows to filter a Response object. * * You can call getResponse() to retrieve the current response. With * setResponse() you can set a new response that will be returned to the * browser. * * @author Bernhard Schussek */ final class ResponseEvent extends KernelEvent { private $response; public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response) { parent::__construct($kernel, $request, $requestType); $this->setResponse($response); } public function getResponse(): Response { return $this->response; } public function setResponse(Response $response): void { $this->response = $response; } } http-kernel/Event/FinishRequestEvent.php000064400000000705150432043210014362 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; /** * Triggered whenever a request is fully processed. * * @author Benjamin Eberlei */ final class FinishRequestEvent extends KernelEvent { } http-kernel/Event/KernelEvent.php000064400000004436150432043210013016 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Contracts\EventDispatcher\Event; /** * Base class for events thrown in the HttpKernel component. * * @author Bernhard Schussek */ class KernelEvent extends Event { private $kernel; private $request; private $requestType; /** * @param int $requestType The request type the kernel is currently processing; one of * HttpKernelInterface::MAIN_REQUEST or HttpKernelInterface::SUB_REQUEST */ public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType) { $this->kernel = $kernel; $this->request = $request; $this->requestType = $requestType; } /** * Returns the kernel in which this event was thrown. * * @return HttpKernelInterface */ public function getKernel() { return $this->kernel; } /** * Returns the request the kernel is currently processing. * * @return Request */ public function getRequest() { return $this->request; } /** * Returns the request type the kernel is currently processing. * * @return int One of HttpKernelInterface::MAIN_REQUEST and * HttpKernelInterface::SUB_REQUEST */ public function getRequestType() { return $this->requestType; } /** * Checks if this is the main request. */ public function isMainRequest(): bool { return HttpKernelInterface::MAIN_REQUEST === $this->requestType; } /** * Checks if this is a master request. * * @return bool * * @deprecated since symfony/http-kernel 5.3, use isMainRequest() instead */ public function isMasterRequest() { trigger_deprecation('symfony/http-kernel', '5.3', '"%s()" is deprecated, use "isMainRequest()" instead.', __METHOD__); return $this->isMainRequest(); } } http-kernel/Event/ViewEvent.php000064400000003022150432043210012476 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Allows to create a response for the return value of a controller. * * Call setResponse() to set the response that will be returned for the * current request. The propagation of this event is stopped as soon as a * response is set. * * @author Bernhard Schussek */ final class ViewEvent extends RequestEvent { /** * The return value of the controller. * * @var mixed */ private $controllerResult; public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult) { parent::__construct($kernel, $request, $requestType); $this->controllerResult = $controllerResult; } /** * Returns the return value of the controller. * * @return mixed */ public function getControllerResult() { return $this->controllerResult; } /** * Assigns the return value of the controller. * * @param mixed $controllerResult The controller return value */ public function setControllerResult($controllerResult): void { $this->controllerResult = $controllerResult; } } http-kernel/README.md000064400000002316150432043210010254 0ustar00HttpKernel Component ==================== The HttpKernel component provides a structured process for converting a Request into a Response by making use of the EventDispatcher component. It's flexible enough to create full-stack frameworks, micro-frameworks or advanced CMS systems like Drupal. Sponsor ------- The HttpKernel component for Symfony 5.4/6.0 is [backed][1] by [Les-Tilleuls.coop][2]. Les-Tilleuls.coop is a team of 50+ Symfony experts who can help you design, develop and fix your projects. We provide a wide range of professional services including development, consulting, coaching, training and audits. We also are highly skilled in JS, Go and DevOps. We are a worker cooperative! Help Symfony by [sponsoring][3] its development! Resources --------- * [Documentation](https://symfony.com/doc/current/components/http_kernel.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) [1]: https://symfony.com/backers [2]: https://les-tilleuls.coop [3]: https://symfony.com/sponsor http-kernel/Attribute/AsController.php000064400000000703150432043210014056 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Attribute; /** * Service tag to autoconfigure controllers. */ #[\Attribute(\Attribute::TARGET_CLASS)] class AsController { public function __construct() { } } http-kernel/Attribute/ArgumentInterface.php000064400000001030150432043210015044 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Attribute; trigger_deprecation('symfony/http-kernel', '5.3', 'The "%s" interface is deprecated.', ArgumentInterface::class); /** * Marker interface for controller argument attributes. * * @deprecated since Symfony 5.3 */ interface ArgumentInterface { } http-kernel/HttpKernelBrowser.php000064400000013610150432043210013131 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\BrowserKit\AbstractBrowser; use Symfony\Component\BrowserKit\CookieJar; use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\Request as DomRequest; use Symfony\Component\BrowserKit\Response as DomResponse; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Simulates a browser and makes requests to an HttpKernel instance. * * @author Fabien Potencier * * @method Request getRequest() * @method Response getResponse() */ class HttpKernelBrowser extends AbstractBrowser { protected $kernel; private $catchExceptions = true; /** * @param array $server The server parameters (equivalent of $_SERVER) */ public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) { // These class properties must be set before calling the parent constructor, as it may depend on it. $this->kernel = $kernel; $this->followRedirects = false; parent::__construct($server, $history, $cookieJar); } /** * Sets whether to catch exceptions when the kernel is handling a request. */ public function catchExceptions(bool $catchExceptions) { $this->catchExceptions = $catchExceptions; } /** * {@inheritdoc} * * @param Request $request * * @return Response */ protected function doRequest(object $request) { $response = $this->kernel->handle($request, HttpKernelInterface::MAIN_REQUEST, $this->catchExceptions); if ($this->kernel instanceof TerminableInterface) { $this->kernel->terminate($request, $response); } return $response; } /** * {@inheritdoc} * * @param Request $request * * @return string */ protected function getScript(object $request) { $kernel = var_export(serialize($this->kernel), true); $request = var_export(serialize($request), true); $errorReporting = error_reporting(); $requires = ''; foreach (get_declared_classes() as $class) { if (0 === strpos($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); $file = \dirname($r->getFileName(), 2).'/autoload.php'; if (file_exists($file)) { $requires .= 'require_once '.var_export($file, true).";\n"; } } } if (!$requires) { throw new \RuntimeException('Composer autoloader not found.'); } $code = <<getHandleScript(); } protected function getHandleScript() { return <<<'EOF' $response = $kernel->handle($request); if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) { $kernel->terminate($request, $response); } echo serialize($response); EOF; } /** * {@inheritdoc} * * @return Request */ protected function filterRequest(DomRequest $request) { $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $server = $request->getServer(), $request->getContent()); if (!isset($server['HTTP_ACCEPT'])) { $httpRequest->headers->remove('Accept'); } foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) { $httpRequest->files->set($key, $value); } return $httpRequest; } /** * Filters an array of files. * * This method created test instances of UploadedFile so that the move() * method can be called on those instances. * * If the size of a file is greater than the allowed size (from php.ini) then * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE. * * @see UploadedFile * * @return array */ protected function filterFiles(array $files) { $filtered = []; foreach ($files as $key => $value) { if (\is_array($value)) { $filtered[$key] = $this->filterFiles($value); } elseif ($value instanceof UploadedFile) { if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { $filtered[$key] = new UploadedFile( '', $value->getClientOriginalName(), $value->getClientMimeType(), \UPLOAD_ERR_INI_SIZE, true ); } else { $filtered[$key] = new UploadedFile( $value->getPathname(), $value->getClientOriginalName(), $value->getClientMimeType(), $value->getError(), true ); } } } return $filtered; } /** * {@inheritdoc} * * @param Request $request * * @return DomResponse */ protected function filterResponse(object $response) { // this is needed to support StreamedResponse ob_start(); $response->sendContent(); $content = ob_get_clean(); return new DomResponse($content, $response->getStatusCode(), $response->headers->all()); } } http-kernel/HttpKernelInterface.php000064400000002717150432043210013414 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * HttpKernelInterface handles a Request to convert it to a Response. * * @author Fabien Potencier */ interface HttpKernelInterface { public const MAIN_REQUEST = 1; public const SUB_REQUEST = 2; /** * @deprecated since symfony/http-kernel 5.3, use MAIN_REQUEST instead. * To ease the migration, this constant won't be removed until Symfony 7.0. */ public const MASTER_REQUEST = self::MAIN_REQUEST; /** * Handles a Request to convert it to a Response. * * When $catch is true, the implementation must catch all exceptions * and do its best to convert them to a Response instance. * * @param int $type The type of the request * (one of HttpKernelInterface::MAIN_REQUEST or HttpKernelInterface::SUB_REQUEST) * @param bool $catch Whether to catch exceptions or not * * @return Response * * @throws \Exception When an Exception occurs during processing */ public function handle(Request $request, int $type = self::MAIN_REQUEST, bool $catch = true); } http-kernel/Config/FileLocator.php000064400000002125150432043210013114 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Config; use Symfony\Component\Config\FileLocator as BaseFileLocator; use Symfony\Component\HttpKernel\KernelInterface; /** * FileLocator uses the KernelInterface to locate resources in bundles. * * @author Fabien Potencier */ class FileLocator extends BaseFileLocator { private $kernel; public function __construct(KernelInterface $kernel) { $this->kernel = $kernel; parent::__construct(); } /** * {@inheritdoc} */ public function locate(string $file, string $currentPath = null, bool $first = true) { if (isset($file[0]) && '@' === $file[0]) { $resource = $this->kernel->locateResource($file); return $first ? $resource : [$resource]; } return parent::locate($file, $currentPath, $first); } } http-kernel/DependencyInjection/FragmentRendererPass.php000064400000004727150432043210017520 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; /** * Adds services tagged kernel.fragment_renderer as HTTP content rendering strategies. * * @author Fabien Potencier */ class FragmentRendererPass implements CompilerPassInterface { private $handlerService; private $rendererTag; public function __construct(string $handlerService = 'fragment.handler', string $rendererTag = 'kernel.fragment_renderer') { if (0 < \func_num_args()) { trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->handlerService = $handlerService; $this->rendererTag = $rendererTag; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->handlerService)) { return; } $definition = $container->getDefinition($this->handlerService); $renderers = []; foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $id => $tags) { $def = $container->getDefinition($id); $class = $container->getParameterBag()->resolveValue($def->getClass()); if (!$r = $container->getReflectionClass($class)) { throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } if (!$r->isSubclassOf(FragmentRendererInterface::class)) { throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, FragmentRendererInterface::class)); } foreach ($tags as $tag) { $renderers[$tag['alias']] = new Reference($id); } } $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers)); } } http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php000064400000005152150432043210022624 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; use Symfony\Component\Stopwatch\Stopwatch; /** * Gathers and configures the argument value resolvers. * * @author Iltar van der Berg */ class ControllerArgumentValueResolverPass implements CompilerPassInterface { use PriorityTaggedServiceTrait; private $argumentResolverService; private $argumentValueResolverTag; private $traceableResolverStopwatch; public function __construct(string $argumentResolverService = 'argument_resolver', string $argumentValueResolverTag = 'controller.argument_value_resolver', string $traceableResolverStopwatch = 'debug.stopwatch') { if (0 < \func_num_args()) { trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->argumentResolverService = $argumentResolverService; $this->argumentValueResolverTag = $argumentValueResolverTag; $this->traceableResolverStopwatch = $traceableResolverStopwatch; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->argumentResolverService)) { return; } $resolvers = $this->findAndSortTaggedServices($this->argumentValueResolverTag, $container); if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has($this->traceableResolverStopwatch)) { foreach ($resolvers as $resolverReference) { $id = (string) $resolverReference; $container->register("debug.$id", TraceableValueResolver::class) ->setDecoratedService($id) ->setArguments([new Reference("debug.$id.inner"), new Reference($this->traceableResolverStopwatch)]); } } $container ->getDefinition($this->argumentResolverService) ->replaceArgument(1, new IteratorArgument($resolvers)) ; } } http-kernel/DependencyInjection/Extension.php000064400000002067150432043210015406 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension; /** * Allow adding classes to the class cache. * * @author Fabien Potencier */ abstract class Extension extends BaseExtension { private $annotatedClasses = []; /** * Gets the annotated classes to cache. * * @return array */ public function getAnnotatedClassesToCompile() { return $this->annotatedClasses; } /** * Adds annotated classes to the class cache. * * @param array $annotatedClasses An array of class patterns */ public function addAnnotatedClassesToCompile(array $annotatedClasses) { $this->annotatedClasses = array_merge($this->annotatedClasses, $annotatedClasses); } } http-kernel/DependencyInjection/ResettableServicePass.php000064400000004625150432043210017676 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; /** * @author Alexander M. Turek */ class ResettableServicePass implements CompilerPassInterface { private $tagName; public function __construct(string $tagName = 'kernel.reset') { if (0 < \func_num_args()) { trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->tagName = $tagName; } /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { if (!$container->has('services_resetter')) { return; } $services = $methods = []; foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) { $services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE); foreach ($tags as $attributes) { if (!isset($attributes['method'])) { throw new RuntimeException(sprintf('Tag "%s" requires the "method" attribute to be set.', $this->tagName)); } if (!isset($methods[$id])) { $methods[$id] = []; } if ('ignore' === ($attributes['on_invalid'] ?? null)) { $attributes['method'] = '?'.$attributes['method']; } $methods[$id][] = $attributes['method']; } } if (!$services) { $container->removeAlias('services_resetter'); $container->removeDefinition('services_resetter'); return; } $container->findDefinition('services_resetter') ->setArgument(0, new IteratorArgument($services)) ->setArgument(1, $methods); } } http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php000064400000010357150432043210021355 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Composer\Autoload\ClassLoader; use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\ErrorHandler\DebugClassLoader; use Symfony\Component\HttpKernel\Kernel; /** * Sets the classes to compile in the cache for the container. * * @author Fabien Potencier */ class AddAnnotatedClassesToCachePass implements CompilerPassInterface { private $kernel; public function __construct(Kernel $kernel) { $this->kernel = $kernel; } /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { $annotatedClasses = []; foreach ($container->getExtensions() as $extension) { if ($extension instanceof Extension) { $annotatedClasses[] = $extension->getAnnotatedClassesToCompile(); } } $annotatedClasses = array_merge($this->kernel->getAnnotatedClassesToCompile(), ...$annotatedClasses); $existingClasses = $this->getClassesInComposerClassMaps(); $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses); $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses)); } /** * Expands the given class patterns using a list of existing classes. * * @param array $patterns The class patterns to expand * @param array $classes The existing classes to match against the patterns */ private function expandClasses(array $patterns, array $classes): array { $expanded = []; // Explicit classes declared in the patterns are returned directly foreach ($patterns as $key => $pattern) { if (!str_ends_with($pattern, '\\') && !str_contains($pattern, '*')) { unset($patterns[$key]); $expanded[] = ltrim($pattern, '\\'); } } // Match patterns with the classes list $regexps = $this->patternsToRegexps($patterns); foreach ($classes as $class) { $class = ltrim($class, '\\'); if ($this->matchAnyRegexps($class, $regexps)) { $expanded[] = $class; } } return array_unique($expanded); } private function getClassesInComposerClassMaps(): array { $classes = []; foreach (spl_autoload_functions() as $function) { if (!\is_array($function)) { continue; } if ($function[0] instanceof DebugClassLoader || $function[0] instanceof LegacyDebugClassLoader) { $function = $function[0]->getClassLoader(); } if (\is_array($function) && $function[0] instanceof ClassLoader) { $classes += array_filter($function[0]->getClassMap()); } } return array_keys($classes); } private function patternsToRegexps(array $patterns): array { $regexps = []; foreach ($patterns as $pattern) { // Escape user input $regex = preg_quote(ltrim($pattern, '\\')); // Wildcards * and ** $regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']); // If this class does not end by a slash, anchor the end if ('\\' !== substr($regex, -1)) { $regex .= '$'; } $regexps[] = '{^\\\\'.$regex.'}'; } return $regexps; } private function matchAnyRegexps(string $class, array $regexps): bool { $isTest = str_contains($class, 'Test'); foreach ($regexps as $regex) { if ($isTest && !str_contains($regex, 'Test')) { continue; } if (preg_match($regex, '\\'.$class)) { return true; } } return false; } } http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php000064400000005607150432043210024016 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Removes empty service-locators registered for ServiceValueResolver. * * @author Nicolas Grekas */ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface { private $controllerLocator; public function __construct(string $controllerLocator = 'argument_resolver.controller_locator') { if (0 < \func_num_args()) { trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->controllerLocator = $controllerLocator; } public function process(ContainerBuilder $container) { $controllerLocator = $container->findDefinition($this->controllerLocator); $controllers = $controllerLocator->getArgument(0); foreach ($controllers as $controller => $argumentRef) { $argumentLocator = $container->getDefinition((string) $argumentRef->getValues()[0]); if (!$argumentLocator->getArgument(0)) { // remove empty argument locators $reason = sprintf('Removing service-argument resolver for controller "%s": no corresponding services exist for the referenced types.', $controller); } else { // any methods listed for call-at-instantiation cannot be actions $reason = false; [$id, $action] = explode('::', $controller); if ($container->hasAlias($id)) { continue; } $controllerDef = $container->getDefinition($id); foreach ($controllerDef->getMethodCalls() as [$method]) { if (0 === strcasecmp($action, $method)) { $reason = sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id); break; } } if (!$reason) { // see Symfony\Component\HttpKernel\Controller\ContainerControllerResolver $controllers[$id.':'.$action] = $argumentRef; if ('__invoke' === $action) { $controllers[$id] = $argumentRef; } continue; } } unset($controllers[$controller]); $container->log($this, $reason); } $controllerLocator->replaceArgument(0, $controllers); } } http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php000064400000002225150432043210021741 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Ensures certain extensions are always loaded. * * @author Kris Wallsmith */ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass { private $extensions; /** * @param string[] $extensions */ public function __construct(array $extensions) { $this->extensions = $extensions; } public function process(ContainerBuilder $container) { foreach ($this->extensions as $extension) { if (!\count($container->getExtensionConfig($extension))) { $container->loadFromExtension($extension, []); } } parent::process($container); } } http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php000064400000003501150432043210021643 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; /** * Register all services that have the "kernel.locale_aware" tag into the listener. * * @author Pierre Bobiet */ class RegisterLocaleAwareServicesPass implements CompilerPassInterface { private $listenerServiceId; private $localeAwareTag; public function __construct(string $listenerServiceId = 'locale_aware_listener', string $localeAwareTag = 'kernel.locale_aware') { if (0 < \func_num_args()) { trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->listenerServiceId = $listenerServiceId; $this->localeAwareTag = $localeAwareTag; } public function process(ContainerBuilder $container) { if (!$container->hasDefinition($this->listenerServiceId)) { return; } $services = []; foreach ($container->findTaggedServiceIds($this->localeAwareTag) as $id => $tags) { $services[] = new Reference($id); } if (!$services) { $container->removeDefinition($this->listenerServiceId); return; } $container ->getDefinition($this->listenerServiceId) ->setArgument(0, new IteratorArgument($services)) ; } } http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php000064400000025554150432043210023331 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\Attribute\Target; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Creates the service-locators required by ServiceValueResolver. * * @author Nicolas Grekas */ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface { private $resolverServiceId; private $controllerTag; private $controllerLocator; private $notTaggedControllerResolverServiceId; public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator', string $notTaggedControllerResolverServiceId = 'argument_resolver.not_tagged_controller') { if (0 < \func_num_args()) { trigger_deprecation('symfony/http-kernel', '5.3', 'Configuring "%s" is deprecated.', __CLASS__); } $this->resolverServiceId = $resolverServiceId; $this->controllerTag = $controllerTag; $this->controllerLocator = $controllerLocator; $this->notTaggedControllerResolverServiceId = $notTaggedControllerResolverServiceId; } public function process(ContainerBuilder $container) { if (false === $container->hasDefinition($this->resolverServiceId) && false === $container->hasDefinition($this->notTaggedControllerResolverServiceId)) { return; } $parameterBag = $container->getParameterBag(); $controllers = []; $publicAliases = []; foreach ($container->getAliases() as $id => $alias) { if ($alias->isPublic() && !$alias->isPrivate()) { $publicAliases[(string) $alias][] = $id; } } foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) { $def = $container->getDefinition($id); $def->setPublic(true); $class = $def->getClass(); $autowire = $def->isAutowired(); $bindings = $def->getBindings(); // resolve service class, taking parent definitions into account while ($def instanceof ChildDefinition) { $def = $container->findDefinition($def->getParent()); $class = $class ?: $def->getClass(); $bindings += $def->getBindings(); } $class = $parameterBag->resolveValue($class); if (!$r = $container->getReflectionClass($class)) { throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class); // get regular public methods $methods = []; $arguments = []; foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) { if ('setContainer' === $r->name && $isContainerAware) { continue; } if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) { $methods[strtolower($r->name)] = [$r, $r->getParameters()]; } } // validate and collect explicit per-actions and per-arguments service references foreach ($tags as $attributes) { if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) { $autowire = true; continue; } foreach (['action', 'argument', 'id'] as $k) { if (!isset($attributes[$k][0])) { throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, \JSON_UNESCAPED_UNICODE), $id)); } } if (!isset($methods[$action = strtolower($attributes['action'])])) { throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class)); } [$r, $parameters] = $methods[$action]; $found = false; foreach ($parameters as $p) { if ($attributes['argument'] === $p->name) { if (!isset($arguments[$r->name][$p->name])) { $arguments[$r->name][$p->name] = $attributes['id']; } $found = true; break; } } if (!$found) { throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $this->controllerTag, $id, $r->name, $attributes['argument'], $class)); } } foreach ($methods as [$r, $parameters]) { /** @var \ReflectionMethod $r */ // create a per-method map of argument-names to service/type-references $args = []; foreach ($parameters as $p) { /** @var \ReflectionParameter $p */ $type = ltrim($target = (string) ProxyHelper::getTypeHint($r, $p), '\\'); $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; if (isset($arguments[$r->name][$p->name])) { $target = $arguments[$r->name][$p->name]; if ('?' !== $target[0]) { $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; } elseif ('' === $target = (string) substr($target, 1)) { throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id)); } elseif ($p->allowsNull() && !$p->isOptional()) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } } elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p)]) || isset($bindings[$bindingName = '$'.$name]) || isset($bindings[$bindingName = $type])) { $binding = $bindings[$bindingName]; [$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues(); $binding->setValues([$bindingValue, $bindingId, true, $bindingType, $bindingFile]); if (!$bindingValue instanceof Reference) { $args[$p->name] = new Reference('.value.'.$container->hash($bindingValue)); $container->register((string) $args[$p->name], 'mixed') ->setFactory('current') ->addArgument([$bindingValue]); } else { $args[$p->name] = $bindingValue; } continue; } elseif (!$type || !$autowire || '\\' !== $target[0]) { continue; } elseif (!$p->allowsNull()) { $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; } if (Request::class === $type || SessionInterface::class === $type) { continue; } if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) { $message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type); // see if the type-hint lives in the same namespace as the controller if (0 === strncmp($type, $class, strrpos($class, '\\'))) { $message .= ' Did you forget to add a use statement?'; } $container->register($erroredId = '.errored.'.$container->hash($message), $type) ->addError($message); $args[$p->name] = new Reference($erroredId, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE); } else { $target = ltrim($target, '\\'); $args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, $p->name) : new Reference($target, $invalidBehavior); } } // register the maps as a per-method service-locators if ($args) { $controllers[$id.'::'.$r->name] = ServiceLocatorTagPass::register($container, $args); foreach ($publicAliases[$id] ?? [] as $alias) { $controllers[$alias.'::'.$r->name] = clone $controllers[$id.'::'.$r->name]; } } } } $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers); if ($container->hasDefinition($this->resolverServiceId)) { $container->getDefinition($this->resolverServiceId) ->replaceArgument(0, $controllerLocatorRef); } if ($container->hasDefinition($this->notTaggedControllerResolverServiceId)) { $container->getDefinition($this->notTaggedControllerResolverServiceId) ->replaceArgument(0, $controllerLocatorRef); } $container->setAlias($this->controllerLocator, (string) $controllerLocatorRef); } } http-kernel/DependencyInjection/LoggerPass.php000064400000002001150432043210015464 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Log\Logger; /** * Registers the default logger if necessary. * * @author Kévin Dunglas */ class LoggerPass implements CompilerPassInterface { /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { $container->setAlias(LoggerInterface::class, 'logger') ->setPublic(false); if ($container->has('logger')) { return; } $container->register('logger', Logger::class) ->setPublic(false); } } http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php000064400000002541150432043210020626 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Psr\Container\ContainerInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Fragment\FragmentHandler; /** * Lazily loads fragment renderers from the dependency injection container. * * @author Fabien Potencier */ class LazyLoadingFragmentHandler extends FragmentHandler { private $container; /** * @var array */ private $initialized = []; public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = false) { $this->container = $container; parent::__construct($requestStack, [], $debug); } /** * {@inheritdoc} */ public function render($uri, string $renderer = 'inline', array $options = []) { if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) { $this->addRenderer($this->container->get($renderer)); $this->initialized[$renderer] = true; } return parent::render($uri, $renderer, $options); } } http-kernel/DependencyInjection/ServicesResetter.php000064400000002513150432043210016727 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Contracts\Service\ResetInterface; /** * Resets provided services. * * @author Alexander M. Turek * @author Nicolas Grekas * * @internal */ class ServicesResetter implements ResetInterface { private $resettableServices; private $resetMethods; /** * @param \Traversable $resettableServices * @param array $resetMethods */ public function __construct(\Traversable $resettableServices, array $resetMethods) { $this->resettableServices = $resettableServices; $this->resetMethods = $resetMethods; } public function reset() { foreach ($this->resettableServices as $id => $service) { foreach ((array) $this->resetMethods[$id] as $resetMethod) { if ('?' === $resetMethod[0] && !method_exists($service, $resetMethod = substr($resetMethod, 1))) { continue; } $service->$resetMethod(); } } } } http-kernel/DependencyInjection/ConfigurableExtension.php000064400000002404150432043210017722 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * This extension sub-class provides first-class integration with the * Config/Definition Component. * * You can use this as base class if * * a) you use the Config/Definition component for configuration, * b) your configuration class is named "Configuration", and * c) the configuration class resides in the DependencyInjection sub-folder. * * @author Johannes M. Schmitt */ abstract class ConfigurableExtension extends Extension { /** * {@inheritdoc} */ final public function load(array $configs, ContainerBuilder $container) { $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container); } /** * Configures the passed container according to the merged configuration. */ abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container); } http-kernel/TerminableInterface.php000064400000001616150432043210013413 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Terminable extends the Kernel request/response cycle with dispatching a post * response event after sending the response and before shutting down the kernel. * * @author Jordi Boggiano * @author Pierre Minnieur */ interface TerminableInterface { /** * Terminates a request/response cycle. * * Should be called after sending the response and before shutting down the kernel. */ public function terminate(Request $request, Response $response); } http-kernel/CHANGELOG.md000064400000041102150432043210010602 0ustar00CHANGELOG ========= 5.4 --- * Add the ability to enable the profiler using a request query parameter, body parameter or attribute * Deprecate `AbstractTestSessionListener::getSession` inject a session in the request instead * Deprecate the `fileLinkFormat` parameter of `DebugHandlersListener` * Add support for configuring log level, and status code by exception class * Allow ignoring "kernel.reset" methods that don't exist with "on_invalid" attribute 5.3 --- * Deprecate `ArgumentInterface` * Add `ArgumentMetadata::getAttributes()` * Deprecate `ArgumentMetadata::getAttribute()`, use `getAttributes()` instead * Mark the class `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` as internal * Deprecate returning a `ContainerBuilder` from `KernelInterface::registerContainerConfiguration()` * Deprecate `HttpKernelInterface::MASTER_REQUEST` and add `HttpKernelInterface::MAIN_REQUEST` as replacement * Deprecate `KernelEvent::isMasterRequest()` and add `isMainRequest()` as replacement * Add `#[AsController]` attribute for declaring standalone controllers on PHP 8 * Add `FragmentUriGeneratorInterface` and `FragmentUriGenerator` to generate the URI of a fragment 5.2.0 ----- * added session usage * made the public `http_cache` service handle requests when available * allowed enabling trusted hosts and proxies using new `kernel.trusted_hosts`, `kernel.trusted_proxies` and `kernel.trusted_headers` parameters * content of request parameter `_password` is now also hidden in the request profiler raw content section * Allowed adding attributes on controller arguments that will be passed to argument resolvers. * kernels implementing the `ExtensionInterface` will now be auto-registered to the container * added parameter `kernel.runtime_environment`, defined as `%env(default:kernel.environment:APP_RUNTIME_ENV)%` * do not set a default `Accept` HTTP header when using `HttpKernelBrowser` 5.1.0 ----- * allowed to use a specific logger channel for deprecations * made `WarmableInterface::warmUp()` return a list of classes or files to preload on PHP 7.4+; not returning an array is deprecated * made kernels implementing `WarmableInterface` be part of the cache warmup stage * deprecated support for `service:action` syntax to reference controllers, use `serviceOrFqcn::method` instead * allowed using public aliases to reference controllers * added session usage reporting when the `_stateless` attribute of the request is set to `true` * added `AbstractSessionListener::onSessionUsage()` to report when the session is used while a request is stateless 5.0.0 ----- * removed support for getting the container from a non-booted kernel * removed the first and second constructor argument of `ConfigDataCollector` * removed `ConfigDataCollector::getApplicationName()` * removed `ConfigDataCollector::getApplicationVersion()` * removed support for `Symfony\Component\Templating\EngineInterface` in `HIncludeFragmentRenderer`, use a `Twig\Environment` only * removed `TranslatorListener` in favor of `LocaleAwareListener` * removed `getRootDir()` and `getName()` from `Kernel` and `KernelInterface` * removed `FilterControllerArgumentsEvent`, use `ControllerArgumentsEvent` instead * removed `FilterControllerEvent`, use `ControllerEvent` instead * removed `FilterResponseEvent`, use `ResponseEvent` instead * removed `GetResponseEvent`, use `RequestEvent` instead * removed `GetResponseForControllerResultEvent`, use `ViewEvent` instead * removed `GetResponseForExceptionEvent`, use `ExceptionEvent` instead * removed `PostResponseEvent`, use `TerminateEvent` instead * removed `SaveSessionListener` in favor of `AbstractSessionListener` * removed `Client`, use `HttpKernelBrowser` instead * added method `getProjectDir()` to `KernelInterface` * removed methods `serialize` and `unserialize` from `DataCollector`, store the serialized state in the data property instead * made `ProfilerStorageInterface` internal * removed the second and third argument of `KernelInterface::locateResource` * removed the second and third argument of `FileLocator::__construct` * removed loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as fallback directories. * removed class `ExceptionListener`, use `ErrorListener` instead 4.4.0 ----- * The `DebugHandlersListener` class has been marked as `final` * Added new Bundle directory convention consistent with standard skeletons * Deprecated the second and third argument of `KernelInterface::locateResource` * Deprecated the second and third argument of `FileLocator::__construct` * Deprecated loading resources from `%kernel.root_dir%/Resources` and `%kernel.root_dir%` as fallback directories. Resources like service definitions are usually loaded relative to the current directory or with a glob pattern. The fallback directories have never been advocated so you likely do not use those in any app based on the SF Standard or Flex edition. * Marked all dispatched event classes as `@final` * Added `ErrorController` to enable the preview and error rendering mechanism * Getting the container from a non-booted kernel is deprecated. * Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`, `ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`, `RequestDataCollector` and `TimeDataCollector` classes as `@final`. * Marked the `RouterDataCollector::collect()` method as `@final`. * The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0. * Deprecated methods `ExceptionEvent::get/setException()`, use `get/setThrowable()` instead * Deprecated class `ExceptionListener`, use `ErrorListener` instead 4.3.0 ----- * renamed `Client` to `HttpKernelBrowser` * `KernelInterface` doesn't extend `Serializable` anymore * deprecated the `Kernel::serialize()` and `unserialize()` methods * increased the priority of `Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener` * made `Symfony\Component\HttpKernel\EventListener\LocaleListener` set the default locale early * deprecated `TranslatorListener` in favor of `LocaleAwareListener` * added the registration of all `LocaleAwareInterface` implementations into the `LocaleAwareListener` * made `FileLinkFormatter` final and not implement `Serializable` anymore * the base `DataCollector` doesn't implement `Serializable` anymore, you should store all the serialized state in the data property instead * `DumpDataCollector` has been marked as `final` * added an event listener to prevent search engines from indexing applications in debug mode. * renamed `FilterControllerArgumentsEvent` to `ControllerArgumentsEvent` * renamed `FilterControllerEvent` to `ControllerEvent` * renamed `FilterResponseEvent` to `ResponseEvent` * renamed `GetResponseEvent` to `RequestEvent` * renamed `GetResponseForControllerResultEvent` to `ViewEvent` * renamed `GetResponseForExceptionEvent` to `ExceptionEvent` * renamed `PostResponseEvent` to `TerminateEvent` * added `HttpClientKernel` for handling requests with an `HttpClientInterface` instance * added `trace_header` and `trace_level` configuration options to `HttpCache` 4.2.0 ----- * deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter * deprecated `KernelInterface::getName()` and the `kernel.name` parameter * deprecated the first and second constructor argument of `ConfigDataCollector` * deprecated `ConfigDataCollector::getApplicationName()` * deprecated `ConfigDataCollector::getApplicationVersion()` 4.1.0 ----- * added orphaned events support to `EventDataCollector` * `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`) * Added support for using `service::method` to reference controllers, making it consistent with other cases. It is recommended over the `service:action` syntax with a single colon, which will be deprecated in the future. * Added the ability to profile individual argument value resolvers via the `Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver` 4.0.0 ----- * removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()` instead * using the `DataCollector::cloneVar()` method requires the VarDumper component * removed the `ValueExporter` class * removed `ControllerResolverInterface::getArguments()` * removed `TraceableControllerResolver::getArguments()` * removed `ControllerResolver::getArguments()` and the ability to resolve arguments * removed the `argument_resolver` service dependency from the `debug.controller_resolver` * removed `LazyLoadingFragmentHandler::addRendererService()` * removed `Psr6CacheClearer::addPool()` * removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`, and `Kernel::getEnvParameters()` * support for the `X-Status-Code` when handling exceptions in the `HttpKernel` has been dropped, use the `HttpKernel::allowCustomResponseCode()` method instead * removed convention-based commands registration * removed the `ChainCacheClearer::add()` method * removed the `CacheaWarmerAggregate::add()` and `setWarmers()` methods * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final 3.4.0 ----- * added a minimalist PSR-3 `Logger` class that writes in `stderr` * made kernels implementing `CompilerPassInterface` able to process the container * deprecated bundle inheritance * added `RebootableInterface` and implemented it in `Kernel` * deprecated commands auto registration * deprecated `EnvParametersResource` * added `Symfony\Component\HttpKernel\Client::catchExceptions()` * deprecated the `ChainCacheClearer::add()` method * deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final * added the possibility to reset the profiler to its initial state * deprecated data collectors without a `reset()` method * deprecated implementing `DebugLoggerInterface` without a `clear()` method 3.3.0 ----- * added `kernel.project_dir` and `Kernel::getProjectDir()` * deprecated `kernel.root_dir` and `Kernel::getRootDir()` * deprecated `Kernel::getEnvParameters()` * deprecated the special `SYMFONY__` environment variables * added the possibility to change the query string parameter used by `UriSigner` * deprecated `LazyLoadingFragmentHandler::addRendererService()` * deprecated `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` * deprecated `Psr6CacheClearer::addPool()` 3.2.0 ----- * deprecated `DataCollector::varToString()`, use `cloneVar()` instead * changed surrogate capability name in `AbstractSurrogate::addSurrogateCapability` to 'symfony' * Added `ControllerArgumentValueResolverPass` 3.1.0 ----- * deprecated passing objects as URI attributes to the ESI and SSI renderers * deprecated `ControllerResolver::getArguments()` * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` as argument to `HttpKernel` * added `Symfony\Component\HttpKernel\Controller\ArgumentResolver` * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getMethod()` * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getRedirect()` * added the `kernel.controller_arguments` event, triggered after controller arguments have been resolved 3.0.0 ----- * removed `Symfony\Component\HttpKernel\Kernel::init()` * removed `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle()` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle()` * removed `Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::setProfiler()` * removed `Symfony\Component\HttpKernel\EventListener\FragmentListener::getLocalIpAddresses()` * removed `Symfony\Component\HttpKernel\EventListener\LocaleListener::setRequest()` * removed `Symfony\Component\HttpKernel\EventListener\RouterListener::setRequest()` * removed `Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest()` * removed `Symfony\Component\HttpKernel\Fragment\FragmentHandler::setRequest()` * removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()` * removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()` * removed `Symfony\Component\HttpKernel\HttpCache\Esi::needsEsiParsing()` * removed `Symfony\Component\HttpKernel\HttpCache\HttpCache::getEsi()` * removed `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel` * removed `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass` * removed `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` * removed `Symfony\Component\HttpKernel\EventListener\EsiListener` * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategy` * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategyInterface` * removed `Symfony\Component\HttpKernel\Log\LoggerInterface` * removed `Symfony\Component\HttpKernel\Log\NullLogger` * removed `Symfony\Component\HttpKernel\Profiler::import()` * removed `Symfony\Component\HttpKernel\Profiler::export()` 2.8.0 ----- * deprecated `Profiler::import` and `Profiler::export` 2.7.0 ----- * added the HTTP status code to profiles 2.6.0 ----- * deprecated `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`, use `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` instead * deprecated unused method `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle` 2.5.0 ----- * deprecated `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`, use `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` instead 2.4.0 ----- * added event listeners for the session * added the KernelEvents::FINISH_REQUEST event 2.3.0 ----- * [BC BREAK] renamed `Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener` to `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` and changed its constructor * deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`, `Symfony\Component\HttpKernel\Exception\FatalErrorException` and `Symfony\Component\HttpKernel\Exception\FlattenException` * deprecated `Symfony\Component\HttpKernel\Kernel::init()` * added the possibility to specify an id an extra attributes to hinclude tags * added the collect of data if a controller is a Closure in the Request collector * pass exceptions from the ExceptionListener to the logger using the logging context to allow for more detailed messages 2.2.0 ----- * [BC BREAK] the path info for sub-request is now always _fragment (or whatever you configured instead of the default) * added Symfony\Component\HttpKernel\EventListener\FragmentListener * added Symfony\Component\HttpKernel\UriSigner * added Symfony\Component\HttpKernel\FragmentRenderer and rendering strategies (in Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface) * added Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel * added ControllerReference to create reference of Controllers (used in the FragmentRenderer class) * [BC BREAK] renamed TimeDataCollector::getTotalTime() to TimeDataCollector::getDuration() * updated the MemoryDataCollector to include the memory used in the kernel.terminate event listeners * moved the Stopwatch classes to a new component * added TraceableControllerResolver * added TraceableEventDispatcher (removed ContainerAwareTraceableEventDispatcher) * added support for WinCache opcode cache in ConfigDataCollector 2.1.0 ----- * [BC BREAK] the charset is now configured via the Kernel::getCharset() method * [BC BREAK] the current locale for the user is not stored anymore in the session * added the HTTP method to the profiler storage * updated all listeners to implement EventSubscriberInterface * added TimeDataCollector * added ContainerAwareTraceableEventDispatcher * moved TraceableEventDispatcherInterface to the EventDispatcher component * added RouterListener, LocaleListener, and StreamedResponseListener * added CacheClearerInterface (and ChainCacheClearer) * added a kernel.terminate event (via TerminableInterface and PostResponseEvent) * added a Stopwatch class * added WarmableInterface * improved extensibility between bundles * added profiler storages for Memcache(d), File-based, MongoDB, Redis * moved Filesystem class to its own component http-kernel/Controller/ArgumentResolverInterface.php000064400000001453150432043210016757 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; /** * An ArgumentResolverInterface instance knows how to determine the * arguments for a specific action. * * @author Fabien Potencier */ interface ArgumentResolverInterface { /** * Returns the arguments to pass to the controller. * * @return array * * @throws \RuntimeException When no value could be provided for a required argument */ public function getArguments(Request $request, callable $controller); } http-kernel/Controller/ArgumentResolver.php000064400000007245150432043210015143 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface; /** * Responsible for resolving the arguments passed to an action. * * @author Iltar van der Berg */ final class ArgumentResolver implements ArgumentResolverInterface { private $argumentMetadataFactory; private $argumentValueResolvers; /** * @param iterable $argumentValueResolvers */ public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = []) { $this->argumentMetadataFactory = $argumentMetadataFactory ?? new ArgumentMetadataFactory(); $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); } /** * {@inheritdoc} */ public function getArguments(Request $request, callable $controller): array { $arguments = []; foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) { foreach ($this->argumentValueResolvers as $resolver) { if (!$resolver->supports($request, $metadata)) { continue; } $resolved = $resolver->resolve($request, $metadata); $atLeastOne = false; foreach ($resolved as $append) { $atLeastOne = true; $arguments[] = $append; } if (!$atLeastOne) { throw new \InvalidArgumentException(sprintf('"%s::resolve()" must yield at least one value.', get_debug_type($resolver))); } // continue to the next controller argument continue 2; } $representative = $controller; if (\is_array($representative)) { $representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]); } elseif (\is_object($representative)) { $representative = \get_class($representative); } throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); } return $arguments; } /** * @return iterable */ public static function getDefaultArgumentValueResolvers(): iterable { return [ new RequestAttributeValueResolver(), new RequestValueResolver(), new SessionValueResolver(), new DefaultValueResolver(), new VariadicValueResolver(), ]; } } http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php000064400000002272150432043210021241 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Yields the default value defined in the action signature when no value has been given. * * @author Iltar van der Berg */ final class DefaultValueResolver implements ArgumentValueResolverInterface { /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic()); } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null; } } http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php000064400000002162150432043210023167 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Yields a non-variadic argument's value from the request attributes. * * @author Iltar van der Berg */ final class RequestAttributeValueResolver implements ArgumentValueResolverInterface { /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { return !$argument->isVariadic() && $request->attributes->has($argument->getName()); } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { yield $request->attributes->get($argument->getName()); } } http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php000064400000003314150432043210021535 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\Stopwatch\Stopwatch; /** * Provides timing information via the stopwatch. * * @author Iltar van der Berg */ final class TraceableValueResolver implements ArgumentValueResolverInterface { private $inner; private $stopwatch; public function __construct(ArgumentValueResolverInterface $inner, Stopwatch $stopwatch) { $this->inner = $inner; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { $method = \get_class($this->inner).'::'.__FUNCTION__; $this->stopwatch->start($method, 'controller.argument_value_resolver'); $return = $this->inner->supports($request, $argument); $this->stopwatch->stop($method); return $return; } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { $method = \get_class($this->inner).'::'.__FUNCTION__; $this->stopwatch->start($method, 'controller.argument_value_resolver'); yield from $this->inner->resolve($request, $argument); $this->stopwatch->stop($method); } } http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php000064400000005743150432043210021263 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Psr\Container\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Yields a service keyed by _controller and argument name. * * @author Nicolas Grekas */ final class ServiceValueResolver implements ArgumentValueResolverInterface { private $container; public function __construct(ContainerInterface $container) { $this->container = $container; } /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { $controller = $request->attributes->get('_controller'); if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { $controller = $controller[0].'::'.$controller[1]; } elseif (!\is_string($controller) || '' === $controller) { return false; } if ('\\' === $controller[0]) { $controller = ltrim($controller, '\\'); } if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); } return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { if (\is_array($controller = $request->attributes->get('_controller'))) { $controller = $controller[0].'::'.$controller[1]; } if ('\\' === $controller[0]) { $controller = ltrim($controller, '\\'); } if (!$this->container->has($controller)) { $i = strrpos($controller, ':'); $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); } try { yield $this->container->get($controller)->get($argument->getName()); } catch (RuntimeException $e) { $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); if ($e->getMessage() === $message) { $message = sprintf('Cannot resolve %s: %s', $what, $message); } $r = new \ReflectionProperty($e, 'message'); $r->setAccessible(true); $r->setValue($e, $message); throw $e; } } } http-kernel/Controller/ArgumentResolver/SessionValueResolver.php000064400000002466150432043210021305 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Yields the Session. * * @author Iltar van der Berg */ final class SessionValueResolver implements ArgumentValueResolverInterface { /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { if (!$request->hasSession()) { return false; } $type = $argument->getType(); if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) { return false; } return $request->getSession() instanceof $type; } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { yield $request->getSession(); } } http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php000064400000005246150432043210023601 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Psr\Container\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Provides an intuitive error message when controller fails because it is not registered as a service. * * @author Simeon Kolev */ final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface { private $container; public function __construct(ContainerInterface $container) { $this->container = $container; } /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { $controller = $request->attributes->get('_controller'); if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { $controller = $controller[0].'::'.$controller[1]; } elseif (!\is_string($controller) || '' === $controller) { return false; } if ('\\' === $controller[0]) { $controller = ltrim($controller, '\\'); } if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); } return false === $this->container->has($controller); } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { if (\is_array($controller = $request->attributes->get('_controller'))) { $controller = $controller[0].'::'.$controller[1]; } if ('\\' === $controller[0]) { $controller = ltrim($controller, '\\'); } if (!$this->container->has($controller)) { $i = strrpos($controller, ':'); $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); } $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); $message = sprintf('Could not resolve %s, maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?', $what); throw new RuntimeException($message); } } http-kernel/Controller/ArgumentResolver/RequestValueResolver.php000064400000002117150432043210021303 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Yields the same instance as the request object passed along. * * @author Iltar van der Berg */ final class RequestValueResolver implements ArgumentValueResolverInterface { /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class); } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { yield $request; } } http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php000064400000002634150432043210021401 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Yields a variadic argument's values from the request attributes. * * @author Iltar van der Berg */ final class VariadicValueResolver implements ArgumentValueResolverInterface { /** * {@inheritdoc} */ public function supports(Request $request, ArgumentMetadata $argument): bool { return $argument->isVariadic() && $request->attributes->has($argument->getName()); } /** * {@inheritdoc} */ public function resolve(Request $request, ArgumentMetadata $argument): iterable { $values = $request->attributes->get($argument->getName()); if (!\is_array($values)) { throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), get_debug_type($values))); } yield from $values; } } http-kernel/Controller/ControllerResolverInterface.php000064400000002514150432043210017317 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; /** * A ControllerResolverInterface implementation knows how to determine the * controller to execute based on a Request object. * * A Controller can be any valid PHP callable. * * @author Fabien Potencier */ interface ControllerResolverInterface { /** * Returns the Controller instance associated with a Request. * * As several resolvers can exist for a single application, a resolver must * return false when it is not able to determine the controller. * * The resolver must only throw an exception when it should be able to load a * controller but cannot because of some errors made by the developer. * * @return callable|false A PHP callable representing the Controller, * or false if this resolver is not able to determine the controller * * @throws \LogicException If a controller was found based on the request but it is not callable */ public function getController(Request $request); } http-kernel/Controller/TraceableControllerResolver.php000064400000001763150432043210017306 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Stopwatch\Stopwatch; /** * @author Fabien Potencier */ class TraceableControllerResolver implements ControllerResolverInterface { private $resolver; private $stopwatch; public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) { $this->resolver = $resolver; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function getController(Request $request) { $e = $this->stopwatch->start('controller.get_callable'); $ret = $this->resolver->getController($request); $e->stop(); return $ret; } } http-kernel/Controller/ErrorController.php000064400000003706150432043210014772 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Renders error or exception pages from a given FlattenException. * * @author Yonel Ceruto * @author Matthias Pigulla */ class ErrorController { private $kernel; private $controller; private $errorRenderer; public function __construct(HttpKernelInterface $kernel, $controller, ErrorRendererInterface $errorRenderer) { $this->kernel = $kernel; $this->controller = $controller; $this->errorRenderer = $errorRenderer; } public function __invoke(\Throwable $exception): Response { $exception = $this->errorRenderer->render($exception); return new Response($exception->getAsString(), $exception->getStatusCode(), $exception->getHeaders()); } public function preview(Request $request, int $code): Response { /* * This Request mimics the parameters set by * \Symfony\Component\HttpKernel\EventListener\ErrorListener::duplicateRequest, with * the additional "showException" flag. */ $subRequest = $request->duplicate(null, null, [ '_controller' => $this->controller, 'exception' => new HttpException($code, 'This is a sample exception.'), 'logger' => null, 'showException' => false, ]); return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST); } } http-kernel/Controller/ContainerControllerResolver.php000064400000005131150432043210017337 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\Container; /** * A controller resolver searching for a controller in a psr-11 container when using the "service::method" notation. * * @author Fabien Potencier * @author Maxime Steinhausser */ class ContainerControllerResolver extends ControllerResolver { protected $container; public function __construct(ContainerInterface $container, LoggerInterface $logger = null) { $this->container = $container; parent::__construct($logger); } protected function createController(string $controller) { if (1 === substr_count($controller, ':')) { $controller = str_replace(':', '::', $controller); trigger_deprecation('symfony/http-kernel', '5.1', 'Referencing controllers with a single colon is deprecated. Use "%s" instead.', $controller); } return parent::createController($controller); } /** * {@inheritdoc} */ protected function instantiateController(string $class) { $class = ltrim($class, '\\'); if ($this->container->has($class)) { return $this->container->get($class); } try { return parent::instantiateController($class); } catch (\Error $e) { } $this->throwExceptionIfControllerWasRemoved($class, $e); if ($e instanceof \ArgumentCountError) { throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define the controller as a service?', $class), 0, $e); } throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class.', $class), 0, $e); } private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous) { if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) { throw new \InvalidArgumentException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous); } } } http-kernel/Controller/ArgumentValueResolverInterface.php000064400000001670150432043210017755 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; /** * Responsible for resolving the value of an argument based on its metadata. * * @author Iltar van der Berg */ interface ArgumentValueResolverInterface { /** * Whether this resolver can resolve the value for the given ArgumentMetadata. * * @return bool */ public function supports(Request $request, ArgumentMetadata $argument); /** * Returns the possible value(s). * * @return iterable */ public function resolve(Request $request, ArgumentMetadata $argument); } http-kernel/Controller/ControllerReference.php000064400000002432150432043210015572 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; /** * Acts as a marker and a data holder for a Controller. * * Some methods in Symfony accept both a URI (as a string) or a controller as * an argument. In the latter case, instead of passing an array representing * the controller, you can use an instance of this class. * * @author Fabien Potencier * * @see FragmentRendererInterface */ class ControllerReference { public $controller; public $attributes = []; public $query = []; /** * @param string $controller The controller name * @param array $attributes An array of parameters to add to the Request attributes * @param array $query An array of parameters to add to the Request query string */ public function __construct(string $controller, array $attributes = [], array $query = []) { $this->controller = $controller; $this->attributes = $attributes; $this->query = $query; } } http-kernel/Controller/ControllerResolver.php000064400000016411150432043210015477 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; /** * This implementation uses the '_controller' request attribute to determine * the controller to execute. * * @author Fabien Potencier * @author Tobias Schultze */ class ControllerResolver implements ControllerResolverInterface { private $logger; public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; } /** * {@inheritdoc} */ public function getController(Request $request) { if (!$controller = $request->attributes->get('_controller')) { if (null !== $this->logger) { $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.'); } return false; } if (\is_array($controller)) { if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) { try { $controller[0] = $this->instantiateController($controller[0]); } catch (\Error | \LogicException $e) { try { // We cannot just check is_callable but have to use reflection because a non-static method // can still be called statically in PHP but we don't want that. This is deprecated in PHP 7, so we // could simplify this with PHP 8. if ((new \ReflectionMethod($controller[0], $controller[1]))->isStatic()) { return $controller; } } catch (\ReflectionException $reflectionException) { throw $e; } throw $e; } } if (!\is_callable($controller)) { throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller)); } return $controller; } if (\is_object($controller)) { if (!\is_callable($controller)) { throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($controller)); } return $controller; } if (\function_exists($controller)) { return $controller; } try { $callable = $this->createController($controller); } catch (\InvalidArgumentException $e) { throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$e->getMessage(), 0, $e); } if (!\is_callable($callable)) { throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable: ', $request->getPathInfo()).$this->getControllerError($callable)); } return $callable; } /** * Returns a callable for the given controller. * * @return callable * * @throws \InvalidArgumentException When the controller cannot be created */ protected function createController(string $controller) { if (!str_contains($controller, '::')) { $controller = $this->instantiateController($controller); if (!\is_callable($controller)) { throw new \InvalidArgumentException($this->getControllerError($controller)); } return $controller; } [$class, $method] = explode('::', $controller, 2); try { $controller = [$this->instantiateController($class), $method]; } catch (\Error | \LogicException $e) { try { if ((new \ReflectionMethod($class, $method))->isStatic()) { return $class.'::'.$method; } } catch (\ReflectionException $reflectionException) { throw $e; } throw $e; } if (!\is_callable($controller)) { throw new \InvalidArgumentException($this->getControllerError($controller)); } return $controller; } /** * Returns an instantiated controller. * * @return object */ protected function instantiateController(string $class) { return new $class(); } private function getControllerError($callable): string { if (\is_string($callable)) { if (str_contains($callable, '::')) { $callable = explode('::', $callable, 2); } else { return sprintf('Function "%s" does not exist.', $callable); } } if (\is_object($callable)) { $availableMethods = $this->getClassMethodsWithoutMagicMethods($callable); $alternativeMsg = $availableMethods ? sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : ''; return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', get_debug_type($callable), $alternativeMsg); } if (!\is_array($callable)) { return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', get_debug_type($callable)); } if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) { return 'Invalid array callable, expected [controller, method].'; } [$controller, $method] = $callable; if (\is_string($controller) && !class_exists($controller)) { return sprintf('Class "%s" does not exist.', $controller); } $className = \is_object($controller) ? get_debug_type($controller) : $controller; if (method_exists($controller, $method)) { return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className); } $collection = $this->getClassMethodsWithoutMagicMethods($controller); $alternatives = []; foreach ($collection as $item) { $lev = levenshtein($method, $item); if ($lev <= \strlen($method) / 3 || str_contains($item, $method)) { $alternatives[] = $item; } } asort($alternatives); $message = sprintf('Expected method "%s" on class "%s"', $method, $className); if (\count($alternatives) > 0) { $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives)); } else { $message .= sprintf('. Available methods: "%s".', implode('", "', $collection)); } return $message; } private function getClassMethodsWithoutMagicMethods($classOrObject): array { $methods = get_class_methods($classOrObject); return array_filter($methods, function (string $method) { return 0 !== strncmp($method, '__', 2); }); } } http-kernel/Controller/TraceableArgumentResolver.php000064400000002017150432043210016736 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Stopwatch\Stopwatch; /** * @author Fabien Potencier */ class TraceableArgumentResolver implements ArgumentResolverInterface { private $resolver; private $stopwatch; public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch) { $this->resolver = $resolver; $this->stopwatch = $stopwatch; } /** * {@inheritdoc} */ public function getArguments(Request $request, callable $controller) { $e = $this->stopwatch->start('controller.get_arguments'); $ret = $this->resolver->getArguments($request, $controller); $e->stop(); return $ret; } } http-kernel/EventListener/FragmentListener.php000064400000005536150432043210015555 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\UriSigner; /** * Handles content fragments represented by special URIs. * * All URL paths starting with /_fragment are handled as * content fragments by this listener. * * Throws an AccessDeniedHttpException exception if the request * is not signed or if it is not an internal sub-request. * * @author Fabien Potencier * * @final */ class FragmentListener implements EventSubscriberInterface { private $signer; private $fragmentPath; /** * @param string $fragmentPath The path that triggers this listener */ public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment') { $this->signer = $signer; $this->fragmentPath = $fragmentPath; } /** * Fixes request attributes when the path is '/_fragment'. * * @throws AccessDeniedHttpException if the request does not come from a trusted IP */ public function onKernelRequest(RequestEvent $event) { $request = $event->getRequest(); if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) { return; } if ($request->attributes->has('_controller')) { // Is a sub-request: no need to parse _path but it should still be removed from query parameters as below. $request->query->remove('_path'); return; } if ($event->isMainRequest()) { $this->validateRequest($request); } parse_str($request->query->get('_path', ''), $attributes); $request->attributes->add($attributes); $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes)); $request->query->remove('_path'); } protected function validateRequest(Request $request) { // is the Request safe? if (!$request->isMethodSafe()) { throw new AccessDeniedHttpException(); } // is the Request signed? if ($this->signer->checkRequest($request)) { return; } throw new AccessDeniedHttpException(); } public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => [['onKernelRequest', 48]], ]; } } http-kernel/EventListener/DisallowRobotsIndexingListener.php000064400000002152150432043210020436 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * Ensures that the application is not indexed by search engines. * * @author Gary PEGEOT */ class DisallowRobotsIndexingListener implements EventSubscriberInterface { private const HEADER_NAME = 'X-Robots-Tag'; public function onResponse(ResponseEvent $event): void { if (!$event->getResponse()->headers->has(static::HEADER_NAME)) { $event->getResponse()->headers->set(static::HEADER_NAME, 'noindex'); } } /** * {@inheritdoc} */ public static function getSubscribedEvents() { return [ KernelEvents::RESPONSE => ['onResponse', -255], ]; } } http-kernel/EventListener/LocaleAwareListener.php000064400000004567150432043210016174 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Contracts\Translation\LocaleAwareInterface; /** * Pass the current locale to the provided services. * * @author Pierre Bobiet */ class LocaleAwareListener implements EventSubscriberInterface { private $localeAwareServices; private $requestStack; /** * @param iterable $localeAwareServices */ public function __construct(iterable $localeAwareServices, RequestStack $requestStack) { $this->localeAwareServices = $localeAwareServices; $this->requestStack = $requestStack; } public function onKernelRequest(RequestEvent $event): void { $this->setLocale($event->getRequest()->getLocale(), $event->getRequest()->getDefaultLocale()); } public function onKernelFinishRequest(FinishRequestEvent $event): void { if (null === $parentRequest = $this->requestStack->getParentRequest()) { foreach ($this->localeAwareServices as $service) { $service->setLocale($event->getRequest()->getDefaultLocale()); } return; } $this->setLocale($parentRequest->getLocale(), $parentRequest->getDefaultLocale()); } public static function getSubscribedEvents() { return [ // must be registered after the Locale listener KernelEvents::REQUEST => [['onKernelRequest', 15]], KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', -15]], ]; } private function setLocale(string $locale, string $defaultLocale): void { foreach ($this->localeAwareServices as $service) { try { $service->setLocale($locale); } catch (\InvalidArgumentException $e) { $service->setLocale($defaultLocale); } } } } http-kernel/EventListener/DumpListener.php000064400000003336150432043210014713 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Dumper\DataDumperInterface; use Symfony\Component\VarDumper\Server\Connection; use Symfony\Component\VarDumper\VarDumper; /** * Configures dump() handler. * * @author Nicolas Grekas */ class DumpListener implements EventSubscriberInterface { private $cloner; private $dumper; private $connection; public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null) { $this->cloner = $cloner; $this->dumper = $dumper; $this->connection = $connection; } public function configure() { $cloner = $this->cloner; $dumper = $this->dumper; $connection = $this->connection; VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) { $data = $cloner->cloneVar($var); if (!$connection || !$connection->write($data)) { $dumper->dump($data); } }); } public static function getSubscribedEvents() { if (!class_exists(ConsoleEvents::class)) { return []; } // Register early to have a working dump() as early as possible return [ConsoleEvents::COMMAND => ['configure', 1024]]; } } http-kernel/EventListener/LocaleListener.php000064400000006066150432043210015210 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\KernelEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Routing\RequestContextAwareInterface; /** * Initializes the locale based on the current request. * * @author Fabien Potencier * * @final */ class LocaleListener implements EventSubscriberInterface { private $router; private $defaultLocale; private $requestStack; private $useAcceptLanguageHeader; private $enabledLocales; public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = []) { $this->defaultLocale = $defaultLocale; $this->requestStack = $requestStack; $this->router = $router; $this->useAcceptLanguageHeader = $useAcceptLanguageHeader; $this->enabledLocales = $enabledLocales; } public function setDefaultLocale(KernelEvent $event) { $event->getRequest()->setDefaultLocale($this->defaultLocale); } public function onKernelRequest(RequestEvent $event) { $request = $event->getRequest(); $this->setLocale($request); $this->setRouterContext($request); } public function onKernelFinishRequest(FinishRequestEvent $event) { if (null !== $parentRequest = $this->requestStack->getParentRequest()) { $this->setRouterContext($parentRequest); } } private function setLocale(Request $request) { if ($locale = $request->attributes->get('_locale')) { $request->setLocale($locale); } elseif ($this->useAcceptLanguageHeader && $this->enabledLocales && ($preferredLanguage = $request->getPreferredLanguage($this->enabledLocales))) { $request->setLocale($preferredLanguage); $request->attributes->set('_vary_by_language', true); } } private function setRouterContext(Request $request) { if (null !== $this->router) { $this->router->getContext()->setParameter('_locale', $request->getLocale()); } } public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => [ ['setDefaultLocale', 100], // must be registered after the Router to have access to the _locale ['onKernelRequest', 16], ], KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], ]; } } http-kernel/EventListener/SurrogateListener.php000064400000003375150432043210015764 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; use Symfony\Component\HttpKernel\KernelEvents; /** * SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates. * * @author Fabien Potencier * * @final */ class SurrogateListener implements EventSubscriberInterface { private $surrogate; public function __construct(SurrogateInterface $surrogate = null) { $this->surrogate = $surrogate; } /** * Filters the Response. */ public function onKernelResponse(ResponseEvent $event) { if (!$event->isMainRequest()) { return; } $kernel = $event->getKernel(); $surrogate = $this->surrogate; if ($kernel instanceof HttpCache) { $surrogate = $kernel->getSurrogate(); if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) { $surrogate = $this->surrogate; } } if (null === $surrogate) { return; } $surrogate->addSurrogateControl($event->getResponse()); } public static function getSubscribedEvents(): array { return [ KernelEvents::RESPONSE => 'onKernelResponse', ]; } } http-kernel/EventListener/ResponseListener.php000064400000003525150432043210015604 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * ResponseListener fixes the Response headers based on the Request. * * @author Fabien Potencier * * @final */ class ResponseListener implements EventSubscriberInterface { private $charset; private $addContentLanguageHeader; public function __construct(string $charset, bool $addContentLanguageHeader = false) { $this->charset = $charset; $this->addContentLanguageHeader = $addContentLanguageHeader; } /** * Filters the Response. */ public function onKernelResponse(ResponseEvent $event) { if (!$event->isMainRequest()) { return; } $response = $event->getResponse(); if (null === $response->getCharset()) { $response->setCharset($this->charset); } if ($this->addContentLanguageHeader && !$response->isInformational() && !$response->isEmpty() && !$response->headers->has('Content-Language')) { $response->headers->set('Content-Language', $event->getRequest()->getLocale()); } if ($event->getRequest()->attributes->get('_vary_by_language')) { $response->setVary('Accept-Language', false); } $response->prepare($event->getRequest()); } public static function getSubscribedEvents(): array { return [ KernelEvents::RESPONSE => 'onKernelResponse', ]; } } http-kernel/EventListener/AbstractSessionListener.php000064400000025751150432043210017122 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Container\ContainerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\SessionUtils; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\Exception\UnexpectedSessionUsageException; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Contracts\Service\ResetInterface; /** * Sets the session onto the request on the "kernel.request" event and saves * it on the "kernel.response" event. * * In addition, if the session has been started it overrides the Cache-Control * header in such a way that all caching is disabled in that case. * If you have a scenario where caching responses with session information in * them makes sense, you can disable this behaviour by setting the header * AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response. * * @author Johannes M. Schmitt * @author Tobias Schultze * * @internal */ abstract class AbstractSessionListener implements EventSubscriberInterface, ResetInterface { public const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl'; protected $container; private $sessionUsageStack = []; private $debug; /** * @var array */ private $sessionOptions; public function __construct(ContainerInterface $container = null, bool $debug = false, array $sessionOptions = []) { $this->container = $container; $this->debug = $debug; $this->sessionOptions = $sessionOptions; } public function onKernelRequest(RequestEvent $event) { if (!$event->isMainRequest()) { return; } $request = $event->getRequest(); if (!$request->hasSession()) { // This variable prevents calling `$this->getSession()` twice in case the Request (and the below factory) is cloned $sess = null; $request->setSessionFactory(function () use (&$sess, $request) { if (!$sess) { $sess = $this->getSession(); } /* * For supporting sessions in php runtime with runners like roadrunner or swoole the session * cookie need read from the cookie bag and set on the session storage. */ if ($sess && !$sess->isStarted()) { $sessionId = $request->cookies->get($sess->getName(), ''); $sess->setId($sessionId); } return $sess; }); } $session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null; $this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0; } public function onKernelResponse(ResponseEvent $event) { if (!$event->isMainRequest()) { return; } $response = $event->getResponse(); $autoCacheControl = !$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER); // Always remove the internal header if present $response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER); if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $event->getRequest()->getSession()) { return; } if ($session->isStarted()) { /* * Saves the session, in case it is still open, before sending the response/headers. * * This ensures several things in case the developer did not save the session explicitly: * * * If a session save handler without locking is used, it ensures the data is available * on the next request, e.g. after a redirect. PHPs auto-save at script end via * session_register_shutdown is executed after fastcgi_finish_request. So in this case * the data could be missing the next request because it might not be saved the moment * the new request is processed. * * A locking save handler (e.g. the native 'files') circumvents concurrency problems like * the one above. But by saving the session before long-running things in the terminate event, * we ensure the session is not blocked longer than needed. * * When regenerating the session ID no locking is involved in PHPs session design. See * https://bugs.php.net/61470 for a discussion. So in this case, the session must * be saved anyway before sending the headers with the new session ID. Otherwise session * data could get lost again for concurrent requests with the new ID. One result could be * that you get logged out after just logging in. * * This listener should be executed as one of the last listeners, so that previous listeners * can still operate on the open session. This prevents the overhead of restarting it. * Listeners after closing the session can still work with the session as usual because * Symfonys session implementation starts the session on demand. So writing to it after * it is saved will just restart it. */ $session->save(); /* * For supporting sessions in php runtime with runners like roadrunner or swoole the session * cookie need to be written on the response object and should not be written by PHP itself. */ $sessionName = $session->getName(); $sessionId = $session->getId(); $sessionCookiePath = $this->sessionOptions['cookie_path'] ?? '/'; $sessionCookieDomain = $this->sessionOptions['cookie_domain'] ?? null; $sessionCookieSecure = $this->sessionOptions['cookie_secure'] ?? false; $sessionCookieHttpOnly = $this->sessionOptions['cookie_httponly'] ?? true; $sessionCookieSameSite = $this->sessionOptions['cookie_samesite'] ?? Cookie::SAMESITE_LAX; SessionUtils::popSessionCookie($sessionName, $sessionId); $request = $event->getRequest(); $requestSessionCookieId = $request->cookies->get($sessionName); if ($requestSessionCookieId && $session->isEmpty()) { $response->headers->clearCookie( $sessionName, $sessionCookiePath, $sessionCookieDomain, $sessionCookieSecure, $sessionCookieHttpOnly, $sessionCookieSameSite ); } elseif ($sessionId !== $requestSessionCookieId) { $expire = 0; $lifetime = $this->sessionOptions['cookie_lifetime'] ?? null; if ($lifetime) { $expire = time() + $lifetime; } $response->headers->setCookie( Cookie::create( $sessionName, $sessionId, $expire, $sessionCookiePath, $sessionCookieDomain, $sessionCookieSecure, $sessionCookieHttpOnly, false, $sessionCookieSameSite ) ); } } if ($session instanceof Session ? $session->getUsageIndex() === end($this->sessionUsageStack) : !$session->isStarted()) { return; } if ($autoCacheControl) { $response ->setExpires(new \DateTime()) ->setPrivate() ->setMaxAge(0) ->headers->addCacheControlDirective('must-revalidate'); } if (!$event->getRequest()->attributes->get('_stateless', false)) { return; } if ($this->debug) { throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.'); } if ($this->container->has('logger')) { $this->container->get('logger')->warning('Session was used while the request was declared stateless.'); } } public function onFinishRequest(FinishRequestEvent $event) { if ($event->isMainRequest()) { array_pop($this->sessionUsageStack); } } public function onSessionUsage(): void { if (!$this->debug) { return; } if ($this->container && $this->container->has('session_collector')) { $this->container->get('session_collector')(); } if (!$requestStack = $this->container && $this->container->has('request_stack') ? $this->container->get('request_stack') : null) { return; } $stateless = false; $clonedRequestStack = clone $requestStack; while (null !== ($request = $clonedRequestStack->pop()) && !$stateless) { $stateless = $request->attributes->get('_stateless'); } if (!$stateless) { return; } if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $requestStack->getCurrentRequest()->getSession()) { return; } if ($session->isStarted()) { $session->save(); } throw new UnexpectedSessionUsageException('Session was used while the request was declared stateless.'); } public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => ['onKernelRequest', 128], // low priority to come after regular response listeners, but higher than StreamedResponseListener KernelEvents::RESPONSE => ['onKernelResponse', -1000], KernelEvents::FINISH_REQUEST => ['onFinishRequest'], ]; } public function reset(): void { if (\PHP_SESSION_ACTIVE === session_status()) { session_abort(); } session_unset(); $_SESSION = []; if (!headers_sent()) { // session id can only be reset when no headers were so we check for headers_sent first session_id(''); } } /** * Gets the session object. * * @return SessionInterface|null */ abstract protected function getSession(); } http-kernel/EventListener/RouterListener.php000064400000015266150432043210015273 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RequestContextAwareInterface; /** * Initializes the context from the request and sets request attributes based on a matching route. * * @author Fabien Potencier * @author Yonel Ceruto * * @final */ class RouterListener implements EventSubscriberInterface { private $matcher; private $context; private $logger; private $requestStack; private $projectDir; private $debug; /** * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * * @throws \InvalidArgumentException */ public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } if (null === $context && !$matcher instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); } $this->matcher = $matcher; $this->context = $context ?? $matcher->getContext(); $this->requestStack = $requestStack; $this->logger = $logger; $this->projectDir = $projectDir; $this->debug = $debug; } private function setCurrentRequest(Request $request = null) { if (null !== $request) { try { $this->context->fromRequest($request); } catch (\UnexpectedValueException $e) { throw new BadRequestHttpException($e->getMessage(), $e, $e->getCode()); } } } /** * After a sub-request is done, we need to reset the routing context to the parent request so that the URL generator * operates on the correct context again. */ public function onKernelFinishRequest(FinishRequestEvent $event) { $this->setCurrentRequest($this->requestStack->getParentRequest()); } public function onKernelRequest(RequestEvent $event) { $request = $event->getRequest(); $this->setCurrentRequest($request); if ($request->attributes->has('_controller')) { // routing is already done return; } // add attributes based on the request (routing) try { // matching a request is more powerful than matching a URL path + context, so try that first if ($this->matcher instanceof RequestMatcherInterface) { $parameters = $this->matcher->matchRequest($request); } else { $parameters = $this->matcher->match($request->getPathInfo()); } if (null !== $this->logger) { $this->logger->info('Matched route "{route}".', [ 'route' => $parameters['_route'] ?? 'n/a', 'route_parameters' => $parameters, 'request_uri' => $request->getUri(), 'method' => $request->getMethod(), ]); } $request->attributes->add($parameters); unset($parameters['_route'], $parameters['_controller']); $request->attributes->set('_route_params', $parameters); } catch (ResourceNotFoundException $e) { $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getUriForPath($request->getPathInfo())); if ($referer = $request->headers->get('referer')) { $message .= sprintf(' (from "%s")', $referer); } throw new NotFoundHttpException($message, $e); } catch (MethodNotAllowedException $e) { $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getUriForPath($request->getPathInfo()), implode(', ', $e->getAllowedMethods())); throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e); } } public function onKernelException(ExceptionEvent $event) { if (!$this->debug || !($e = $event->getThrowable()) instanceof NotFoundHttpException) { return; } if ($e->getPrevious() instanceof NoConfigurationException) { $event->setResponse($this->createWelcomeResponse()); } } public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => [['onKernelRequest', 32]], KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], KernelEvents::EXCEPTION => ['onKernelException', -64], ]; } private function createWelcomeResponse(): Response { $version = Kernel::VERSION; $projectDir = realpath((string) $this->projectDir).\DIRECTORY_SEPARATOR; $docVersion = substr(Kernel::VERSION, 0, 3); ob_start(); include \dirname(__DIR__).'/Resources/welcome.html.php'; return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND); } } http-kernel/EventListener/ValidateRequestListener.php000064400000002264150432043210017107 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * Validates Requests. * * @author Magnus Nordlander * * @final */ class ValidateRequestListener implements EventSubscriberInterface { /** * Performs the validation. */ public function onKernelRequest(RequestEvent $event) { if (!$event->isMainRequest()) { return; } $request = $event->getRequest(); if ($request::getTrustedProxies()) { $request->getClientIps(); } $request->getHost(); } /** * {@inheritdoc} */ public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => [ ['onKernelRequest', 256], ], ]; } } http-kernel/EventListener/AddRequestFormatsListener.php000064400000002313150432043210017375 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * Adds configured formats to each request. * * @author Gildas Quemener * * @final */ class AddRequestFormatsListener implements EventSubscriberInterface { protected $formats; public function __construct(array $formats) { $this->formats = $formats; } /** * Adds request formats. */ public function onKernelRequest(RequestEvent $event) { $request = $event->getRequest(); foreach ($this->formats as $format => $mimeTypes) { $request->setFormat($format, $mimeTypes); } } /** * {@inheritdoc} */ public static function getSubscribedEvents(): array { return [KernelEvents::REQUEST => ['onKernelRequest', 100]]; } } http-kernel/EventListener/SessionListener.php000064400000003460150432043210015427 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpKernel\Event\RequestEvent; /** * Sets the session in the request. * * When the passed container contains a "session_storage" entry which * holds a NativeSessionStorage instance, the "cookie_secure" option * will be set to true whenever the current main request is secure. * * @author Fabien Potencier * * @final */ class SessionListener extends AbstractSessionListener { public function onKernelRequest(RequestEvent $event) { parent::onKernelRequest($event); if (!$event->isMainRequest() || (!$this->container->has('session') && !$this->container->has('session_factory'))) { return; } if ($this->container->has('session_storage') && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage && ($mainRequest = $this->container->get('request_stack')->getMainRequest()) && $mainRequest->isSecure() ) { $storage->setOptions(['cookie_secure' => true]); } } protected function getSession(): ?SessionInterface { if ($this->container->has('session')) { return $this->container->get('session'); } if ($this->container->has('session_factory')) { return $this->container->get('session_factory')->createSession(); } return null; } } http-kernel/EventListener/ErrorListener.php000064400000014114150432043210015073 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\Debug\Exception\FlattenException as LegacyFlattenException; use Symfony\Component\ErrorHandler\Exception\FlattenException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; /** * @author Fabien Potencier */ class ErrorListener implements EventSubscriberInterface { protected $controller; protected $logger; protected $debug; protected $exceptionsMapping; public function __construct($controller, LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = []) { $this->controller = $controller; $this->logger = $logger; $this->debug = $debug; $this->exceptionsMapping = $exceptionsMapping; } public function logKernelException(ExceptionEvent $event) { $throwable = $event->getThrowable(); $logLevel = null; foreach ($this->exceptionsMapping as $class => $config) { if ($throwable instanceof $class && $config['log_level']) { $logLevel = $config['log_level']; break; } } $e = FlattenException::createFromThrowable($throwable); $this->logException($throwable, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine()), $logLevel); } public function onKernelException(ExceptionEvent $event) { if (null === $this->controller) { return; } $throwable = $event->getThrowable(); $request = $this->duplicateRequest($throwable, $event->getRequest()); try { $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { $f = FlattenException::createFromThrowable($e); $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), $e->getFile(), $e->getLine())); $prev = $e; do { if ($throwable === $wrapper = $prev) { throw $e; } } while ($prev = $wrapper->getPrevious()); $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); $prev->setAccessible(true); $prev->setValue($wrapper, $throwable); throw $e; } foreach ($this->exceptionsMapping as $exception => $config) { if ($throwable instanceof $exception && $config['status_code']) { $response->setStatusCode($config['status_code']); break; } } $event->setResponse($response); if ($this->debug) { $event->getRequest()->attributes->set('_remove_csp_headers', true); } } public function removeCspHeader(ResponseEvent $event): void { if ($this->debug && $event->getRequest()->attributes->get('_remove_csp_headers', false)) { $event->getResponse()->headers->remove('Content-Security-Policy'); } } public function onControllerArguments(ControllerArgumentsEvent $event) { $e = $event->getRequest()->attributes->get('exception'); if (!$e instanceof \Throwable || false === $k = array_search($e, $event->getArguments(), true)) { return; } $r = new \ReflectionFunction(\Closure::fromCallable($event->getController())); $r = $r->getParameters()[$k] ?? null; if ($r && (!($r = $r->getType()) instanceof \ReflectionNamedType || \in_array($r->getName(), [FlattenException::class, LegacyFlattenException::class], true))) { $arguments = $event->getArguments(); $arguments[$k] = FlattenException::createFromThrowable($e); $event->setArguments($arguments); } } public static function getSubscribedEvents(): array { return [ KernelEvents::CONTROLLER_ARGUMENTS => 'onControllerArguments', KernelEvents::EXCEPTION => [ ['logKernelException', 0], ['onKernelException', -128], ], KernelEvents::RESPONSE => ['removeCspHeader', -128], ]; } /** * Logs an exception. */ protected function logException(\Throwable $exception, string $message, string $logLevel = null): void { if (null !== $this->logger) { if (null !== $logLevel) { $this->logger->log($logLevel, $message, ['exception' => $exception]); } elseif (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { $this->logger->critical($message, ['exception' => $exception]); } else { $this->logger->error($message, ['exception' => $exception]); } } } /** * Clones the request for the exception. */ protected function duplicateRequest(\Throwable $exception, Request $request): Request { $attributes = [ '_controller' => $this->controller, 'exception' => $exception, 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, ]; $request = $request->duplicate(null, null, $attributes); $request->setMethod('GET'); return $request; } } http-kernel/EventListener/ProfilerListener.php000064400000011041150432043210015560 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestMatcherInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\Event\TerminateEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Profiler\Profile; use Symfony\Component\HttpKernel\Profiler\Profiler; /** * ProfilerListener collects data for the current request by listening to the kernel events. * * @author Fabien Potencier * * @final */ class ProfilerListener implements EventSubscriberInterface { protected $profiler; protected $matcher; protected $onlyException; protected $onlyMainRequests; protected $exception; /** @var \SplObjectStorage */ protected $profiles; protected $requestStack; protected $collectParameter; /** @var \SplObjectStorage */ protected $parents; /** * @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise * @param bool $onlyMainRequests True if the profiler only collects data when the request is the main request, false otherwise */ public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, string $collectParameter = null) { $this->profiler = $profiler; $this->matcher = $matcher; $this->onlyException = $onlyException; $this->onlyMainRequests = $onlyMainRequests; $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); $this->requestStack = $requestStack; $this->collectParameter = $collectParameter; } /** * Handles the onKernelException event. */ public function onKernelException(ExceptionEvent $event) { if ($this->onlyMainRequests && !$event->isMainRequest()) { return; } $this->exception = $event->getThrowable(); } /** * Handles the onKernelResponse event. */ public function onKernelResponse(ResponseEvent $event) { if ($this->onlyMainRequests && !$event->isMainRequest()) { return; } if ($this->onlyException && null === $this->exception) { return; } $request = $event->getRequest(); if (null !== $this->collectParameter && null !== $collectParameterValue = $request->get($this->collectParameter)) { true === $collectParameterValue || filter_var($collectParameterValue, \FILTER_VALIDATE_BOOLEAN) ? $this->profiler->enable() : $this->profiler->disable(); } $exception = $this->exception; $this->exception = null; if (null !== $this->matcher && !$this->matcher->matches($request)) { return; } if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) { return; } $this->profiles[$request] = $profile; $this->parents[$request] = $this->requestStack->getParentRequest(); } public function onKernelTerminate(TerminateEvent $event) { // attach children to parents foreach ($this->profiles as $request) { if (null !== $parentRequest = $this->parents[$request]) { if (isset($this->profiles[$parentRequest])) { $this->profiles[$parentRequest]->addChild($this->profiles[$request]); } } } // save profiles foreach ($this->profiles as $request) { $this->profiler->saveProfile($this->profiles[$request]); } $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); } public static function getSubscribedEvents(): array { return [ KernelEvents::RESPONSE => ['onKernelResponse', -100], KernelEvents::EXCEPTION => ['onKernelException', 0], KernelEvents::TERMINATE => ['onKernelTerminate', -1024], ]; } } http-kernel/EventListener/AbstractTestSessionListener.php000064400000007653150432043210017763 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * TestSessionListener. * * Saves session in test environment. * * @author Bulat Shakirzyanov * @author Fabien Potencier * * @internal * * @deprecated the TestSessionListener use the default SessionListener instead */ abstract class AbstractTestSessionListener implements EventSubscriberInterface { private $sessionId; private $sessionOptions; public function __construct(array $sessionOptions = []) { $this->sessionOptions = $sessionOptions; trigger_deprecation('symfony/http-kernel', '5.4', 'The %s is deprecated use the %s instead.', __CLASS__, AbstractSessionListener::class); } public function onKernelRequest(RequestEvent $event) { if (!$event->isMainRequest()) { return; } // bootstrap the session if ($event->getRequest()->hasSession()) { $session = $event->getRequest()->getSession(); } elseif (!$session = $this->getSession()) { return; } $cookies = $event->getRequest()->cookies; if ($cookies->has($session->getName())) { $this->sessionId = $cookies->get($session->getName()); $session->setId($this->sessionId); } } /** * Checks if session was initialized and saves if current request is the main request * Runs on 'kernel.response' in test environment. */ public function onKernelResponse(ResponseEvent $event) { if (!$event->isMainRequest()) { return; } $request = $event->getRequest(); if (!$request->hasSession()) { return; } $session = $request->getSession(); if ($wasStarted = $session->isStarted()) { $session->save(); } if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { $params = session_get_cookie_params() + ['samesite' => null]; foreach ($this->sessionOptions as $k => $v) { if (str_starts_with($k, 'cookie_')) { $params[substr($k, 7)] = $v; } } foreach ($event->getResponse()->headers->getCookies() as $cookie) { if ($session->getName() === $cookie->getName() && $params['path'] === $cookie->getPath() && $params['domain'] == $cookie->getDomain()) { return; } } $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'], false, $params['samesite'] ?: null)); $this->sessionId = $session->getId(); } } public static function getSubscribedEvents(): array { return [ KernelEvents::REQUEST => ['onKernelRequest', 127], // AFTER SessionListener KernelEvents::RESPONSE => ['onKernelResponse', -128], ]; } /** * Gets the session object. * * @deprecated since Symfony 5.4, will be removed in 6.0. * * @return SessionInterface|null */ abstract protected function getSession(); } http-kernel/EventListener/DebugHandlersListener.php000064400000016202150432043210016511 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\ErrorHandler\ErrorHandler; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\KernelEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * Configures errors and exceptions handlers. * * @author Nicolas Grekas * * @final * * @internal since Symfony 5.3 */ class DebugHandlersListener implements EventSubscriberInterface { private $earlyHandler; private $exceptionHandler; private $logger; private $deprecationLogger; private $levels; private $throwAt; private $scream; private $scope; private $firstCall = true; private $hasTerminatedWithException; /** * @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception * @param array|int|null $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged * @param bool $scope Enables/disables scoping mode */ public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, $scope = true, $deprecationLogger = null, $fileLinkFormat = null) { if (!\is_bool($scope)) { trigger_deprecation('symfony/http-kernel', '5.4', 'Passing a $fileLinkFormat is deprecated.'); $scope = $deprecationLogger; $deprecationLogger = $fileLinkFormat; } $handler = set_exception_handler('var_dump'); $this->earlyHandler = \is_array($handler) ? $handler[0] : null; restore_exception_handler(); $this->exceptionHandler = $exceptionHandler; $this->logger = $logger; $this->levels = $levels ?? \E_ALL; $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? \E_ALL : null)); $this->scream = $scream; $this->scope = $scope; $this->deprecationLogger = $deprecationLogger; } /** * Configures the error handler. */ public function configure(object $event = null) { if ($event instanceof ConsoleEvent && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { return; } if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMainRequest()) { return; } $this->firstCall = $this->hasTerminatedWithException = false; $handler = set_exception_handler('var_dump'); $handler = \is_array($handler) ? $handler[0] : null; restore_exception_handler(); if (!$handler instanceof ErrorHandler) { $handler = $this->earlyHandler; } if ($handler instanceof ErrorHandler) { if ($this->logger || $this->deprecationLogger) { $this->setDefaultLoggers($handler); if (\is_array($this->levels)) { $levels = 0; foreach ($this->levels as $type => $log) { $levels |= $type; } } else { $levels = $this->levels; } if ($this->scream) { $handler->screamAt($levels); } if ($this->scope) { $handler->scopeAt($levels & ~\E_USER_DEPRECATED & ~\E_DEPRECATED); } else { $handler->scopeAt(0, true); } $this->logger = $this->deprecationLogger = $this->levels = null; } if (null !== $this->throwAt) { $handler->throwAt($this->throwAt, true); } } if (!$this->exceptionHandler) { if ($event instanceof KernelEvent) { if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) { $request = $event->getRequest(); $hasRun = &$this->hasTerminatedWithException; $this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) { if ($hasRun) { throw $e; } $hasRun = true; $kernel->terminateWithException($e, $request); }; } } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) { $output = $event->getOutput(); if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); } $this->exceptionHandler = static function (\Throwable $e) use ($app, $output) { $app->renderThrowable($e, $output); }; } } if ($this->exceptionHandler) { if ($handler instanceof ErrorHandler) { $handler->setExceptionHandler($this->exceptionHandler); } $this->exceptionHandler = null; } } private function setDefaultLoggers(ErrorHandler $handler): void { if (\is_array($this->levels)) { $levelsDeprecatedOnly = []; $levelsWithoutDeprecated = []; foreach ($this->levels as $type => $log) { if (\E_DEPRECATED == $type || \E_USER_DEPRECATED == $type) { $levelsDeprecatedOnly[$type] = $log; } else { $levelsWithoutDeprecated[$type] = $log; } } } else { $levelsDeprecatedOnly = $this->levels & (\E_DEPRECATED | \E_USER_DEPRECATED); $levelsWithoutDeprecated = $this->levels & ~\E_DEPRECATED & ~\E_USER_DEPRECATED; } $defaultLoggerLevels = $this->levels; if ($this->deprecationLogger && $levelsDeprecatedOnly) { $handler->setDefaultLogger($this->deprecationLogger, $levelsDeprecatedOnly); $defaultLoggerLevels = $levelsWithoutDeprecated; } if ($this->logger && $defaultLoggerLevels) { $handler->setDefaultLogger($this->logger, $defaultLoggerLevels); } } public static function getSubscribedEvents(): array { $events = [KernelEvents::REQUEST => ['configure', 2048]]; if (\defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { $events[ConsoleEvents::COMMAND] = ['configure', 2048]; } return $events; } } http-kernel/EventListener/TestSessionListener.php000064400000002433150432043210016266 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Container\ContainerInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface; /** * Sets the session in the request. * * @author Fabien Potencier * * @final * * @deprecated the TestSessionListener use the default SessionListener instead */ class TestSessionListener extends AbstractTestSessionListener { private $container; public function __construct(ContainerInterface $container, array $sessionOptions = []) { $this->container = $container; parent::__construct($sessionOptions); } /** * @deprecated since Symfony 5.4, will be removed in 6.0. */ protected function getSession(): ?SessionInterface { trigger_deprecation('symfony/http-kernel', '5.4', '"%s" is deprecated and will be removed in 6.0, inject a session in the request instead.', __METHOD__); if ($this->container->has('session')) { return $this->container->get('session'); } return null; } } http-kernel/EventListener/StreamedResponseListener.php000064400000002321150432043210017262 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; /** * StreamedResponseListener is responsible for sending the Response * to the client. * * @author Fabien Potencier * * @final */ class StreamedResponseListener implements EventSubscriberInterface { /** * Filters the Response. */ public function onKernelResponse(ResponseEvent $event) { if (!$event->isMainRequest()) { return; } $response = $event->getResponse(); if ($response instanceof StreamedResponse) { $response->send(); } } public static function getSubscribedEvents(): array { return [ KernelEvents::RESPONSE => ['onKernelResponse', -1024], ]; } } http-kernel/KernelInterface.php000064400000007457150432043210012562 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Bundle\BundleInterface; /** * The Kernel is the heart of the Symfony system. * * It manages an environment made of application kernel and bundles. * * @method string getBuildDir() Returns the build directory - not implementing it is deprecated since Symfony 5.2. * This directory should be used to store build artifacts, and can be read-only at runtime. * Caches written at runtime should be stored in the "cache directory" ({@see KernelInterface::getCacheDir()}). * * @author Fabien Potencier */ interface KernelInterface extends HttpKernelInterface { /** * Returns an array of bundles to register. * * @return iterable */ public function registerBundles(); /** * Loads the container configuration. */ public function registerContainerConfiguration(LoaderInterface $loader); /** * Boots the current kernel. */ public function boot(); /** * Shutdowns the kernel. * * This method is mainly useful when doing functional testing. */ public function shutdown(); /** * Gets the registered bundle instances. * * @return array */ public function getBundles(); /** * Returns a bundle. * * @return BundleInterface * * @throws \InvalidArgumentException when the bundle is not enabled */ public function getBundle(string $name); /** * Returns the file path for a given bundle resource. * * A Resource can be a file or a directory. * * The resource name must follow the following pattern: * * "@BundleName/path/to/a/file.something" * * where BundleName is the name of the bundle * and the remaining part is the relative path in the bundle. * * @return string * * @throws \InvalidArgumentException if the file cannot be found or the name is not valid * @throws \RuntimeException if the name contains invalid/unsafe characters */ public function locateResource(string $name); /** * Gets the environment. * * @return string */ public function getEnvironment(); /** * Checks if debug mode is enabled. * * @return bool */ public function isDebug(); /** * Gets the project dir (path of the project's composer file). * * @return string */ public function getProjectDir(); /** * Gets the current container. * * @return ContainerInterface */ public function getContainer(); /** * Gets the request start time (not available if debug is disabled). * * @return float */ public function getStartTime(); /** * Gets the cache directory. * * Since Symfony 5.2, the cache directory should be used for caches that are written at runtime. * For caches and artifacts that can be warmed at compile-time and deployed as read-only, * use the new "build directory" returned by the {@see getBuildDir()} method. * * @return string */ public function getCacheDir(); /** * Gets the log directory. * * @return string */ public function getLogDir(); /** * Gets the charset of the application. * * @return string */ public function getCharset(); } http-kernel/HttpKernel.php000064400000023537150432043210011576 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\Event\ControllerEvent; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\Event\TerminateEvent; use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\ControllerDoesNotReturnResponseException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; // Help opcache.preload discover always-needed symbols class_exists(ControllerArgumentsEvent::class); class_exists(ControllerEvent::class); class_exists(ExceptionEvent::class); class_exists(FinishRequestEvent::class); class_exists(RequestEvent::class); class_exists(ResponseEvent::class); class_exists(TerminateEvent::class); class_exists(ViewEvent::class); class_exists(KernelEvents::class); /** * HttpKernel notifies events to convert a Request object to a Response one. * * @author Fabien Potencier */ class HttpKernel implements HttpKernelInterface, TerminableInterface { protected $dispatcher; protected $resolver; protected $requestStack; private $argumentResolver; public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null) { $this->dispatcher = $dispatcher; $this->resolver = $resolver; $this->requestStack = $requestStack ?? new RequestStack(); $this->argumentResolver = $argumentResolver ?? new ArgumentResolver(); } /** * {@inheritdoc} */ public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true) { $request->headers->set('X-Php-Ob-Level', (string) ob_get_level()); try { return $this->handleRaw($request, $type); } catch (\Exception $e) { if ($e instanceof RequestExceptionInterface) { $e = new BadRequestHttpException($e->getMessage(), $e); } if (false === $catch) { $this->finishRequest($request, $type); throw $e; } return $this->handleThrowable($e, $request, $type); } } /** * {@inheritdoc} */ public function terminate(Request $request, Response $response) { $this->dispatcher->dispatch(new TerminateEvent($this, $request, $response), KernelEvents::TERMINATE); } /** * @internal */ public function terminateWithException(\Throwable $exception, Request $request = null) { if (!$request = $request ?: $this->requestStack->getMainRequest()) { throw $exception; } $response = $this->handleThrowable($exception, $request, self::MAIN_REQUEST); $response->sendHeaders(); $response->sendContent(); $this->terminate($request, $response); } /** * Handles a request to convert it to a response. * * Exceptions are not caught. * * @throws \LogicException If one of the listener does not behave as expected * @throws NotFoundHttpException When controller cannot be found */ private function handleRaw(Request $request, int $type = self::MAIN_REQUEST): Response { $this->requestStack->push($request); // request $event = new RequestEvent($this, $request, $type); $this->dispatcher->dispatch($event, KernelEvents::REQUEST); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); } // load controller if (false === $controller = $this->resolver->getController($request)) { throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo())); } $event = new ControllerEvent($this, $controller, $request, $type); $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER); $controller = $event->getController(); // controller arguments $arguments = $this->argumentResolver->getArguments($request, $controller); $event = new ControllerArgumentsEvent($this, $controller, $arguments, $request, $type); $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER_ARGUMENTS); $controller = $event->getController(); $arguments = $event->getArguments(); // call controller $response = $controller(...$arguments); // view if (!$response instanceof Response) { $event = new ViewEvent($this, $request, $type, $response); $this->dispatcher->dispatch($event, KernelEvents::VIEW); if ($event->hasResponse()) { $response = $event->getResponse(); } else { $msg = sprintf('The controller must return a "Symfony\Component\HttpFoundation\Response" object but it returned %s.', $this->varToString($response)); // the user may have forgotten to return something if (null === $response) { $msg .= ' Did you forget to add a return statement somewhere in your controller?'; } throw new ControllerDoesNotReturnResponseException($msg, $controller, __FILE__, __LINE__ - 17); } } return $this->filterResponse($response, $request, $type); } /** * Filters a response object. * * @throws \RuntimeException if the passed object is not a Response instance */ private function filterResponse(Response $response, Request $request, int $type): Response { $event = new ResponseEvent($this, $request, $type, $response); $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->finishRequest($request, $type); return $event->getResponse(); } /** * Publishes the finish request event, then pop the request from the stack. * * Note that the order of the operations is important here, otherwise * operations such as {@link RequestStack::getParentRequest()} can lead to * weird results. */ private function finishRequest(Request $request, int $type) { $this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST); $this->requestStack->pop(); } /** * Handles a throwable by trying to convert it to a Response. * * @throws \Exception */ private function handleThrowable(\Throwable $e, Request $request, int $type): Response { $event = new ExceptionEvent($this, $request, $type, $e); $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); // a listener might have replaced the exception $e = $event->getThrowable(); if (!$event->hasResponse()) { $this->finishRequest($request, $type); throw $e; } $response = $event->getResponse(); // the developer asked for a specific status code if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { // ensure that we actually have an error response if ($e instanceof HttpExceptionInterface) { // keep the HTTP status code and headers $response->setStatusCode($e->getStatusCode()); $response->headers->add($e->getHeaders()); } else { $response->setStatusCode(500); } } try { return $this->filterResponse($response, $request, $type); } catch (\Exception $e) { return $response; } } /** * Returns a human-readable string for the specified variable. */ private function varToString($var): string { if (\is_object($var)) { return sprintf('an object of type %s', \get_class($var)); } if (\is_array($var)) { $a = []; foreach ($var as $k => $v) { $a[] = sprintf('%s => ...', $k); } return sprintf('an array ([%s])', mb_substr(implode(', ', $a), 0, 255)); } if (\is_resource($var)) { return sprintf('a resource (%s)', get_resource_type($var)); } if (null === $var) { return 'null'; } if (false === $var) { return 'a boolean value (false)'; } if (true === $var) { return 'a boolean value (true)'; } if (\is_string($var)) { return sprintf('a string ("%s%s")', mb_substr($var, 0, 255), mb_strlen($var) > 255 ? '...' : ''); } if (is_numeric($var)) { return sprintf('a number (%s)', (string) $var); } return (string) $var; } } http-kernel/composer.json000064400000005103150432043210011514 0ustar00{ "name": "symfony/http-kernel", "type": "library", "description": "Provides a structured process for converting a Request into a Response", "keywords": [], "homepage": "https://symfony.com", "license": "MIT", "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "require": { "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1|^3", "symfony/error-handler": "^4.4|^5.0|^6.0", "symfony/event-dispatcher": "^5.0|^6.0", "symfony/http-foundation": "^5.3.7|^6.0", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-php73": "^1.9", "symfony/polyfill-php80": "^1.16", "psr/log": "^1|^2" }, "require-dev": { "symfony/browser-kit": "^5.4|^6.0", "symfony/config": "^5.0|^6.0", "symfony/console": "^4.4|^5.0|^6.0", "symfony/css-selector": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^5.3|^6.0", "symfony/dom-crawler": "^4.4|^5.0|^6.0", "symfony/expression-language": "^4.4|^5.0|^6.0", "symfony/finder": "^4.4|^5.0|^6.0", "symfony/http-client-contracts": "^1.1|^2|^3", "symfony/process": "^4.4|^5.0|^6.0", "symfony/routing": "^4.4|^5.0|^6.0", "symfony/stopwatch": "^4.4|^5.0|^6.0", "symfony/translation": "^4.4|^5.0|^6.0", "symfony/translation-contracts": "^1.1|^2|^3", "psr/cache": "^1.0|^2.0|^3.0", "twig/twig": "^2.13|^3.0.4" }, "provide": { "psr/log-implementation": "1.0|2.0" }, "conflict": { "symfony/browser-kit": "<5.4", "symfony/cache": "<5.0", "symfony/config": "<5.0", "symfony/console": "<4.4", "symfony/form": "<5.0", "symfony/dependency-injection": "<5.3", "symfony/doctrine-bridge": "<5.0", "symfony/http-client": "<5.0", "symfony/mailer": "<5.0", "symfony/messenger": "<5.0", "symfony/translation": "<5.0", "symfony/twig-bridge": "<5.0", "symfony/validator": "<5.0", "twig/twig": "<2.13" }, "suggest": { "symfony/browser-kit": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpKernel\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "minimum-stability": "dev" } http-kernel/ControllerMetadata/ArgumentMetadataFactory.php000064400000004760150432043210020052 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\ControllerMetadata; /** * Builds {@see ArgumentMetadata} objects based on the given Controller. * * @author Iltar van der Berg */ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface { /** * {@inheritdoc} */ public function createArgumentMetadata($controller): array { $arguments = []; if (\is_array($controller)) { $reflection = new \ReflectionMethod($controller[0], $controller[1]); } elseif (\is_object($controller) && !$controller instanceof \Closure) { $reflection = (new \ReflectionObject($controller))->getMethod('__invoke'); } else { $reflection = new \ReflectionFunction($controller); } foreach ($reflection->getParameters() as $param) { $attributes = []; if (\PHP_VERSION_ID >= 80000) { foreach ($param->getAttributes() as $reflectionAttribute) { if (class_exists($reflectionAttribute->getName())) { $attributes[] = $reflectionAttribute->newInstance(); } } } $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull(), $attributes); } return $arguments; } /** * Returns an associated type to the given parameter if available. */ private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function): ?string { if (!$type = $parameter->getType()) { return null; } $name = $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type; if ($function instanceof \ReflectionMethod) { $lcName = strtolower($name); switch ($lcName) { case 'self': return $function->getDeclaringClass()->name; case 'parent': return ($parent = $function->getDeclaringClass()->getParentClass()) ? $parent->name : null; } } return $name; } } http-kernel/ControllerMetadata/ArgumentMetadata.php000064400000010353150432043210016515 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\ControllerMetadata; use Symfony\Component\HttpKernel\Attribute\ArgumentInterface; /** * Responsible for storing metadata of an argument. * * @author Iltar van der Berg */ class ArgumentMetadata { public const IS_INSTANCEOF = 2; private $name; private $type; private $isVariadic; private $hasDefaultValue; private $defaultValue; private $isNullable; private $attributes; /** * @param object[] $attributes */ public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false, $attributes = []) { $this->name = $name; $this->type = $type; $this->isVariadic = $isVariadic; $this->hasDefaultValue = $hasDefaultValue; $this->defaultValue = $defaultValue; $this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue); if (null === $attributes || $attributes instanceof ArgumentInterface) { trigger_deprecation('symfony/http-kernel', '5.3', 'The "%s" constructor expects an array of PHP attributes as last argument, %s given.', __CLASS__, get_debug_type($attributes)); $attributes = $attributes ? [$attributes] : []; } $this->attributes = $attributes; } /** * Returns the name as given in PHP, $foo would yield "foo". * * @return string */ public function getName() { return $this->name; } /** * Returns the type of the argument. * * The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+. * * @return string|null */ public function getType() { return $this->type; } /** * Returns whether the argument is defined as "...$variadic". * * @return bool */ public function isVariadic() { return $this->isVariadic; } /** * Returns whether the argument has a default value. * * Implies whether an argument is optional. * * @return bool */ public function hasDefaultValue() { return $this->hasDefaultValue; } /** * Returns whether the argument accepts null values. * * @return bool */ public function isNullable() { return $this->isNullable; } /** * Returns the default value of the argument. * * @throws \LogicException if no default value is present; {@see self::hasDefaultValue()} * * @return mixed */ public function getDefaultValue() { if (!$this->hasDefaultValue) { throw new \LogicException(sprintf('Argument $%s does not have a default value. Use "%s::hasDefaultValue()" to avoid this exception.', $this->name, __CLASS__)); } return $this->defaultValue; } /** * Returns the attribute (if any) that was set on the argument. */ public function getAttribute(): ?ArgumentInterface { trigger_deprecation('symfony/http-kernel', '5.3', 'Method "%s()" is deprecated, use "getAttributes()" instead.', __METHOD__); if (!$this->attributes) { return null; } return $this->attributes[0] instanceof ArgumentInterface ? $this->attributes[0] : null; } /** * @return object[] */ public function getAttributes(string $name = null, int $flags = 0): array { if (!$name) { return $this->attributes; } $attributes = []; if ($flags & self::IS_INSTANCEOF) { foreach ($this->attributes as $attribute) { if ($attribute instanceof $name) { $attributes[] = $attribute; } } } else { foreach ($this->attributes as $attribute) { if (\get_class($attribute) === $name) { $attributes[] = $attribute; } } } return $attributes; } } http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php000064400000001201150432043210021656 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\ControllerMetadata; /** * Builds method argument data. * * @author Iltar van der Berg */ interface ArgumentMetadataFactoryInterface { /** * @param string|object|array $controller The controller to resolve the arguments for * * @return ArgumentMetadata[] */ public function createArgumentMetadata($controller); } http-kernel/CacheClearer/ChainCacheClearer.php000064400000001523150432043210015252 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheClearer; /** * ChainCacheClearer. * * @author Dustin Dobervich * * @final */ class ChainCacheClearer implements CacheClearerInterface { private $clearers; /** * @param iterable $clearers */ public function __construct(iterable $clearers = []) { $this->clearers = $clearers; } /** * {@inheritdoc} */ public function clear(string $cacheDir) { foreach ($this->clearers as $clearer) { $clearer->clear($cacheDir); } } } http-kernel/CacheClearer/CacheClearerInterface.php000064400000001001150432043210016117 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheClearer; /** * CacheClearerInterface. * * @author Dustin Dobervich */ interface CacheClearerInterface { /** * Clears any caches necessary. */ public function clear(string $cacheDir); } http-kernel/CacheClearer/Psr6CacheClearer.php000064400000003274150432043210015067 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\CacheClearer; use Psr\Cache\CacheItemPoolInterface; /** * @author Nicolas Grekas */ class Psr6CacheClearer implements CacheClearerInterface { private $pools = []; /** * @param array $pools */ public function __construct(array $pools = []) { $this->pools = $pools; } /** * @return bool */ public function hasPool(string $name) { return isset($this->pools[$name]); } /** * @return CacheItemPoolInterface * * @throws \InvalidArgumentException If the cache pool with the given name does not exist */ public function getPool(string $name) { if (!$this->hasPool($name)) { throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name)); } return $this->pools[$name]; } /** * @return bool * * @throws \InvalidArgumentException If the cache pool with the given name does not exist */ public function clearPool(string $name) { if (!isset($this->pools[$name])) { throw new \InvalidArgumentException(sprintf('Cache pool not found: "%s".', $name)); } return $this->pools[$name]->clear(); } /** * {@inheritdoc} */ public function clear(string $cacheDir) { foreach ($this->pools as $pool) { $pool->clear(); } } } http-kernel/Bundle/BundleInterface.php000064400000003030150432043210013743 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Bundle; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** * BundleInterface. * * @author Fabien Potencier */ interface BundleInterface extends ContainerAwareInterface { /** * Boots the Bundle. */ public function boot(); /** * Shutdowns the Bundle. */ public function shutdown(); /** * Builds the bundle. * * It is only ever called once when the cache is empty. */ public function build(ContainerBuilder $container); /** * Returns the container extension that should be implicitly loaded. * * @return ExtensionInterface|null */ public function getContainerExtension(); /** * Returns the bundle name (the class short name). * * @return string */ public function getName(); /** * Gets the Bundle namespace. * * @return string */ public function getNamespace(); /** * Gets the Bundle directory path. * * The path should always be returned as a Unix path (with /). * * @return string */ public function getPath(); } http-kernel/Bundle/Bundle.php000064400000010415150432043210012127 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Bundle; use Symfony\Component\Console\Application; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerAwareTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** * An implementation of BundleInterface that adds a few conventions for DependencyInjection extensions. * * @author Fabien Potencier */ abstract class Bundle implements BundleInterface { use ContainerAwareTrait; protected $name; protected $extension; protected $path; private $namespace; /** * {@inheritdoc} */ public function boot() { } /** * {@inheritdoc} */ public function shutdown() { } /** * {@inheritdoc} * * This method can be overridden to register compilation passes, * other extensions, ... */ public function build(ContainerBuilder $container) { } /** * Returns the bundle's container extension. * * @return ExtensionInterface|null * * @throws \LogicException */ public function getContainerExtension() { if (null === $this->extension) { $extension = $this->createContainerExtension(); if (null !== $extension) { if (!$extension instanceof ExtensionInterface) { throw new \LogicException(sprintf('Extension "%s" must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', get_debug_type($extension))); } // check naming convention $basename = preg_replace('/Bundle$/', '', $this->getName()); $expectedAlias = Container::underscore($basename); if ($expectedAlias != $extension->getAlias()) { throw new \LogicException(sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', $expectedAlias, $extension->getAlias())); } $this->extension = $extension; } else { $this->extension = false; } } return $this->extension ?: null; } /** * {@inheritdoc} */ public function getNamespace() { if (null === $this->namespace) { $this->parseClassName(); } return $this->namespace; } /** * {@inheritdoc} */ public function getPath() { if (null === $this->path) { $reflected = new \ReflectionObject($this); $this->path = \dirname($reflected->getFileName()); } return $this->path; } /** * Returns the bundle name (the class short name). */ final public function getName(): string { if (null === $this->name) { $this->parseClassName(); } return $this->name; } public function registerCommands(Application $application) { } /** * Returns the bundle's container extension class. * * @return string */ protected function getContainerExtensionClass() { $basename = preg_replace('/Bundle$/', '', $this->getName()); return $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension'; } /** * Creates the bundle's container extension. * * @return ExtensionInterface|null */ protected function createContainerExtension() { return class_exists($class = $this->getContainerExtensionClass()) ? new $class() : null; } private function parseClassName() { $pos = strrpos(static::class, '\\'); $this->namespace = false === $pos ? '' : substr(static::class, 0, $pos); if (null === $this->name) { $this->name = false === $pos ? static::class : substr(static::class, $pos + 1); } } } http-kernel/Fragment/EsiFragmentRenderer.php000064400000001063150432043210015142 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; /** * Implements the ESI rendering strategy. * * @author Fabien Potencier */ class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer { /** * {@inheritdoc} */ public function getName() { return 'esi'; } } http-kernel/Fragment/RoutableFragmentRenderer.php000064400000002742150432043210016204 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\EventListener\FragmentListener; /** * Adds the possibility to generate a fragment URI for a given Controller. * * @author Fabien Potencier */ abstract class RoutableFragmentRenderer implements FragmentRendererInterface { /** * @internal */ protected $fragmentPath = '/_fragment'; /** * Sets the fragment path that triggers the fragment listener. * * @see FragmentListener */ public function setFragmentPath(string $path) { $this->fragmentPath = $path; } /** * Generates a fragment URI for a given controller. * * @param bool $absolute Whether to generate an absolute URL or not * @param bool $strict Whether to allow non-scalar attributes or not * * @return string */ protected function generateFragmentUri(ControllerReference $reference, Request $request, bool $absolute = false, bool $strict = true) { return (new FragmentUriGenerator($this->fragmentPath))->generate($reference, $request, $absolute, $strict, false); } } http-kernel/Fragment/InlineFragmentRenderer.php000064400000011646150432043210015650 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel. * * @author Fabien Potencier */ class InlineFragmentRenderer extends RoutableFragmentRenderer { private $kernel; private $dispatcher; public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) { $this->kernel = $kernel; $this->dispatcher = $dispatcher; } /** * {@inheritdoc} * * Additional available options: * * * alt: an alternative URI to render in case of an error */ public function render($uri, Request $request, array $options = []) { $reference = null; if ($uri instanceof ControllerReference) { $reference = $uri; // Remove attributes from the generated URI because if not, the Symfony // routing system will use them to populate the Request attributes. We don't // want that as we want to preserve objects (so we manually set Request attributes // below instead) $attributes = $reference->attributes; $reference->attributes = []; // The request format and locale might have been overridden by the user foreach (['_format', '_locale'] as $key) { if (isset($attributes[$key])) { $reference->attributes[$key] = $attributes[$key]; } } $uri = $this->generateFragmentUri($uri, $request, false, false); $reference->attributes = array_merge($attributes, $reference->attributes); } $subRequest = $this->createSubRequest($uri, $request); // override Request attributes as they can be objects (which are not supported by the generated URI) if (null !== $reference) { $subRequest->attributes->add($reference->attributes); } $level = ob_get_level(); try { return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { // we dispatch the exception event to trigger the logging // the response that comes back is ignored if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { $event = new ExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); } // let's clean up the output buffers that were created by the sub-request Response::closeOutputBuffers($level, false); if (isset($options['alt'])) { $alt = $options['alt']; unset($options['alt']); return $this->render($alt, $request, $options); } if (!isset($options['ignore_errors']) || !$options['ignore_errors']) { throw $e; } return new Response(); } } protected function createSubRequest(string $uri, Request $request) { $cookies = $request->cookies->all(); $server = $request->server->all(); unset($server['HTTP_IF_MODIFIED_SINCE']); unset($server['HTTP_IF_NONE_MATCH']); $subRequest = Request::create($uri, 'get', [], $cookies, [], $server); if ($request->headers->has('Surrogate-Capability')) { $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); } static $setSession; if (null === $setSession) { $setSession = \Closure::bind(static function ($subRequest, $request) { $subRequest->session = $request->session; }, null, Request::class); } $setSession($subRequest, $request); if ($request->get('_format')) { $subRequest->attributes->set('_format', $request->get('_format')); } if ($request->getDefaultLocale() !== $request->getLocale()) { $subRequest->setLocale($request->getLocale()); } return $subRequest; } /** * {@inheritdoc} */ public function getName() { return 'inline'; } } http-kernel/Fragment/SsiFragmentRenderer.php000064400000001063150432043210015160 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; /** * Implements the SSI rendering strategy. * * @author Sebastian Krebs */ class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer { /** * {@inheritdoc} */ public function getName() { return 'ssi'; } } http-kernel/Fragment/FragmentHandler.php000064400000007217150432043210014317 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\Exception\HttpException; /** * Renders a URI that represents a resource fragment. * * This class handles the rendering of resource fragments that are included into * a main resource. The handling of the rendering is managed by specialized renderers. * * @author Fabien Potencier * * @see FragmentRendererInterface */ class FragmentHandler { private $debug; private $renderers = []; private $requestStack; /** * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances * @param bool $debug Whether the debug mode is enabled or not */ public function __construct(RequestStack $requestStack, array $renderers = [], bool $debug = false) { $this->requestStack = $requestStack; foreach ($renderers as $renderer) { $this->addRenderer($renderer); } $this->debug = $debug; } /** * Adds a renderer. */ public function addRenderer(FragmentRendererInterface $renderer) { $this->renderers[$renderer->getName()] = $renderer; } /** * Renders a URI and returns the Response content. * * Available options: * * * ignore_errors: true to return an empty string in case of an error * * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * * @return string|null * * @throws \InvalidArgumentException when the renderer does not exist * @throws \LogicException when no main request is being handled */ public function render($uri, string $renderer = 'inline', array $options = []) { if (!isset($options['ignore_errors'])) { $options['ignore_errors'] = !$this->debug; } if (!isset($this->renderers[$renderer])) { throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer)); } if (!$request = $this->requestStack->getCurrentRequest()) { throw new \LogicException('Rendering a fragment can only be done when handling a Request.'); } return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options)); } /** * Delivers the Response as a string. * * When the Response is a StreamedResponse, the content is streamed immediately * instead of being returned. * * @return string|null The Response content or null when the Response is streamed * * @throws \RuntimeException when the Response is not successful */ protected function deliver(Response $response) { if (!$response->isSuccessful()) { $responseStatusCode = $response->getStatusCode(); throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %d).', $this->requestStack->getCurrentRequest()->getUri(), $responseStatusCode), 0, new HttpException($responseStatusCode)); } if (!$response instanceof StreamedResponse) { return $response->getContent(); } $response->sendContent(); return null; } } http-kernel/Fragment/FragmentRendererInterface.php000064400000001744150432043210016330 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerReference; /** * Interface implemented by all rendering strategies. * * @author Fabien Potencier */ interface FragmentRendererInterface { /** * Renders a URI and returns the Response content. * * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance * * @return Response */ public function render($uri, Request $request, array $options = []); /** * Gets the name of the strategy. * * @return string */ public function getName(); } http-kernel/Fragment/FragmentUriGenerator.php000064400000006722150432043210015350 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\UriSigner; /** * Generates a fragment URI. * * @author Kévin Dunglas * @author Fabien Potencier */ final class FragmentUriGenerator implements FragmentUriGeneratorInterface { private $fragmentPath; private $signer; private $requestStack; public function __construct(string $fragmentPath, UriSigner $signer = null, RequestStack $requestStack = null) { $this->fragmentPath = $fragmentPath; $this->signer = $signer; $this->requestStack = $requestStack; } /** * {@inheritDoc} */ public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string { if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) { throw new \LogicException('Generating a fragment URL can only be done when handling a Request.'); } if ($sign && null === $this->signer) { throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.'); } if ($strict) { $this->checkNonScalar($controller->attributes); } // We need to forward the current _format and _locale values as we don't have // a proper routing pattern to do the job for us. // This makes things inconsistent if you switch from rendering a controller // to rendering a route if the route pattern does not contain the special // _format and _locale placeholders. if (!isset($controller->attributes['_format'])) { $controller->attributes['_format'] = $request->getRequestFormat(); } if (!isset($controller->attributes['_locale'])) { $controller->attributes['_locale'] = $request->getLocale(); } $controller->attributes['_controller'] = $controller->controller; $controller->query['_path'] = http_build_query($controller->attributes, '', '&'); $path = $this->fragmentPath.'?'.http_build_query($controller->query, '', '&'); // we need to sign the absolute URI, but want to return the path only. $fragmentUri = $sign || $absolute ? $request->getUriForPath($path) : $request->getBaseUrl().$path; if (!$sign) { return $fragmentUri; } $fragmentUri = $this->signer->sign($fragmentUri); return $absolute ? $fragmentUri : substr($fragmentUri, \strlen($request->getSchemeAndHttpHost())); } private function checkNonScalar(array $values): void { foreach ($values as $key => $value) { if (\is_array($value)) { $this->checkNonScalar($value); } elseif (!is_scalar($value) && null !== $value) { throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key)); } } } } http-kernel/Fragment/HIncludeFragmentRenderer.php000064400000006431150432043210016121 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\UriSigner; use Twig\Environment; /** * Implements the Hinclude rendering strategy. * * @author Fabien Potencier */ class HIncludeFragmentRenderer extends RoutableFragmentRenderer { private $globalDefaultTemplate; private $signer; private $twig; private $charset; /** * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) */ public function __construct(Environment $twig = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8') { $this->twig = $twig; $this->globalDefaultTemplate = $globalDefaultTemplate; $this->signer = $signer; $this->charset = $charset; } /** * Checks if a templating engine has been set. * * @return bool */ public function hasTemplating() { return null !== $this->twig; } /** * {@inheritdoc} * * Additional available options: * * * default: The default content (it can be a template name or the content) * * id: An optional hx:include tag id attribute * * attributes: An optional array of hx:include tag attributes */ public function render($uri, Request $request, array $options = []) { if ($uri instanceof ControllerReference) { $uri = (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request); } // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content. $uri = str_replace('&', '&', $uri); $template = $options['default'] ?? $this->globalDefaultTemplate; if (null !== $this->twig && $template && $this->twig->getLoader()->exists($template)) { $content = $this->twig->render($template); } else { $content = $template; } $attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : []; if (isset($options['id']) && $options['id']) { $attributes['id'] = $options['id']; } $renderedAttributes = ''; if (\count($attributes) > 0) { $flags = \ENT_QUOTES | \ENT_SUBSTITUTE; foreach ($attributes as $attribute => $value) { $renderedAttributes .= sprintf( ' %s="%s"', htmlspecialchars($attribute, $flags, $this->charset, false), htmlspecialchars($value, $flags, $this->charset, false) ); } } return new Response(sprintf('%s', $uri, $renderedAttributes, $content)); } /** * {@inheritdoc} */ public function getName() { return 'hinclude'; } } http-kernel/Fragment/FragmentUriGeneratorInterface.php000064400000002050150432043210017157 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; /** * Interface implemented by rendering strategies able to generate an URL for a fragment. * * @author Kévin Dunglas */ interface FragmentUriGeneratorInterface { /** * Generates a fragment URI for a given controller. * * @param bool $absolute Whether to generate an absolute URL or not * @param bool $strict Whether to allow non-scalar attributes or not * @param bool $sign Whether to sign the URL or not * * @return string */ public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string; } http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php000064400000006756150432043210020077 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; use Symfony\Component\HttpKernel\UriSigner; /** * Implements Surrogate rendering strategy. * * @author Fabien Potencier */ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer { private $surrogate; private $inlineStrategy; private $signer; /** * The "fallback" strategy when surrogate is not available should always be an * instance of InlineFragmentRenderer. * * @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported */ public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null) { $this->surrogate = $surrogate; $this->inlineStrategy = $inlineStrategy; $this->signer = $signer; } /** * {@inheritdoc} * * Note that if the current Request has no surrogate capability, this method * falls back to use the inline rendering strategy. * * Additional available options: * * * alt: an alternative URI to render in case of an error * * comment: a comment to add when returning the surrogate tag * * Note, that not all surrogate strategies support all options. For now * 'alt' and 'comment' are only supported by ESI. * * @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface */ public function render($uri, Request $request, array $options = []) { if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) { if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) { throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.'); } return $this->inlineStrategy->render($uri, $request, $options); } if ($uri instanceof ControllerReference) { $uri = $this->generateSignedFragmentUri($uri, $request); } $alt = $options['alt'] ?? null; if ($alt instanceof ControllerReference) { $alt = $this->generateSignedFragmentUri($alt, $request); } $tag = $this->surrogate->renderIncludeTag($uri, $alt, $options['ignore_errors'] ?? false, $options['comment'] ?? ''); return new Response($tag); } private function generateSignedFragmentUri(ControllerReference $uri, Request $request): string { return (new FragmentUriGenerator($this->fragmentPath, $this->signer))->generate($uri, $request); } private function containsNonScalars(array $values): bool { foreach ($values as $value) { if (\is_array($value)) { return $this->containsNonScalars($value); } elseif (!is_scalar($value) && null !== $value) { return true; } } return false; } } http-kernel/RebootableInterface.php000064400000001423150432043210013403 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; /** * Allows the Kernel to be rebooted using a temporary cache directory. * * @author Nicolas Grekas */ interface RebootableInterface { /** * Reboots a kernel. * * The getBuildDir() method of a rebootable kernel should not be called * while building the container. Use the %kernel.build_dir% parameter instead. * * @param string|null $warmupDir pass null to reboot in the regular build directory */ public function reboot(?string $warmupDir); } http-kernel/Profiler/Profile.php000064400000011640150432043210012670 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; /** * Profile. * * @author Fabien Potencier */ class Profile { private $token; /** * @var DataCollectorInterface[] */ private $collectors = []; private $ip; private $method; private $url; private $time; private $statusCode; /** * @var Profile */ private $parent; /** * @var Profile[] */ private $children = []; public function __construct(string $token) { $this->token = $token; } public function setToken(string $token) { $this->token = $token; } /** * Gets the token. * * @return string */ public function getToken() { return $this->token; } /** * Sets the parent token. */ public function setParent(self $parent) { $this->parent = $parent; } /** * Returns the parent profile. * * @return self|null */ public function getParent() { return $this->parent; } /** * Returns the parent token. * * @return string|null */ public function getParentToken() { return $this->parent ? $this->parent->getToken() : null; } /** * Returns the IP. * * @return string|null */ public function getIp() { return $this->ip; } public function setIp(?string $ip) { $this->ip = $ip; } /** * Returns the request method. * * @return string|null */ public function getMethod() { return $this->method; } public function setMethod(string $method) { $this->method = $method; } /** * Returns the URL. * * @return string|null */ public function getUrl() { return $this->url; } public function setUrl(?string $url) { $this->url = $url; } /** * @return int */ public function getTime() { return $this->time ?? 0; } public function setTime(int $time) { $this->time = $time; } public function setStatusCode(int $statusCode) { $this->statusCode = $statusCode; } /** * @return int|null */ public function getStatusCode() { return $this->statusCode; } /** * Finds children profilers. * * @return self[] */ public function getChildren() { return $this->children; } /** * Sets children profiler. * * @param Profile[] $children */ public function setChildren(array $children) { $this->children = []; foreach ($children as $child) { $this->addChild($child); } } /** * Adds the child token. */ public function addChild(self $child) { $this->children[] = $child; $child->setParent($this); } public function getChildByToken(string $token): ?self { foreach ($this->children as $child) { if ($token === $child->getToken()) { return $child; } } return null; } /** * Gets a Collector by name. * * @return DataCollectorInterface * * @throws \InvalidArgumentException if the collector does not exist */ public function getCollector(string $name) { if (!isset($this->collectors[$name])) { throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); } return $this->collectors[$name]; } /** * Gets the Collectors associated with this profile. * * @return DataCollectorInterface[] */ public function getCollectors() { return $this->collectors; } /** * Sets the Collectors associated with this profile. * * @param DataCollectorInterface[] $collectors */ public function setCollectors(array $collectors) { $this->collectors = []; foreach ($collectors as $collector) { $this->addCollector($collector); } } /** * Adds a Collector. */ public function addCollector(DataCollectorInterface $collector) { $this->collectors[$collector->getName()] = $collector; } /** * @return bool */ public function hasCollector(string $name) { return isset($this->collectors[$name]); } /** * @return array */ public function __sleep() { return ['token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time', 'statusCode']; } } http-kernel/Profiler/ProfilerStorageInterface.php000064400000002702150432043210016217 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * ProfilerStorageInterface. * * This interface exists for historical reasons. The only supported * implementation is FileProfilerStorage. * * As the profiler must only be used on non-production servers, the file storage * is more than enough and no other implementations will ever be supported. * * @internal * * @author Fabien Potencier */ interface ProfilerStorageInterface { /** * Finds profiler tokens for the given criteria. * * @param int|null $limit The maximum number of tokens to return * @param int|null $start The start date to search from * @param int|null $end The end date to search to */ public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null): array; /** * Reads data associated with the given token. * * The method returns false if the token does not exist in the storage. */ public function read(string $token): ?Profile; /** * Saves a Profile. */ public function write(Profile $profile): bool; /** * Purges all data from the database. */ public function purge(); } http-kernel/Profiler/FileProfilerStorage.php000064400000021401150432043210015173 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; /** * Storage for profiler using files. * * @author Alexandre Salomé */ class FileProfilerStorage implements ProfilerStorageInterface { /** * Folder where profiler data are stored. * * @var string */ private $folder; /** * Constructs the file storage using a "dsn-like" path. * * Example : "file:/path/to/the/storage/folder" * * @throws \RuntimeException */ public function __construct(string $dsn) { if (!str_starts_with($dsn, 'file:')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn)); } $this->folder = substr($dsn, 5); if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) { throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder)); } } /** * {@inheritdoc} */ public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null): array { $file = $this->getIndexFilename(); if (!file_exists($file)) { return []; } $file = fopen($file, 'r'); fseek($file, 0, \SEEK_END); $result = []; while (\count($result) < $limit && $line = $this->readLineFromFile($file)) { $values = str_getcsv($line); [$csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode] = $values; $csvTime = (int) $csvTime; if ($ip && !str_contains($csvIp, $ip) || $url && !str_contains($csvUrl, $url) || $method && !str_contains($csvMethod, $method) || $statusCode && !str_contains($csvStatusCode, $statusCode)) { continue; } if (!empty($start) && $csvTime < $start) { continue; } if (!empty($end) && $csvTime > $end) { continue; } $result[$csvToken] = [ 'token' => $csvToken, 'ip' => $csvIp, 'method' => $csvMethod, 'url' => $csvUrl, 'time' => $csvTime, 'parent' => $csvParent, 'status_code' => $csvStatusCode, ]; } fclose($file); return array_values($result); } /** * {@inheritdoc} */ public function purge() { $flags = \FilesystemIterator::SKIP_DOTS; $iterator = new \RecursiveDirectoryIterator($this->folder, $flags); $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST); foreach ($iterator as $file) { if (is_file($file)) { unlink($file); } else { rmdir($file); } } } /** * {@inheritdoc} */ public function read(string $token): ?Profile { if (!$token || !file_exists($file = $this->getFilename($token))) { return null; } if (\function_exists('gzcompress')) { $file = 'compress.zlib://'.$file; } return $this->createProfileFromData($token, unserialize(file_get_contents($file))); } /** * {@inheritdoc} * * @throws \RuntimeException */ public function write(Profile $profile): bool { $file = $this->getFilename($profile->getToken()); $profileIndexed = is_file($file); if (!$profileIndexed) { // Create directory $dir = \dirname($file); if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) { throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir)); } } $profileToken = $profile->getToken(); // when there are errors in sub-requests, the parent and/or children tokens // may equal the profile token, resulting in infinite loops $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null; $childrenToken = array_filter(array_map(function (Profile $p) use ($profileToken) { return $profileToken !== $p->getToken() ? $p->getToken() : null; }, $profile->getChildren())); // Store profile $data = [ 'token' => $profileToken, 'parent' => $parentToken, 'children' => $childrenToken, 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), 'url' => $profile->getUrl(), 'time' => $profile->getTime(), 'status_code' => $profile->getStatusCode(), ]; $context = stream_context_create(); if (\function_exists('gzcompress')) { $file = 'compress.zlib://'.$file; stream_context_set_option($context, 'zlib', 'level', 3); } if (false === file_put_contents($file, serialize($data), 0, $context)) { return false; } if (!$profileIndexed) { // Add to index if (false === $file = fopen($this->getIndexFilename(), 'a')) { return false; } fputcsv($file, [ $profile->getToken(), $profile->getIp(), $profile->getMethod(), $profile->getUrl(), $profile->getTime(), $profile->getParentToken(), $profile->getStatusCode(), ]); fclose($file); } return true; } /** * Gets filename to store data, associated to the token. * * @return string */ protected function getFilename(string $token) { // Uses 4 last characters, because first are mostly the same. $folderA = substr($token, -2, 2); $folderB = substr($token, -4, 2); return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token; } /** * Gets the index filename. * * @return string */ protected function getIndexFilename() { return $this->folder.'/index.csv'; } /** * Reads a line in the file, backward. * * This function automatically skips the empty lines and do not include the line return in result value. * * @param resource $file The file resource, with the pointer placed at the end of the line to read * * @return mixed */ protected function readLineFromFile($file) { $line = ''; $position = ftell($file); if (0 === $position) { return null; } while (true) { $chunkSize = min($position, 1024); $position -= $chunkSize; fseek($file, $position); if (0 === $chunkSize) { // bof reached break; } $buffer = fread($file, $chunkSize); if (false === ($upTo = strrpos($buffer, "\n"))) { $line = $buffer.$line; continue; } $position += $upTo; $line = substr($buffer, $upTo + 1).$line; fseek($file, max(0, $position), \SEEK_SET); if ('' !== $line) { break; } } return '' === $line ? null : $line; } protected function createProfileFromData(string $token, array $data, Profile $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); $profile->setMethod($data['method']); $profile->setUrl($data['url']); $profile->setTime($data['time']); $profile->setStatusCode($data['status_code']); $profile->setCollectors($data['data']); if (!$parent && $data['parent']) { $parent = $this->read($data['parent']); } if ($parent) { $profile->setParent($parent); } foreach ($data['children'] as $token) { if (!$token || !file_exists($file = $this->getFilename($token))) { continue; } if (\function_exists('gzcompress')) { $file = 'compress.zlib://'.$file; } $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile)); } return $profile; } } http-kernel/Profiler/Profiler.php000064400000014711150432043210013054 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\Profiler; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Contracts\Service\ResetInterface; /** * Profiler. * * @author Fabien Potencier */ class Profiler implements ResetInterface { private $storage; /** * @var DataCollectorInterface[] */ private $collectors = []; private $logger; private $initiallyEnabled = true; private $enabled = true; public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true) { $this->storage = $storage; $this->logger = $logger; $this->initiallyEnabled = $this->enabled = $enable; } /** * Disables the profiler. */ public function disable() { $this->enabled = false; } /** * Enables the profiler. */ public function enable() { $this->enabled = true; } /** * Loads the Profile for the given Response. * * @return Profile|null */ public function loadProfileFromResponse(Response $response) { if (!$token = $response->headers->get('X-Debug-Token')) { return null; } return $this->loadProfile($token); } /** * Loads the Profile for the given token. * * @return Profile|null */ public function loadProfile(string $token) { return $this->storage->read($token); } /** * Saves a Profile. * * @return bool */ public function saveProfile(Profile $profile) { // late collect foreach ($profile->getCollectors() as $collector) { if ($collector instanceof LateDataCollectorInterface) { $collector->lateCollect(); } } if (!($ret = $this->storage->write($profile)) && null !== $this->logger) { $this->logger->warning('Unable to store the profiler information.', ['configured_storage' => \get_class($this->storage)]); } return $ret; } /** * Purges all data from the storage. */ public function purge() { $this->storage->purge(); } /** * Finds profiler tokens for the given criteria. * * @param string|null $limit The maximum number of tokens to return * @param string|null $start The start date to search from * @param string|null $end The end date to search to * * @return array * * @see https://php.net/datetime.formats for the supported date/time formats */ public function find(?string $ip, ?string $url, ?string $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null) { return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode); } /** * Collects data for the given Response. * * @return Profile|null */ public function collect(Request $request, Response $response, \Throwable $exception = null) { if (false === $this->enabled) { return null; } $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); $profile->setTime(time()); $profile->setUrl($request->getUri()); $profile->setMethod($request->getMethod()); $profile->setStatusCode($response->getStatusCode()); try { $profile->setIp($request->getClientIp()); } catch (ConflictingHeadersException $e) { $profile->setIp('Unknown'); } if ($prevToken = $response->headers->get('X-Debug-Token')) { $response->headers->set('X-Previous-Debug-Token', $prevToken); } $response->headers->set('X-Debug-Token', $profile->getToken()); foreach ($this->collectors as $collector) { $collector->collect($request, $response, $exception); // we need to clone for sub-requests $profile->addCollector(clone $collector); } return $profile; } public function reset() { foreach ($this->collectors as $collector) { $collector->reset(); } $this->enabled = $this->initiallyEnabled; } /** * Gets the Collectors associated with this profiler. * * @return array */ public function all() { return $this->collectors; } /** * Sets the Collectors associated with this profiler. * * @param DataCollectorInterface[] $collectors An array of collectors */ public function set(array $collectors = []) { $this->collectors = []; foreach ($collectors as $collector) { $this->add($collector); } } /** * Adds a Collector. */ public function add(DataCollectorInterface $collector) { $this->collectors[$collector->getName()] = $collector; } /** * Returns true if a Collector for the given name exists. * * @param string $name A collector name * * @return bool */ public function has(string $name) { return isset($this->collectors[$name]); } /** * Gets a Collector by name. * * @param string $name A collector name * * @return DataCollectorInterface * * @throws \InvalidArgumentException if the collector does not exist */ public function get(string $name) { if (!isset($this->collectors[$name])) { throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name)); } return $this->collectors[$name]; } private function getTimestamp(?string $value): ?int { if (null === $value || '' === $value) { return null; } try { $value = new \DateTime(is_numeric($value) ? '@'.$value : $value); } catch (\Exception $e) { return null; } return $value->getTimestamp(); } } http-kernel/LICENSE000064400000002051150432043210007776 0ustar00Copyright (c) 2004-2021 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. http-kernel/HttpClientKernel.php000064400000007512150432043210012730 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\Mime\Part\AbstractPart; use Symfony\Component\Mime\Part\DataPart; use Symfony\Component\Mime\Part\Multipart\FormDataPart; use Symfony\Component\Mime\Part\TextPart; use Symfony\Contracts\HttpClient\HttpClientInterface; // Help opcache.preload discover always-needed symbols class_exists(ResponseHeaderBag::class); /** * An implementation of a Symfony HTTP kernel using a "real" HTTP client. * * @author Fabien Potencier */ final class HttpClientKernel implements HttpKernelInterface { private $client; public function __construct(HttpClientInterface $client = null) { if (null === $client && !class_exists(HttpClient::class)) { throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); } $this->client = $client ?? HttpClient::create(); } public function handle(Request $request, int $type = HttpKernelInterface::MAIN_REQUEST, bool $catch = true): Response { $headers = $this->getHeaders($request); $body = ''; if (null !== $part = $this->getBody($request)) { $headers = array_merge($headers, $part->getPreparedHeaders()->toArray()); $body = $part->bodyToIterable(); } $response = $this->client->request($request->getMethod(), $request->getUri(), [ 'headers' => $headers, 'body' => $body, ] + $request->attributes->get('http_client_options', [])); $response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch)); $response->headers->remove('X-Body-File'); $response->headers->remove('X-Body-Eval'); $response->headers->remove('X-Content-Digest'); $response->headers = new class($response->headers->all()) extends ResponseHeaderBag { protected function computeCacheControlValue(): string { return $this->getCacheControlHeader(); // preserve the original value } }; return $response; } private function getBody(Request $request): ?AbstractPart { if (\in_array($request->getMethod(), ['GET', 'HEAD'])) { return null; } if (!class_exists(AbstractPart::class)) { throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".'); } if ($content = $request->getContent()) { return new TextPart($content, 'utf-8', 'plain', '8bit'); } $fields = $request->request->all(); foreach ($request->files->all() as $name => $file) { $fields[$name] = DataPart::fromPath($file->getPathname(), $file->getClientOriginalName(), $file->getClientMimeType()); } return new FormDataPart($fields); } private function getHeaders(Request $request): array { $headers = []; foreach ($request->headers as $key => $value) { $headers[$key] = $value; } $cookies = []; foreach ($request->cookies->all() as $name => $value) { $cookies[] = $name.'='.$value; } if ($cookies) { $headers['cookie'] = implode('; ', $cookies); } return $headers; } } http-kernel/HttpCache/Ssi.php000064400000005546150432043210012117 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Ssi implements the SSI capabilities to Request and Response instances. * * @author Sebastian Krebs */ class Ssi extends AbstractSurrogate { /** * {@inheritdoc} */ public function getName() { return 'ssi'; } /** * {@inheritdoc} */ public function addSurrogateControl(Response $response) { if (str_contains($response->getContent(), '', $uri); } /** * {@inheritdoc} */ public function process(Request $request, Response $response) { $type = $response->headers->get('Content-Type'); if (empty($type)) { $type = 'text/html'; } $parts = explode(';', $type); if (!\in_array($parts[0], $this->contentTypes)) { return $response; } // we don't use a proper XML parser here as we can have SSI tags in a plain text response $content = $response->getContent(); $chunks = preg_split('##', $content, -1, \PREG_SPLIT_DELIM_CAPTURE); $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); $i = 1; while (isset($chunks[$i])) { $options = []; preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, \PREG_SET_ORDER); foreach ($matches as $set) { $options[$set[1]] = $set[2]; } if (!isset($options['virtual'])) { throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.'); } $chunks[$i] = sprintf('surrogate->handle($this, %s, \'\', false) ?>'."\n", var_export($options['virtual'], true) ); ++$i; $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); ++$i; } $content = implode('', $chunks); $response->setContent($content); $response->headers->set('X-Body-Eval', 'SSI'); // remove SSI/1.0 from the Surrogate-Control header $this->removeFromControl($response); return $response; } } http-kernel/HttpCache/SurrogateInterface.php000064400000004300150432043210015140 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; interface SurrogateInterface { /** * Returns surrogate name. * * @return string */ public function getName(); /** * Returns a new cache strategy instance. * * @return ResponseCacheStrategyInterface */ public function createCacheStrategy(); /** * Checks that at least one surrogate has Surrogate capability. * * @return bool */ public function hasSurrogateCapability(Request $request); /** * Adds Surrogate-capability to the given Request. */ public function addSurrogateCapability(Request $request); /** * Adds HTTP headers to specify that the Response needs to be parsed for Surrogate. * * This method only adds an Surrogate HTTP header if the Response has some Surrogate tags. */ public function addSurrogateControl(Response $response); /** * Checks that the Response needs to be parsed for Surrogate tags. * * @return bool */ public function needsParsing(Response $response); /** * Renders a Surrogate tag. * * @param string $alt An alternate URI * @param string $comment A comment to add as an esi:include tag * * @return string */ public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = ''); /** * Replaces a Response Surrogate tags with the included resource content. * * @return Response */ public function process(Request $request, Response $response); /** * Handles a Surrogate from the cache. * * @param string $alt An alternative URI * * @return string * * @throws \RuntimeException * @throws \Exception */ public function handle(HttpCache $cache, string $uri, string $alt, bool $ignoreErrors); } http-kernel/HttpCache/Store.php000064400000032611150432043210012446 0ustar00 * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Store implements all the logic for storing cache metadata (Request and Response headers). * * @author Fabien Potencier */ class Store implements StoreInterface { protected $root; /** @var \SplObjectStorage */ private $keyCache; /** @var array */ private $locks = []; /** * @throws \RuntimeException */ public function __construct(string $root) { $this->root = $root; if (!is_dir($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) { throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root)); } $this->keyCache = new \SplObjectStorage(); } /** * Cleanups storage. */ public function cleanup() { // unlock everything foreach ($this->locks as $lock) { flock($lock, \LOCK_UN); fclose($lock); } $this->locks = []; } /** * Tries to lock the cache for a given Request, without blocking. * * @return bool|string true if the lock is acquired, the path to the current lock otherwise */ public function lock(Request $request) { $key = $this->getCacheKey($request); if (!isset($this->locks[$key])) { $path = $this->getPath($key); if (!is_dir(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { return $path; } $h = fopen($path, 'c'); if (!flock($h, \LOCK_EX | \LOCK_NB)) { fclose($h); return $path; } $this->locks[$key] = $h; } return true; } /** * Releases the lock for the given Request. * * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise */ public function unlock(Request $request) { $key = $this->getCacheKey($request); if (isset($this->locks[$key])) { flock($this->locks[$key], \LOCK_UN); fclose($this->locks[$key]); unset($this->locks[$key]); return true; } return false; } public function isLocked(Request $request) { $key = $this->getCacheKey($request); if (isset($this->locks[$key])) { return true; // shortcut if lock held by this process } if (!is_file($path = $this->getPath($key))) { return false; } $h = fopen($path, 'r'); flock($h, \LOCK_EX | \LOCK_NB, $wouldBlock); flock($h, \LOCK_UN); // release the lock we just acquired fclose($h); return (bool) $wouldBlock; } /** * Locates a cached Response for the Request provided. * * @return Response|null */ public function lookup(Request $request) { $key = $this->getCacheKey($request); if (!$entries = $this->getMetadata($key)) { return null; } // find a cached entry that matches the request. $match = null; foreach ($entries as $entry) { if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? implode(', ', $entry[1]['vary']) : '', $request->headers->all(), $entry[0])) { $match = $entry; break; } } if (null === $match) { return null; } $headers = $match[1]; if (file_exists($path = $this->getPath($headers['x-content-digest'][0]))) { return $this->restoreResponse($headers, $path); } // TODO the metaStore referenced an entity that doesn't exist in // the entityStore. We definitely want to return nil but we should // also purge the entry from the meta-store when this is detected. return null; } /** * Writes a cache entry to the store for the given Request and Response. * * Existing entries are read and any that match the response are removed. This * method calls write with the new list of cache entries. * * @return string * * @throws \RuntimeException */ public function write(Request $request, Response $response) { $key = $this->getCacheKey($request); $storedEnv = $this->persistRequest($request); if ($response->headers->has('X-Body-File')) { // Assume the response came from disk, but at least perform some safeguard checks if (!$response->headers->has('X-Content-Digest')) { throw new \RuntimeException('A restored response must have the X-Content-Digest header.'); } $digest = $response->headers->get('X-Content-Digest'); if ($this->getPath($digest) !== $response->headers->get('X-Body-File')) { throw new \RuntimeException('X-Body-File and X-Content-Digest do not match.'); } // Everything seems ok, omit writing content to disk } else { $digest = $this->generateContentDigest($response); $response->headers->set('X-Content-Digest', $digest); if (!$this->save($digest, $response->getContent(), false)) { throw new \RuntimeException('Unable to store the entity.'); } if (!$response->headers->has('Transfer-Encoding')) { $response->headers->set('Content-Length', \strlen($response->getContent())); } } // read existing cache entries, remove non-varying, and add this one to the list $entries = []; $vary = $response->headers->get('vary'); foreach ($this->getMetadata($key) as $entry) { if (!isset($entry[1]['vary'][0])) { $entry[1]['vary'] = ['']; } if ($entry[1]['vary'][0] != $vary || !$this->requestsMatch($vary ?? '', $entry[0], $storedEnv)) { $entries[] = $entry; } } $headers = $this->persistResponse($response); unset($headers['age']); array_unshift($entries, [$storedEnv, $headers]); if (!$this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } return $key; } /** * Returns content digest for $response. * * @return string */ protected function generateContentDigest(Response $response) { return 'en'.hash('sha256', $response->getContent()); } /** * Invalidates all cache entries that match the request. * * @throws \RuntimeException */ public function invalidate(Request $request) { $modified = false; $key = $this->getCacheKey($request); $entries = []; foreach ($this->getMetadata($key) as $entry) { $response = $this->restoreResponse($entry[1]); if ($response->isFresh()) { $response->expire(); $modified = true; $entries[] = [$entry[0], $this->persistResponse($response)]; } else { $entries[] = $entry; } } if ($modified && !$this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } } /** * Determines whether two Request HTTP header sets are non-varying based on * the vary response header value provided. * * @param string|null $vary A Response vary header * @param array $env1 A Request HTTP header array * @param array $env2 A Request HTTP header array */ private function requestsMatch(?string $vary, array $env1, array $env2): bool { if (empty($vary)) { return true; } foreach (preg_split('/[\s,]+/', $vary) as $header) { $key = str_replace('_', '-', strtolower($header)); $v1 = $env1[$key] ?? null; $v2 = $env2[$key] ?? null; if ($v1 !== $v2) { return false; } } return true; } /** * Gets all data associated with the given key. * * Use this method only if you know what you are doing. */ private function getMetadata(string $key): array { if (!$entries = $this->load($key)) { return []; } return unserialize($entries) ?: []; } /** * Purges data for the given URL. * * This method purges both the HTTP and the HTTPS version of the cache entry. * * @return bool true if the URL exists with either HTTP or HTTPS scheme and has been purged, false otherwise */ public function purge(string $url) { $http = preg_replace('#^https:#', 'http:', $url); $https = preg_replace('#^http:#', 'https:', $url); $purgedHttp = $this->doPurge($http); $purgedHttps = $this->doPurge($https); return $purgedHttp || $purgedHttps; } /** * Purges data for the given URL. */ private function doPurge(string $url): bool { $key = $this->getCacheKey(Request::create($url)); if (isset($this->locks[$key])) { flock($this->locks[$key], \LOCK_UN); fclose($this->locks[$key]); unset($this->locks[$key]); } if (is_file($path = $this->getPath($key))) { unlink($path); return true; } return false; } /** * Loads data for the given key. */ private function load(string $key): ?string { $path = $this->getPath($key); return is_file($path) && false !== ($contents = @file_get_contents($path)) ? $contents : null; } /** * Save data for the given key. */ private function save(string $key, string $data, bool $overwrite = true): bool { $path = $this->getPath($key); if (!$overwrite && file_exists($path)) { return true; } if (isset($this->locks[$key])) { $fp = $this->locks[$key]; @ftruncate($fp, 0); @fseek($fp, 0); $len = @fwrite($fp, $data); if (\strlen($data) !== $len) { @ftruncate($fp, 0); return false; } } else { if (!is_dir(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { return false; } $tmpFile = tempnam(\dirname($path), basename($path)); if (false === $fp = @fopen($tmpFile, 'w')) { @unlink($tmpFile); return false; } @fwrite($fp, $data); @fclose($fp); if ($data != file_get_contents($tmpFile)) { @unlink($tmpFile); return false; } if (false === @rename($tmpFile, $path)) { @unlink($tmpFile); return false; } } @chmod($path, 0666 & ~umask()); return true; } public function getPath(string $key) { return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6); } /** * Generates a cache key for the given Request. * * This method should return a key that must only depend on a * normalized version of the request URI. * * If the same URI can have more than one representation, based on some * headers, use a Vary header to indicate them, and each representation will * be stored independently under the same cache key. * * @return string */ protected function generateCacheKey(Request $request) { return 'md'.hash('sha256', $request->getUri()); } /** * Returns a cache key for the given Request. */ private function getCacheKey(Request $request): string { if (isset($this->keyCache[$request])) { return $this->keyCache[$request]; } return $this->keyCache[$request] = $this->generateCacheKey($request); } /** * Persists the Request HTTP headers. */ private function persistRequest(Request $request): array { return $request->headers->all(); } /** * Persists the Response HTTP headers. */ private function persistResponse(Response $response): array { $headers = $response->headers->all(); $headers['X-Status'] = [$response->getStatusCode()]; return $headers; } /** * Restores a Response from the HTTP headers and body. */ private function restoreResponse(array $headers, string $path = null): Response { $status = $headers['X-Status'][0]; unset($headers['X-Status']); if (null !== $path) { $headers['X-Body-File'] = [$path]; } return new Response($path, $status, $headers); } } http-kernel/HttpCache/ResponseCacheStrategyInterface.php000064400000001751150432043210017441 0ustar00 * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Response; /** * ResponseCacheStrategyInterface implementations know how to compute the * Response cache HTTP header based on the different response cache headers. * * @author Fabien Potencier */ interface ResponseCacheStrategyInterface { /** * Adds a Response. */ public function add(Response $response); /** * Updates the Response HTTP headers based on the embedded Responses. */ public function update(Response $response); } http-kernel/HttpCache/ResponseCacheStrategy.php000064400000021646150432043210015625 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Response; /** * ResponseCacheStrategy knows how to compute the Response cache HTTP header * based on the different response cache headers. * * This implementation changes the main response TTL to the smallest TTL received * or force validation if one of the surrogates has validation cache strategy. * * @author Fabien Potencier */ class ResponseCacheStrategy implements ResponseCacheStrategyInterface { /** * Cache-Control headers that are sent to the final response if they appear in ANY of the responses. */ private const OVERRIDE_DIRECTIVES = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate']; /** * Cache-Control headers that are sent to the final response if they appear in ALL of the responses. */ private const INHERIT_DIRECTIVES = ['public', 'immutable']; private $embeddedResponses = 0; private $isNotCacheableResponseEmbedded = false; private $age = 0; private $flagDirectives = [ 'no-cache' => null, 'no-store' => null, 'no-transform' => null, 'must-revalidate' => null, 'proxy-revalidate' => null, 'public' => null, 'private' => null, 'immutable' => null, ]; private $ageDirectives = [ 'max-age' => null, 's-maxage' => null, 'expires' => null, ]; /** * {@inheritdoc} */ public function add(Response $response) { ++$this->embeddedResponses; foreach (self::OVERRIDE_DIRECTIVES as $directive) { if ($response->headers->hasCacheControlDirective($directive)) { $this->flagDirectives[$directive] = true; } } foreach (self::INHERIT_DIRECTIVES as $directive) { if (false !== $this->flagDirectives[$directive]) { $this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive); } } $age = $response->getAge(); $this->age = max($this->age, $age); if ($this->willMakeFinalResponseUncacheable($response)) { $this->isNotCacheableResponseEmbedded = true; return; } $isHeuristicallyCacheable = $response->headers->hasCacheControlDirective('public'); $maxAge = $response->headers->hasCacheControlDirective('max-age') ? (int) $response->headers->getCacheControlDirective('max-age') : null; $this->storeRelativeAgeDirective('max-age', $maxAge, $age, $isHeuristicallyCacheable); $sharedMaxAge = $response->headers->hasCacheControlDirective('s-maxage') ? (int) $response->headers->getCacheControlDirective('s-maxage') : $maxAge; $this->storeRelativeAgeDirective('s-maxage', $sharedMaxAge, $age, $isHeuristicallyCacheable); $expires = $response->getExpires(); $expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null; $this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0, $isHeuristicallyCacheable); } /** * {@inheritdoc} */ public function update(Response $response) { // if we have no embedded Response, do nothing if (0 === $this->embeddedResponses) { return; } // Remove validation related headers of the master response, // because some of the response content comes from at least // one embedded response (which likely has a different caching strategy). $response->setEtag(null); $response->setLastModified(null); $this->add($response); $response->headers->set('Age', $this->age); if ($this->isNotCacheableResponseEmbedded) { if ($this->flagDirectives['no-store']) { $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate'); } else { $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); } return; } $flags = array_filter($this->flagDirectives); if (isset($flags['must-revalidate'])) { $flags['no-cache'] = true; } $response->headers->set('Cache-Control', implode(', ', array_keys($flags))); $maxAge = null; if (is_numeric($this->ageDirectives['max-age'])) { $maxAge = $this->ageDirectives['max-age'] + $this->age; $response->headers->addCacheControlDirective('max-age', $maxAge); } if (is_numeric($this->ageDirectives['s-maxage'])) { $sMaxage = $this->ageDirectives['s-maxage'] + $this->age; if ($maxAge !== $sMaxage) { $response->headers->addCacheControlDirective('s-maxage', $sMaxage); } } if (is_numeric($this->ageDirectives['expires'])) { $date = clone $response->getDate(); $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds'); $response->setExpires($date); } } /** * RFC2616, Section 13.4. * * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 */ private function willMakeFinalResponseUncacheable(Response $response): bool { // RFC2616: A response received with a status code of 200, 203, 300, 301 or 410 // MAY be stored by a cache […] unless a cache-control directive prohibits caching. if ($response->headers->hasCacheControlDirective('no-cache') || $response->headers->getCacheControlDirective('no-store') ) { return true; } // Last-Modified and Etag headers cannot be merged, they render the response uncacheable // by default (except if the response also has max-age etc.). if (\in_array($response->getStatusCode(), [200, 203, 300, 301, 410]) && null === $response->getLastModified() && null === $response->getEtag() ) { return false; } // RFC2616: A response received with any other status code (e.g. status codes 302 and 307) // MUST NOT be returned in a reply to a subsequent request unless there are // cache-control directives or another header(s) that explicitly allow it. $cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private']; foreach ($cacheControl as $key) { if ($response->headers->hasCacheControlDirective($key)) { return false; } } if ($response->headers->has('Expires')) { return false; } return true; } /** * Store lowest max-age/s-maxage/expires for the final response. * * The response might have been stored in cache a while ago. To keep things comparable, * we have to subtract the age so that the value is normalized for an age of 0. * * If the value is lower than the currently stored value, we update the value, to keep a rolling * minimal value of each instruction. * * If the value is NULL and the isHeuristicallyCacheable parameter is false, the directive will * not be set on the final response. In this case, not all responses had the directive set and no * value can be found that satisfies the requirements of all responses. The directive will be dropped * from the final response. * * If the isHeuristicallyCacheable parameter is true, however, the current response has been marked * as cacheable in a public (shared) cache, but did not provide an explicit lifetime that would serve * as an upper bound. In this case, we can proceed and possibly keep the directive on the final response. */ private function storeRelativeAgeDirective(string $directive, ?int $value, int $age, bool $isHeuristicallyCacheable) { if (null === $value) { if ($isHeuristicallyCacheable) { /* * See https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2 * This particular response does not require maximum lifetime; heuristics might be applied. * Other responses, however, might have more stringent requirements on maximum lifetime. * So, return early here so that the final response can have the more limiting value set. */ return; } $this->ageDirectives[$directive] = false; } if (false !== $this->ageDirectives[$directive]) { $value -= $age; $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value; } } } http-kernel/HttpCache/StoreInterface.php000064400000004160150432043210014265 0ustar00 * * This code is partially based on the Rack-Cache library by Ryan Tomayko, * which is released under the MIT license. * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Interface implemented by HTTP cache stores. * * @author Fabien Potencier */ interface StoreInterface { /** * Locates a cached Response for the Request provided. * * @return Response|null */ public function lookup(Request $request); /** * Writes a cache entry to the store for the given Request and Response. * * Existing entries are read and any that match the response are removed. This * method calls write with the new list of cache entries. * * @return string The key under which the response is stored */ public function write(Request $request, Response $response); /** * Invalidates all cache entries that match the request. */ public function invalidate(Request $request); /** * Locks the cache for a given Request. * * @return bool|string true if the lock is acquired, the path to the current lock otherwise */ public function lock(Request $request); /** * Releases the lock for the given Request. * * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise */ public function unlock(Request $request); /** * Returns whether or not a lock exists. * * @return bool true if lock exists, false otherwise */ public function isLocked(Request $request); /** * Purges data for the given URL. * * @return bool true if the URL exists and has been purged, false otherwise */ public function purge(string $url); /** * Cleanups storage. */ public function cleanup(); } http-kernel/HttpCache/SubRequestHandler.php000064400000007521150432043210014754 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\IpUtils; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; /** * @author Nicolas Grekas * * @internal */ class SubRequestHandler { public static function handle(HttpKernelInterface $kernel, Request $request, int $type, bool $catch): Response { // save global state related to trusted headers and proxies $trustedProxies = Request::getTrustedProxies(); $trustedHeaderSet = Request::getTrustedHeaderSet(); // remove untrusted values $remoteAddr = $request->server->get('REMOTE_ADDR'); if (!$remoteAddr || !IpUtils::checkIp($remoteAddr, $trustedProxies)) { $trustedHeaders = [ 'FORWARDED' => $trustedHeaderSet & Request::HEADER_FORWARDED, 'X_FORWARDED_FOR' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_FOR, 'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST, 'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO, 'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT, 'X_FORWARDED_PREFIX' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PREFIX, ]; foreach (array_filter($trustedHeaders) as $name => $key) { $request->headers->remove($name); $request->server->remove('HTTP_'.$name); } } // compute trusted values, taking any trusted proxies into account $trustedIps = []; $trustedValues = []; foreach (array_reverse($request->getClientIps()) as $ip) { $trustedIps[] = $ip; $trustedValues[] = sprintf('for="%s"', $ip); } if ($ip !== $remoteAddr) { $trustedIps[] = $remoteAddr; $trustedValues[] = sprintf('for="%s"', $remoteAddr); } // set trusted values, reusing as much as possible the global trusted settings if (Request::HEADER_FORWARDED & $trustedHeaderSet) { $trustedValues[0] .= sprintf(';host="%s";proto=%s', $request->getHttpHost(), $request->getScheme()); $request->headers->set('Forwarded', $v = implode(', ', $trustedValues)); $request->server->set('HTTP_FORWARDED', $v); } if (Request::HEADER_X_FORWARDED_FOR & $trustedHeaderSet) { $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); $request->server->set('HTTP_X_FORWARDED_FOR', $v); } elseif (!(Request::HEADER_FORWARDED & $trustedHeaderSet)) { Request::setTrustedProxies($trustedProxies, $trustedHeaderSet | Request::HEADER_X_FORWARDED_FOR); $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); $request->server->set('HTTP_X_FORWARDED_FOR', $v); } // fix the client IP address by setting it to 127.0.0.1, // which is the core responsibility of this method $request->server->set('REMOTE_ADDR', '127.0.0.1'); // ensure 127.0.0.1 is set as trusted proxy if (!IpUtils::checkIp('127.0.0.1', $trustedProxies)) { Request::setTrustedProxies(array_merge($trustedProxies, ['127.0.0.1']), Request::getTrustedHeaderSet()); } try { return $kernel->handle($request, $type, $catch); } finally { // restore global state Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); } } } http-kernel/HttpCache/Esi.php000064400000007144150432043210012075 0ustar00 * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** * Esi implements the ESI capabilities to Request and Response instances. * * For more information, read the following W3C notes: * * * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang) * * * Edge Architecture Specification (http://www.w3.org/TR/edge-arch) * * @author Fabien Potencier */ class Esi extends AbstractSurrogate { public function getName() { return 'esi'; } /** * {@inheritdoc} */ public function addSurrogateControl(Response $response) { if (str_contains($response->getContent(), 'headers->set('Surrogate-Control', 'content="ESI/1.0"'); } } /** * {@inheritdoc} */ public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = '') { $html = sprintf('', $uri, $ignoreErrors ? ' onerror="continue"' : '', $alt ? sprintf(' alt="%s"', $alt) : '' ); if (!empty($comment)) { return sprintf("\n%s", $comment, $html); } return $html; } /** * {@inheritdoc} */ public function process(Request $request, Response $response) { $type = $response->headers->get('Content-Type'); if (empty($type)) { $type = 'text/html'; } $parts = explode(';', $type); if (!\in_array($parts[0], $this->contentTypes)) { return $response; } // we don't use a proper XML parser here as we can have ESI tags in a plain text response $content = $response->getContent(); $content = preg_replace('#.*?#s', '', $content); $content = preg_replace('#]+>#s', '', $content); $chunks = preg_split('##', $content, -1, \PREG_SPLIT_DELIM_CAPTURE); $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]); $i = 1; while (isset($chunks[$i])) { $options = []; preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, \PREG_SET_ORDER); foreach ($matches as $set) { $options[$set[1]] = $set[2]; } if (!isset($options['src'])) { throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.'); } $chunks[$i] = sprintf('surrogate->handle($this, %s, %s, %s) ?>'."\n", var_export($options['src'], true), var_export($options['alt'] ?? '', true), isset($options['onerror']) && 'continue' === $options['onerror'] ? 'true' : 'false' ); ++$i; $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]); ++$i; } $content = implode('', $chunks); $response->setContent($content); $response->headers->set('X-Body-Eval', 'ESI'); // remove ESI/1.0 from the Surrogate-Control header $this->removeFromControl($response); return $response; } }