Annotation of embedaddon/php/Zend/zend_multibyte.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | Zend Engine                                                          |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 2.00 of the Zend license,     |
        !             8:    | that is bundled with this package in the file LICENSE, and is        | 
        !             9:    | available through the world-wide-web at                              |
        !            10:    | http://www.zend.com/license/2_00.txt.                                |
        !            11:    | If you did not receive a copy of the Zend license and are unable to  |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@zend.com so we can mail you a copy immediately.              |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Authors: Masaki Fujimoto <fujimoto@php.net>                          |
        !            16:    |          Rui Hirokawa <hirokawa@php.net>                             |
        !            17:    +----------------------------------------------------------------------+
        !            18: */
        !            19: 
        !            20: /* $Id: zend_multibyte.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            21: 
        !            22: #include "zend.h"
        !            23: #include "zend_compile.h"
        !            24: #include "zend_operators.h"
        !            25: #include "zend_multibyte.h"
        !            26: 
        !            27: #ifdef ZEND_MULTIBYTE
        !            28: static size_t zend_multibyte_encoding_filter(unsigned char **to, size_t *to_length, const char *to_encoding, const unsigned char *from, size_t from_length, const char *from_encoding TSRMLS_DC);
        !            29: size_t sjis_input_filter(unsigned char **buf, size_t *length, const unsigned char *sjis, size_t sjis_length TSRMLS_DC);
        !            30: size_t sjis_output_filter(unsigned char **buf, size_t *length, const unsigned char *sjis, size_t sjis_length TSRMLS_DC);
        !            31: static char* zend_multibyte_assemble_encoding_list(zend_encoding **encoding_list, size_t encoding_list_size);
        !            32: static int zend_multibyte_parse_encoding_list(const char *encoding_list,
        !            33: size_t encoding_list_size, zend_encoding ***result, size_t *result_size);
        !            34: static zend_encoding *zend_multibyte_find_script_encoding(zend_encoding *onetime_encoding TSRMLS_DC);
        !            35: static zend_encoding *zend_multibyte_detect_unicode(TSRMLS_D);
        !            36: static zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC);
        !            37: 
        !            38: /*
        !            39:  * encodings
        !            40:  */
        !            41: static const char *ucs2_aliases[] = {"ISO-10646-UCS-2", "UCS2" , "UNICODE", NULL};
        !            42: static zend_encoding encoding_ucs2 = {
        !            43:        NULL,
        !            44:        NULL,
        !            45:        "UCS-2",
        !            46:        (const char *(*)[])&ucs2_aliases,
        !            47:        0
        !            48: };
        !            49: 
        !            50: static zend_encoding encoding_ucs2be = {
        !            51:        NULL,
        !            52:        NULL,
        !            53:        "UCS-2BE",
        !            54:        NULL,
        !            55:        0
        !            56: };
        !            57: 
        !            58: static zend_encoding encoding_ucs2le = {
        !            59:        NULL,
        !            60:        NULL,
        !            61:        "UCS-2LE",
        !            62:        NULL,
        !            63:        0
        !            64: };
        !            65: 
        !            66: static const char *ucs4_aliases[] = {"ISO-10646-UCS-4", "UCS4", NULL};
        !            67: static zend_encoding encoding_ucs4 = {
        !            68:        NULL,
        !            69:        NULL,
        !            70:        "UCS-4",
        !            71:        (const char *(*)[])&ucs4_aliases,
        !            72:        0
        !            73: };
        !            74: 
        !            75: static zend_encoding encoding_ucs4be = {
        !            76:        NULL,
        !            77:        NULL,
        !            78:        "UCS-4BE",
        !            79:        NULL,
        !            80:        0
        !            81: };
        !            82: 
        !            83: static zend_encoding encoding_ucs4le = {
        !            84:        NULL,
        !            85:        NULL,
        !            86:        "UCS-4LE",
        !            87:        NULL,
        !            88:        0
        !            89: };
        !            90: 
        !            91: static const char *utf32_aliases[] = {"utf32", NULL};
        !            92: static zend_encoding encoding_utf32 = {
        !            93:        NULL,
        !            94:        NULL,
        !            95:        "UTF-32",
        !            96:        (const char *(*)[])&utf32_aliases,
        !            97:        0
        !            98: };
        !            99: 
        !           100: static zend_encoding encoding_utf32be = {
        !           101:        NULL,
        !           102:        NULL,
        !           103:        "UTF-32BE",
        !           104:        NULL,
        !           105:        0
        !           106: };
        !           107: 
        !           108: static zend_encoding encoding_utf32le = {
        !           109:        NULL,
        !           110:        NULL,
        !           111:        "UTF-32LE",
        !           112:        NULL,
        !           113:        0
        !           114: };
        !           115: 
        !           116: static const char *utf16_aliases[] = {"utf16", NULL};
        !           117: static zend_encoding encoding_utf16 = {
        !           118:        NULL,
        !           119:        NULL,
        !           120:        "UTF-16",
        !           121:        (const char *(*)[])&utf16_aliases,
        !           122:        0
        !           123: };
        !           124: 
        !           125: static zend_encoding encoding_utf16be = {
        !           126:        NULL,
        !           127:        NULL,
        !           128:        "UTF-16BE",
        !           129:        NULL,
        !           130:        0
        !           131: };
        !           132: 
        !           133: static zend_encoding encoding_utf16le = {
        !           134:        NULL,
        !           135:        NULL,
        !           136:        "UTF-16LE",
        !           137:        NULL,
        !           138:        0
        !           139: };
        !           140: 
        !           141: static const char *utf8_aliases[] = {"utf8", NULL};
        !           142: static zend_encoding encoding_utf8 = {
        !           143:        NULL,
        !           144:        NULL,
        !           145:        "UTF-8",
        !           146:        (const char *(*)[])&utf8_aliases,
        !           147:        1
        !           148: };
        !           149: 
        !           150: static const char *ascii_aliases[] = {"ANSI_X3.4-1968", "iso-ir-6", "ANSI_X3.4-1986", "ISO_646.irv:1991", "US-ASCII", "ISO646-US", "us", "IBM367", "cp367", "csASCII", NULL};
        !           151: static zend_encoding encoding_ascii = {
        !           152:        NULL,
        !           153:        NULL,
        !           154:        "ASCII",
        !           155:        (const char *(*)[])&ascii_aliases,
        !           156:        1
        !           157: };
        !           158: 
        !           159: static const char *euc_jp_aliases[] = {"EUC", "EUC_JP", "eucJP", "x-euc-jp", NULL};
        !           160: static zend_encoding encoding_euc_jp = {
        !           161:        NULL,
        !           162:        NULL,
        !           163:        "EUC-JP",
        !           164:        (const char *(*)[])&euc_jp_aliases,
        !           165:        1
        !           166: };
        !           167: 
        !           168: static const char *sjis_aliases[] = {"x-sjis", "SJIS", "SHIFT-JIS", NULL};
        !           169: static zend_encoding encoding_sjis = {
        !           170:        sjis_input_filter,
        !           171:        sjis_output_filter,
        !           172:        "Shift_JIS",
        !           173:        (const char *(*)[])&sjis_aliases,
        !           174:        0
        !           175: };
        !           176: 
        !           177: static const char *eucjp_win_aliases[] = {"eucJP-open", NULL};
        !           178: static zend_encoding encoding_eucjp_win = {
        !           179:        NULL,
        !           180:        NULL,
        !           181:        "eucJP-win",
        !           182:        (const char *(*)[])&eucjp_win_aliases,
        !           183:        1
        !           184: };
        !           185: 
        !           186: static const char *sjis_win_aliases[] = {"SJIS-open", "MS_Kanji", "Windows-31J", "CP932", NULL};
        !           187: static zend_encoding encoding_sjis_win = {
        !           188:        /* sjis-filters does not care about diffs of Shift_JIS and CP932 */
        !           189:        sjis_input_filter,
        !           190:        sjis_output_filter,
        !           191:        "SJIS-win",
        !           192:        (const char *(*)[])&sjis_win_aliases,
        !           193:        0
        !           194: };
        !           195: 
        !           196: static const char *jis_aliases[] = {"ISO-2022-JP", NULL};
        !           197: static zend_encoding encoding_jis = {
        !           198:        NULL,
        !           199:        NULL,
        !           200:        "JIS",
        !           201:        (const char *(*)[])&jis_aliases,
        !           202:        0
        !           203: };
        !           204: 
        !           205: static const char *euc_cn_aliases[] = {"CN-GB", "EUC_CN", "eucCN", "x-euc-cn", "gb2312", NULL};
        !           206: static zend_encoding encoding_euc_cn = {
        !           207:        NULL,
        !           208:        NULL,
        !           209:        "EUC-CN",
        !           210:        (const char *(*)[])&euc_cn_aliases,
        !           211:        1
        !           212: };
        !           213: 
        !           214: static const char *cp936_aliases[] = {"CP-936", NULL};
        !           215: static zend_encoding encoding_cp936 = {
        !           216:        NULL,
        !           217:        NULL,
        !           218:        "CP936",
        !           219:        (const char *(*)[])&cp936_aliases,
        !           220:        0
        !           221: };
        !           222: 
        !           223: static const char *hz_aliases[] = {"HZ-GB-2312", NULL};
        !           224: static zend_encoding encoding_hz = {
        !           225:        NULL,
        !           226:        NULL,
        !           227:        "HZ",
        !           228:        (const char *(*)[])&hz_aliases,
        !           229:        0
        !           230: };
        !           231: 
        !           232: static const char *euc_tw_aliases[] = {"EUC_TW", "eucTW", "x-euc-tw", NULL};
        !           233: static zend_encoding encoding_euc_tw = {
        !           234:        NULL,
        !           235:        NULL,
        !           236:        "EUC-TW",
        !           237:        (const char *(*)[])&euc_tw_aliases,
        !           238:        1
        !           239: };
        !           240: 
        !           241: static const char *big5_aliases[] = {"BIG5", "CN-BIG5", "BIG-FIVE", "BIGFIVE", "CP950", NULL};
        !           242: static zend_encoding encoding_big5 = {
        !           243:        NULL,
        !           244:        NULL,
        !           245:        "BIG-5",
        !           246:        (const char *(*)[])&big5_aliases,
        !           247:        0
        !           248: };
        !           249: 
        !           250: static const char *euc_kr_aliases[] = {"EUC_KR", "eucKR", "x-euc-kr", NULL};
        !           251: static zend_encoding encoding_euc_kr = {
        !           252:        NULL,
        !           253:        NULL,
        !           254:        "EUC-KR",
        !           255:        (const char *(*)[])&euc_kr_aliases,
        !           256:        1
        !           257: };
        !           258: 
        !           259: static const char *uhc_aliases[] = {"CP949", NULL};
        !           260: static zend_encoding encoding_uhc = {
        !           261:        NULL,
        !           262:        NULL,
        !           263:        "UHC",
        !           264:        (const char *(*)[])&uhc_aliases,
        !           265:        1
        !           266: };
        !           267: 
        !           268: static zend_encoding encoding_2022kr = {
        !           269:        NULL,
        !           270:        NULL,
        !           271:        "ISO-2022-KR",
        !           272:        NULL,
        !           273:        0
        !           274: };
        !           275: 
        !           276: static const char *cp1252_aliases[] = {"cp1252", NULL};
        !           277: static zend_encoding encoding_cp1252 = {
        !           278:        NULL,
        !           279:        NULL,
        !           280:        "Windows-1252",
        !           281:        (const char *(*)[])&cp1252_aliases,
        !           282:        1
        !           283: };
        !           284: 
        !           285: static const char *iso_8859_1_aliases[] = {"ISO_8859-1", "latin1", NULL};
        !           286: static zend_encoding encoding_8859_1 = {
        !           287:        NULL,
        !           288:        NULL,
        !           289:        "ISO-8859-1",
        !           290:        (const char *(*)[])&iso_8859_1_aliases,
        !           291:        1
        !           292: };
        !           293: 
        !           294: static const char *iso_8859_2_aliases[] = {"ISO_8859-2", "latin2", NULL};
        !           295: static zend_encoding encoding_8859_2 = {
        !           296:        NULL,
        !           297:        NULL,
        !           298:        "ISO-8859-2",
        !           299:        (const char *(*)[])&iso_8859_2_aliases,
        !           300:        1
        !           301: };
        !           302: 
        !           303: static const char *iso_8859_3_aliases[] = {"ISO_8859-3", "latin3", NULL};
        !           304: static zend_encoding encoding_8859_3 = {
        !           305:        NULL,
        !           306:        NULL,
        !           307:        "ISO-8859-3",
        !           308:        (const char *(*)[])&iso_8859_3_aliases,
        !           309:        1
        !           310: };
        !           311: 
        !           312: static const char *iso_8859_4_aliases[] = {"ISO_8859-4", "latin4", NULL};
        !           313: static zend_encoding encoding_8859_4 = {
        !           314:        NULL,
        !           315:        NULL,
        !           316:        "ISO-8859-4",
        !           317:        (const char *(*)[])&iso_8859_4_aliases,
        !           318:        1
        !           319: };
        !           320: 
        !           321: static const char *iso_8859_5_aliases[] = {"ISO_8859-5", "cyrillic", NULL};
        !           322: static zend_encoding encoding_8859_5 = {
        !           323:        NULL,
        !           324:        NULL,
        !           325:        "ISO-8859-5",
        !           326:        (const char *(*)[])&iso_8859_5_aliases,
        !           327:        1
        !           328: };
        !           329: 
        !           330: static const char *iso_8859_6_aliases[] = {"ISO_8859-6", "arabic", NULL};
        !           331: static zend_encoding encoding_8859_6 = {
        !           332:        NULL,
        !           333:        NULL,
        !           334:        "ISO-8859-6",
        !           335:        (const char *(*)[])&iso_8859_6_aliases,
        !           336:        1
        !           337: };
        !           338: 
        !           339: static const char *iso_8859_7_aliases[] = {"ISO_8859-7", "greek", NULL};
        !           340: static zend_encoding encoding_8859_7 = {
        !           341:        NULL,
        !           342:        NULL,
        !           343:        "ISO-8859-7",
        !           344:        (const char *(*)[])&iso_8859_7_aliases,
        !           345:        1
        !           346: };
        !           347: 
        !           348: static const char *iso_8859_8_aliases[] = {"ISO_8859-8", "hebrew", NULL};
        !           349: static zend_encoding encoding_8859_8 = {
        !           350:        NULL,
        !           351:        NULL,
        !           352:        "ISO-8859-8",
        !           353:        (const char *(*)[])&iso_8859_8_aliases,
        !           354:        1
        !           355: };
        !           356: 
        !           357: static const char *iso_8859_9_aliases[] = {"ISO_8859-9", "latin5", NULL};
        !           358: static zend_encoding encoding_8859_9 = {
        !           359:        NULL,
        !           360:        NULL,
        !           361:        "ISO-8859-9",
        !           362:        (const char *(*)[])&iso_8859_9_aliases,
        !           363:        1
        !           364: };
        !           365: 
        !           366: static const char *iso_8859_10_aliases[] = {"ISO_8859-10", "latin6", NULL};
        !           367: static zend_encoding encoding_8859_10 = {
        !           368:        NULL,
        !           369:        NULL,
        !           370:        "ISO-8859-10",
        !           371:        (const char *(*)[])&iso_8859_10_aliases,
        !           372:        1
        !           373: };
        !           374: 
        !           375: static const char *iso_8859_13_aliases[] = {"ISO_8859-13", NULL};
        !           376: static zend_encoding encoding_8859_13 = {
        !           377:        NULL,
        !           378:        NULL,
        !           379:        "ISO-8859-13",
        !           380:        (const char *(*)[])&iso_8859_13_aliases,
        !           381:        1
        !           382: };
        !           383: 
        !           384: static const char *iso_8859_14_aliases[] = {"ISO_8859-14", "latin8", NULL};
        !           385: static zend_encoding encoding_8859_14 = {
        !           386:        NULL,
        !           387:        NULL,
        !           388:        "ISO-8859-14",
        !           389:        (const char *(*)[])&iso_8859_14_aliases,
        !           390:        1
        !           391: };
        !           392: 
        !           393: static const char *iso_8859_15_aliases[] = {"ISO_8859-15", NULL};
        !           394: static zend_encoding encoding_8859_15 = {
        !           395:        NULL,
        !           396:        NULL,
        !           397:        "ISO-8859-15",
        !           398:        (const char *(*)[])&iso_8859_15_aliases,
        !           399:        1
        !           400: };
        !           401: 
        !           402: static const char *cp1251_aliases[] = {"CP1251", "CP-1251", "WINDOWS-1251", NULL};
        !           403: static zend_encoding encoding_cp1251 = {
        !           404:        NULL,
        !           405:        NULL,
        !           406:        "Windows-1251",
        !           407:        (const char *(*)[])&cp1251_aliases,
        !           408:        1
        !           409: };
        !           410: 
        !           411: static const char *cp866_aliases[] = {"CP866", "CP-866", "IBM-866", NULL};
        !           412: static zend_encoding encoding_cp866 = {
        !           413:        NULL,
        !           414:        NULL,
        !           415:        "CP866",
        !           416:        (const char *(*)[])&cp866_aliases,
        !           417:        1
        !           418: };
        !           419: 
        !           420: static const char *koi8r_aliases[] = {"KOI8-R", "KOI8R", NULL};
        !           421: static zend_encoding encoding_koi8r = {
        !           422:        NULL,
        !           423:        NULL,
        !           424:        "KOI8-R",
        !           425:        (const char *(*)[])&koi8r_aliases,
        !           426:        1
        !           427: };
        !           428: 
        !           429: static const char *koi8u_aliases[] = {"KOI8-U", "KOI8U", NULL};
        !           430: static zend_encoding encoding_koi8u = {
        !           431:        NULL,
        !           432:        NULL,
        !           433:        "KOI8-U",
        !           434:        (const char *(*)[])&koi8u_aliases,
        !           435:        1
        !           436: };
        !           437: 
        !           438: static const char *cp1254_aliases[] = {"cp1254", NULL};
        !           439: static zend_encoding encoding_cp1254 = {
        !           440:        NULL,
        !           441:        NULL,
        !           442:        "Windows-1254",
        !           443:        (const char *(*)[])&cp1254_aliases,
        !           444:        1
        !           445: };
        !           446: 
        !           447: static const char *armscii8_aliases[] = { "ArmSCII8", "ARMSCII-8", "ARMSCII8", NULL};
        !           448: static zend_encoding encoding_armscii8 = {
        !           449:        NULL,
        !           450:        NULL,
        !           451:        "ArmSCII-8",
        !           452:        (const char *(*)[])&armscii8_aliases,
        !           453:        1
        !           454: };
        !           455: 
        !           456: static const char *cp850_aliases[] = {"IBM850", NULL};
        !           457: static zend_encoding encoding_cp850 = {
        !           458:        NULL,
        !           459:        NULL,
        !           460:        "CP850",
        !           461:        (const char *(*)[])&cp850_aliases,
        !           462:        1
        !           463: };
        !           464: 
        !           465: static zend_encoding *zend_encoding_table[] = {
        !           466:        &encoding_ucs4,
        !           467:        &encoding_ucs4be,
        !           468:        &encoding_ucs4le,
        !           469:        &encoding_ucs2,
        !           470:        &encoding_ucs2be,
        !           471:        &encoding_ucs2le,
        !           472:        &encoding_utf32,
        !           473:        &encoding_utf32be,
        !           474:        &encoding_utf32le,
        !           475:        &encoding_utf16,
        !           476:        &encoding_utf16be,
        !           477:        &encoding_utf16le,
        !           478:        &encoding_utf8,
        !           479:        &encoding_ascii,
        !           480:        &encoding_euc_jp,
        !           481:        &encoding_sjis,
        !           482:        &encoding_eucjp_win,
        !           483:        &encoding_sjis_win,
        !           484:        &encoding_jis,
        !           485:        &encoding_cp1252,
        !           486:        &encoding_8859_1,
        !           487:        &encoding_8859_2,
        !           488:        &encoding_8859_3,
        !           489:        &encoding_8859_4,
        !           490:        &encoding_8859_5,
        !           491:        &encoding_8859_6,
        !           492:        &encoding_8859_7,
        !           493:        &encoding_8859_8,
        !           494:        &encoding_8859_9,
        !           495:        &encoding_8859_10,
        !           496:        &encoding_8859_13,
        !           497:        &encoding_8859_14,
        !           498:        &encoding_8859_15,
        !           499:        &encoding_euc_cn,
        !           500:        &encoding_cp936,
        !           501:        &encoding_hz,
        !           502:        &encoding_euc_tw,
        !           503:        &encoding_big5,
        !           504:        &encoding_euc_kr,
        !           505:        &encoding_uhc,
        !           506:        &encoding_2022kr,
        !           507:        &encoding_cp1251,
        !           508:        &encoding_cp866,
        !           509:        &encoding_koi8r,
        !           510:        &encoding_koi8u,
        !           511:        &encoding_armscii8,
        !           512:        &encoding_cp1254,
        !           513:        &encoding_cp850,
        !           514:        NULL
        !           515: };
        !           516: 
        !           517: 
        !           518: 
        !           519: ZEND_API int zend_multibyte_set_script_encoding(const char *encoding_list,
        !           520: size_t encoding_list_size TSRMLS_DC)
        !           521: {
        !           522:        if (CG(script_encoding_list)) {
        !           523:                efree(CG(script_encoding_list));
        !           524:                CG(script_encoding_list) = NULL;
        !           525:        }
        !           526:        CG(script_encoding_list_size) = 0;
        !           527: 
        !           528:        if (!encoding_list) {
        !           529:                return 0;
        !           530:        }
        !           531: 
        !           532:        zend_multibyte_parse_encoding_list(encoding_list, encoding_list_size, &(CG(script_encoding_list)), &(CG(script_encoding_list_size)));
        !           533: 
        !           534:        return 0;
        !           535: }
        !           536: 
        !           537: 
        !           538: ZEND_API int zend_multibyte_set_internal_encoding(const char *encoding_name TSRMLS_DC)
        !           539: {
        !           540:        CG(internal_encoding) = zend_multibyte_fetch_encoding(encoding_name);
        !           541:        return 0;
        !           542: }
        !           543: 
        !           544: ZEND_API int zend_multibyte_set_functions(zend_encoding_detector encoding_detector, zend_encoding_converter encoding_converter, zend_encoding_oddlen encoding_oddlen TSRMLS_DC)
        !           545: {
        !           546:        CG(encoding_detector) = encoding_detector;
        !           547:        CG(encoding_converter) = encoding_converter;
        !           548:        CG(encoding_oddlen) = encoding_oddlen;
        !           549:        return 0;
        !           550: }
        !           551: 
        !           552: 
        !           553: ZEND_API int zend_multibyte_set_filter(zend_encoding *onetime_encoding TSRMLS_DC)
        !           554: {
        !           555:        LANG_SCNG(script_encoding) = zend_multibyte_find_script_encoding(onetime_encoding TSRMLS_CC);
        !           556:        LANG_SCNG(internal_encoding) = CG(internal_encoding);
        !           557: 
        !           558:        /* judge input/output filter */
        !           559:        LANG_SCNG(input_filter) = NULL;
        !           560:        LANG_SCNG(output_filter) = NULL;
        !           561: 
        !           562:        if (!LANG_SCNG(script_encoding)) {
        !           563:                return 0;
        !           564:        }
        !           565: 
        !           566:        if (!LANG_SCNG(internal_encoding) || LANG_SCNG(script_encoding) == LANG_SCNG(internal_encoding)) {
        !           567:                /* if encoding specfic filters exist, use them */
        !           568:                if (LANG_SCNG(script_encoding)->input_filter && LANG_SCNG(script_encoding)->output_filter) {
        !           569:                        LANG_SCNG(input_filter) = LANG_SCNG(script_encoding)->input_filter;
        !           570:                        LANG_SCNG(output_filter) = LANG_SCNG(script_encoding)->output_filter;
        !           571:                        return 0;
        !           572:                }
        !           573: 
        !           574:                if (!LANG_SCNG(script_encoding)->compatible) {
        !           575:                        /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
        !           576:                        LANG_SCNG(internal_encoding) = LANG_SCNG(script_encoding);
        !           577:                        LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
        !           578:                        LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
        !           579:                        return 0;
        !           580:                } else {
        !           581:                        /* nothing to do in this case */
        !           582:                        return 0;
        !           583:                }
        !           584:        }
        !           585: 
        !           586:        /* LANG_SCNG(internal_encoding) cannot be NULL here */
        !           587:        if (LANG_SCNG(internal_encoding)->compatible) {
        !           588:                LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
        !           589:                return 0;
        !           590:        } else if (LANG_SCNG(script_encoding)->compatible) {
        !           591:                LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
        !           592:                return 0;
        !           593:        }
        !           594: 
        !           595:        /* both script and internal encodings are incompatible w/ flex */
        !           596:        LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
        !           597:        LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
        !           598: 
        !           599:        return 0;
        !           600: }
        !           601: 
        !           602: 
        !           603: ZEND_API zend_encoding* zend_multibyte_fetch_encoding(const char *encoding_name)
        !           604: {
        !           605:        int i, j;
        !           606:        zend_encoding *encoding;
        !           607: 
        !           608:        if (!encoding_name) {
        !           609:                return NULL;
        !           610:        }
        !           611: 
        !           612:        for (i = 0; (encoding = zend_encoding_table[i]) != NULL; i++) {
        !           613:                if (zend_binary_strcasecmp(encoding->name, strlen(encoding->name), encoding_name, strlen(encoding_name)) == 0) {
        !           614:                        return encoding;
        !           615:                }
        !           616:        }
        !           617: 
        !           618:        for (i = 0; (encoding = zend_encoding_table[i]) != NULL; i++) {
        !           619:                if (encoding->aliases != NULL) {
        !           620:                        for (j = 0; (*encoding->aliases)[j] != NULL; j++) {
        !           621:                                if (zend_binary_strcasecmp((*encoding->aliases)[j], strlen((*encoding->aliases)[j]), encoding_name, strlen(encoding_name)) == 0) {
        !           622:                                        return encoding;
        !           623:                                }
        !           624:                        }
        !           625:                }
        !           626:        }
        !           627: 
        !           628:        return NULL;
        !           629: }
        !           630: 
        !           631: 
        !           632: ZEND_API size_t zend_multibyte_script_encoding_filter(unsigned char **to, size_t
        !           633: *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
        !           634: {
        !           635:        const char *name;
        !           636: 
        !           637:        if (LANG_SCNG(internal_encoding) == NULL || LANG_SCNG(internal_encoding)->compatible == 0) {
        !           638:                name = "UTF-8";
        !           639:        } else {
        !           640:                name = LANG_SCNG(internal_encoding)->name;
        !           641:        }
        !           642: 
        !           643:        return zend_multibyte_encoding_filter(to, to_length, name, from, from_length, LANG_SCNG(script_encoding)->name TSRMLS_CC);
        !           644: }
        !           645: 
        !           646: ZEND_API size_t zend_multibyte_internal_encoding_filter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
        !           647: {
        !           648:        const char *name;
        !           649: 
        !           650:        if (LANG_SCNG(script_encoding)->compatible == 0) {
        !           651:                name = "UTF-8";
        !           652:        } else {
        !           653:                name = LANG_SCNG(script_encoding)->name;
        !           654:        }
        !           655: 
        !           656:        return zend_multibyte_encoding_filter(to, to_length, LANG_SCNG(internal_encoding)->name, from, from_length, name TSRMLS_CC);
        !           657: }
        !           658: 
        !           659: static size_t zend_multibyte_encoding_filter(unsigned char **to, size_t *to_length, const char *to_encoding, const unsigned char *from, size_t from_length, const char *from_encoding TSRMLS_DC)
        !           660: {
        !           661:        size_t oddlen;
        !           662: 
        !           663:        if (!CG(encoding_converter)) {
        !           664:                return 0;
        !           665:        }
        !           666: 
        !           667:        if (CG(encoding_oddlen)) {
        !           668:                oddlen = CG(encoding_oddlen)(from, from_length, from_encoding TSRMLS_CC);
        !           669:                if (oddlen > 0) {
        !           670:                        from_length -= oddlen;
        !           671:                }
        !           672:        }
        !           673: 
        !           674:        if (CG(encoding_converter)(to, to_length, from, from_length, to_encoding, from_encoding TSRMLS_CC) != 0) {
        !           675:                return 0;
        !           676:        }
        !           677: 
        !           678:        return from_length;
        !           679: }
        !           680: 
        !           681: 
        !           682: /*
        !           683:  *     Shift_JIS Input/Output Filter
        !           684:  */
        !           685: static const unsigned char table_sjis[] = { /* 0x80-0x9f,0xE0-0xEF */
        !           686:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           687:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           688:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           689:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           690:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           691:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           692:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           693:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           694:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           695:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           696:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           697:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           698:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           699:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           700:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           701:   3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 0, 0, 0
        !           702: };
        !           703: 
        !           704: size_t sjis_input_filter(unsigned char **buf, size_t *length, const unsigned char *sjis, size_t sjis_length TSRMLS_DC)
        !           705: {
        !           706:        const unsigned char *p;
        !           707:        unsigned char *q;
        !           708:        unsigned char  c1, c2;
        !           709: 
        !           710:        *buf = (unsigned char*)emalloc(sjis_length * 3 / 2 + 1);
        !           711:        if (!*buf)
        !           712:                return 0;
        !           713:        *length = 0;
        !           714: 
        !           715:        p = sjis;
        !           716:        q = *buf;
        !           717: 
        !           718:        /* convert [SJIS -> EUC-JP] (for lex scan) -- some other better ways? */
        !           719:        while (*p && (p - sjis) < sjis_length) {
        !           720:                if (!(*p & 0x80)) {
        !           721:                        *q++ = *p++;
        !           722:                        continue;
        !           723:                }
        !           724: 
        !           725:                /* handling 8 bit code */
        !           726:                if (table_sjis[*p] == 1) {
        !           727:                        /* 1 byte kana */
        !           728:                        *q++ = 0x8e;
        !           729:                        *q++ = *p++;
        !           730:                        continue;
        !           731:                }
        !           732: 
        !           733:                if (!*(p+1)) {
        !           734:                        *q++ = *p++;
        !           735:                        break;
        !           736:                }
        !           737: 
        !           738:                if (table_sjis[*p] == 2) {
        !           739:                        /* 2 byte kanji code */
        !           740:                        c1 = *p++;
        !           741:                        if (!*p || (p - sjis) >= sjis_length) {
        !           742:                                break;
        !           743:                        }
        !           744:                        c2 = *p++;
        !           745:                        c1 -= (c1 <= 0x9f) ? 0x71 : 0xb1;
        !           746:                        c1 = (c1 << 1) + 1;
        !           747:                        if (c2 >= 0x9e) {
        !           748:                                c2 -= 0x7e;
        !           749:                                c1++;
        !           750:                        } else if (c2 > 0x7f) {
        !           751:                                c2 -= 0x20;
        !           752:                        } else {
        !           753:                                c2 -= 0x1f;
        !           754:                        }
        !           755: 
        !           756:                        c1 |= 0x80;
        !           757:                        c2 |= 0x80;
        !           758: 
        !           759:                        *q++ = c1;
        !           760:                        *q++ = c2;
        !           761:                } else {
        !           762:                        /*
        !           763:                         * for user defined chars (ATTENTION)
        !           764:                         *
        !           765:                         * THESE ARE NOT CODE FOR CONVERSION! :-P
        !           766:                         * (using *ILLEGALLY* 3byte EUC-JP space)
        !           767:                         *
        !           768:                         * we cannot perfectly (== 1 to 1)  convert these chars to EUC-JP.
        !           769:                         * so, these code are for perfect RESTORING in sjis_output_filter()
        !           770:                         */
        !           771:                        c1 = *p++;
        !           772:                        if (!*p || (p - sjis) >= sjis_length) {
        !           773:                                break;
        !           774:                        }
        !           775:                        c2 = *p++;
        !           776:                        *q++ = 0x8f;
        !           777:                        /*
        !           778:                         * MAP TO (EUC-JP):
        !           779:                         * type A: 0xeba1 - 0xf4fe
        !           780:                         * type B: 0xf5a1 - 0xfefe
        !           781:                         * type C: 0xa1a1 - 0xa6fe
        !           782:                         */
        !           783:                        c1 -= (c1 > 0xf9) ? (0x79+0x71) : (0x0a+0xb1);
        !           784:                        c1 = (c1 << 1) + 1;
        !           785:                        if (c2 >= 0x9e) {
        !           786:                                c2 -= 0x7e;
        !           787:                                c1++;
        !           788:                        } else if (c2 > 0x7f) {
        !           789:                                c2 -= 0x20;
        !           790:                        } else {
        !           791:                                c2 -= 0x1f;
        !           792:                        }
        !           793:                        
        !           794:                        c1 |= 0x80;
        !           795:                        c2 |= 0x80;
        !           796: 
        !           797:                        *q++ = c1;
        !           798:                        *q++ = c2;
        !           799:                }
        !           800:        }
        !           801:        *q = '\0';
        !           802:        *length = q - *buf;
        !           803: 
        !           804:        return *length;
        !           805: }
        !           806: 
        !           807: static const unsigned char table_eucjp[] = { /* 0xA1-0xFE */
        !           808:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           809:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           810:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           811:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           812:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           813:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           814:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           815:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           816:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
        !           817:   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        !           818:   1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           819:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           820:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           821:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           822:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        !           823:   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1
        !           824: };
        !           825: 
        !           826: size_t sjis_output_filter(unsigned char **sjis, size_t *sjis_length, const unsigned char *buf, size_t length TSRMLS_DC)
        !           827: {
        !           828:        unsigned char c1, c2;
        !           829:        unsigned char *p;
        !           830:        const unsigned char *q;
        !           831: 
        !           832:        if (!sjis || !sjis_length) {
        !           833:                return 0;
        !           834:        }
        !           835: 
        !           836:        /* always Shift_JIS <= EUC-JP */
        !           837:        *sjis = (unsigned char*)emalloc(length+1);
        !           838:        if (!sjis) {
        !           839:                return 0;
        !           840:        }
        !           841:        p = *sjis;
        !           842:        q = buf;
        !           843: 
        !           844:        /* restore converted strings [EUC-JP -> Shift_JIS] */
        !           845:        while (*q && (q - buf) < length) {
        !           846:                if (!(*q & 0x80)) {
        !           847:                        *p++ = *q++;
        !           848:                        continue;
        !           849:                }
        !           850: 
        !           851:                /* hankaku kana */
        !           852:                if (*q == 0x8e) {
        !           853:                        q++;
        !           854:                        if (*q) {
        !           855:                                *p++ = *q++;
        !           856:                        }
        !           857:                        continue;
        !           858:                }
        !           859: 
        !           860:                /* 2 byte kanji code */
        !           861:                if (table_eucjp[*q] == 2) {
        !           862:                        c1 = (*q++ & ~0x80) & 0xff;
        !           863:                        if (*q) {
        !           864:                                c2 = (*q++ & ~0x80) & 0xff;
        !           865:                        } else {
        !           866:                                q--;
        !           867:                                break;
        !           868:                        }
        !           869: 
        !           870:                        c2 += (c1 & 0x01) ? 0x1f : 0x7d;
        !           871:                        if (c2 >= 0x7f) {
        !           872:                                c2++;
        !           873:                        }
        !           874:                        c1 = ((c1 - 0x21) >> 1) + 0x81;
        !           875:                        if (c1 > 0x9f) {
        !           876:                                c1 += 0x40;
        !           877:                        }
        !           878:                        
        !           879:                        *p++ = c1;
        !           880:                        *p++ = c2;
        !           881:                        continue;
        !           882:                }
        !           883: 
        !           884:                if (*q == 0x8f) {
        !           885:                        q++;
        !           886:                        if (*q) {
        !           887:                                c1 = (*q++ & ~0x80) & 0xff;
        !           888:                        } else {
        !           889:                                q--;
        !           890:                                break;
        !           891:                        }
        !           892:                        if (*q) {
        !           893:                                c2 = (*q++ & ~0x80) & 0xff;
        !           894:                        } else {
        !           895:                                q -= 2;
        !           896:                                break;
        !           897:                        }
        !           898:                        
        !           899:                        c2 += (c1 & 0x01) ? 0x1f : 0x7d;
        !           900:                        if (c2 >= 0x7f) {
        !           901:                                c2++;
        !           902:                        }
        !           903:                        c1 = ((c1 - 0x21) >> 1) + 0x81;
        !           904:                        if (c1 > 0x9f) {
        !           905:                                c1 += 0x40;
        !           906:                        }
        !           907:                        
        !           908:                        if (c1 >= 0x81 && c1 <= 0x9f) {
        !           909:                                c1 += 0x79;
        !           910:                        } else {
        !           911:                                c1 += 0x0a;
        !           912:                        }
        !           913:                        
        !           914:                        *p++ = c1;
        !           915:                        *p++ = c2;
        !           916:                        continue;
        !           917:                }
        !           918: 
        !           919:                /* some other chars (may not happen) */
        !           920:                *p++ = *q++;
        !           921:        }
        !           922:        *p = '\0';
        !           923:        *sjis_length = p - *sjis;
        !           924: 
        !           925:        return q-buf;   /* return length we actually read */
        !           926: }
        !           927: 
        !           928: 
        !           929: static char *zend_multibyte_assemble_encoding_list(zend_encoding **encoding_list, size_t encoding_list_size)
        !           930: {
        !           931:        int i, list_size = 0;
        !           932:        const char *name;
        !           933:        char *list = NULL;
        !           934: 
        !           935:        if (!encoding_list || !encoding_list_size) {
        !           936:                return NULL;
        !           937:        }
        !           938: 
        !           939:        for (i = 0; i < encoding_list_size; i++) {
        !           940:                name = (*(encoding_list+i))->name;
        !           941:                if (name) {
        !           942:                        list_size += strlen(name) + 1;
        !           943:                        if (!list) {
        !           944:                                list = (char*)emalloc(list_size);
        !           945:                                if (!list) {
        !           946:                                        return NULL;
        !           947:                                }
        !           948:                                *list = '\0';
        !           949:                        } else {
        !           950:                                list = (char*)erealloc(list, list_size);
        !           951:                                if (!list) {
        !           952:                                        return NULL;
        !           953:                                }
        !           954:                                strcat(list, ",");
        !           955:                        }
        !           956:                        strcat(list, name);
        !           957:                }
        !           958:        }
        !           959:        return list;
        !           960: }
        !           961: 
        !           962: 
        !           963: static int zend_multibyte_parse_encoding_list(const char *encoding_list,
        !           964: size_t encoding_list_size, zend_encoding ***result, size_t *result_size)
        !           965: {
        !           966:        int n, size;
        !           967:        char *p, *p1, *p2, *endp, *tmpstr;
        !           968:        zend_encoding **list, **entry, *encoding;
        !           969: 
        !           970:        list = NULL;
        !           971:        if (encoding_list == NULL || encoding_list_size <= 0) {
        !           972:                return -1;
        !           973:        } else {
        !           974:                /* copy the encoding_list string for work */
        !           975:                tmpstr = (char *)estrndup(encoding_list, encoding_list_size);
        !           976:                if (tmpstr == NULL) {
        !           977:                        return -1;
        !           978:                }
        !           979:                /* count the number of listed encoding names */
        !           980:                endp = tmpstr + encoding_list_size;
        !           981:                n = 1;
        !           982:                p1 = tmpstr;
        !           983:                while ((p2 = zend_memnstr(p1, ",", 1, endp)) != NULL) {
        !           984:                        p1 = p2 + 1;
        !           985:                        n++;
        !           986:                }
        !           987:                size = n;
        !           988:                /* make list */
        !           989:                list = (zend_encoding**)ecalloc(size, sizeof(zend_encoding*));
        !           990:                if (list != NULL) {
        !           991:                        entry = list;
        !           992:                        n = 0;
        !           993:                        p1 = tmpstr;
        !           994:                        do {
        !           995:                                p2 = p = zend_memnstr(p1, ",", 1, endp);
        !           996:                                if (p == NULL) {
        !           997:                                        p = endp;
        !           998:                                }
        !           999:                                *p = '\0';
        !          1000:                                /* trim spaces */
        !          1001:                                while (p1 < p && (*p1 == ' ' || *p1 == '\t')) {
        !          1002:                                        p1++;
        !          1003:                                }
        !          1004:                                p--;
        !          1005:                                while (p > p1 && (*p == ' ' || *p == '\t')) {
        !          1006:                                        *p = '\0';
        !          1007:                                        p--;
        !          1008:                                }
        !          1009:                                /* convert to the encoding number and check encoding */
        !          1010:                                encoding = zend_multibyte_fetch_encoding(p1);
        !          1011:                                if (encoding)
        !          1012:                                {
        !          1013:                                        *entry++ = encoding;
        !          1014:                                        n++;
        !          1015:                                }
        !          1016:                                p1 = p2 + 1;
        !          1017:                        } while (n < size && p2 != NULL);
        !          1018:                        *result = list;
        !          1019:                        *result_size = n;
        !          1020:                }
        !          1021:                efree(tmpstr);
        !          1022:        }
        !          1023: 
        !          1024:        if (list == NULL) {
        !          1025:                return -1;
        !          1026:        }
        !          1027: 
        !          1028:        return 0;
        !          1029: }
        !          1030: 
        !          1031: 
        !          1032: static zend_encoding* zend_multibyte_find_script_encoding(zend_encoding *onetime_encoding TSRMLS_DC)
        !          1033: {
        !          1034:        zend_encoding *script_encoding;
        !          1035:        char *name, *list;
        !          1036: 
        !          1037:        /* onetime_encoding is prior to everything */
        !          1038:        if (onetime_encoding != NULL) {
        !          1039:                return onetime_encoding;
        !          1040:        }
        !          1041: 
        !          1042:        if (CG(detect_unicode)) {
        !          1043:                /* check out bom(byte order mark) and see if containing wchars */
        !          1044:                script_encoding = zend_multibyte_detect_unicode(TSRMLS_C);
        !          1045:                if (script_encoding != NULL) {
        !          1046:                        /* bom or wchar detection is prior to 'script_encoding' option */
        !          1047:                        return script_encoding;
        !          1048:                }
        !          1049:        }
        !          1050: 
        !          1051:        /* if no script_encoding specified, just leave alone */
        !          1052:        if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) {
        !          1053:                return NULL;
        !          1054:        }
        !          1055: 
        !          1056:        /* if multiple encodings specified, detect automagically */
        !          1057:        if (CG(script_encoding_list_size) > 1 && CG(encoding_detector)) {
        !          1058:                list = zend_multibyte_assemble_encoding_list(CG(script_encoding_list),
        !          1059:                                CG(script_encoding_list_size));
        !          1060:                name = CG(encoding_detector)(LANG_SCNG(script_org), 
        !          1061:                                LANG_SCNG(script_org_size), list TSRMLS_CC);
        !          1062:                if (list) {
        !          1063:                        efree(list);
        !          1064:                }
        !          1065:                if (name) {
        !          1066:                        script_encoding = zend_multibyte_fetch_encoding(name);
        !          1067:                        efree(name);
        !          1068:                } else {
        !          1069:                        script_encoding = NULL;
        !          1070:                }
        !          1071:                return script_encoding;
        !          1072:        }
        !          1073: 
        !          1074:        return *(CG(script_encoding_list));
        !          1075: }
        !          1076: 
        !          1077: 
        !          1078: static zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D)
        !          1079: {
        !          1080:        zend_encoding *script_encoding = NULL;
        !          1081:        int bom_size;
        !          1082:        unsigned char *script;
        !          1083: 
        !          1084:        if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) {
        !          1085:                return NULL;
        !          1086:        }
        !          1087: 
        !          1088:        /* check out BOM */
        !          1089:        if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) {
        !          1090:                script_encoding = &encoding_utf32be;
        !          1091:                bom_size = sizeof(BOM_UTF32_BE)-1;
        !          1092:        } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) {
        !          1093:                script_encoding = &encoding_utf32le;
        !          1094:                bom_size = sizeof(BOM_UTF32_LE)-1;
        !          1095:        } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) {
        !          1096:                script_encoding = &encoding_utf16be;
        !          1097:                bom_size = sizeof(BOM_UTF16_BE)-1;
        !          1098:        } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) {
        !          1099:                script_encoding = &encoding_utf16le;
        !          1100:                bom_size = sizeof(BOM_UTF16_LE)-1;
        !          1101:        } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) {
        !          1102:                script_encoding = &encoding_utf8;
        !          1103:                bom_size = sizeof(BOM_UTF8)-1;
        !          1104:        }
        !          1105: 
        !          1106:        if (script_encoding) {
        !          1107:                /* remove BOM */
        !          1108:                script = (unsigned char*)emalloc(LANG_SCNG(script_org_size)+1-bom_size);
        !          1109:                memcpy(script, LANG_SCNG(script_org)+bom_size, LANG_SCNG(script_org_size)+1-bom_size);
        !          1110:                efree(LANG_SCNG(script_org));
        !          1111:                LANG_SCNG(script_org) = script;
        !          1112:                LANG_SCNG(script_org_size) -= bom_size;
        !          1113: 
        !          1114:                return script_encoding;
        !          1115:        }
        !          1116: 
        !          1117:        /* script contains NULL bytes -> auto-detection */
        !          1118:        if (memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size))) {
        !          1119:                /* make best effort if BOM is missing */
        !          1120:                return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC);
        !          1121:        }
        !          1122: 
        !          1123:        return NULL;
        !          1124: }
        !          1125: 
        !          1126: static zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC)
        !          1127: {
        !          1128:        const unsigned char *p;
        !          1129:        int wchar_size = 2;
        !          1130:        int le = 0;
        !          1131: 
        !          1132:        /* utf-16 or utf-32? */
        !          1133:        p = script;
        !          1134:        while ((p-script) < script_size) {
        !          1135:                p = memchr(p, 0, script_size-(p-script)-2);
        !          1136:                if (!p) {
        !          1137:                        break;
        !          1138:                }
        !          1139:                if (*(p+1) == '\0' && *(p+2) == '\0') {
        !          1140:                        wchar_size = 4;
        !          1141:                        break;
        !          1142:                }
        !          1143: 
        !          1144:                /* searching for UTF-32 specific byte orders, so this will do */
        !          1145:                p += 4;
        !          1146:        }
        !          1147: 
        !          1148:        /* BE or LE? */
        !          1149:        p = script;
        !          1150:        while ((p-script) < script_size) {
        !          1151:                if (*p == '\0' && *(p+wchar_size-1) != '\0') {
        !          1152:                        /* BE */
        !          1153:                        le = 0;
        !          1154:                        break;
        !          1155:                } else if (*p != '\0' && *(p+wchar_size-1) == '\0') {
        !          1156:                        /* LE* */
        !          1157:                        le = 1;
        !          1158:                        break;
        !          1159:                }
        !          1160:                p += wchar_size;
        !          1161:        }
        !          1162: 
        !          1163:        if (wchar_size == 2) {
        !          1164:                return le ? &encoding_utf16le : &encoding_utf16be;
        !          1165:        } else {
        !          1166:                return le ? &encoding_utf32le : &encoding_utf32be;
        !          1167:        }
        !          1168: 
        !          1169:        return NULL;
        !          1170: }
        !          1171: #endif /* ZEND_MULTIBYTE */
        !          1172: 
        !          1173: /*
        !          1174:  * Local variables:
        !          1175:  * tab-width: 4
        !          1176:  * c-basic-offset: 4
        !          1177:  * End:
        !          1178:  * vim600: sw=4 ts=4 tw=78
        !          1179:  * vim<600: sw=4 ts=4 tw=78
        !          1180:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>